Skip to content

Commit a658c94

Browse files
authored
chore: automatically generate dbauthz when new queries are added (#8007)
* chore: automatically generate dbauthz when new queries are added * Merge system functions
1 parent c12c9f1 commit a658c94

File tree

8 files changed

+3682
-3530
lines changed

8 files changed

+3682
-3530
lines changed

coderd/database/dbauthz/dbauthz.go

+2,051
Large diffs are not rendered by default.

coderd/database/dbauthz/dbauthz_test.go

+1,429
Large diffs are not rendered by default.

coderd/database/dbauthz/querier.go

-1,634
This file was deleted.

coderd/database/dbauthz/querier_test.go

-1,155
This file was deleted.

coderd/database/dbauthz/system.go

-440
This file was deleted.

coderd/database/dbauthz/system_test.go

-301
This file was deleted.

coderd/database/gen/authz/main.go

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
package main
2+
3+
import (
4+
"go/format"
5+
"go/token"
6+
"log"
7+
"os"
8+
9+
"github.com/dave/dst"
10+
"github.com/dave/dst/decorator"
11+
"github.com/dave/dst/decorator/resolver/goast"
12+
"github.com/dave/dst/decorator/resolver/guess"
13+
"golang.org/x/xerrors"
14+
)
15+
16+
func main() {
17+
err := run()
18+
if err != nil {
19+
log.Fatal(err)
20+
}
21+
}
22+
23+
func run() error {
24+
funcs, err := readStoreInterface()
25+
if err != nil {
26+
return err
27+
}
28+
funcByName := map[string]struct{}{}
29+
for _, f := range funcs {
30+
funcByName[f.Name] = struct{}{}
31+
}
32+
declByName := map[string]*dst.FuncDecl{}
33+
34+
dbauthz, err := os.ReadFile("./dbauthz/dbauthz.go")
35+
if err != nil {
36+
return xerrors.Errorf("read dbauthz: %w", err)
37+
}
38+
39+
// Required to preserve imports!
40+
f, err := decorator.NewDecoratorWithImports(token.NewFileSet(), "dbauthz", goast.New()).Parse(dbauthz)
41+
if err != nil {
42+
return xerrors.Errorf("parse dbauthz: %w", err)
43+
}
44+
45+
for i := 0; i < len(f.Decls); i++ {
46+
funcDecl, ok := f.Decls[i].(*dst.FuncDecl)
47+
if !ok || funcDecl.Recv == nil || len(funcDecl.Recv.List) == 0 {
48+
continue
49+
}
50+
// Check if the receiver is the struct we're interested in
51+
starExpr, ok := funcDecl.Recv.List[0].Type.(*dst.StarExpr)
52+
if !ok {
53+
continue
54+
}
55+
ident, ok := starExpr.X.(*dst.Ident)
56+
if !ok || ident.Name != "querier" {
57+
continue
58+
}
59+
if _, ok := funcByName[funcDecl.Name.Name]; !ok {
60+
continue
61+
}
62+
declByName[funcDecl.Name.Name] = funcDecl
63+
f.Decls = append(f.Decls[:i], f.Decls[i+1:]...)
64+
i--
65+
}
66+
67+
for _, fn := range funcs {
68+
decl, ok := declByName[fn.Name]
69+
if !ok {
70+
// Not implemented!
71+
decl = &dst.FuncDecl{
72+
Name: dst.NewIdent(fn.Name),
73+
Type: &dst.FuncType{
74+
Func: true,
75+
TypeParams: fn.Func.TypeParams,
76+
Params: fn.Func.Params,
77+
Results: fn.Func.Results,
78+
Decs: fn.Func.Decs,
79+
},
80+
Recv: &dst.FieldList{
81+
List: []*dst.Field{{
82+
Names: []*dst.Ident{dst.NewIdent("q")},
83+
Type: dst.NewIdent("*querier"),
84+
}},
85+
},
86+
Decs: dst.FuncDeclDecorations{
87+
NodeDecs: dst.NodeDecs{
88+
Before: dst.EmptyLine,
89+
After: dst.EmptyLine,
90+
},
91+
},
92+
Body: &dst.BlockStmt{
93+
List: []dst.Stmt{
94+
&dst.ExprStmt{
95+
X: &dst.CallExpr{
96+
Fun: &dst.Ident{
97+
Name: "panic",
98+
},
99+
Args: []dst.Expr{
100+
&dst.BasicLit{
101+
Kind: token.STRING,
102+
Value: "\"Not implemented\"",
103+
},
104+
},
105+
},
106+
},
107+
},
108+
},
109+
}
110+
}
111+
f.Decls = append(f.Decls, decl)
112+
}
113+
114+
file, err := os.OpenFile("./dbauthz/dbauthz.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o755)
115+
if err != nil {
116+
return xerrors.Errorf("open dbauthz: %w", err)
117+
}
118+
defer file.Close()
119+
120+
// Required to preserve imports!
121+
restorer := decorator.NewRestorerWithImports("dbauthz", guess.New())
122+
restored, err := restorer.RestoreFile(f)
123+
if err != nil {
124+
return xerrors.Errorf("restore dbauthz: %w", err)
125+
}
126+
err = format.Node(file, restorer.Fset, restored)
127+
return err
128+
}
129+
130+
type storeMethod struct {
131+
Name string
132+
Func *dst.FuncType
133+
}
134+
135+
func readStoreInterface() ([]storeMethod, error) {
136+
querier, err := os.ReadFile("./querier.go")
137+
if err != nil {
138+
return nil, xerrors.Errorf("read querier: %w", err)
139+
}
140+
f, err := decorator.Parse(querier)
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
var sqlcQuerier *dst.InterfaceType
146+
for _, decl := range f.Decls {
147+
genDecl, ok := decl.(*dst.GenDecl)
148+
if !ok {
149+
continue
150+
}
151+
152+
for _, spec := range genDecl.Specs {
153+
typeSpec, ok := spec.(*dst.TypeSpec)
154+
if !ok {
155+
continue
156+
}
157+
if typeSpec.Name.Name != "sqlcQuerier" {
158+
continue
159+
}
160+
sqlcQuerier, ok = typeSpec.Type.(*dst.InterfaceType)
161+
if !ok {
162+
return nil, xerrors.Errorf("unexpected sqlcQuerier type: %T", typeSpec.Type)
163+
}
164+
break
165+
}
166+
}
167+
if sqlcQuerier == nil {
168+
return nil, xerrors.Errorf("sqlcQuerier not found")
169+
}
170+
funcs := []storeMethod{}
171+
for _, method := range sqlcQuerier.Methods.List {
172+
funcType, ok := method.Type.(*dst.FuncType)
173+
if !ok {
174+
continue
175+
}
176+
177+
for _, t := range []*dst.FieldList{funcType.Params, funcType.Results} {
178+
if t == nil {
179+
continue
180+
}
181+
for _, f := range t.List {
182+
ident, ok := f.Type.(*dst.Ident)
183+
if !ok {
184+
continue
185+
}
186+
if !ident.IsExported() {
187+
continue
188+
}
189+
ident.Path = "github.com/coder/coder/coderd/database"
190+
}
191+
}
192+
193+
funcs = append(funcs, storeMethod{
194+
Name: method.Names[0].Name,
195+
Func: funcType,
196+
})
197+
}
198+
return funcs, nil
199+
}

coderd/database/generate.sh

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
6363
go run gen/fake/main.go
6464
go run golang.org/x/tools/cmd/goimports@latest -w ./dbfake/dbfake.go
6565

66+
go run gen/authz/main.go
67+
go run golang.org/x/tools/cmd/goimports@latest -w ./dbauthz/dbauthz.go
68+
6669
go run gen/metrics/main.go
6770
go run golang.org/x/tools/cmd/goimports@latest -w ./dbmetrics/dbmetrics.go
6871
)

0 commit comments

Comments
 (0)