Skip to content

Commit

Permalink
refactor: auth to domain and handler to main
Browse files Browse the repository at this point in the history
  • Loading branch information
litsynp committed Sep 10, 2023
1 parent 47c10c4 commit 13c0617
Show file tree
Hide file tree
Showing 15 changed files with 181 additions and 146 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
package server
package handler

import (
"encoding/json"
"fmt"
"net/http"

"firebase.google.com/go/auth"
"github.com/pet-sitter/pets-next-door-api/api/commonviews"
"github.com/pet-sitter/pets-next-door-api/internal/configs"
"github.com/pet-sitter/pets-next-door-api/internal/domain/auth"
"github.com/pet-sitter/pets-next-door-api/internal/domain/user"
kakaoinfra "github.com/pet-sitter/pets-next-door-api/internal/infra/kakao"
)

type authHandler struct {
authService auth.AuthService
kakaoClient kakaoinfra.IKakaoClient
}

func newAuthHandler(kakaoClient kakaoinfra.IKakaoClient) *authHandler {
func NewAuthHandler(authService auth.AuthService, kakaoClient kakaoinfra.IKakaoClient) *authHandler {
return &authHandler{
authService: authService,
kakaoClient: kakaoClient,
}
}
Expand All @@ -28,7 +30,7 @@ func newAuthHandler(kakaoClient kakaoinfra.IKakaoClient) *authHandler {
// @Tags auth
// @Success 302
// @Router /auth/login/kakao [get]
func (h *authHandler) kakaoLogin(w http.ResponseWriter, r *http.Request) {
func (h *authHandler) KakaoLogin(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://kauth.kakao.com/oauth/authorize?"+
"client_id="+configs.KakaoRestAPIKey+
"&redirect_uri="+configs.KakaoRedirectURI+
Expand All @@ -38,21 +40,13 @@ func (h *authHandler) kakaoLogin(w http.ResponseWriter, r *http.Request) {
)
}

type kakaoCallbackResponse struct {
AuthToken string `json:"authToken"`
FirebaseProviderType user.FirebaseProviderType `json:"fbProviderType"`
FirebaseUID string `json:"fbUid"`
Email string `json:"email"`
PhotoURL string `json:"photoURL"`
}

// kakaoCallback godoc
// @Summary Kakao 회원가입 콜백 API
// @Description Kakao 로그인 콜백을 처리하고, 사용자 기본 정보와 함께 Firebase Custom Token을 발급합니다.
// @Tags auth
// @Success 200 {object} kakaoCallbackResponse
// @Success 200 {object} auth.KakaoCallbackResponse
// @Router /auth/callback/kakao [get]
func (h *authHandler) kakaoCallback(w http.ResponseWriter, r *http.Request) {
func (h *authHandler) KakaoCallback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")

tokenView, err := h.kakaoClient.FetchAccessToken(code)
Expand All @@ -68,16 +62,15 @@ func (h *authHandler) kakaoCallback(w http.ResponseWriter, r *http.Request) {
}

ctx := r.Context()
authClient := ctx.Value(firebaseAuthClientKey).(*auth.Client)
customToken, err := authClient.CustomToken(ctx, fmt.Sprintf("%d", userProfile.ID))
customToken, err := h.authService.CustomToken(ctx, fmt.Sprintf("%d", userProfile.ID))
if err != nil {
commonviews.Unauthorized(w, nil, err.Error())
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(kakaoCallbackResponse{
json.NewEncoder(w).Encode(auth.KakaoCallbackResponse{
AuthToken: customToken,
FirebaseProviderType: user.FirebaseProviderTypeKakao,
FirebaseUID: fmt.Sprintf("%d", userProfile.ID),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package handler

import (
"net/http"
Expand All @@ -13,7 +13,7 @@ type mediaHandler struct {
mediaService media.MediaServicer
}

func newMediaHandler(mediaService media.MediaServicer) *mediaHandler {
func NewMediaHandler(mediaService media.MediaServicer) *mediaHandler {
return &mediaHandler{
mediaService: mediaService,
}
Expand All @@ -27,7 +27,7 @@ func newMediaHandler(mediaService media.MediaServicer) *mediaHandler {
// @Param id path int true "미디어 ID"
// @Success 200 {object} media.MediaView
// @Router /media/{id} [get]
func (h *mediaHandler) findMediaByID(w http.ResponseWriter, r *http.Request) {
func (h *mediaHandler) FindMediaByID(w http.ResponseWriter, r *http.Request) {
id, err := webutils.ParseIdFromPath(r, "id")
if err != nil || id <= 0 {
commonviews.NotFound(w, nil, "invalid media ID")
Expand Down Expand Up @@ -57,7 +57,7 @@ func (h *mediaHandler) findMediaByID(w http.ResponseWriter, r *http.Request) {
// @Param file formData file true "이미지 파일"
// @Success 201 {object} media.MediaView
// @Router /media/images [post]
func (h *mediaHandler) uploadImage(w http.ResponseWriter, r *http.Request) {
func (h *mediaHandler) UploadImage(w http.ResponseWriter, r *http.Request) {
if err := r.ParseMultipartForm(10 << 20); err != nil {
commonviews.BadRequest(w, nil, err.Error())
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package handler

import (
"encoding/json"
Expand All @@ -7,17 +7,20 @@ import (

"github.com/go-playground/validator"
"github.com/pet-sitter/pets-next-door-api/api/commonviews"
"github.com/pet-sitter/pets-next-door-api/internal/domain/auth"
"github.com/pet-sitter/pets-next-door-api/internal/domain/pet"
"github.com/pet-sitter/pets-next-door-api/internal/domain/user"
)

type UserHandler struct {
userService user.UserServicer
authService auth.AuthService
}

func newUserHandler(userService user.UserServicer) *UserHandler {
func NewUserHandler(userService user.UserServicer, authService auth.AuthService) *UserHandler {
return &UserHandler{
userService: userService,
authService: authService,
}
}

Expand Down Expand Up @@ -88,7 +91,7 @@ func (h *UserHandler) FindUserStatusByEmail(w http.ResponseWriter, r *http.Reque
// @Success 200 {object} user.FindUserResponse
// @Router /users/me [get]
func (h *UserHandler) FindMyProfile(w http.ResponseWriter, r *http.Request) {
idToken, err := verifyAuth(r.Context(), r.Header.Get("Authorization"))
idToken, err := h.authService.VerifyAuth(r.Context(), r.Header.Get("Authorization"))
if err != nil {
commonviews.Unauthorized(w, nil, "unauthorized")
log.Printf("verifyAuth error: %v\n", err)
Expand Down Expand Up @@ -117,7 +120,7 @@ func (h *UserHandler) FindMyProfile(w http.ResponseWriter, r *http.Request) {
// @Success 200 {object} user.UpdateUserResponse
// @Router /users/me [put]
func (h *UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) {
idToken, err := verifyAuth(r.Context(), r.Header.Get("Authorization"))
idToken, err := h.authService.VerifyAuth(r.Context(), r.Header.Get("Authorization"))
if err != nil {
commonviews.Unauthorized(w, nil, "unauthorized")
return
Expand Down Expand Up @@ -158,7 +161,7 @@ func (h *UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) {
// @Success 200
// @Router /users/me/pets [put]
func (h *UserHandler) AddMyPets(w http.ResponseWriter, r *http.Request) {
idToken, err := verifyAuth(r.Context(), r.Header.Get("Authorization"))
idToken, err := h.authService.VerifyAuth(r.Context(), r.Header.Get("Authorization"))
if err != nil {
commonviews.Unauthorized(w, nil, "unauthorized")
return
Expand Down Expand Up @@ -188,7 +191,7 @@ func (h *UserHandler) AddMyPets(w http.ResponseWriter, r *http.Request) {
// @Success 200 {object} pet.FindMyPetsView
// @Router /users/me/pets [get]
func (h *UserHandler) FindMyPets(w http.ResponseWriter, r *http.Request) {
idToken, err := verifyAuth(r.Context(), r.Header.Get("Authorization"))
idToken, err := h.authService.VerifyAuth(r.Context(), r.Header.Get("Authorization"))
if err != nil {
commonviews.Unauthorized(w, nil, "unauthorized")
return
Expand Down
3 changes: 1 addition & 2 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/pet-sitter/pets-next-door-api/internal/configs"
firebaseinfra "github.com/pet-sitter/pets-next-door-api/internal/infra/firebase"
"github.com/pet-sitter/pets-next-door-api/internal/server"

_ "github.com/pet-sitter/pets-next-door-api/pkg/docs"
)
Expand Down Expand Up @@ -37,7 +36,7 @@ func main() {
app = firebaseinfra.NewFirebaseAppFromCredentialsPath(configs.FirebaseCredentialsPath)
}

r := server.NewRouter(app)
r := NewRouter(app)

log.Printf("Starting server on port %s", configs.Port)
log.Fatal(http.ListenAndServe(":"+configs.Port, r))
Expand Down
38 changes: 21 additions & 17 deletions internal/server/router.go → cmd/server/router.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package main

import (
"context"
Expand All @@ -8,37 +8,41 @@ import (

"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/pet-sitter/pets-next-door-api/cmd/server/handler"
"github.com/pet-sitter/pets-next-door-api/internal/configs"
"github.com/pet-sitter/pets-next-door-api/internal/domain/auth"
"github.com/pet-sitter/pets-next-door-api/internal/domain/media"
"github.com/pet-sitter/pets-next-door-api/internal/domain/user"
"github.com/pet-sitter/pets-next-door-api/internal/infra/database"
firebaseinfra "github.com/pet-sitter/pets-next-door-api/internal/infra/firebase"
kakaoinfra "github.com/pet-sitter/pets-next-door-api/internal/infra/kakao"
s3infra "github.com/pet-sitter/pets-next-door-api/internal/infra/s3"
"github.com/pet-sitter/pets-next-door-api/internal/postgres"
pndMiddleware "github.com/pet-sitter/pets-next-door-api/lib/middleware"
httpSwagger "github.com/swaggo/http-swagger/v2"
)

func NewRouter(app *firebaseinfra.FirebaseApp) *chi.Mux {
r := chi.NewRouter()

registerMiddlewares(r, app)
addRoutes(r)

return r
}

func registerMiddlewares(r *chi.Mux, app *firebaseinfra.FirebaseApp) {
authClient, err := app.Auth(context.Background())
authService := auth.NewFirebaseBearerAuthService(authClient)
if err != nil {
log.Fatalf("error initializing app: %v\n", err)
}

registerMiddlewares(r, app, authService)
addRoutes(r, authService)

return r
}

func registerMiddlewares(r *chi.Mux, app *firebaseinfra.FirebaseApp, authService auth.AuthService) {
r.Use(middleware.Logger)
r.Use(buildFirebaseAuthMiddleware(authClient))
r.Use(pndMiddleware.BuildAuthMiddleware(&authService, auth.FirebaseAuthClientKey))
}

func addRoutes(r *chi.Mux) {
func addRoutes(r *chi.Mux, authService auth.AuthService) {
db, err := database.Open(configs.DatabaseURL)
if err != nil {
log.Fatalf("error opening database: %v\n", err)
Expand All @@ -60,9 +64,9 @@ func addRoutes(r *chi.Mux) {
mediaService,
)

authHandler := newAuthHandler(kakaoinfra.NewKakaoClient())
userHandler := newUserHandler(userService)
mediaHandler := newMediaHandler(mediaService)
authHandler := handler.NewAuthHandler(authService, kakaoinfra.NewKakaoClient())
userHandler := handler.NewUserHandler(userService, authService)
mediaHandler := handler.NewMediaHandler(mediaService)

r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
Expand All @@ -75,12 +79,12 @@ func addRoutes(r *chi.Mux) {

r.Route("/api", func(r chi.Router) {
r.Route("/auth", func(r chi.Router) {
r.Get("/login/kakao", authHandler.kakaoLogin)
r.Get("/callback/kakao", authHandler.kakaoCallback)
r.Get("/login/kakao", authHandler.KakaoLogin)
r.Get("/callback/kakao", authHandler.KakaoCallback)
})
r.Route("/media", func(r chi.Router) {
r.Get("/{id}", mediaHandler.findMediaByID)
r.Post("/images", mediaHandler.uploadImage)
r.Get("/{id}", mediaHandler.FindMediaByID)
r.Post("/images", mediaHandler.UploadImage)
})
r.Route("/users", func(r chi.Router) {
r.Post("/", userHandler.RegisterUser)
Expand Down
5 changes: 5 additions & 0 deletions internal/domain/auth/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package auth

type ContextKey string

const FirebaseAuthClientKey ContextKey = "firebaseAuthClient"
46 changes: 46 additions & 0 deletions internal/domain/auth/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package auth

import (
"context"
"fmt"
"strings"

"firebase.google.com/go/auth"
)

type AuthService interface {
VerifyAuth(ctx context.Context, authHeader string) (*auth.Token, error)
CustomToken(ctx context.Context, uid string) (string, error)
}

type FirebaseBearerAuthService struct {
authClient *auth.Client
}

func NewFirebaseBearerAuthService(authClient *auth.Client) *FirebaseBearerAuthService {
return &FirebaseBearerAuthService{
authClient: authClient,
}
}

func (s *FirebaseBearerAuthService) VerifyAuth(ctx context.Context, authHeader string) (*auth.Token, error) {
idToken, err := s.stripBearerToken(authHeader)
if err != nil {
return nil, err
}

authToken, err := s.authClient.VerifyIDToken(ctx, idToken)
return authToken, err
}

func (s *FirebaseBearerAuthService) CustomToken(ctx context.Context, uid string) (string, error) {
return s.authClient.CustomToken(ctx, uid)
}

func (s *FirebaseBearerAuthService) stripBearerToken(authHeader string) (string, error) {
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:7]) == "BEARER " {
return authHeader[7:], nil
}

return authHeader, fmt.Errorf("invalid auth header")
}
11 changes: 11 additions & 0 deletions internal/domain/auth/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package auth

import "github.com/pet-sitter/pets-next-door-api/internal/domain/user"

type KakaoCallbackResponse struct {
AuthToken string `json:"authToken"`
FirebaseProviderType user.FirebaseProviderType `json:"fbProviderType"`
FirebaseUID string `json:"fbUid"`
Email string `json:"email"`
PhotoURL string `json:"photoURL"`
}
38 changes: 0 additions & 38 deletions internal/server/auth.go

This file was deleted.

5 changes: 0 additions & 5 deletions internal/server/context.go

This file was deleted.

Loading

0 comments on commit 13c0617

Please sign in to comment.