Files
Jesse Hallam 462f34ac6c Generate default_roles_permissions.js from a live server snapshot (#36698)
* Generate default_roles_permissions.js from a live server snapshot

Replace the hand-maintained default_roles_permissions.js with a
generated file. The generator (scripts/default_permissions_generator/)
boots a real app.NewServer() against a temporary database created by
storetest.MakeSqlSettings, lets all schema and app-level migrations run
naturally, then snapshots the resulting Roles table into the JS file.

This eliminates the drift risk of the previous hand-maintained map:
new migrations are picked up automatically because the same server
initialization path is used here as in production.

The CI job gets a postgres service and sets IS_CI=true so the generator
uses the same host-switching logic as the rest of the test suite.
Locally, make start-docker provides the postgres instance.

* Address CodeRabbit feedback: pin checkout SHA, add permissions, add .PHONY entries
2026-05-25 15:03:11 -03:00

126 lines
3.3 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"flag"
"fmt"
"os"
"slices"
"strings"
"text/template"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/channels/app"
"github.com/mattermost/mattermost/server/v8/channels/store/storetest"
"github.com/mattermost/mattermost/server/v8/channels/utils"
"github.com/mattermost/mattermost/server/v8/config"
)
type roleEntry struct {
Name string
Permissions string
}
var tmpl = template.Must(template.New("").Parse(`// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// Code generated by generate_default_roles_permissions.go. DO NOT EDIT.
export const defaultRolesPermissions = {
{{- range .}}
{{.Name}}: '{{.Permissions}}',
{{- end}}
};
`))
func main() {
outPath := flag.String("out", "", "output file path")
flag.Parse()
if *outPath == "" {
fmt.Fprintln(os.Stderr, "usage: generate_default_roles_permissions -out <path>")
os.Exit(1)
}
if err := utils.TranslationsPreInit(); err != nil {
fmt.Fprintf(os.Stderr, "warning: could not load translations: %v\n", err)
}
sqlSettings := storetest.MakeSqlSettings(model.DatabaseDriverPostgres)
defer storetest.CleanupSqlSettings(sqlSettings)
cfg := model.Config{}
cfg.SetDefaults()
cfg.SqlSettings = *sqlSettings
memStore, err := config.NewMemoryStoreWithOptions(&config.MemoryStoreOptions{
InitialConfig: &cfg,
})
if err != nil {
fmt.Fprintf(os.Stderr, "error creating config store: %v\n", err)
os.Exit(1)
}
cfgStore, err := config.NewStoreFromBacking(memStore, nil, false)
if err != nil {
fmt.Fprintf(os.Stderr, "error creating config store: %v\n", err)
os.Exit(1)
}
// NewServer runs both schema migrations (via sqlstore.New) and all
// app-level migrations (doAppMigrations) as part of its initialization.
server, err := app.NewServer(app.ConfigStore(cfgStore))
if err != nil {
fmt.Fprintf(os.Stderr, "error creating server: %v\n", err)
os.Exit(1)
}
defer server.Shutdown()
roles, err := server.Store().Role().GetAll()
if err != nil {
fmt.Fprintf(os.Stderr, "error reading roles: %v\n", err)
os.Exit(1)
}
defaultNames := make(map[string]bool, len(model.MakeDefaultRoles()))
for name := range model.MakeDefaultRoles() {
defaultNames[name] = true
}
var roleNames []string
roleByName := make(map[string]*model.Role, len(roles))
for _, r := range roles {
if defaultNames[r.Name] {
roleNames = append(roleNames, r.Name)
roleByName[r.Name] = r
}
}
slices.Sort(roleNames)
entries := make([]roleEntry, 0, len(roleNames))
for _, name := range roleNames {
perms := make([]string, len(roleByName[name].Permissions))
copy(perms, roleByName[name].Permissions)
slices.Sort(perms)
perms = slices.Compact(perms)
entries = append(entries, roleEntry{
Name: name,
Permissions: strings.Join(perms, " "),
})
}
var b strings.Builder
if err := tmpl.Execute(&b, entries); err != nil {
fmt.Fprintf(os.Stderr, "error executing template: %v\n", err)
os.Exit(1)
}
if err := os.WriteFile(*outPath, []byte(b.String()), 0644); err != nil {
fmt.Fprintf(os.Stderr, "error writing %s: %v\n", *outPath, err)
os.Exit(1)
}
fmt.Printf("Generated %s\n", *outPath)
}