Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MG-1744 - Improve error handling #40

Closed
wants to merge 11 commits into from
64 changes: 35 additions & 29 deletions pkg/clients/postgres/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@ import (

"github.com/absmach/magistrala/internal/api"
"github.com/absmach/magistrala/pkg/clients"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/absmach/magistrala/pkg/groups"
"github.com/absmach/magistrala/pkg/postgres"
"github.com/jackc/pgtype"
)

var (
MsgErrMarshalMeta = "failed to marshal JSON metadata"
MsgErrUnmarshalMeta = "failed to unmarshal JSON metadata"
MsgErrFailedScan = "failed to scan DB value to struct"
MsgErrFailedQuery = "failed to execute DB query"
MsgErrFailedTotal = "failed to calculate total"
)

type Repository struct {
DB postgres.Database
}
Expand All @@ -30,6 +37,7 @@ func (repo *Repository) Update(ctx context.Context, client clients.Client) (clie
if client.Name != "" {
query = append(query, "name = :name,")
}

if client.Metadata != nil {
query = append(query, "metadata = :metadata,")
}
Expand Down Expand Up @@ -95,14 +103,14 @@ func (repo *Repository) RetrieveByID(ctx context.Context, id string) (clients.Cl

row, err := repo.DB.NamedQueryContext(ctx, q, dbc)
if err != nil {
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.Client{}, repoerr.NewReadError(MsgErrFailedQuery, err)
}
defer row.Close()

dbc = DBClient{}
if row.Next() {
if err := row.StructScan(&dbc); err != nil {
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.Client{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

return ToClient(dbc)
Expand All @@ -129,7 +137,7 @@ func (repo *Repository) RetrieveByIdentity(ctx context.Context, identity string)
dbc = DBClient{}
if row.Next() {
if err := row.StructScan(&dbc); err != nil {
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.Client{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

return ToClient(dbc)
Expand All @@ -141,27 +149,26 @@ func (repo *Repository) RetrieveByIdentity(ctx context.Context, identity string)
func (repo *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
query, err := PageQuery(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, err
}

q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)

dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, err
}
q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, repoerr.NewReadError("failed to read from the DB", err)
}
defer rows.Close()

var items []clients.Client
for rows.Next() {
dbc := DBClient{}
if err := rows.StructScan(&dbc); err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

c, err := ToClient(dbc)
Expand All @@ -175,7 +182,7 @@ func (repo *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clien

total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewReadError(MsgErrFailedTotal, err)
}

page := clients.ClientsPage{
Expand All @@ -193,24 +200,23 @@ func (repo *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clien
func (repo *Repository) RetrieveAllBasicInfo(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
sq, tq := constructSearchQuery(pm)

q := fmt.Sprintf(`SELECT c.id, c.name, c.created_at, c.updated_at FROM clients c %s LIMIT :limit OFFSET :offset;`, sq)

dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, err
}

q := fmt.Sprintf(`SELECT c.id, c.name, c.created_at, c.updated_at FROM clients c %s LIMIT :limit OFFSET :offset;`, sq)
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, repoerr.NewReadError(MsgErrFailedQuery, err)
}
defer rows.Close()

var items []clients.Client
for rows.Next() {
dbc := DBClient{}
if err := rows.StructScan(&dbc); err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

c, err := ToClient(dbc)
Expand All @@ -224,7 +230,7 @@ func (repo *Repository) RetrieveAllBasicInfo(ctx context.Context, pm clients.Pag
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, tq)
total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewReadError(MsgErrFailedTotal, err)
}

page := clients.ClientsPage{
Expand All @@ -247,27 +253,27 @@ func (repo *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (
}
query, err := PageQuery(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, err
}

q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)

dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, err
}
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
return clients.ClientsPage{}, err
}
defer rows.Close()

var items []clients.Client
for rows.Next() {
dbc := DBClient{}
if err := rows.StructScan(&dbc); err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

c, err := ToClient(dbc)
Expand All @@ -281,7 +287,7 @@ func (repo *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (

total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return clients.ClientsPage{}, repoerr.NewReadError(MsgErrFailedTotal, err)
}

page := clients.ClientsPage{
Expand All @@ -299,7 +305,7 @@ func (repo *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (
func (repo *Repository) update(ctx context.Context, client clients.Client, query string) (clients.Client, error) {
dbc, err := ToDBClient(client)
if err != nil {
return clients.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
return clients.Client{}, err
}

row, err := repo.DB.NamedQueryContext(ctx, query, dbc)
Expand All @@ -311,7 +317,7 @@ func (repo *Repository) update(ctx context.Context, client clients.Client, query
dbc = DBClient{}
if row.Next() {
if err := row.StructScan(&dbc); err != nil {
return clients.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
return clients.Client{}, repoerr.NewTypeError(MsgErrFailedScan, err)
}

return ToClient(dbc)
Expand Down Expand Up @@ -355,7 +361,7 @@ func ToDBClient(c clients.Client) (DBClient, error) {
if len(c.Metadata) > 0 {
b, err := json.Marshal(c.Metadata)
if err != nil {
return DBClient{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
return DBClient{}, repoerr.NewTypeError(MsgErrMarshalMeta, err)
}
data = b
}
Expand Down Expand Up @@ -392,7 +398,7 @@ func ToClient(c DBClient) (clients.Client, error) {
var metadata clients.Metadata
if c.Metadata != nil {
if err := json.Unmarshal([]byte(c.Metadata), &metadata); err != nil {
return clients.Client{}, errors.Wrap(errors.ErrMalformedEntity, err)
return clients.Client{}, repoerr.NewTypeError(MsgErrUnmarshalMeta, err)
}
}
var tags []string
Expand Down Expand Up @@ -432,7 +438,7 @@ func ToClient(c DBClient) (clients.Client, error) {
func ToDBClientsPage(pm clients.Page) (dbClientsPage, error) {
_, data, err := postgres.CreateMetadataQuery("", pm.Metadata)
if err != nil {
return dbClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
return dbClientsPage{}, err
}
return dbClientsPage{
Name: pm.Name,
Expand Down Expand Up @@ -465,7 +471,7 @@ type dbClientsPage struct {
func PageQuery(pm clients.Page) (string, error) {
mq, _, err := postgres.CreateMetadataQuery("", pm.Metadata)
if err != nil {
return "", errors.Wrap(errors.ErrMalformedEntity, err)
return "", err
}
var query []string
var emq string
Expand Down
8 changes: 4 additions & 4 deletions pkg/clients/postgres/clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ func TestRetrieveAll(t *testing.T) {
},
Clients: []mgclients.Client(nil),
},
err: repoerr.ErrViewEntity,
err: repoerr.NewTypeError(pgclients.MsgErrMarshalMeta, nil),
},
{
desc: "with name",
Expand Down Expand Up @@ -909,7 +909,7 @@ func TestRetrieveByIDs(t *testing.T) {
},
Clients: []mgclients.Client(nil),
},
err: errors.ErrMalformedEntity,
err: repoerr.NewTypeError(pgclients.MsgErrMarshalMeta, nil),
},
}

Expand All @@ -922,7 +922,7 @@ func TestRetrieveByIDs(t *testing.T) {
assert.Equal(t, c.response.Offset, response.Offset)
assert.ElementsMatch(t, response.Clients, c.response.Clients)
default:
assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected %s to contain %s\n", err, c.err))
assert.True(t, errors.ContainsType(err, c.err), fmt.Sprintf("%s: expected %s to contain %s\n", c.desc, err, c.err))
}
}
}
Expand Down Expand Up @@ -1342,7 +1342,7 @@ func TestUpdate(t *testing.T) {
"update": make(chan int),
},
},
err: repoerr.ErrUpdateEntity,
err: repoerr.NewTypeError(pgclients.MsgErrMarshalMeta, nil),
},
{
desc: "update metadata for disabled client",
Expand Down
20 changes: 20 additions & 0 deletions pkg/errors/api/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package api

import "github.com/absmach/magistrala/pkg/errors"

type (
ContentTypeError struct {
*errors.CustomError
}

ValidationError struct {
*errors.CustomError
}

InvalidParamsError struct {
*errors.CustomError
}
)
24 changes: 24 additions & 0 deletions pkg/errors/auth/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package auth

import "github.com/absmach/magistrala/pkg/errors"

type (

// AuthenticationError indicates failure occurred while authenticating the entity.
AuthenticationError struct {
*errors.CustomError
}

// AuthorizationError indicates failure occurred while authorizing the entity.
AuthorizationError struct {
*errors.CustomError
}
)

func NewAuthNError(text string, err error) error {
return &AuthenticationError{errors.NewErr(text, err)}
}

func NewAuthZError(text string, err error) error {
return &AuthenticationError{errors.NewErr(text, err)}
}
Loading
Loading