mStar
7f7bf1cacf
New small script to generate various functions for roles because manually typing out all the permissions sucks
139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"gitlab.com/mstarongitlab/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")
|
|
)
|
|
|
|
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(`// This file is autogenerated, do not edit
|
|
// If you need to refresh the content, run go generate again
|
|
`)
|
|
outBuilder.WriteString(pkgString + "\n\n")
|
|
outBuilder.WriteString("import \"slices\"\n\n")
|
|
|
|
// Build role collapse function
|
|
outBuilder.WriteString(
|
|
`func CollapseRolesIntoOne(roles ...*Role) Role {
|
|
startingRole := RoleDeepCopy(&DefaultUserRole)
|
|
slices.SortFunc(roles, func(a, b *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("\n\nfunc RoleDeepCopy(o *Role) Role {\n")
|
|
outBuilder.WriteString(` n := 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")
|
|
|
|
// And write the entire thing to the output
|
|
fmt.Fprint(output, outBuilder.String())
|
|
}
|