mirror of https://github.com/grafana/grafana.git
User: Handle unique constraints errors (#101274)
* Handle unique constraints errors
This commit is contained in:
parent
8d7108d774
commit
c1d9d4d15a
|
|
@ -2,11 +2,15 @@ package userimpl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/events"
|
"github.com/grafana/grafana/pkg/events"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
|
|
@ -72,7 +76,7 @@ func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, handleSQLError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.ID, nil
|
return cmd.ID, nil
|
||||||
|
|
@ -580,3 +584,30 @@ func setOptional[T any](v *T, add func(v T)) {
|
||||||
add(*v)
|
add(*v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleSQLError(err error) error {
|
||||||
|
if isUniqueConstraintError(err) {
|
||||||
|
return user.ErrUserAlreadyExists
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUniqueConstraintError(err error) bool {
|
||||||
|
// check mysql error code
|
||||||
|
var me *mysql.MySQLError
|
||||||
|
if errors.As(err, &me) && me.Number == 1062 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// for postgres we check the error message
|
||||||
|
if strings.Contains(err.Error(), "duplicate key value") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var se sqlite3.Error
|
||||||
|
if errors.As(err, &se) && se.ExtendedCode == sqlite3.ErrConstraintUnique {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,19 @@ func TestIntegrationUserDataAccess(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("error on duplicated user", func(t *testing.T) {
|
||||||
|
_, err := userStore.Insert(context.Background(),
|
||||||
|
&user.User{
|
||||||
|
Email: "test@email.com",
|
||||||
|
Name: "test1",
|
||||||
|
Login: "test1",
|
||||||
|
Created: time.Now(),
|
||||||
|
Updated: time.Now(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.ErrorIs(t, err, user.ErrUserAlreadyExists)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("get user", func(t *testing.T) {
|
t.Run("get user", func(t *testing.T) {
|
||||||
_, err := userStore.GetByEmail(context.Background(),
|
_, err := userStore.GetByEmail(context.Background(),
|
||||||
&user.GetUserByEmailQuery{Email: "test@email.com"},
|
&user.GetUserByEmailQuery{Email: "test@email.com"},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue