From 7f7bf1cacf2417567821db4d3bc96a9926b3bb4b Mon Sep 17 00:00:00 2001 From: mStar Date: Wed, 18 Sep 2024 10:51:45 +0200 Subject: [PATCH] Autogenerate roles function bullshit New small script to generate various functions for roles because manually typing out all the permissions sucks --- cmd/RolesColapser/main.go | 139 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 cmd/RolesColapser/main.go diff --git a/cmd/RolesColapser/main.go b/cmd/RolesColapser/main.go new file mode 100644 index 0000000..86ac3f3 --- /dev/null +++ b/cmd/RolesColapser/main.go @@ -0,0 +1,139 @@ +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()) +}