Line data Source code
1 : package middleware
2 :
3 : import (
4 : "net/http"
5 :
6 : "github.com/gin-gonic/gin"
7 :
8 : "resume/internal/adapter/http/handlerutil"
9 : "resume/internal/domain/repository"
10 : "resume/internal/shared/apperr"
11 : "resume/internal/shared/ctx/auth"
12 : )
13 :
14 : // ResolveUser は、Firebase UID からユーザー情報を解決するミドルウェアです。
15 : type ResolveUser struct {
16 : userRepo repository.UserRepository
17 : }
18 :
19 : // NewResolveUser は、ユーザー解決ミドルウェアを初期化して返します。
20 2 : func NewResolveUser(userRepo repository.UserRepository) *ResolveUser {
21 2 : return &ResolveUser{userRepo: userRepo}
22 2 : }
23 :
24 : // InjectResolveUser --- 1) 認証“任意”版: 認証が入っていれば user_id を解決・セット。無ければ素通り。
25 0 : func (m *ResolveUser) InjectResolveUser() gin.HandlerFunc {
26 0 : return func(c *gin.Context) {
27 0 : // OPTIONS は素通り(CORSプリフライト対策。RequireAuth と合わせる)
28 0 : if c.Request.Method == http.MethodOptions {
29 0 : c.Next()
30 0 : return
31 0 : }
32 :
33 0 : claims, ok := auth.From(c.Request.Context())
34 0 : if !ok || claims.UID == "" {
35 0 : // 認証なし → そのまま素通り
36 0 : c.Next()
37 0 : return
38 0 : }
39 :
40 0 : u, err := m.userRepo.FindByUID(c.Request.Context(), claims.UID)
41 0 : if err != nil {
42 0 : handlerutil.WriteError(c, apperr.Wrap(apperr.CodeInternal, "failed to load user", err, nil))
43 0 : return
44 0 : }
45 0 : if u == nil || u.ID == 0 {
46 0 : // 「任意」版なので未登録でも素通り(必要ならここで消すこともできる)
47 0 : c.Next()
48 0 : return
49 0 : }
50 :
51 0 : auth.SetUserID(c, uint64(u.ID))
52 0 : c.Next()
53 : }
54 : }
55 :
56 : // RequireResolveUser --- 2) 認証“必須”版: ユーザー未登録や解決失敗ならエラーで打ち切り。
57 2 : func (m *ResolveUser) RequireResolveUser() gin.HandlerFunc {
58 3 : return func(c *gin.Context) {
59 1 : // OPTIONS は素通り
60 1 : if c.Request.Method == http.MethodOptions {
61 0 : c.Next()
62 0 : return
63 0 : }
64 :
65 1 : claims, ok := auth.From(c.Request.Context())
66 1 : if !ok || claims.UID == "" {
67 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeUnauthorized, "unauthorized", nil))
68 0 : return
69 0 : }
70 :
71 1 : u, err := m.userRepo.FindByUID(c.Request.Context(), claims.UID)
72 1 : if err != nil {
73 0 : handlerutil.WriteError(c, apperr.Wrap(apperr.CodeInternal, "failed to load user", err, nil))
74 0 : return
75 0 : }
76 1 : if u == nil || u.ID == 0 {
77 0 : // チーム方針で 401/404/412 のどれかに揃えてOK。ここは 401 に寄せています。
78 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeUnauthorized, "user not registered", nil))
79 0 : return
80 0 : }
81 :
82 1 : auth.SetUserID(c, uint64(u.ID))
83 1 : c.Next()
84 : }
85 : }
|