diff --git a/Makefile b/Makefile index 83b75ef2..e423fa54 100644 --- a/Makefile +++ b/Makefile @@ -16,4 +16,4 @@ build-static: .PHONY: test test: - go test -mod=vendor -tags testing -v $(TEST_ARGS) -timeout=15m -parallel=4 ./... + go test -race -mod=vendor -tags testing -v $(TEST_ARGS) -timeout=15m -parallel=4 -count=1 ./... diff --git a/database/sql/models.go b/database/sql/models.go index de3b9e24..bb88bda9 100644 --- a/database/sql/models.go +++ b/database/sql/models.go @@ -78,8 +78,8 @@ type Repository struct { Base CredentialsName string - Owner string `gorm:"index:idx_owner,unique"` - Name string `gorm:"index:idx_owner,unique"` + Owner string `gorm:"index:idx_owner_nocase,unique,collate:nocase"` + Name string `gorm:"index:idx_owner_nocase,unique,collate:nocase"` WebhookSecret []byte Pools []Pool `gorm:"foreignKey:RepoID"` } @@ -88,7 +88,7 @@ type Organization struct { Base CredentialsName string - Name string `gorm:"uniqueIndex"` + Name string `gorm:"index:idx_org_name_nocase,collate:nocase"` WebhookSecret []byte Pools []Pool `gorm:"foreignKey:OrgID"` } diff --git a/database/sql/organizations.go b/database/sql/organizations.go index bb61070d..36a810c9 100644 --- a/database/sql/organizations.go +++ b/database/sql/organizations.go @@ -374,7 +374,7 @@ func (s *sqlDatabase) getOrgByID(ctx context.Context, id string, preload ...stri func (s *sqlDatabase) getOrg(ctx context.Context, name string) (Organization, error) { var org Organization - q := s.conn.Where("name = ?", name) + q := s.conn.Where("name = ? COLLATE NOCASE", name) q = q.First(&org) if q.Error != nil { if errors.Is(q.Error, gorm.ErrRecordNotFound) { diff --git a/database/sql/organizations_test.go b/database/sql/organizations_test.go index 7b55e8d4..1765288c 100644 --- a/database/sql/organizations_test.go +++ b/database/sql/organizations_test.go @@ -139,6 +139,13 @@ func (s *OrgTestSuite) TestGetOrganization() { s.Require().Equal(s.Fixtures.Orgs[0].ID, org.ID) } +func (s *OrgTestSuite) TestGetOrganizationCaseInsensitive() { + org, err := s.Store.GetOrganization(context.Background(), "TeSt-oRg-1") + + s.Require().Nil(err) + s.Require().Equal("test-org-1", org.Name) +} + func (s *OrgTestSuite) TestGetOrganizationNotFound() { _, err := s.Store.GetOrganization(context.Background(), "dummy-name") diff --git a/database/sql/repositories.go b/database/sql/repositories.go index 48cfe9a4..c97daf43 100644 --- a/database/sql/repositories.go +++ b/database/sql/repositories.go @@ -282,7 +282,7 @@ func (s *sqlDatabase) UpdateRepositoryPool(ctx context.Context, repoID, poolID s func (s *sqlDatabase) getRepo(ctx context.Context, owner, name string) (Repository, error) { var repo Repository - q := s.conn.Where("name = ? and owner = ?", name, owner). + q := s.conn.Where("name = ? COLLATE NOCASE and owner = ? COLLATE NOCASE", name, owner). First(&repo) q = q.First(&repo) diff --git a/database/sql/sql.go b/database/sql/sql.go index 21c8e566..a523d354 100644 --- a/database/sql/sql.go +++ b/database/sql/sql.go @@ -16,6 +16,7 @@ package sql import ( "context" + "log" "github.com/pkg/errors" "gorm.io/driver/mysql" @@ -79,6 +80,17 @@ type sqlDatabase struct { } func (s *sqlDatabase) migrateDB() error { + if s.conn.Migrator().HasIndex(&Organization{}, "idx_organizations_name") { + if err := s.conn.Migrator().DropIndex(&Organization{}, "idx_organizations_name"); err != nil { + log.Printf("failed to drop index idx_organizations_name: %s", err) + } + } + + if s.conn.Migrator().HasIndex(&Repository{}, "idx_owner") { + if err := s.conn.Migrator().DropIndex(&Repository{}, "idx_owner"); err != nil { + log.Printf("failed to drop index idx_owner: %s", err) + } + } if err := s.conn.AutoMigrate( &Tag{}, &Pool{}, diff --git a/database/sql/users.go b/database/sql/users.go index 24e10f02..4c84a1f3 100644 --- a/database/sql/users.go +++ b/database/sql/users.go @@ -85,10 +85,7 @@ func (s *sqlDatabase) CreateUser(ctx context.Context, user params.NewUserParams) func (s *sqlDatabase) HasAdminUser(ctx context.Context) bool { var user User q := s.conn.Model(&User{}).Where("is_admin = ?", true).First(&user) - if q.Error != nil { - return false - } - return true + return q.Error == nil } func (s *sqlDatabase) GetUser(ctx context.Context, user string) (params.User, error) { diff --git a/runner/pool/organization.go b/runner/pool/organization.go index 675ce85c..546d28b2 100644 --- a/runner/pool/organization.go +++ b/runner/pool/organization.go @@ -17,6 +17,7 @@ package pool import ( "context" "fmt" + "strings" "sync" "garm/config" @@ -182,7 +183,7 @@ func (r *organization) GetPoolByID(poolID string) (params.Pool, error) { } func (r *organization) ValidateOwner(job params.WorkflowJob) error { - if job.Organization.Login != r.cfg.Name { + if !strings.EqualFold(job.Organization.Login, r.cfg.Name) { return runnerErrors.NewBadRequestError("job not meant for this pool manager") } return nil diff --git a/runner/pool/repository.go b/runner/pool/repository.go index 59dae638..6416efe5 100644 --- a/runner/pool/repository.go +++ b/runner/pool/repository.go @@ -17,6 +17,7 @@ package pool import ( "context" "fmt" + "strings" "sync" "garm/config" @@ -184,7 +185,7 @@ func (r *repository) GetPoolByID(poolID string) (params.Pool, error) { } func (r *repository) ValidateOwner(job params.WorkflowJob) error { - if job.Repository.Name != r.cfg.Name || job.Repository.Owner.Login != r.cfg.Owner { + if !strings.EqualFold(job.Repository.Name, r.cfg.Name) || !strings.EqualFold(job.Repository.Owner.Login, r.cfg.Owner) { return runnerErrors.NewBadRequestError("job not meant for this pool manager") } return nil