diff --git a/comment.go b/comment.go index e4f87b8..c0bb539 100644 --- a/comment.go +++ b/comment.go @@ -159,8 +159,12 @@ func (c *Comment) Security() *spec.SecurityRequirements { return nil } + return convertSecAnnotationToSecurityRequirements(c.Annotations) +} + +func convertSecAnnotationToSecurityRequirements(annotations []annotation.Annotation) *spec.SecurityRequirements { ret := spec.NewSecurityRequirements() - for _, annot := range c.Annotations { + for _, annot := range annotations { annot, ok := annot.(*annotation.SecurityAnnotation) if ok { ret.With(spec.NewSecurityRequirement().Authenticate(annot.Name, annot.Params...)) diff --git a/plugins/echo/echo.go b/plugins/echo/echo.go index 77afc79..bb5aa71 100644 --- a/plugins/echo/echo.go +++ b/plugins/echo/echo.go @@ -162,13 +162,10 @@ func (e *Plugin) parseAPI(ctx *eapi.Context, callExpr *ast.CallExpr) (api *eapi. fullPath := path.Join(prefix, e.normalizePath(strings.Trim(arg0.Value, "\""))) method := selExpr.Sel.Name api = eapi.NewAPI(method, fullPath) - api.Spec.LoadFromFuncDecl(ctx.Package().Fset, handlerFnDef.Decl) + api.Spec.LoadFromFuncDecl(ctx, handlerFnDef.Decl) if api.Spec.OperationID == "" { api.Spec.OperationID = handlerFnDef.Pkg().Name + "." + handlerFnDef.Decl.Name.Name } - if len(api.Spec.Tags) == 0 { - api.Spec.Tags = ctx.Env.LookupTags() - } newHandlerAnalyzer( ctx.NewEnv().WithPackage(handlerFnDef.Pkg()).WithFile(handlerFnDef.File()), api, diff --git a/plugins/gin/gin.go b/plugins/gin/gin.go index 3190214..93da152 100644 --- a/plugins/gin/gin.go +++ b/plugins/gin/gin.go @@ -175,13 +175,10 @@ func (e *Plugin) parseAPI(ctx *analyzer.Context, callExpr *ast.CallExpr) (api *a fullPath := path.Join(prefix, e.normalizePath(strings.Trim(arg0.Value, "\""))) method := selExpr.Sel.Name api = analyzer.NewAPI(method, fullPath) - api.Spec.LoadFromFuncDecl(ctx.Package().Fset, handlerFnDef.Decl) + api.Spec.LoadFromFuncDecl(ctx, handlerFnDef.Decl) if api.Spec.OperationID == "" { api.Spec.OperationID = handlerFnDef.Pkg().Name + "." + handlerFnDef.Decl.Name.Name } - if len(api.Spec.Tags) == 0 { - api.Spec.Tags = ctx.Env.LookupTags() - } newHandlerParser( ctx.NewEnv().WithPackage(handlerFnDef.Pkg()).WithFile(handlerFnDef.File()), api, diff --git a/plugins/gin/testdata/server/docs/openapi.json b/plugins/gin/testdata/server/docs/openapi.json index 92eac03..538c840 100755 --- a/plugins/gin/testdata/server/docs/openapi.json +++ b/plugins/gin/testdata/server/docs/openapi.json @@ -245,6 +245,14 @@ "description": "参数无效" } }, + "security": [ + { + "oauth2": [ + "goods:read", + "goods:write" + ] + } + ], "summary": "创建商品", "tags": [ "Goods" @@ -345,6 +353,14 @@ } } }, + "security": [ + { + "oauth2": [ + "goods:read", + "goods:write" + ] + } + ], "summary": "下架商品", "tags": [ "Goods" @@ -377,6 +393,13 @@ } } }, + "security": [ + { + "oauth2": [ + "goods:read" + ] + } + ], "summary": "商品详情", "tags": [ "Goods" diff --git a/plugins/gin/testdata/server/router.go b/plugins/gin/testdata/server/router.go index e4b3dd1..69a5d52 100644 --- a/plugins/gin/testdata/server/router.go +++ b/plugins/gin/testdata/server/router.go @@ -26,9 +26,13 @@ func ServeHttp() *gin.Engine { g := r.Group("/api") // @tags Goods + // @security oauth2 goods:read { - g.POST("/goods", shop.GoodsCreate) - g.POST("/goods/:guid/down", shop.GoodsDown) + // @security oauth2 goods:read goods:write + { + g.POST("/goods", shop.GoodsCreate) + g.POST("/goods/:guid/down", shop.GoodsDown) + } g = g.Group("/v2") g.GET("/goods/:guid", shop.GoodsInfo) } diff --git a/route.go b/route.go index 40deb04..1bc9940 100644 --- a/route.go +++ b/route.go @@ -2,10 +2,10 @@ package eapi import ( "go/ast" - "go/token" "net/http" "strings" + "github.com/gotomicro/eapi/annotation" "github.com/gotomicro/eapi/spec" ) @@ -74,9 +74,9 @@ func NewAPISpec() *APISpec { } // LoadFromFuncDecl load annotations/description from comments of handler function -func (s *APISpec) LoadFromFuncDecl(fSet *token.FileSet, funcDecl *ast.FuncDecl) { +func (s *APISpec) LoadFromFuncDecl(ctx *Context, funcDecl *ast.FuncDecl) { cg := funcDecl.Doc - comment := ParseComment(cg, fSet) + comment := ParseComment(cg, ctx.Package().Fset) if comment != nil { s.Summary = comment.Summary() s.Description = strings.TrimSpace(comment.TrimPrefix(funcDecl.Name.Name)) @@ -86,10 +86,15 @@ func (s *APISpec) LoadFromFuncDecl(fSet *token.FileSet, funcDecl *ast.FuncDecl) tags := comment.Tags() if len(tags) > 0 { s.Tags = comment.Tags() + } else { + s.Tags = ctx.Env.LookupTags() } s.OperationID = comment.ID() s.Consumes = append(s.Consumes, comment.Consumes()...) s.Deprecated = comment.Deprecated() s.Security = comment.Security() + if s.Security == nil { + s.Security = convertSecAnnotationToSecurityRequirements(ctx.Env.LookupAnnotations(annotation.Security)) + } } }