105 lines
3.2 KiB
Go
105 lines
3.2 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"github.com/mainflux/mainflux/internal/postgres"
|
|
mfclients "github.com/mainflux/mainflux/pkg/clients"
|
|
pgclients "github.com/mainflux/mainflux/pkg/clients/postgres"
|
|
"github.com/mainflux/mainflux/pkg/errors"
|
|
)
|
|
|
|
var _ mfclients.Repository = (*clientRepo)(nil)
|
|
|
|
type clientRepo struct {
|
|
pgclients.ClientRepository
|
|
}
|
|
|
|
type Repository interface {
|
|
mfclients.Repository
|
|
|
|
// Save persists the client account. A non-nil error is returned to indicate
|
|
// operation failure.
|
|
Save(ctx context.Context, client ...mfclients.Client) ([]mfclients.Client, error)
|
|
|
|
// RetrieveBySecret retrieves a client based on the secret (key).
|
|
RetrieveBySecret(ctx context.Context, key string) (mfclients.Client, error)
|
|
}
|
|
|
|
// NewRepository instantiates a PostgreSQL
|
|
// implementation of Clients repository.
|
|
func NewRepository(db postgres.Database) Repository {
|
|
return &clientRepo{
|
|
ClientRepository: pgclients.ClientRepository{DB: db},
|
|
}
|
|
}
|
|
|
|
func (repo clientRepo) Save(ctx context.Context, cs ...mfclients.Client) ([]mfclients.Client, error) {
|
|
tx, err := repo.ClientRepository.DB.BeginTxx(ctx, nil)
|
|
if err != nil {
|
|
return []mfclients.Client{}, errors.Wrap(errors.ErrCreateEntity, err)
|
|
}
|
|
var clients []mfclients.Client
|
|
|
|
for _, cli := range cs {
|
|
q := `INSERT INTO clients (id, name, tags, owner_id, identity, secret, metadata, created_at, updated_at, updated_by, status)
|
|
VALUES (:id, :name, :tags, :owner_id, :identity, :secret, :metadata, :created_at, :updated_at, :updated_by, :status)
|
|
RETURNING id, name, tags, identity, secret, metadata, COALESCE(owner_id, '') AS owner_id, status, created_at, updated_at, updated_by`
|
|
|
|
dbcli, err := pgclients.ToDBClient(cli)
|
|
if err != nil {
|
|
return []mfclients.Client{}, errors.Wrap(errors.ErrCreateEntity, err)
|
|
}
|
|
|
|
row, err := repo.ClientRepository.DB.NamedQueryContext(ctx, q, dbcli)
|
|
if err != nil {
|
|
if err := tx.Rollback(); err != nil {
|
|
return []mfclients.Client{}, postgres.HandleError(err, errors.ErrCreateEntity)
|
|
}
|
|
return []mfclients.Client{}, errors.Wrap(errors.ErrCreateEntity, err)
|
|
}
|
|
|
|
defer row.Close()
|
|
row.Next()
|
|
dbcli = pgclients.DBClient{}
|
|
if err := row.StructScan(&dbcli); err != nil {
|
|
return []mfclients.Client{}, err
|
|
}
|
|
|
|
client, err := pgclients.ToClient(dbcli)
|
|
if err != nil {
|
|
return []mfclients.Client{}, err
|
|
}
|
|
clients = append(clients, client)
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
return []mfclients.Client{}, errors.Wrap(errors.ErrCreateEntity, err)
|
|
}
|
|
|
|
return clients, nil
|
|
}
|
|
|
|
func (repo clientRepo) RetrieveBySecret(ctx context.Context, key string) (mfclients.Client, error) {
|
|
q := fmt.Sprintf(`SELECT id, name, tags, COALESCE(owner_id, '') AS owner_id, identity, secret, metadata, created_at, updated_at, updated_by, status
|
|
FROM clients
|
|
WHERE secret = $1 AND status = %d`, mfclients.EnabledStatus)
|
|
|
|
dbc := pgclients.DBClient{
|
|
Secret: key,
|
|
}
|
|
|
|
if err := repo.DB.QueryRowxContext(ctx, q, key).StructScan(&dbc); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return mfclients.Client{}, errors.Wrap(errors.ErrNotFound, err)
|
|
}
|
|
return mfclients.Client{}, errors.Wrap(errors.ErrViewEntity, err)
|
|
}
|
|
|
|
return pgclients.ToClient(dbc)
|
|
}
|