mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
NOISSUE - Handle Domain & Channel Route not available error during creation (#3180)
Signed-off-by: Arvindh <arvindh91@gmail.com>
This commit is contained in:
@@ -192,6 +192,7 @@ 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.ErrRouteNotAvailable),
|
||||
errors.Contains(err, errors.ErrChannelRouteNotAvailable),
|
||||
errors.Contains(err, errors.ErrDomainRouteNotAvailable):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
@@ -29,6 +30,8 @@ const (
|
||||
rolesTableNamePrefix = "channels"
|
||||
entityTableName = "channels"
|
||||
entityIDColumnName = "id"
|
||||
|
||||
pgDuplicateErrCode = "23505"
|
||||
)
|
||||
|
||||
var _ channels.Repository = (*channelRepository)(nil)
|
||||
@@ -64,7 +67,7 @@ func (cr *channelRepository) Save(ctx context.Context, chs ...channels.Channel)
|
||||
|
||||
row, err := cr.db.NamedQueryContext(ctx, q, dbchs)
|
||||
if err != nil {
|
||||
return []channels.Channel{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
|
||||
return []channels.Channel{}, handleSaveError(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
|
||||
defer row.Close()
|
||||
@@ -86,6 +89,16 @@ func (cr *channelRepository) Save(ctx context.Context, chs ...channels.Channel)
|
||||
return reChs, nil
|
||||
}
|
||||
|
||||
func handleSaveError(wrapper, err error) error {
|
||||
if pqErr, ok := err.(*pgconn.PgError); ok && pqErr.Code == pgDuplicateErrCode {
|
||||
switch pqErr.ConstraintName {
|
||||
case "unique_domain_route_not_null":
|
||||
return errors.ErrRouteNotAvailable
|
||||
}
|
||||
}
|
||||
return postgres.HandleError(wrapper, err)
|
||||
}
|
||||
|
||||
func (cr *channelRepository) Update(ctx context.Context, channel channels.Channel) (channels.Channel, error) {
|
||||
var query []string
|
||||
var upq string
|
||||
@@ -733,7 +746,7 @@ indirect_child_groups AS (
|
||||
groups indirect_child_groups ON indirect_child_groups.path <@ dlgws.path
|
||||
WHERE
|
||||
indirect_child_groups.domain_id = '%s'
|
||||
AND NOT EXISTS (
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM direct_groups_with_subgroup dgws
|
||||
WHERE dgws.id = indirect_child_groups.id
|
||||
|
||||
@@ -172,7 +172,7 @@ func TestSave(t *testing.T) {
|
||||
Route: duplicateRoute,
|
||||
},
|
||||
resp: []channels.Channel{},
|
||||
err: repoerr.ErrConflict,
|
||||
err: errors.ErrRouteNotAvailable,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ func (svc service) CreateChannels(ctx context.Context, session authn.Session, ch
|
||||
|
||||
savedChs, err := svc.repo.Save(ctx, reChs...)
|
||||
if err != nil {
|
||||
if errors.Contains(err, errors.ErrRouteNotAvailable) {
|
||||
return []Channel{}, []roles.RoleProvision{}, errors.ErrRouteNotAvailable
|
||||
}
|
||||
return []Channel{}, []roles.RoleProvision{}, errors.Wrap(svcerr.ErrCreateEntity, err)
|
||||
}
|
||||
chIDs := []string{}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
@@ -30,6 +31,8 @@ const (
|
||||
rolesTableNamePrefix = "domains"
|
||||
entityTableName = "domains"
|
||||
entityIDColumnName = "id"
|
||||
|
||||
pgDuplicateErrCode = "23505"
|
||||
)
|
||||
|
||||
type domainRepo struct {
|
||||
@@ -59,7 +62,7 @@ func (repo domainRepo) SaveDomain(ctx context.Context, d domains.Domain) (dd dom
|
||||
|
||||
row, err := repo.db.NamedQueryContext(ctx, q, dbd)
|
||||
if err != nil {
|
||||
return domains.Domain{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
|
||||
return domains.Domain{}, handleSaveError(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
@@ -80,6 +83,16 @@ func (repo domainRepo) SaveDomain(ctx context.Context, d domains.Domain) (dd dom
|
||||
return domain, nil
|
||||
}
|
||||
|
||||
func handleSaveError(wrapper, err error) error {
|
||||
if pqErr, ok := err.(*pgconn.PgError); ok && pqErr.Code == pgDuplicateErrCode {
|
||||
switch pqErr.ConstraintName {
|
||||
case "domains_route_key":
|
||||
return errors.ErrRouteNotAvailable
|
||||
}
|
||||
}
|
||||
return postgres.HandleError(wrapper, err)
|
||||
}
|
||||
|
||||
// RetrieveDomainByIDWithRoles retrieves Domain by its unique ID along with member roles.
|
||||
func (repo domainRepo) RetrieveDomainByIDWithRoles(ctx context.Context, id string, memberID string) (domains.Domain, error) {
|
||||
q := `
|
||||
|
||||
@@ -89,6 +89,15 @@ func Migration() (*migrate.MemoryMigrationSource, error) {
|
||||
`ALTER TABLE invitations ALTER COLUMN rejected_at TYPE TIMESTAMP;`,
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: "domain_5",
|
||||
Up: []string{
|
||||
`ALTER TABLE domains RENAME CONSTRAINT domains_alias_key TO domains_route_key;`,
|
||||
},
|
||||
Down: []string{
|
||||
`ALTER TABLE domains RENAME CONSTRAINT domains_route_key TO domains_alias_key;`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,9 @@ func (svc service) CreateDomain(ctx context.Context, session authn.Session, d Do
|
||||
// Domain is created in repo first, because Roles table have foreign key relation with Domain ID
|
||||
dom, err := svc.repo.SaveDomain(ctx, d)
|
||||
if err != nil {
|
||||
if errors.Contains(err, errors.ErrRouteNotAvailable) {
|
||||
return Domain{}, []roles.RoleProvision{}, errors.ErrRouteNotAvailable
|
||||
}
|
||||
return Domain{}, []roles.RoleProvision{}, errors.Wrap(svcerr.ErrCreateEntity, err)
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -45,4 +45,7 @@ var (
|
||||
|
||||
// ErrChannelRouteNotAvailable indicates that the channel route is not available.
|
||||
ErrChannelRouteNotAvailable = New("channel route not available")
|
||||
|
||||
// ErrRouteNotAvailable indicates that the username is not available.
|
||||
ErrRouteNotAvailable = New("route not available")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user