feat: roles system backend
This commit is contained in:
1 parent
44cca46d5e
commit
8c6c6456da
50 files changed
+2578
-22
No files matched your search
@@ -0,0 +1,134 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"RenewCMS/internal/domain/role"
|
||||
"RenewCMS/internal/infrastructure/persistence/database"
|
||||
"RenewCMS/internal/infrastructure/persistence/models"
|
||||
persistence "RenewCMS/internal/infrastructure/persistence/repositories"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRoleRepositoryFailures(t *testing.T) {
|
||||
broken := func(t *testing.T, table string) *persistence.RoleRepository {
|
||||
t.Helper()
|
||||
db := openMigratedRolesDB(t)
|
||||
if err := db.Migrator().DropTable(table); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return persistence.NewRoleRepository(db)
|
||||
}
|
||||
|
||||
t.Run("List fails when the roles table is missing", func(t *testing.T) {
|
||||
if _, err := broken(t, "roles").List(); err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get distinguishes a missing role from a storage failure", func(t *testing.T) {
|
||||
repo := persistence.NewRoleRepository(openMigratedRolesDB(t))
|
||||
if _, err := repo.Get(9999); !errors.Is(err, role.ErrRoleNotFound) {
|
||||
t.Errorf("want ErrRoleNotFound, got %v", err)
|
||||
}
|
||||
if _, err := broken(t, "roles").Get(1); err == nil || errors.Is(err, role.ErrRoleNotFound) {
|
||||
t.Errorf("want storage error, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GetByName reports a missing role", func(t *testing.T) {
|
||||
repo := persistence.NewRoleRepository(openMigratedRolesDB(t))
|
||||
if _, err := repo.GetByName("Nobody"); !errors.Is(err, role.ErrRoleNotFound) {
|
||||
t.Errorf("want ErrRoleNotFound, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ListGrants and role loading fail when grants cannot be read", func(t *testing.T) {
|
||||
repo := broken(t, "role_permissions")
|
||||
if _, err := repo.ListGrants(1); err == nil {
|
||||
t.Error("ListGrants: expected error")
|
||||
}
|
||||
if _, err := repo.Get(1); err == nil {
|
||||
t.Error("Get: expected error")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Create persists grants and returns them", func(t *testing.T) {
|
||||
db := openMigratedRolesDB(t)
|
||||
repo := persistence.NewRoleRepository(db)
|
||||
created, err := repo.Create(role.Role{Name: "Contributor", Version: 1, Grants: []role.Grant{{Key: "content.read", Scope: role.ScopeAll}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(created.Grants) != 1 || created.Grants[0].Key != "content.read" {
|
||||
t.Errorf("returned grants: %+v", created.Grants)
|
||||
}
|
||||
if countRows(t, db, &models.RolePermission{}) != 73 {
|
||||
t.Errorf("grant rows not stored")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Create rolls back when the grants cannot be stored", func(t *testing.T) {
|
||||
db := openMigratedRolesDB(t)
|
||||
if err := db.Migrator().DropTable("role_permissions"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
repo := persistence.NewRoleRepository(db)
|
||||
before := countRows(t, db, &models.Role{})
|
||||
_, err := repo.Create(role.Role{Name: "Contributor", Version: 1, Grants: []role.Grant{{Key: "content.read", Scope: role.ScopeAll}}})
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
if countRows(t, db, &models.Role{}) != before {
|
||||
t.Errorf("role row not rolled back")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Create fails when the roles table is missing", func(t *testing.T) {
|
||||
if _, err := broken(t, "roles").Create(role.Role{Name: "X", Version: 1}); err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Save returns the stored role with its new grants", func(t *testing.T) {
|
||||
db := openMigratedRolesDB(t)
|
||||
repo := persistence.NewRoleRepository(db)
|
||||
writer := storedRole(t, db, "Writer")
|
||||
writer.Grants = []role.Grant{{Key: "media.delete", Scope: role.ScopeOwn}}
|
||||
saved, err := repo.Save(writer)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if saved.ID != writer.ID || len(saved.Grants) != 1 || saved.Grants[0].Key != "media.delete" {
|
||||
t.Errorf("saved: %+v", saved)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Save reports a missing role and storage failures", func(t *testing.T) {
|
||||
repo := persistence.NewRoleRepository(openMigratedRolesDB(t))
|
||||
if _, err := repo.Save(role.Role{ID: 9999, Name: "Ghost", Version: 1}); !errors.Is(err, role.ErrRoleNotFound) {
|
||||
t.Errorf("want ErrRoleNotFound, got %v", err)
|
||||
}
|
||||
db := openMigratedRolesDB(t)
|
||||
writer := storedRole(t, db, "Writer")
|
||||
if err := db.Migrator().DropTable("role_permissions"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := persistence.NewRoleRepository(db).Save(writer); err == nil {
|
||||
t.Error("expected storage error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBackfillUserRoleIDsWithoutBuiltInRoles(t *testing.T) {
|
||||
db := openUnmigratedSQLite(t)
|
||||
if err := db.AutoMigrate(&models.Role{}, &models.RolePermission{}, &models.User{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
createUserRow(t, db, 1, "owner", nil)
|
||||
if err := database.BackfillUserRoleIDs(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if userRow(t, db, 1).RoleID != nil {
|
||||
t.Errorf("role_id must stay unset when no built-in role exists")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user