NOISSUE - Handle user registration errors (#3177)

Signed-off-by: Arvindh <arvindh91@gmail.com>
This commit is contained in:
Arvindh
2025-10-08 23:26:54 +05:30
committed by GitHub
parent bc7727c275
commit b0e9e43b9e
5 changed files with 53 additions and 14 deletions
+5
View File
@@ -190,6 +190,11 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
}
switch {
case errors.Contains(err, errors.ErrEmailAlreadyExists),
errors.Contains(err, errors.ErrUsernameNotAvailable),
errors.Contains(err, errors.ErrChannelRouteNotAvailable),
errors.Contains(err, errors.ErrDomainRouteNotAvailable):
w.WriteHeader(http.StatusBadRequest)
case errors.Contains(err, svcerr.ErrAuthorization),
errors.Contains(err, svcerr.ErrDomainAuthorization),
errors.Contains(err, svcerr.ErrUnauthorizedPAT),
+21 -11
View File
@@ -3,36 +3,46 @@
package errors
import "errors"
var (
// ErrMalformedEntity indicates a malformed entity specification.
ErrMalformedEntity = New("malformed entity specification")
// ErrUnsupportedContentType indicates invalid content type.
ErrUnsupportedContentType = errors.New("invalid content type")
ErrUnsupportedContentType = New("invalid content type")
// ErrUnidentified indicates unidentified error.
ErrUnidentified = errors.New("unidentified error")
ErrUnidentified = New("unidentified error")
// ErrEmptyPath indicates empty file path.
ErrEmptyPath = errors.New("empty file path")
ErrEmptyPath = New("empty file path")
// ErrStatusAlreadyAssigned indicated that the client or group has already been assigned the status.
ErrStatusAlreadyAssigned = errors.New("status already assigned")
ErrStatusAlreadyAssigned = New("status already assigned")
// ErrRollbackTx indicates failed to rollback transaction.
ErrRollbackTx = errors.New("failed to rollback transaction")
ErrRollbackTx = New("failed to rollback transaction")
// ErrAuthentication indicates failure occurred while authenticating the entity.
ErrAuthentication = errors.New("failed to perform authentication over the entity")
ErrAuthentication = New("failed to perform authentication over the entity")
// ErrAuthorization indicates failure occurred while authorizing the entity.
ErrAuthorization = errors.New("failed to perform authorization over the entity")
ErrAuthorization = New("failed to perform authorization over the entity")
// ErrMissingDomainMember indicates member is not part of a domain.
ErrMissingDomainMember = errors.New("member id is not member of domain")
ErrMissingDomainMember = New("member id is not member of domain")
// ErrMissingMember indicates member is not found.
ErrMissingMember = errors.New("member id is not found")
ErrMissingMember = New("member id is not found")
// ErrEmailAlreadyExists indicates that the email id already exists.
ErrEmailAlreadyExists = New("email id already exists")
// ErrUsernameNotAvailable indicates that the username is not available.
ErrUsernameNotAvailable = New("username not available")
// ErrDomainRouteNotAvailable indicates that the domain route is not available.
ErrDomainRouteNotAvailable = New("domain route not available")
// ErrChannelRouteNotAvailable indicates that the channel route is not available.
ErrChannelRouteNotAvailable = New("channel route not available")
)
+9
View File
@@ -118,6 +118,15 @@ func Migration() *migrate.MemoryMigrationSource {
`DROP TABLE users_verifications;`,
},
},
{
Id: "clients_08",
Up: []string{
`ALTER TABLE users RENAME CONSTRAINT clients_identity_key TO clients_email_key;`,
},
Down: []string{
`ALTER TABLE users RENAME CONSTRAINT clients_email_key TO clients_identity_key;`,
},
},
},
}
}
+16 -1
View File
@@ -18,8 +18,11 @@ import (
"github.com/absmach/supermq/pkg/postgres"
"github.com/absmach/supermq/users"
"github.com/jackc/pgtype"
"github.com/jackc/pgx/v5/pgconn"
)
var pgDuplicateErrCode = "23505"
type userRepo struct {
Repository users.UserRepository
}
@@ -42,7 +45,7 @@ func (repo *userRepo) Save(ctx context.Context, c users.User) (users.User, error
row, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbu)
if err != nil {
return users.User{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
return users.User{}, handleSaveError(repoerr.ErrCreateEntity, err)
}
defer row.Close()
@@ -62,6 +65,18 @@ func (repo *userRepo) Save(ctx context.Context, c users.User) (users.User, error
return user, nil
}
func handleSaveError(wrapper, err error) error {
if pqErr, ok := err.(*pgconn.PgError); ok && pqErr.Code == pgDuplicateErrCode {
switch pqErr.ConstraintName {
case "clients_email_key":
return errors.ErrEmailAlreadyExists
case "clients_username_key":
return errors.ErrUsernameNotAvailable
}
}
return postgres.HandleError(wrapper, err)
}
func (repo *userRepo) CheckSuperAdmin(ctx context.Context, adminID string) error {
q := "SELECT 1 FROM users WHERE id = $1 AND role = $2"
rows, err := repo.Repository.DB.QueryContext(ctx, q, adminID, users.AdminRole)
+2 -2
View File
@@ -80,7 +80,7 @@ func TestUsersSave(t *testing.T) {
Metadata: users.Metadata{},
Status: users.EnabledStatus,
},
err: repoerr.ErrConflict,
err: errors.ErrEmailAlreadyExists,
},
{
desc: "add user with duplicate user name",
@@ -96,7 +96,7 @@ func TestUsersSave(t *testing.T) {
Metadata: users.Metadata{},
Status: users.EnabledStatus,
},
err: repoerr.ErrConflict,
err: errors.ErrUsernameNotAvailable,
},
{
desc: "add user with invalid user id",