/
template.go
117 lines (93 loc) · 2.66 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package generator
import (
"bytes"
"context"
_ "embed"
"errors"
"fmt"
"io"
"text/template"
"golang.org/x/tools/go/packages"
"github.com/ameliaikeda/rbac/generator/core"
)
type Output struct {
Roles io.ReadWriter
Permissions io.ReadWriter
}
func Generate(_ context.Context, generator *core.Generator) (*Output, error) {
if err := validate(generator); err != nil {
return nil, err
}
roleTemplate, err := template.New("roles").Parse(generator.RoleMetadata.Template)
if err != nil {
return nil, err
}
permissionTemplate, err := template.New("permissions").Parse(generator.PermissionMetadata.Template)
if err != nil {
return nil, err
}
output := &Output{
Roles: &bytes.Buffer{},
Permissions: &bytes.Buffer{},
}
if err := roleTemplate.Execute(output.Roles, generator); err != nil {
return nil, err
}
if err := permissionTemplate.Execute(output.Permissions, generator); err != nil {
return nil, err
}
return output, nil
}
type ValidationError struct {
field string
}
func (err ValidationError) Error() string {
return fmt.Sprintf("validation error: field %s is required.", err.field)
}
func missing(param string) error {
return &ValidationError{
field: param,
}
}
func validate(gen *core.Generator) error {
switch {
case len(gen.Roles) == 0:
return missing("roles")
case len(gen.Permissions) == 0:
return missing("permissions")
case gen.PermissionMetadata.Package == "":
return missing("config.permissions.package")
case gen.PermissionMetadata.Template == "":
return missing("config.permissions.template")
case gen.PermissionMetadata.Filename == "":
return missing("config.permissions.filename")
case gen.PermissionMetadata.ImportPath == "" && gen.RoleMetadata.Package != gen.PermissionMetadata.Package:
return missing("config.permissions.import-path")
case gen.RoleMetadata.Package == "":
return missing("config.roles.package")
case gen.RoleMetadata.Template == "":
return missing("config.roles.template")
case gen.RoleMetadata.Filename == "":
return missing("config.roles.filename")
case gen.RoleMetadata.ImportPath == "" && gen.RoleMetadata.Package != gen.PermissionMetadata.Package:
return missing("config.roles.import-path")
}
return nil
}
func ImportPath(path string) (string, error) {
pkgs, err := packages.Load(&packages.Config{}, path)
if err != nil {
return "", err
}
if len(pkgs) != 1 {
return "", errors.New(fmt.Sprintf("rbac: unable to identify package path from path %s", path))
}
pkg := pkgs[0]
if pkg == nil {
return "", errors.New(fmt.Sprintf("rbac: import package path resolved to nil: %s", path))
}
if pkg.Module != nil {
return pkg.Module.Path, nil
}
return pkg.PkgPath, nil
}