Copy and adapt role helper generator to new system
This commit is contained in:
parent
69927c76ff
commit
2afb14c4b3
2 changed files with 535 additions and 0 deletions
195
cmd/NewRoleHelperGenerator/main.go
Normal file
195
cmd/NewRoleHelperGenerator/main.go
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
Tool for generating helper functions for storage.Role structs inside of the storage package
|
||||
It generates the following functions:
|
||||
- CollapseRolesIntoOne: Collapse a list of roles into one singular role. Each value will be set to the
|
||||
value of the role with the highest priority
|
||||
- RoleDeepCopy: Copy a role, including all arrays. Every value will be copied too
|
||||
- CompareRoles: Compare two roles. Returns true only if all fields are equal
|
||||
(if one of the fields is nil, that field is seen as equal)
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||
)
|
||||
|
||||
var findRoleStructRegex = regexp.MustCompile(`type Role struct \{([\s\S]+)\}\n\n/\*`)
|
||||
|
||||
var (
|
||||
flagInputFile = flag.String("input", "", "Specify the input file. If empty, read from stdin")
|
||||
flagOutputFile = flag.String(
|
||||
"output",
|
||||
"",
|
||||
"Specify the output file. If empty, writes to stdout",
|
||||
)
|
||||
flagOutputModule = flag.String(
|
||||
"mod",
|
||||
"",
|
||||
"Module for the output file. If empty, use mod of input file",
|
||||
)
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
var input io.Reader
|
||||
var output io.Writer
|
||||
|
||||
if *flagInputFile == "" {
|
||||
input = os.Stdin
|
||||
} else {
|
||||
file, err := os.Open(*flagInputFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
input = file
|
||||
}
|
||||
if *flagOutputFile == "" {
|
||||
output = os.Stdout
|
||||
} else {
|
||||
file, err := os.Create(*flagOutputFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
output = file
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !findRoleStructRegex.Match(data) {
|
||||
panic("Input doesn't contain role struct")
|
||||
}
|
||||
content := findRoleStructRegex.FindStringSubmatch(string(data))[1]
|
||||
lines := strings.Split(content, "\n")
|
||||
lines = sliceutils.Map(lines, func(t string) string { return strings.TrimSpace(t) })
|
||||
importantLines := sliceutils.Filter(lines, func(t string) bool {
|
||||
if strings.HasPrefix(t, "//") {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(t, "gorm.Model") {
|
||||
return false
|
||||
}
|
||||
data := sliceutils.Filter(strings.Split(t, " "), func(t string) bool { return t != "" })
|
||||
if len(data) < 2 {
|
||||
return false
|
||||
}
|
||||
if !strings.HasPrefix(data[1], "*") && !strings.HasPrefix(data[1], "[]") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
nameTypeMap := map[string]string{}
|
||||
for _, line := range importantLines {
|
||||
parts := sliceutils.Filter(strings.Split(line, " "), func(t string) bool { return t != "" })
|
||||
nameTypeMap[parts[0]] = parts[1]
|
||||
}
|
||||
pkgString, _, _ := strings.Cut(string(data), "\n")
|
||||
|
||||
outBuilder := strings.Builder{}
|
||||
outBuilder.WriteString(`// Code generated by cmd/RolesGenerator DO NOT EDIT.
|
||||
// If you need to refresh the content, run go generate again
|
||||
`)
|
||||
if *flagOutputModule == "" {
|
||||
outBuilder.WriteString(pkgString + "\n\n")
|
||||
} else {
|
||||
outBuilder.WriteString("package " + *flagOutputModule + "\n\n")
|
||||
}
|
||||
outBuilder.WriteString(
|
||||
`import (
|
||||
"slices"
|
||||
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
)
|
||||
|
||||
`,
|
||||
)
|
||||
|
||||
// Build role collapse function
|
||||
outBuilder.WriteString(
|
||||
`func CollapseRolesIntoOne(roles ...models.Role) models.Role {
|
||||
startingRole := RoleDeepCopy(models.DefaultUserRole)
|
||||
slices.SortFunc(roles, func(a, b models.Role) int { return int(int64(a.Priority)-int64(b.Priority)) })
|
||||
for _, role := range roles {
|
||||
`)
|
||||
// Write all the stupid conditions here
|
||||
for valName, valType := range nameTypeMap {
|
||||
if strings.HasPrefix(valType, "[]") {
|
||||
outBuilder.WriteString(fmt.Sprintf(` if role.%s != nil {
|
||||
startingRole.%s = append(startingRole.%s, role.%s...)
|
||||
}
|
||||
`, valName, valName, valName, valName))
|
||||
} else {
|
||||
outBuilder.WriteString(fmt.Sprintf(` if role.%s != nil {
|
||||
*startingRole.%s = *role.%s
|
||||
}
|
||||
`, valName, valName, valName))
|
||||
}
|
||||
}
|
||||
// Then finish up with the end of the function
|
||||
outBuilder.WriteString(
|
||||
` }
|
||||
return startingRole
|
||||
}
|
||||
`)
|
||||
|
||||
// Then build the deep copy function
|
||||
outBuilder.WriteString("\nfunc RoleDeepCopy(o models.Role) models.Role {\n")
|
||||
outBuilder.WriteString(` n := models.Role{}
|
||||
n.Model = o.Model
|
||||
n.Name = o.Name
|
||||
n.Priority = o.Priority
|
||||
n.IsUserRole = o.IsUserRole
|
||||
n.IsBuiltIn = o.IsBuiltIn
|
||||
`)
|
||||
for valName, valType := range nameTypeMap {
|
||||
if strings.HasPrefix(valType, "[]") {
|
||||
outBuilder.WriteString(fmt.Sprintf(" n.%s = slices.Clone(o.%s)\n", valName, valName))
|
||||
} else {
|
||||
outBuilder.WriteString(fmt.Sprintf(` if o.%s == nil { n.%s = nil } else {
|
||||
t := *o.%s
|
||||
n.%s = &t
|
||||
}
|
||||
`, valName, valName, valName, valName))
|
||||
}
|
||||
}
|
||||
outBuilder.WriteString(" return n\n}\n\n")
|
||||
|
||||
// Build compare function
|
||||
outBuilder.WriteString("func CompareRoles(a, b *models.Role) bool {\n")
|
||||
outBuilder.WriteString(" return ")
|
||||
lastName, lastType := "", ""
|
||||
for valName, valType := range nameTypeMap {
|
||||
lastName = valName
|
||||
lastType = valType
|
||||
outBuilder.WriteString(fmt.Sprintf("(a.%s == nil || b.%s == nil || ", valName, valName))
|
||||
if strings.HasPrefix(valType, "[]") {
|
||||
outBuilder.WriteString(
|
||||
fmt.Sprintf("sliceutils.CompareUnordered(a.%s,b.%s)) && ", valName, valName),
|
||||
)
|
||||
} else {
|
||||
outBuilder.WriteString(fmt.Sprintf("a.%s == b.%s) && ", valName, valName))
|
||||
}
|
||||
}
|
||||
outBuilder.WriteString("(a == nil || b == nil || ")
|
||||
if strings.HasPrefix(lastType, "[]") {
|
||||
outBuilder.WriteString(
|
||||
fmt.Sprintf("sliceutils.CompareUnordered(a.%s,b.%s))", lastName, lastName),
|
||||
)
|
||||
} else {
|
||||
outBuilder.WriteString(fmt.Sprintf("a.%s == b.%s)", lastName, lastName))
|
||||
}
|
||||
outBuilder.WriteString("\n}")
|
||||
|
||||
// And write the entire thing to the output
|
||||
fmt.Fprint(output, outBuilder.String())
|
||||
}
|
340
storage-new/role_generated.go
Normal file
340
storage-new/role_generated.go
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue