fix(api): enforce project identifier uniqueness
This commit is contained in:
@@ -7,7 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"senlinai-agent/backend/internal/models"
|
||||
)
|
||||
@@ -29,6 +31,35 @@ func TestFindOwnedProjectScopesIdentityByOwner(t *testing.T) {
|
||||
require.True(t, errors.Is(err, gorm.ErrRecordNotFound))
|
||||
}
|
||||
|
||||
func TestProjectIdentifierDatabaseConstraintIsScopedByOwner(t *testing.T) {
|
||||
database := newTestDB(t)
|
||||
first := models.SenlinAgentProject{OwnerID: 1, Name: "Alpha", Identifier: "SHARED"}
|
||||
require.NoError(t, database.Create(&first).Error)
|
||||
|
||||
duplicate := models.SenlinAgentProject{OwnerID: 1, Name: "Duplicate", Identifier: "SHARED"}
|
||||
require.ErrorIs(t, database.Create(&duplicate).Error, gorm.ErrDuplicatedKey)
|
||||
|
||||
otherOwner := models.SenlinAgentProject{OwnerID: 2, Name: "Allowed", Identifier: "SHARED"}
|
||||
require.NoError(t, database.Create(&otherOwner).Error)
|
||||
}
|
||||
|
||||
func TestProjectIdentifierDatabaseErrorMapsToConflict(t *testing.T) {
|
||||
database := newTestDB(t)
|
||||
first := models.SenlinAgentProject{OwnerID: 1, Name: "Alpha", Identifier: "SHARED"}
|
||||
require.NoError(t, database.Create(&first).Error)
|
||||
duplicate := models.SenlinAgentProject{OwnerID: 1, Name: "Duplicate", Identifier: "SHARED"}
|
||||
databaseErr := database.Create(&duplicate).Error
|
||||
require.ErrorIs(t, databaseErr, gorm.ErrDuplicatedKey)
|
||||
|
||||
require.ErrorIs(t, projectWriteError(databaseErr), ErrProjectIdentifierConflict)
|
||||
}
|
||||
|
||||
func TestPostgresDuplicateKeyErrorMapsToProjectConflict(t *testing.T) {
|
||||
databaseErr := postgres.Dialector{}.Translate(&pgconn.PgError{Code: "23505"})
|
||||
require.ErrorIs(t, databaseErr, gorm.ErrDuplicatedKey)
|
||||
require.ErrorIs(t, projectWriteError(databaseErr), ErrProjectIdentifierConflict)
|
||||
}
|
||||
|
||||
func TestProjectTagsAreScopedToProject(t *testing.T) {
|
||||
newTestDB(t)
|
||||
service := NewService()
|
||||
@@ -318,7 +349,7 @@ func TestCreateCronPlanAddsPlanToOwnedProject(t *testing.T) {
|
||||
|
||||
func newTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
database, err := gorm.Open(sqlite.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())), &gorm.Config{})
|
||||
database, err := gorm.Open(sqlite.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())), &gorm.Config{TranslateError: true})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, models.AutoMigrate(database))
|
||||
models.DBService = database
|
||||
|
||||
Reference in New Issue
Block a user