diff --git a/go.mod b/go.mod index f44e2e5..2698c10 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( ariga.io/atlas v0.23.0 entgo.io/ent v0.13.1 github.com/MicahParks/keyfunc/v3 v3.3.3 + github.com/gin-contrib/zap v1.1.3 github.com/gin-gonic/gin v1.10.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang-migrate/migrate/v4 v4.17.1 diff --git a/go.sum b/go.sum index 30bd985..742638e 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,8 @@ github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-contrib/zap v1.1.3 h1:9e/U9fYd4/OBfmSEBs5hHZq114uACn7bpuzvCkcJySA= +github.com/gin-contrib/zap v1.1.3/go.mod h1:+BD/6NYZKJyUpqVoJEvgeq9GLz8pINEQvak9LHNOTSE= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= diff --git a/internal/access/bind.go b/internal/access/bind.go index dcd27b5..fe83958 100644 --- a/internal/access/bind.go +++ b/internal/access/bind.go @@ -15,5 +15,5 @@ var ( ) func init() { - panic("ent not impl, if impl, uncommit this line") + //panic("ent not impl, if impl, uncommit this line") } diff --git a/internal/access/http_context.go b/internal/access/http_context.go index 3f93c5a..09bb592 100644 --- a/internal/access/http_context.go +++ b/internal/access/http_context.go @@ -1,13 +1 @@ package access - -import ( - "framework_v2/internal/providers" - "github.com/gin-gonic/gin" -) - -type User providers.JwtIDToken - -type Metadata struct { - Http *gin.Context - User User -} diff --git a/internal/cmd/http.go b/internal/cmd/http.go index dcad895..0efd0d6 100644 --- a/internal/cmd/http.go +++ b/internal/cmd/http.go @@ -2,6 +2,7 @@ package cmd import ( "framework_v2/internal/access" + internalHttp "framework_v2/internal/http" "framework_v2/internal/providers" "github.com/spf13/cobra" ) @@ -12,12 +13,12 @@ var httpCommand = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { providers.InitConfig() providers.InitLogger() - providers.InitEnt() - providers.InitRedis() + //providers.InitEnt() + //providers.InitRedis() providers.InitJwksRefresh() providers.InitAsynQClient() providers.InitGin() - providers.InitApiRoutes() + internalHttp.InitHttp() StartHttp() }, diff --git a/internal/consts/http_metadata.go b/internal/consts/http_metadata.go new file mode 100644 index 0000000..cf1e8e3 --- /dev/null +++ b/internal/consts/http_metadata.go @@ -0,0 +1,10 @@ +package consts + +import ( + "github.com/gin-gonic/gin" +) + +type Metadata struct { + Http *gin.Context + User *UserTokenInfo +} diff --git a/internal/consts/user.go b/internal/consts/user.go new file mode 100644 index 0000000..f6fc680 --- /dev/null +++ b/internal/consts/user.go @@ -0,0 +1,24 @@ +package consts + +type UserTokenInfo struct { + Exp int `json:"exp"` + Iat int `json:"iat"` + AuthTime int `json:"auth_time"` + Jti string `json:"jti"` + Iss string `json:"iss"` + Aud string `json:"aud"` + Sub string `json:"sub"` + Typ string `json:"typ"` + Azp string `json:"azp"` + SessionState string `json:"session_state"` + AtHash string `json:"at_hash"` + Acr string `json:"acr"` + Sid string `json:"sid"` + EmailVerified bool `json:"email_verified"` + Name string `json:"name"` + PreferredUsername string `json:"preferred_username"` + GivenName string `json:"given_name"` + FamilyName string `json:"family_name"` + Email string `json:"email"` + Groups []string `json:"groups"` +} diff --git a/internal/controllers/.gitkeep b/internal/controllers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/controllers/user/main.go b/internal/controllers/user/main.go deleted file mode 100644 index 948c86a..0000000 --- a/internal/controllers/user/main.go +++ /dev/null @@ -1,8 +0,0 @@ -package user - -import ( - "framework_v2/internal/access" -) - -func CurrentUser(metadata *access.Metadata) { -} diff --git a/internal/http/controllers/user/main.go b/internal/http/controllers/user/main.go new file mode 100644 index 0000000..395a53b --- /dev/null +++ b/internal/http/controllers/user/main.go @@ -0,0 +1,13 @@ +package user + +import ( + "framework_v2/internal/consts" + "github.com/gin-gonic/gin" + "net/http" +) + +func CurrentUser(req *consts.Metadata) { + req.Http.JSON(http.StatusOK, gin.H{ + "req": req.User, + }) +} diff --git a/internal/http/http.go b/internal/http/http.go new file mode 100644 index 0000000..23932ef --- /dev/null +++ b/internal/http/http.go @@ -0,0 +1,14 @@ +package http + +import ( + "framework_v2/internal/access" + "framework_v2/internal/http/routes" +) + +func InitHttp() { + if access.Router == nil { + panic("You must call InitGin() before InitHttp()") + } + + routes.InitApiRoutes() +} diff --git a/internal/providers/routes.go b/internal/http/routes/api.go similarity index 50% rename from internal/providers/routes.go rename to internal/http/routes/api.go index 1bf29e6..c967b38 100644 --- a/internal/providers/routes.go +++ b/internal/http/routes/api.go @@ -1,6 +1,6 @@ -package providers +package routes -import "framework_v2/internal/controllers/user" +import "framework_v2/internal/http/controllers/user" func InitApiRoutes() { HandleRoute(GET, "/", user.CurrentUser) diff --git a/internal/http/routes/routes.go b/internal/http/routes/routes.go new file mode 100644 index 0000000..8fb9094 --- /dev/null +++ b/internal/http/routes/routes.go @@ -0,0 +1,45 @@ +package routes + +import ( + "framework_v2/internal/access" + "framework_v2/internal/consts" + "github.com/gin-gonic/gin" +) + +type httpMethod int + +var httpMethodStr = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"} + +func (h httpMethod) String() string { + return httpMethodStr[h-1] +} + +const ( + GET httpMethod = iota + 1 + POST + PUT + DELETE + PATCH + HEAD + OPTIONS +) + +type HandlerFunc func(metadata *consts.Metadata) + +func HandleRoute(method httpMethod, relativePath string, controller HandlerFunc, middlewares ...gin.HandlerFunc) { + access.Router.Handle(method.String(), relativePath, func(c *gin.Context) { + for _, middleware := range middlewares { + middleware(c) + } + + handleWithMetadata(c, controller) + }) +} + +func handleWithMetadata(c *gin.Context, controller HandlerFunc) { + var metadata = &consts.Metadata{ + Http: c, + } + + controller(metadata) +} diff --git a/internal/providers/gin.go b/internal/providers/gin.go index b37f84f..6c53d6f 100644 --- a/internal/providers/gin.go +++ b/internal/providers/gin.go @@ -2,48 +2,16 @@ package providers import ( "framework_v2/internal/access" + ginzap "github.com/gin-contrib/zap" "github.com/gin-gonic/gin" + "time" ) func InitGin() { - access.Router = gin.Default() - access.Router.Use(gin.Recovery()) -} - -type httpMethod int - -var httpMethodStr = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"} - -func (h httpMethod) String() string { - return httpMethodStr[h-1] -} - -const ( - GET httpMethod = iota + 1 - POST - PUT - DELETE - PATCH - HEAD - OPTIONS -) - -type HandlerFunc func(metadata *access.Metadata) - -func HandleRoute(method httpMethod, relativePath string, controller HandlerFunc, middlewares ...gin.HandlerFunc) { - access.Router.Handle(method.String(), relativePath, func(c *gin.Context) { - for _, middleware := range middlewares { - middleware(c) - } - - handleWithMetadata(c, controller) - }) -} - -func handleWithMetadata(c *gin.Context, controller HandlerFunc) { - var metadata = &access.Metadata{ - Http: c, - } - - controller(metadata) + gin.SetMode(gin.ReleaseMode) + + access.Router = gin.New() + + access.Router.Use(gin.Recovery(), ginzap.Ginzap(access.Logger, time.RFC3339, true)) + access.Router.Use(ginzap.RecoveryWithZap(access.Logger, true)) } diff --git a/internal/providers/interceptor/auth.go b/internal/providers/interceptor/auth.go index 250cecf..017402f 100644 --- a/internal/providers/interceptor/auth.go +++ b/internal/providers/interceptor/auth.go @@ -2,6 +2,7 @@ package interceptor import ( "context" + "framework_v2/internal/consts" "framework_v2/internal/providers" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" @@ -17,10 +18,10 @@ func JwtAuth(ctx context.Context) (context.Context, error) { } sub := "anonymous" - var jwtIdToken *providers.JwtIDToken + var jwtIdToken *consts.UserTokenInfo if providers.Config.DebugMode.Enable { - jwtIdToken = &providers.JwtIDToken{ + jwtIdToken = &consts.UserTokenInfo{ Sub: sub, } } else { diff --git a/internal/providers/jwks.go b/internal/providers/jwks.go index 4845b94..3d29df9 100644 --- a/internal/providers/jwks.go +++ b/internal/providers/jwks.go @@ -3,6 +3,7 @@ package providers import ( "context" "errors" + "framework_v2/internal/consts" "github.com/MicahParks/keyfunc/v3" "github.com/golang-jwt/jwt/v5" "time" @@ -12,29 +13,6 @@ var refreshRate = 1 * time.Hour var Jwks keyfunc.Keyfunc -type JwtIDToken struct { - Exp int `json:"exp"` - Iat int `json:"iat"` - AuthTime int `json:"auth_time"` - Jti string `json:"jti"` - Iss string `json:"iss"` - Aud string `json:"aud"` - Sub string `json:"sub"` - Typ string `json:"typ"` - Azp string `json:"azp"` - SessionState string `json:"session_state"` - AtHash string `json:"at_hash"` - Acr string `json:"acr"` - Sid string `json:"sid"` - EmailVerified bool `json:"email_verified"` - Name string `json:"name"` - PreferredUsername string `json:"preferred_username"` - GivenName string `json:"given_name"` - FamilyName string `json:"family_name"` - Email string `json:"email"` - Groups []string `json:"groups"` -} - var ( ErrJWKSNotInitialized = errors.New("JWKS is not initialized") ) @@ -73,12 +51,12 @@ func ParseJWT(jwtB64 string) (*jwt.Token, error) { return token, err } -func GetAuthFromCtx(ctx context.Context) *JwtIDToken { +func GetAuthFromCtx(ctx context.Context) *consts.UserTokenInfo { auth := ctx.Value("auth") if auth == nil { return nil } - return auth.(*JwtIDToken) + return auth.(*consts.UserTokenInfo) } diff --git a/internal/providers/user.go b/internal/providers/user.go deleted file mode 100644 index 9dee655..0000000 --- a/internal/providers/user.go +++ /dev/null @@ -1,11 +0,0 @@ -package providers - -func (*JwtIDToken) InGroup(user *JwtIDToken, groupName string) bool { - for _, g := range user.Groups { - if g == groupName { - return true - } - } - - return false -}