11package middleware
22
33import (
4+ "errors"
5+ "fmt"
6+ "net/http"
7+ "strings"
8+
49 echo "github.com/labstack/echo/v4"
510 "github.com/reearth/reearth/server/internal/adapter/internal"
611 "github.com/reearth/reearth/server/internal/infrastructure/accounts"
12+ "github.com/reearth/reearth/server/internal/infrastructure/accounts/gqlerror"
13+ "github.com/reearth/reearthx/log"
714)
815
916type AccountsMiddlewares []echo.MiddlewareFunc
@@ -14,7 +21,8 @@ type NewAccountsMiddlewaresParam struct {
1421
1522func NewAccountsMiddlewares (param * NewAccountsMiddlewaresParam ) AccountsMiddlewares {
1623 return []echo.MiddlewareFunc {
17- jwtContextMiddleware (),
24+ // jwtContextMiddleware(),
25+ newAccountsMiddleware (param .AccountsClient ),
1826 }
1927}
2028
@@ -23,19 +31,72 @@ type NewAccountsMiddlewaresMockParam struct {
2331 AccountsClient * accounts.Client
2432}
2533
26- func jwtContextMiddleware () echo.MiddlewareFunc {
34+ // func jwtContextMiddleware() echo.MiddlewareFunc {
35+ // return func(next echo.HandlerFunc) echo.HandlerFunc {
36+ // return func(c echo.Context) error {
37+ // authHeader := c.Request().Header.Get("Authorization")
38+ // if authHeader != "" {
39+ // // Remove the "Bearer " prefix from the Authorization header to extract the token
40+ // const bearerPrefix = "Bearer "
41+ // if len(authHeader) > len(bearerPrefix) && authHeader[:len(bearerPrefix)] == bearerPrefix {
42+ // token := authHeader[len(bearerPrefix):]
43+ // ctx := internal.SetContextJWT(c.Request().Context(), token)
44+ // c.SetRequest(c.Request().WithContext(ctx))
45+ // }
46+ // }
47+ // }
48+ // }
49+ // }
50+
51+ var accountsMiddlewareSkipPaths = []string {
52+ "/api/ping" ,
53+ "/api/published/" ,
54+ "/plugins/" ,
55+ "/assets/" ,
56+ "/favicon.ico" ,
57+ }
58+
59+ func shouldSkipAccountsMiddleware (method , path string ) bool {
60+ // Only skip authentication for GET requests
61+ if method != http .MethodGet {
62+ return false
63+ }
64+
65+ for _ , skipPath := range accountsMiddlewareSkipPaths {
66+ if skipPath == path || strings .HasPrefix (path , skipPath ) {
67+ return true
68+ }
69+ }
70+ return false
71+ }
72+
73+ func newAccountsMiddleware (accountsClient * accounts.Client ) echo.MiddlewareFunc {
2774 return func (next echo.HandlerFunc ) echo.HandlerFunc {
2875 return func (c echo.Context ) error {
29- authHeader := c .Request ().Header .Get ("Authorization" )
30- if authHeader != "" {
31- // Remove the "Bearer " prefix from the Authorization header to extract the token
32- const bearerPrefix = "Bearer "
33- if len (authHeader ) > len (bearerPrefix ) && authHeader [:len (bearerPrefix )] == bearerPrefix {
34- token := authHeader [len (bearerPrefix ):]
35- ctx := internal .SetContextJWT (c .Request ().Context (), token )
36- c .SetRequest (c .Request ().WithContext (ctx ))
76+
77+ if shouldSkipAccountsMiddleware (c .Request ().Method , c .Request ().URL .Path ) {
78+ return next (c )
79+ }
80+
81+ ctx := c .Request ().Context ()
82+
83+ // TODO: Optimize performance by including necessary user information (userID, email, etc.)
84+ // directly in the JWT token instead of executing a GQL query on every request.
85+ // This will eliminate the overhead of making an API call to fetch user data for each request.
86+ u , err := accountsClient .UserRepo .FindMe (ctx )
87+ if err != nil {
88+ if errors .Is (err , gqlerror .ErrUnauthorized ) {
89+ return echo .NewHTTPError (http .StatusUnauthorized , "unauthorized: user not found" )
3790 }
91+ log .Errorc (ctx , fmt .Errorf ("[Accounts Middleware] failed to fetch user: %w" , err ))
92+ return echo .NewHTTPError (http .StatusInternalServerError , "server error: failed to fetch user" )
3893 }
94+ if u == nil {
95+ return echo .NewHTTPError (http .StatusUnauthorized , "unauthorized: user not found" )
96+ }
97+
98+ ctx = internal .SetContextUser (ctx , u )
99+ c .SetRequest (c .Request ().WithContext (ctx ))
39100 return next (c )
40101 }
41102 }
0 commit comments