Files
gochat/internal/repository/permissible_repo_test.go
T
2026-06-04 15:44:48 +08:00

326 lines
10 KiB
Go

package repository
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"github.com/gochat/gochat/internal/model"
)
// Helper: create prerequisite Account + PlatformApp for Permissible tests.
func createPermissiblePrereqs(t *testing.T, db *gorm.DB) (*model.Account, *model.PlatformApp) {
t.Helper()
account := &model.Account{Name: "PermTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
active := true
app := &model.PlatformApp{
Name: "PermTestApp",
AccountID: &account.ID,
Description: "Test platform app for permissible",
Type: "api",
Status: "active",
Active: &active,
}
require.NoError(t, db.Create(app).Error)
return account, app
}
// Helper: create a second PlatformApp for multi-app tests.
func createSecondPlatformApp(t *testing.T, db *gorm.DB, accountID uint) *model.PlatformApp {
t.Helper()
active := true
app := &model.PlatformApp{
Name: "PermTestApp2",
AccountID: &accountID,
Description: "Second test platform app",
Type: "api",
Status: "active",
Active: &active,
}
require.NoError(t, db.Create(app).Error)
return app
}
// ========== 1. Create + GetByID roundtrip ==========
func TestPermissibleRepo_CreateAndGetByID(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
perm := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
err := repo.Create(context.Background(), perm)
require.NoError(t, err)
assert.NotZero(t, perm.ID, "ID should be set after Create")
assert.Equal(t, app.ID, perm.PlatformAppID)
assert.Equal(t, model.PermissibleTypeAccount, perm.PermissibleType)
assert.Equal(t, account.ID, perm.PermissibleID)
// GetByID roundtrip
found, err := repo.GetByID(context.Background(), perm.ID)
require.NoError(t, err)
assert.Equal(t, perm.ID, found.ID)
assert.Equal(t, app.ID, found.PlatformAppID)
assert.Equal(t, model.PermissibleTypeAccount, found.PermissibleType)
assert.Equal(t, account.ID, found.PermissibleID)
}
// ========== 2. FindByPlatformAppID ==========
func TestPermissibleRepo_FindByPlatformAppID(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
// Create multiple permissibles for the same app (different resource types)
perm1 := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
perm2 := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeUser,
PermissibleID: account.ID,
}
require.NoError(t, repo.Create(context.Background(), perm1))
require.NoError(t, repo.Create(context.Background(), perm2))
results, err := repo.FindByPlatformAppID(context.Background(), app.ID)
require.NoError(t, err)
assert.Len(t, results, 2)
// Verify both types are present
types := map[string]bool{}
for _, p := range results {
types[p.PermissibleType] = true
assert.Equal(t, app.ID, p.PlatformAppID)
}
assert.True(t, types[model.PermissibleTypeAccount])
assert.True(t, types[model.PermissibleTypeUser])
}
func TestPermissibleRepo_FindByPlatformAppID_Empty(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
_, app := createPermissiblePrereqs(t, db)
results, err := repo.FindByPlatformAppID(context.Background(), app.ID)
require.NoError(t, err)
assert.Len(t, results, 0)
}
// ========== 3. FindByResource (which apps can access Account X) ==========
func TestPermissibleRepo_FindByResource(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app1 := createPermissiblePrereqs(t, db)
app2 := createSecondPlatformApp(t, db, account.ID)
// Both apps get access to the same Account resource
require.NoError(t, repo.Create(context.Background(), &model.Permissible{
PlatformAppID: app1.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}))
require.NoError(t, repo.Create(context.Background(), &model.Permissible{
PlatformAppID: app2.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}))
// FindByResource should return both permissibles
results, err := repo.FindByResource(context.Background(), model.PermissibleTypeAccount, account.ID)
require.NoError(t, err)
assert.Len(t, results, 2)
// Verify both apps are represented
appIDs := map[uint]bool{}
for _, p := range results {
appIDs[p.PlatformAppID] = true
assert.Equal(t, model.PermissibleTypeAccount, p.PermissibleType)
assert.Equal(t, account.ID, p.PermissibleID)
}
assert.True(t, appIDs[app1.ID])
assert.True(t, appIDs[app2.ID])
}
// ========== 4. FindByPlatformAppAndResource (check if app has permission on specific resource) ==========
func TestPermissibleRepo_FindByPlatformAppAndResource(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
perm := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
require.NoError(t, repo.Create(context.Background(), perm))
// Found: app has permission on this resource
found, err := repo.FindByPlatformAppAndResource(context.Background(), app.ID, model.PermissibleTypeAccount, account.ID)
require.NoError(t, err)
assert.Equal(t, perm.ID, found.ID)
assert.Equal(t, app.ID, found.PlatformAppID)
assert.Equal(t, model.PermissibleTypeAccount, found.PermissibleType)
assert.Equal(t, account.ID, found.PermissibleID)
}
func TestPermissibleRepo_FindByPlatformAppAndResource_NotFound(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
// No permissible created — should return gorm.ErrRecordNotFound
_, err := repo.FindByPlatformAppAndResource(context.Background(), app.ID, model.PermissibleTypeAccount, account.ID)
assert.Error(t, err)
assert.Equal(t, gorm.ErrRecordNotFound, err)
}
// ========== 5. Delete single Permissible ==========
func TestPermissibleRepo_Delete(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
perm := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
require.NoError(t, repo.Create(context.Background(), perm))
err := repo.Delete(context.Background(), perm.ID)
require.NoError(t, err)
// Verify it's gone
_, err = repo.GetByID(context.Background(), perm.ID)
assert.Error(t, err)
assert.Equal(t, gorm.ErrRecordNotFound, err)
}
// ========== 6. DeleteByPlatformAppAndResource ==========
func TestPermissibleRepo_DeleteByPlatformAppAndResource(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
// Create two permissibles: one for Account, one for User
permAccount := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
permUser := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeUser,
PermissibleID: account.ID,
}
require.NoError(t, repo.Create(context.Background(), permAccount))
require.NoError(t, repo.Create(context.Background(), permUser))
// Delete only the Account permission
err := repo.DeleteByPlatformAppAndResource(context.Background(), app.ID, model.PermissibleTypeAccount, account.ID)
require.NoError(t, err)
// Account permission should be gone
_, err = repo.FindByPlatformAppAndResource(context.Background(), app.ID, model.PermissibleTypeAccount, account.ID)
assert.Equal(t, gorm.ErrRecordNotFound, err)
// User permission should still exist
found, err := repo.FindByPlatformAppAndResource(context.Background(), app.ID, model.PermissibleTypeUser, account.ID)
require.NoError(t, err)
assert.Equal(t, permUser.ID, found.ID)
}
// ========== 7. DeleteByPlatformAppID (cleanup when app is deleted) ==========
func TestPermissibleRepo_DeleteByPlatformAppID(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
app2 := createSecondPlatformApp(t, db, account.ID)
// Create permissibles for both apps
require.NoError(t, repo.Create(context.Background(), &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}))
require.NoError(t, repo.Create(context.Background(), &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeUser,
PermissibleID: account.ID,
}))
require.NoError(t, repo.Create(context.Background(), &model.Permissible{
PlatformAppID: app2.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}))
// Delete all permissibles for app1
err := repo.DeleteByPlatformAppID(context.Background(), app.ID)
require.NoError(t, err)
// App1's permissibles should all be gone
results, err := repo.FindByPlatformAppID(context.Background(), app.ID)
require.NoError(t, err)
assert.Len(t, results, 0)
// App2's permissible should still exist
results, err = repo.FindByPlatformAppID(context.Background(), app2.ID)
require.NoError(t, err)
assert.Len(t, results, 1)
assert.Equal(t, model.PermissibleTypeAccount, results[0].PermissibleType)
}
// ========== 8. Duplicate permission should error (unique constraint) ==========
func TestPermissibleRepo_DuplicatePermissionError(t *testing.T) {
db := setupTestDB(t, &model.Permissible{}, &model.PlatformApp{})
repo := NewPermissibleRepo(db)
account, app := createPermissiblePrereqs(t, db)
perm := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
require.NoError(t, repo.Create(context.Background(), perm))
// Attempt to create duplicate (same platform_app_id + permissible_type + permissible_id)
dup := &model.Permissible{
PlatformAppID: app.ID,
PermissibleType: model.PermissibleTypeAccount,
PermissibleID: account.ID,
}
err := repo.Create(context.Background(), dup)
assert.Error(t, err, "duplicate permissible should return an error")
}