From 5dd70f1e44db8527633b787680211aba8e18ba93 Mon Sep 17 00:00:00 2001 From: olegdemchenko Date: Wed, 28 Sep 2016 21:21:50 +0300 Subject: [PATCH] policies implementation --- g_docs.go | 33 ++++++++++++++++ g_policies.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ watch.go | 1 + 3 files changed, 138 insertions(+) create mode 100644 g_policies.go diff --git a/g_docs.go b/g_docs.go index a92c917..6a651bb 100644 --- a/g_docs.go +++ b/g_docs.go @@ -149,6 +149,9 @@ func generateDocs(curpath string) { Name: strings.Trim(s, "/"), Description: v, }) + if policy := policyList[controllerName]; policy != nil { + policyPathList[version+s] = policy + } } } } @@ -189,6 +192,8 @@ func generateDocs(curpath string) { if err != nil || erryml != nil { panic(err) } + + generatePolicies(curpath) } // return version and the others params @@ -321,6 +326,7 @@ func analisyscontrollerPkg(localName, pkgpath string) { //parse controller definition comments if strings.TrimSpace(specDecl.Doc.Text()) != "" { controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() + controllerFindPolicies(specDecl.Doc, s.(*ast.TypeSpec).Name.Name, pkgpath) } } } @@ -368,6 +374,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat opts := swagger.Operation{ Responses: make(map[string]swagger.Response), } + policy := Policy{} if comments != nil && comments.List != nil { for _, c := range comments.List { t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) @@ -543,6 +550,11 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat opts.Produces = append(opts.Produces, ahtml) } } + } else if strings.HasPrefix(t, "@policy") { + policyFields := strings.FieldsFunc(t[len("@policy"):], func(c rune) bool {return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c!='_'}) + for _, val := range policyFields { + policy.Policies = append(policy.Policies, val) + } } } } @@ -575,6 +587,27 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat item.Options = &opts } controllerList[pkgpath+controllerName][routerPath] = item + + if len(policy.Policies) > 0 { + policy.Method = strings.ToLower(HTTPMethod) + if i := strings.Index(routerPath, ":"); i < 0 { + policy.Path = routerPath + } else { + policy.Path = routerPath[:i] + } + policyMethods := policyList[pkgpath+controllerName] + if policyMethods == nil { + policyMethods = make(map[string]*Policy) + policyList[pkgpath+controllerName] = policyMethods + } + if pm := policyMethods[policy.Method]; pm != nil { + for _, curPolicy := range policy.Policies { + pm.Policies = append(pm.Policies, curPolicy) + } + } else { + policyMethods[policy.Method] = &policy + } + } } return nil } diff --git a/g_policies.go b/g_policies.go new file mode 100644 index 0000000..5c4f92d --- /dev/null +++ b/g_policies.go @@ -0,0 +1,104 @@ +// Copyright 2016 bee authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "go/ast" + "os" + "path" + "strings" + "text/template" + "unicode" +) + +type Policy struct { + Method string + Path string + Policies []string +} + +var ( + policyList = make(map[string]map[string]*Policy) //controllername -> method -> policy + policyPathList = make(map[string]map[string]*Policy) //path -> method -> policy +) + +func controllerFindPolicies(comments *ast.CommentGroup, controllerName, pkgpath string) { + if comments == nil || comments.List == nil { + return + } + for _, c := range comments.List { + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + if strings.HasPrefix(t, "@policy") { + policy := Policy{ + Method: "*", + } + policyFields := strings.FieldsFunc(t[len("@policy"):], func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_' }) + for _, val := range policyFields { + policy.Policies = append(policy.Policies, val) + } + policyMethods := policyList[pkgpath+controllerName] + if policyMethods == nil { + policyMethods = make(map[string]*Policy) + policyList[pkgpath+controllerName] = policyMethods + } + if pm := policyMethods[policy.Method]; pm != nil { + for _, curPolicy := range policy.Policies { + pm.Policies = append(pm.Policies, curPolicy) + } + } else { + policyMethods[policy.Method] = &policy + } + } + } +} + +func generatePolicies(curpath string) { + fn := template.FuncMap{ + "join": strings.Join, + } + + tmpl, err := template.New("policy template").Funcs(fn).Parse(policyTpl) + if err != nil { + panic("Can't parse policy template: " + err.Error()) + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, policyPathList) + if err != nil { + panic("Can't execute policy template: " + err.Error()) + + } + policyFile, err := os.Create(path.Join(curpath, "policies", "policies_autogen.go")) + if err != nil { + panic(err) + } + defer policyFile.Close() + + _, err = policyFile.Write(buf.Bytes()) + if err != nil { + panic(err) + } +} + +var policyTpl = `// This file was auto-generated by bee tools, do not change it! +package policies + +import "github.com/astaxie/beego" + +func init() { +{{ range $path, $policyList := . }}{{ range $, $policy := $policyList }} beego.Policy("{{$path}}{{$policy.Path}}", "{{$policy.Method}}", {{ join $policy.Policies ", " }}) +{{ end }}{{ end }} +} +` diff --git a/watch.go b/watch.go index efde48a..56e45b4 100644 --- a/watch.go +++ b/watch.go @@ -253,6 +253,7 @@ var ignoredFilesRegExps = []string{ `.(\w+).go.swp`, `(\w+).go~`, `(\w+).tmp`, + `policies_autogen.go`, } // checkIfWatchExt returns true if the name HasSuffix .