feat: add admin screens, permissions and navigation

Seven admin controllers in a "Studia BM" navigation group, guarded by
jz.bm.access_courses, jz.bm.access_schedule and jz.bm.access_materials,
with Polish and English labels. Date and time fields are checked by the
models before a save and answered as 422 on the field.
This commit is contained in:
Jakub Zych
2026-10-02 14:26:26 +02:00
parent 1046237771
commit 577fa14d3d
42 changed files with 1234 additions and 11 deletions

43
updates/updates_test.go Normal file
View File

@@ -0,0 +1,43 @@
package updates_test
import (
"os"
"regexp"
"slices"
"strings"
"testing"
bm "git.golem15.com/jakub/sm-bm-plugin"
)
var migrationFile = regexp.MustCompile(`^(\d{14})_[a-z0-9_]+\.go$`)
// The set must run in ID order (foreign keys point at earlier tables), and
// every migration file is named after its ID.
func TestMigrationOrder(t *testing.T) {
var ids []string
for _, m := range (&bm.Plugin{}).Migrations() {
if m.Migrate == nil || m.Rollback == nil {
t.Errorf("migration %s has no Migrate or Rollback", m.ID)
}
ids = append(ids, m.ID)
}
if !slices.IsSorted(ids) {
t.Errorf("migration IDs are not ascending: %v", ids)
}
entries, err := os.ReadDir(".")
if err != nil {
t.Fatal(err)
}
var files []string
for _, e := range entries {
name := e.Name()
if e.IsDir() || !migrationFile.MatchString(name) {
continue
}
files = append(files, strings.TrimSuffix(name, ".go"))
}
if !slices.Equal(files, ids) {
t.Errorf("migration files %v, want one per ID %v", files, ids)
}
}