mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-27 13:48:49 +08:00
NOISSUE - Implement errors package in Authentication service (#1105)
* Implement errors package in Authn service Signed-off-by: Ivan Milošević <iva@blokovi.com> * remove imported and not used fmt package Signed-off-by: Ivan Milošević <iva@blokovi.com> * wrapped errors when issued new key Signed-off-by: Ivan Milošević <iva@blokovi.com> * remove blank line Signed-off-by: Ivan Milošević <iva@blokovi.com> * Change error message in tests Remove nil case in encode error Signed-off-by: Ivan Milošević <iva@blokovi.com> * return back nil value error handling Signed-off-by: Ivan Milošević <iva@blokovi.com>
This commit is contained in:
parent
57f7ee2595
commit
e438be4250
@ -58,42 +58,50 @@ func TestIssue(t *testing.T) {
|
|||||||
id string
|
id string
|
||||||
kind uint32
|
kind uint32
|
||||||
err error
|
err error
|
||||||
|
code codes.Code
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "issue for user with valid token",
|
desc: "issue for user with valid token",
|
||||||
id: email,
|
id: email,
|
||||||
kind: authn.UserKey,
|
kind: authn.UserKey,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
code: codes.OK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "issue recovery key",
|
desc: "issue recovery key",
|
||||||
id: email,
|
id: email,
|
||||||
kind: authn.RecoveryKey,
|
kind: authn.RecoveryKey,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
code: codes.OK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "issue API key",
|
desc: "issue API key",
|
||||||
id: userKey.Secret,
|
id: userKey.Secret,
|
||||||
kind: authn.APIKey,
|
kind: authn.APIKey,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
code: codes.OK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "issue for invalid key type",
|
desc: "issue for invalid key type",
|
||||||
id: email,
|
id: email,
|
||||||
kind: 32,
|
kind: 32,
|
||||||
err: status.Error(codes.InvalidArgument, "received invalid token request"),
|
err: status.Error(codes.InvalidArgument, "received invalid token request"),
|
||||||
|
code: codes.InvalidArgument,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "issue for user that exist",
|
desc: "issue for user that exist",
|
||||||
id: "",
|
id: "",
|
||||||
kind: authn.APIKey,
|
kind: authn.APIKey,
|
||||||
err: status.Error(codes.Unauthenticated, "unauthorized access"),
|
err: status.Error(codes.Unauthenticated, "unauthorized access"),
|
||||||
|
code: codes.Unauthenticated,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := client.Issue(context.Background(), &mainflux.IssueReq{Issuer: tc.id, Type: tc.kind})
|
_, err := client.Issue(context.Background(), &mainflux.IssueReq{Issuer: tc.id, Type: tc.kind})
|
||||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.err, err))
|
e, ok := status.FromError(err)
|
||||||
|
assert.True(t, ok, "gRPC status can't be extracted from the error")
|
||||||
|
assert.Equal(t, tc.code, e.Code(), fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.code, e.Code()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,36 +124,43 @@ func TestIdentify(t *testing.T) {
|
|||||||
token string
|
token string
|
||||||
id string
|
id string
|
||||||
err error
|
err error
|
||||||
|
code codes.Code
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "identify user with recovery token",
|
desc: "identify user with recovery token",
|
||||||
token: recoveryKey.Secret,
|
token: recoveryKey.Secret,
|
||||||
id: email,
|
id: email,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
code: codes.OK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "identify user with API token",
|
desc: "identify user with API token",
|
||||||
token: apiKey.Secret,
|
token: apiKey.Secret,
|
||||||
id: email,
|
id: email,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
code: codes.OK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "identify user with invalid user token",
|
desc: "identify user with invalid user token",
|
||||||
token: "invalid",
|
token: "invalid",
|
||||||
id: "",
|
id: "",
|
||||||
err: status.Error(codes.Unauthenticated, "unauthorized access"),
|
err: status.Error(codes.Unauthenticated, "unauthorized access"),
|
||||||
|
code: codes.Unauthenticated,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "identify user that doesn't exist",
|
desc: "identify user that doesn't exist",
|
||||||
token: "",
|
token: "",
|
||||||
id: "",
|
id: "",
|
||||||
err: status.Error(codes.InvalidArgument, "received invalid token request"),
|
err: status.Error(codes.InvalidArgument, "received invalid token request"),
|
||||||
|
code: codes.InvalidArgument,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
id, err := client.Identify(context.Background(), &mainflux.Token{Value: tc.token})
|
id, err := client.Identify(context.Background(), &mainflux.Token{Value: tc.token})
|
||||||
assert.Equal(t, tc.id, id.GetValue(), fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.id, id.GetValue()))
|
assert.Equal(t, tc.id, id.GetValue(), fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.id, id.GetValue()))
|
||||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.err, err))
|
e, ok := status.FromError(err)
|
||||||
|
assert.True(t, ok, "gRPC status can't be extracted from the error")
|
||||||
|
assert.Equal(t, tc.code, e.Code(), fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.code, e.Code()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
kitgrpc "github.com/go-kit/kit/transport/grpc"
|
kitgrpc "github.com/go-kit/kit/transport/grpc"
|
||||||
mainflux "github.com/mainflux/mainflux"
|
mainflux "github.com/mainflux/mainflux"
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@ -74,12 +75,14 @@ func encodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encodeError(err error) error {
|
func encodeError(err error) error {
|
||||||
switch err {
|
switch {
|
||||||
case nil:
|
case errors.Contains(err, nil):
|
||||||
return nil
|
return nil
|
||||||
case authn.ErrMalformedEntity:
|
case errors.Contains(err, authn.ErrMalformedEntity):
|
||||||
return status.Error(codes.InvalidArgument, "received invalid token request")
|
return status.Error(codes.InvalidArgument, "received invalid token request")
|
||||||
case authn.ErrUnauthorizedAccess, authn.ErrKeyExpired:
|
case errors.Contains(err, authn.ErrUnauthorizedAccess):
|
||||||
|
return status.Error(codes.Unauthenticated, err.Error())
|
||||||
|
case errors.Contains(err, authn.ErrKeyExpired):
|
||||||
return status.Error(codes.Unauthenticated, err.Error())
|
return status.Error(codes.Unauthenticated, err.Error())
|
||||||
default:
|
default:
|
||||||
return status.Error(codes.Internal, "internal server error")
|
return status.Error(codes.Internal, "internal server error")
|
||||||
|
@ -48,3 +48,7 @@ func (res revokeKeyRes) Headers() map[string]string {
|
|||||||
func (res revokeKeyRes) Empty() bool {
|
func (res revokeKeyRes) Empty() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type errorRes struct {
|
||||||
|
Err string `json:"error"`
|
||||||
|
}
|
||||||
|
@ -6,7 +6,6 @@ package http
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -16,6 +15,7 @@ import (
|
|||||||
"github.com/go-zoo/bone"
|
"github.com/go-zoo/bone"
|
||||||
"github.com/mainflux/mainflux"
|
"github.com/mainflux/mainflux"
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
@ -67,7 +67,7 @@ func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) {
|
|||||||
issuer: r.Header.Get("Authorization"),
|
issuer: r.Header.Get("Authorization"),
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(authn.ErrMalformedEntity, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
@ -100,28 +100,28 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||||
w.Header().Set("Content-Type", contentType)
|
switch {
|
||||||
|
case errors.Contains(err, authn.ErrMalformedEntity):
|
||||||
switch err {
|
|
||||||
case authn.ErrMalformedEntity:
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
case authn.ErrUnauthorizedAccess:
|
case errors.Contains(err, authn.ErrUnauthorizedAccess):
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
case authn.ErrNotFound:
|
case errors.Contains(err, authn.ErrNotFound):
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
case authn.ErrConflict:
|
case errors.Contains(err, authn.ErrConflict):
|
||||||
w.WriteHeader(http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
case io.EOF, io.ErrUnexpectedEOF:
|
case errors.Contains(err, io.EOF):
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
case errUnsupportedContentType:
|
case errors.Contains(err, io.ErrUnexpectedEOF):
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
case errors.Contains(err, errUnsupportedContentType):
|
||||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||||
default:
|
default:
|
||||||
switch err.(type) {
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
case *json.SyntaxError:
|
}
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
errorVal, ok := err.(errors.Error)
|
||||||
case *json.UnmarshalTypeError:
|
if ok {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
if err := json.NewEncoder(w).Encode(errorRes{Err: errorVal.Msg()}); err != nil {
|
||||||
default:
|
w.Header().Set("Content-Type", contentType)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
"github.com/mainflux/mainflux/authn/jwt"
|
"github.com/mainflux/mainflux/authn/jwt"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -48,7 +49,7 @@ func TestIssue(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := tokenizer.Issue(tc.key)
|
_, err := tokenizer.Issue(tc.key)
|
||||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s expected %s, got %s", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s, got %s", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ func TestParse(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
key, err := tokenizer.Parse(tc.token)
|
key, err := tokenizer.Parse(tc.token)
|
||||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s expected %s, got %s", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s, got %s", tc.desc, tc.err, err))
|
||||||
assert.Equal(t, tc.key, key, fmt.Sprintf("%s expected %v, got %v", tc.desc, tc.key, key))
|
assert.Equal(t, tc.key, key, fmt.Sprintf("%s expected %v, got %v", tc.desc, tc.key, key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type claims struct {
|
type claims struct {
|
||||||
@ -68,9 +69,9 @@ func (svc tokenizer) Parse(token string) (authn.Key, error) {
|
|||||||
if c.Type != nil && *c.Type == authn.APIKey {
|
if c.Type != nil && *c.Type == authn.APIKey {
|
||||||
return c.toKey(), nil
|
return c.toKey(), nil
|
||||||
}
|
}
|
||||||
return authn.Key{}, authn.ErrKeyExpired
|
return authn.Key{}, errors.Wrap(authn.ErrKeyExpired, err)
|
||||||
}
|
}
|
||||||
return authn.Key{}, authn.ErrUnauthorizedAccess
|
return authn.Key{}, errors.Wrap(authn.ErrUnauthorizedAccess, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.toKey(), nil
|
return c.toKey(), nil
|
||||||
|
@ -7,8 +7,14 @@ import (
|
|||||||
|
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errSave = errors.New("failed to save key in database")
|
||||||
|
errRetrieve = errors.New("failed to retrieve key from database")
|
||||||
|
errDelete = errors.New("failed to delete key from database")
|
||||||
|
)
|
||||||
var _ authn.KeyRepository = (*repo)(nil)
|
var _ authn.KeyRepository = (*repo)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -37,11 +43,11 @@ func (kr repo) Save(ctx context.Context, key authn.Key) (string, error) {
|
|||||||
pqErr, ok := err.(*pq.Error)
|
pqErr, ok := err.(*pq.Error)
|
||||||
if ok {
|
if ok {
|
||||||
if pqErr.Code.Name() == errDuplicate {
|
if pqErr.Code.Name() == errDuplicate {
|
||||||
return "", authn.ErrConflict
|
return "", errors.Wrap(authn.ErrConflict, pqErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", err
|
return "", errors.Wrap(errSave, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dbKey.ID, nil
|
return dbKey.ID, nil
|
||||||
@ -53,10 +59,10 @@ func (kr repo) Retrieve(ctx context.Context, issuer, id string) (authn.Key, erro
|
|||||||
if err := kr.db.QueryRowxContext(ctx, q, issuer, id).StructScan(&key); err != nil {
|
if err := kr.db.QueryRowxContext(ctx, q, issuer, id).StructScan(&key); err != nil {
|
||||||
pqErr, ok := err.(*pq.Error)
|
pqErr, ok := err.(*pq.Error)
|
||||||
if err == sql.ErrNoRows || ok && errInvalid == pqErr.Code.Name() {
|
if err == sql.ErrNoRows || ok && errInvalid == pqErr.Code.Name() {
|
||||||
return authn.Key{}, authn.ErrNotFound
|
return authn.Key{}, errors.Wrap(authn.ErrNotFound, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return authn.Key{}, err
|
return authn.Key{}, errors.Wrap(errRetrieve, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toKey(key), nil
|
return toKey(key), nil
|
||||||
@ -69,7 +75,7 @@ func (kr repo) Remove(ctx context.Context, issuer, id string) error {
|
|||||||
Issuer: issuer,
|
Issuer: issuer,
|
||||||
}
|
}
|
||||||
if _, err := kr.db.NamedExecContext(ctx, q, key); err != nil {
|
if _, err := kr.db.NamedExecContext(ctx, q, key); err != nil {
|
||||||
return err
|
return errors.Wrap(errDelete, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
"github.com/mainflux/mainflux/authn/postgres"
|
"github.com/mainflux/mainflux/authn/postgres"
|
||||||
"github.com/mainflux/mainflux/authn/uuid"
|
"github.com/mainflux/mainflux/authn/uuid"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -53,7 +54,7 @@ func TestKeySave(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := repo.Save(context.Background(), tc.key)
|
_, err := repo.Save(context.Background(), tc.key)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ func TestKeyRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := repo.Retrieve(context.Background(), tc.issuer, tc.id)
|
_, err := repo.Retrieve(context.Background(), tc.issuer, tc.id)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +144,6 @@ func TestKeyRemove(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
err := repo.Remove(context.Background(), tc.issuer, tc.id)
|
err := repo.Remove(context.Background(), tc.issuer, tc.id)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@ package authn
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -28,6 +29,12 @@ var (
|
|||||||
|
|
||||||
// ErrConflict indicates that entity already exists.
|
// ErrConflict indicates that entity already exists.
|
||||||
ErrConflict = errors.New("entity already exists")
|
ErrConflict = errors.New("entity already exists")
|
||||||
|
|
||||||
|
errIssueUser = errors.New("failed to issue new user key")
|
||||||
|
errIssueTmp = errors.New("failed to issue new temporary key")
|
||||||
|
errRevoke = errors.New("failed to remove key")
|
||||||
|
errRetrieve = errors.New("failed to retrieve key data")
|
||||||
|
errIdentify = errors.New("failed to validate token")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service specifies an API that must be fullfiled by the domain service
|
// Service specifies an API that must be fullfiled by the domain service
|
||||||
@ -84,16 +91,18 @@ func (svc service) Issue(ctx context.Context, issuer string, key Key) (Key, erro
|
|||||||
func (svc service) Revoke(ctx context.Context, issuer, id string) error {
|
func (svc service) Revoke(ctx context.Context, issuer, id string) error {
|
||||||
email, err := svc.login(issuer)
|
email, err := svc.login(issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(errRevoke, err)
|
||||||
}
|
}
|
||||||
|
if err := svc.keys.Remove(ctx, email, id); err != nil {
|
||||||
return svc.keys.Remove(ctx, email, id)
|
return errors.Wrap(errRevoke, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svc service) Retrieve(ctx context.Context, issuer, id string) (Key, error) {
|
func (svc service) Retrieve(ctx context.Context, issuer, id string) (Key, error) {
|
||||||
email, err := svc.login(issuer)
|
email, err := svc.login(issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errRetrieve, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return svc.keys.Retrieve(ctx, email, id)
|
return svc.keys.Retrieve(ctx, email, id)
|
||||||
@ -102,7 +111,7 @@ func (svc service) Retrieve(ctx context.Context, issuer, id string) (Key, error)
|
|||||||
func (svc service) Identify(ctx context.Context, token string) (string, error) {
|
func (svc service) Identify(ctx context.Context, token string) (string, error) {
|
||||||
c, err := svc.tokenizer.Parse(token)
|
c, err := svc.tokenizer.Parse(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.Wrap(errIdentify, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
@ -133,7 +142,7 @@ func (svc service) tmpKey(issuer string, duration time.Duration, key Key) (Key,
|
|||||||
key.ExpiresAt = key.IssuedAt.Add(duration)
|
key.ExpiresAt = key.IssuedAt.Add(duration)
|
||||||
val, err := svc.tokenizer.Issue(key)
|
val, err := svc.tokenizer.Issue(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errIssueTmp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
key.Secret = val
|
key.Secret = val
|
||||||
@ -143,24 +152,24 @@ func (svc service) tmpKey(issuer string, duration time.Duration, key Key) (Key,
|
|||||||
func (svc service) userKey(ctx context.Context, issuer string, key Key) (Key, error) {
|
func (svc service) userKey(ctx context.Context, issuer string, key Key) (Key, error) {
|
||||||
email, err := svc.login(issuer)
|
email, err := svc.login(issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errIssueUser, err)
|
||||||
}
|
}
|
||||||
key.Issuer = email
|
key.Issuer = email
|
||||||
|
|
||||||
id, err := svc.idp.ID()
|
id, err := svc.idp.ID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errIssueUser, err)
|
||||||
}
|
}
|
||||||
key.ID = id
|
key.ID = id
|
||||||
|
|
||||||
value, err := svc.tokenizer.Issue(key)
|
value, err := svc.tokenizer.Issue(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errIssueUser, err)
|
||||||
}
|
}
|
||||||
key.Secret = value
|
key.Secret = value
|
||||||
|
|
||||||
if _, err := svc.keys.Save(ctx, key); err != nil {
|
if _, err := svc.keys.Save(ctx, key); err != nil {
|
||||||
return Key{}, err
|
return Key{}, errors.Wrap(errIssueUser, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return key, nil
|
return key, nil
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
"github.com/mainflux/mainflux/authn/jwt"
|
"github.com/mainflux/mainflux/authn/jwt"
|
||||||
"github.com/mainflux/mainflux/authn/mocks"
|
"github.com/mainflux/mainflux/authn/mocks"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ func TestIssue(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := svc.Issue(context.Background(), tc.issuer, tc.key)
|
_, err := svc.Issue(context.Background(), tc.issuer, tc.key)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestRevoke(t *testing.T) {
|
func TestRevoke(t *testing.T) {
|
||||||
@ -144,7 +145,7 @@ func TestRevoke(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
err := svc.Revoke(context.Background(), tc.issuer, tc.id)
|
err := svc.Revoke(context.Background(), tc.issuer, tc.id)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestRetrieve(t *testing.T) {
|
func TestRetrieve(t *testing.T) {
|
||||||
@ -205,7 +206,7 @@ func TestRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
_, err := svc.Retrieve(context.Background(), tc.issuer, tc.id)
|
_, err := svc.Retrieve(context.Background(), tc.issuer, tc.id)
|
||||||
assert.Equal(t, err, tc.err, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestIdentify(t *testing.T) {
|
func TestIdentify(t *testing.T) {
|
||||||
@ -272,7 +273,7 @@ func TestIdentify(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
id, err := svc.Identify(context.Background(), tc.key)
|
id, err := svc.Identify(context.Background(), tc.key)
|
||||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
||||||
assert.Equal(t, tc.id, id, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.id, id))
|
assert.Equal(t, tc.id, id, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.id, id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,12 @@ package uuid
|
|||||||
import (
|
import (
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/mainflux/mainflux/authn"
|
"github.com/mainflux/mainflux/authn"
|
||||||
|
"github.com/mainflux/mainflux/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// errGeneratingID indicates error in generating UUID
|
||||||
|
var errGeneratingID = errors.New("failed to generate uuid")
|
||||||
|
|
||||||
var _ authn.IdentityProvider = (*uuidIdentityProvider)(nil)
|
var _ authn.IdentityProvider = (*uuidIdentityProvider)(nil)
|
||||||
|
|
||||||
type uuidIdentityProvider struct{}
|
type uuidIdentityProvider struct{}
|
||||||
@ -21,7 +25,7 @@ func New() authn.IdentityProvider {
|
|||||||
func (idp *uuidIdentityProvider) ID() (string, error) {
|
func (idp *uuidIdentityProvider) ID() (string, error) {
|
||||||
id, err := uuid.NewV4()
|
id, err := uuid.NewV4()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.Wrap(errGeneratingID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return id.String(), nil
|
return id.String(), nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user