diff --git a/Makefile b/Makefile index 545602a3613..6b07e3e7ddf 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,9 @@ MF_DOCKER_IMAGE_NAME_PREFIX ?= mainflux BUILD_DIR = build -SERVICES = clients users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \ +SERVICES = users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \ mongodb-reader cassandra-writer cassandra-reader postgres-writer postgres-reader timescale-writer timescale-reader cli \ - bootstrap opcua auth twins mqtt provision certs smtp-notifier smpp-notifier + bootstrap opcua twins mqtt provision certs smtp-notifier smpp-notifier DOCKERS = $(addprefix docker_,$(SERVICES)) DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES)) CGO_ENABLED ?= 0 @@ -78,7 +78,7 @@ test: proto: protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto - protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative clients/policies/*.proto + protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative users/policies/*.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto $(SERVICES): diff --git a/auth/README.md b/auth/README.md deleted file mode 100644 index 61bfe52ce6c..00000000000 --- a/auth/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# Auth - Authentication and Authorization service - -Auth service provides authentication features as an API for managing authentication keys as well as administering groups of entities - `things` and `users`. - -# Authentication -User service is using Auth service gRPC API to obtain login token or password reset token. Authentication key consists of the following fields: -- ID - key ID -- Type - one of the three types described below -- IssuerID - an ID of the Mainflux User who issued the key -- Subject - user email -- IssuedAt - the timestamp when the key is issued -- ExpiresAt - the timestamp after which the key is invalid - -There are *three types of authentication keys*: - -- User key - keys issued to the user upon login request -- API key - keys issued upon the user request -- Recovery key - password recovery key - -Authentication keys are represented and distributed by the corresponding [JWT](jwt.io). - -User keys are issued when user logs in. Each user request (other than `registration` and `login`) contains user key that is used to authenticate the user. - -API keys are similar to the User keys. The main difference is that API keys have configurable expiration time. If no time is set, the key will never expire. For that reason, API keys are _the only key type that can be revoked_. This also means that, despite being used as a JWT, it requires a query to the database to validate the API key. The user with API key can perform all the same actions as the user with login key (can act on behalf of the user for Thing, Channel, or user profile management), *except issuing new API keys*. - -Recovery key is the password recovery key. It's short-lived token used for password recovery process. - -For in-depth explanation of the aforementioned scenarios, as well as thorough -understanding of Mainflux, please check out the [official documentation][doc]. - -The following actions are supported: - -- create (all key types) -- verify (all key types) -- obtain (API keys only) -- revoke (API keys only) - -# Groups -User and Things service are using Auth gRPC API to get the list of ids that are part of a group. Groups can be organized as tree structure. -Group consists of the following fields: - -- ID - ULID id uniquely representing group -- Name - name of the group, name of the group is unique at the same level of tree hierarchy for a given tree. -- ParentID - id of the parent group -- OwnerID - id of the user that created a group -- Description - free form text, up to 1024 characters -- Metadata - Arbitrary, object-encoded group's data -- Path - tree path consisting of group ids -- CreatedAt - timestamp at which the group is created -- UpdatedAt - timestamp at which the group is updated - -## Configuration - -The service is configured using the environment variables presented in the -following table. Note that any unset variables will be replaced with their -default values. - -| Variable | Description | Default | -|-------------------------------|--------------------------------------------------------------------------|----------------| -| MF_AUTH_LOG_LEVEL | Service level (debug, info, warn, error) | info | -| MF_AUTH_DB_HOST | Database host address | localhost | -| MF_AUTH_DB_PORT | Database host port | 5432 | -| MF_AUTH_DB_USER | Database user | mainflux | -| MF_AUTH_DB_PASSWORD | Database password | mainflux | -| MF_AUTH_DB | Name of the database used by the service | auth | -| MF_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable | -| MF_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | | -| MF_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | | -| MF_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | | -| MF_AUTH_HTTP_PORT | Auth service HTTP port | 8180 | -| MF_AUTH_GRPC_PORT | Auth service gRPC port | 8181 | -| MF_AUTH_SERVER_CERT | Path to server certificate in pem format | | -| MF_AUTH_SERVER_KEY | Path to server key in pem format | | -| MF_AUTH_SECRET | String used for signing tokens | auth | -| MF_AUTH_LOGIN_TOKEN_DURATION | The login token expiration period | 10h | -| MF_JAEGER_URL | Jaeger server URL | localhost:6831 | -| MF_KETO_READ_REMOTE_HOST | Keto Read Host | mainflux-keto | -| MF_KETO_WRITE_REMOTE_HOST | Keto Write Host | mainflux-keto | -| MF_KETO_READ_REMOTE_PORT | Keto Read Port | 4466 | -| MF_KETO_WRITE_REMOTE_PORT | Keto Write Port | 4467 | - -## Deployment - -The service itself is distributed as Docker container. Check the [`auth`](https://github.com/mainflux/mainflux/blob/master/docker/docker-compose.yml#L71-L94) service section in -docker-compose to see how service is deployed. - - -To start the service outside of the container, execute the following shell script: - -```bash -# download the latest version of the service -go get github.com/mainflux/mainflux - -cd $GOPATH/src/github.com/mainflux/mainflux - -# compile the service -make auth - -# copy binary to bin -make install - -# set the environment variables and run the service -MF_AUTH_LOG_LEVEL=[Service log level] MF_AUTH_DB_HOST=[Database host address] MF_AUTH_DB_PORT=[Database host port] MF_AUTH_DB_USER=[Database user] MF_AUTH_DB_PASS=[Database password] MF_AUTH_DB=[Name of the database used by the service] MF_AUTH_DB_SSL_MODE=[SSL mode to connect to the database with] MF_AUTH_DB_SSL_CERT=[Path to the PEM encoded certificate file] MF_AUTH_DB_SSL_KEY=[Path to the PEM encoded key file] MF_AUTH_DB_SSL_ROOT_CERT=[Path to the PEM encoded root certificate file] MF_AUTH_HTTP_PORT=[Service HTTP port] MF_AUTH_GRPC_PORT=[Service gRPC port] MF_AUTH_SECRET=[String used for signing tokens] MF_AUTH_SERVER_CERT=[Path to server certificate] MF_AUTH_SERVER_KEY=[Path to server key] MF_JAEGER_URL=[Jaeger server URL] MF_AUTH_LOGIN_TOKEN_DURATION=[The login token expiration period] $GOBIN/mainflux-auth -``` - -If `MF_EMAIL_TEMPLATE` doesn't point to any file service will function but password reset functionality will not work. - -## Usage - -For more information about service capabilities and its usage, please check out -the [API documentation](https://api.mainflux.io/?urls.primaryName=auth-openapi.yml). - -[doc]: https://docs.mainflux.io diff --git a/auth/api/doc.go b/auth/api/doc.go deleted file mode 100644 index 93a6c7a2c15..00000000000 --- a/auth/api/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package api contains implementation of Auth service HTTP API. -package api diff --git a/auth/api/grpc/client.go b/auth/api/grpc/client.go deleted file mode 100644 index eccf5aafa74..00000000000 --- a/auth/api/grpc/client.go +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package grpc - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - kitot "github.com/go-kit/kit/tracing/opentracing" - kitgrpc "github.com/go-kit/kit/transport/grpc" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" - opentracing "github.com/opentracing/opentracing-go" - "google.golang.org/grpc" -) - -const ( - svcName = "mainflux.AuthService" -) - -var _ mainflux.AuthServiceClient = (*grpcClient)(nil) - -type grpcClient struct { - issue endpoint.Endpoint - identify endpoint.Endpoint - authorize endpoint.Endpoint - addPolicy endpoint.Endpoint - deletePolicy endpoint.Endpoint - listPolicies endpoint.Endpoint - assign endpoint.Endpoint - members endpoint.Endpoint - timeout time.Duration -} - -// NewClient returns new gRPC client instance. -func NewClient(tracer opentracing.Tracer, conn *grpc.ClientConn, timeout time.Duration) mainflux.AuthServiceClient { - return &grpcClient{ - issue: kitot.TraceClient(tracer, "issue")(kitgrpc.NewClient( - conn, - svcName, - "Issue", - encodeIssueRequest, - decodeIssueResponse, - mainflux.UserIdentity{}, - ).Endpoint()), - identify: kitot.TraceClient(tracer, "identify")(kitgrpc.NewClient( - conn, - svcName, - "Identify", - encodeIdentifyRequest, - decodeIdentifyResponse, - mainflux.UserIdentity{}, - ).Endpoint()), - authorize: kitot.TraceClient(tracer, "authorize")(kitgrpc.NewClient( - conn, - svcName, - "Authorize", - encodeAuthorizeRequest, - decodeAuthorizeResponse, - mainflux.AuthorizeRes{}, - ).Endpoint()), - addPolicy: kitot.TraceClient(tracer, "add_policy")(kitgrpc.NewClient( - conn, - svcName, - "AddPolicy", - encodeAddPolicyRequest, - decodeAddPolicyResponse, - mainflux.AddPolicyRes{}, - ).Endpoint()), - deletePolicy: kitot.TraceClient(tracer, "delete_policy")(kitgrpc.NewClient( - conn, - svcName, - "DeletePolicy", - encodeDeletePolicyRequest, - decodeDeletePolicyResponse, - mainflux.DeletePolicyRes{}, - ).Endpoint()), - listPolicies: kitot.TraceClient(tracer, "list_policies")(kitgrpc.NewClient( - conn, - svcName, - "ListPolicies", - encodeListPoliciesRequest, - decodeListPoliciesResponse, - mainflux.ListPoliciesRes{}, - ).Endpoint()), - assign: kitot.TraceClient(tracer, "assign")(kitgrpc.NewClient( - conn, - svcName, - "Assign", - encodeAssignRequest, - decodeAssignResponse, - mainflux.AuthorizeRes{}, - ).Endpoint()), - members: kitot.TraceClient(tracer, "members")(kitgrpc.NewClient( - conn, - svcName, - "Members", - encodeMembersRequest, - decodeMembersResponse, - mainflux.MembersRes{}, - ).Endpoint()), - - timeout: timeout, - } -} - -func (client grpcClient) Issue(ctx context.Context, req *mainflux.IssueReq, _ ...grpc.CallOption) (*mainflux.Token, error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.issue(ctx, issueReq{id: req.GetId(), email: req.GetEmail(), keyType: req.Type}) - if err != nil { - return nil, err - } - - ir := res.(identityRes) - return &mainflux.Token{Value: ir.id}, nil -} - -func encodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(issueReq) - return &mainflux.IssueReq{Id: req.id, Email: req.email, Type: req.keyType}, nil -} - -func decodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.UserIdentity) - return identityRes{id: res.GetId(), email: res.GetEmail()}, nil -} - -func (client grpcClient) Identify(ctx context.Context, token *mainflux.Token, _ ...grpc.CallOption) (*mainflux.UserIdentity, error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.identify(ctx, identityReq{token: token.GetValue()}) - if err != nil { - return nil, err - } - - ir := res.(identityRes) - return &mainflux.UserIdentity{Id: ir.id, Email: ir.email}, nil -} - -func encodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(identityReq) - return &mainflux.Token{Value: req.token}, nil -} - -func decodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.UserIdentity) - return identityRes{id: res.GetId(), email: res.GetEmail()}, nil -} - -func (client grpcClient) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.authorize(ctx, authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub()}) - if err != nil { - return &mainflux.AuthorizeRes{}, err - } - - ar := res.(authorizeRes) - return &mainflux.AuthorizeRes{Authorized: ar.authorized}, err -} - -func decodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.AuthorizeRes) - return authorizeRes{authorized: res.Authorized}, nil -} - -func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(authReq) - return &mainflux.AuthorizeReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - }, nil -} - -func (client grpcClient) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.addPolicy(ctx, policyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()}) - if err != nil { - return &mainflux.AddPolicyRes{}, err - } - - apr := res.(addPolicyRes) - return &mainflux.AddPolicyRes{Authorized: apr.authorized}, err -} - -func decodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.AddPolicyRes) - return addPolicyRes{authorized: res.Authorized}, nil -} - -func encodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(policyReq) - return &mainflux.AddPolicyReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - }, nil -} - -func (client grpcClient) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.deletePolicy(ctx, policyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()}) - if err != nil { - return &mainflux.DeletePolicyRes{}, err - } - - dpr := res.(deletePolicyRes) - return &mainflux.DeletePolicyRes{Deleted: dpr.deleted}, err -} - -func decodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.DeletePolicyRes) - return deletePolicyRes{deleted: res.GetDeleted()}, nil -} - -func encodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(policyReq) - return &mainflux.DeletePolicyReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - }, nil -} - -func (client grpcClient) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.listPolicies(ctx, listPoliciesReq{Obj: in.GetObj(), Act: in.GetAct(), Sub: in.GetSub()}) - if err != nil { - return &mainflux.ListPoliciesRes{}, err - } - - lpr := res.(listPoliciesRes) - return &mainflux.ListPoliciesRes{Policies: lpr.policies}, err -} - -func decodeListPoliciesResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.ListPoliciesRes) - return listPoliciesRes{policies: res.GetPolicies()}, nil -} - -func encodeListPoliciesRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(listPoliciesReq) - return &mainflux.ListPoliciesReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - }, nil -} - -func (client grpcClient) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.members(ctx, membersReq{ - token: req.GetToken(), - groupID: req.GetGroupID(), - memberType: req.GetType(), - offset: req.GetOffset(), - limit: req.GetLimit(), - }) - if err != nil { - return &mainflux.MembersRes{}, err - } - - mr := res.(membersRes) - - return &mainflux.MembersRes{ - Offset: mr.offset, - Limit: mr.limit, - Total: mr.total, - Type: mr.groupType, - Members: mr.members, - }, err -} - -func encodeMembersRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(membersReq) - return &mainflux.MembersReq{ - Token: req.token, - Offset: req.offset, - Limit: req.limit, - GroupID: req.groupID, - Type: req.memberType, - }, nil -} - -func decodeMembersResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.MembersRes) - return membersRes{ - offset: res.Offset, - limit: res.Limit, - total: res.Total, - members: res.Members, - }, nil -} - -func (client grpcClient) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - _, err = client.assign(ctx, assignReq{token: req.GetToken(), groupID: req.GetGroupID(), memberID: req.GetMemberID()}) - if err != nil { - return &empty.Empty{}, err - } - - return &empty.Empty{}, err -} - -func encodeAssignRequest(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*mainflux.AuthorizeRes) - return authorizeRes{authorized: res.Authorized}, nil -} - -func decodeAssignResponse(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(authReq) - return &mainflux.AuthorizeReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - }, nil -} diff --git a/auth/api/grpc/doc.go b/auth/api/grpc/doc.go deleted file mode 100644 index 331229c21c0..00000000000 --- a/auth/api/grpc/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package grpc contains implementation of Auth service gRPC API. -package grpc diff --git a/auth/api/grpc/endpoint.go b/auth/api/grpc/endpoint.go deleted file mode 100644 index c0e09c3621a..00000000000 --- a/auth/api/grpc/endpoint.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package grpc - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/auth" -) - -func issueEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(issueReq) - if err := req.validate(); err != nil { - return issueRes{}, err - } - - key := auth.Key{ - Type: req.keyType, - Subject: req.email, - IssuerID: req.id, - IssuedAt: time.Now().UTC(), - } - - _, secret, err := svc.Issue(ctx, "", key) - if err != nil { - return issueRes{}, err - } - - return issueRes{secret}, nil - } -} - -func identifyEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(identityReq) - if err := req.validate(); err != nil { - return identityRes{}, err - } - - id, err := svc.Identify(ctx, req.token) - if err != nil { - return identityRes{}, err - } - - ret := identityRes{ - id: id.ID, - email: id.Email, - } - return ret, nil - } -} - -func authorizeEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(authReq) - - if err := req.validate(); err != nil { - return authorizeRes{}, err - } - - err := svc.Authorize(ctx, auth.PolicyReq{Subject: req.Sub, Object: req.Obj, Relation: req.Act}) - if err != nil { - return authorizeRes{}, err - } - return authorizeRes{authorized: true}, err - } -} - -func addPolicyEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(policyReq) - if err := req.validate(); err != nil { - return addPolicyRes{}, err - } - - err := svc.AddPolicy(ctx, auth.PolicyReq{Subject: req.Sub, Object: req.Obj, Relation: req.Act}) - if err != nil { - return addPolicyRes{}, err - } - return addPolicyRes{authorized: true}, err - } -} - -func deletePolicyEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(policyReq) - if err := req.validate(); err != nil { - return deletePolicyRes{}, err - } - - err := svc.DeletePolicy(ctx, auth.PolicyReq{Subject: req.Sub, Object: req.Obj, Relation: req.Act}) - if err != nil { - return deletePolicyRes{}, err - } - return deletePolicyRes{deleted: true}, nil - } -} - -func listPoliciesEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listPoliciesReq) - - page, err := svc.ListPolicies(ctx, auth.PolicyReq{Subject: req.Sub, Object: req.Obj, Relation: req.Act}) - if err != nil { - return deletePolicyRes{}, err - } - return listPoliciesRes{policies: page.Policies}, nil - } -} - -func assignEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(assignReq) - - if err := req.validate(); err != nil { - return emptyRes{}, err - } - - _, err := svc.Identify(ctx, req.token) - if err != nil { - return emptyRes{}, err - } - - err = svc.Assign(ctx, req.token, req.memberID, req.groupID, req.groupType) - if err != nil { - return emptyRes{}, err - } - return emptyRes{}, nil - - } -} - -func membersEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(membersReq) - if err := req.validate(); err != nil { - return membersRes{}, err - } - - pm := auth.PageMetadata{ - Offset: req.offset, - Limit: req.limit, - } - mp, err := svc.ListMembers(ctx, req.token, req.groupID, req.memberType, pm) - if err != nil { - return membersRes{}, err - } - var members []string - for _, m := range mp.Members { - members = append(members, m.ID) - } - return membersRes{ - offset: req.offset, - limit: req.limit, - total: mp.PageMetadata.Total, - members: members, - }, nil - } -} diff --git a/auth/api/grpc/endpoint_test.go b/auth/api/grpc/endpoint_test.go deleted file mode 100644 index 8e1ad8ba182..00000000000 --- a/auth/api/grpc/endpoint_test.go +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package grpc_test - -import ( - "context" - "fmt" - "net" - "testing" - "time" - - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - grpcapi "github.com/mainflux/mainflux/auth/api/grpc" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/mocks" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -const ( - port = 8081 - secret = "secret" - email = "test@example.com" - id = "testID" - thingsType = "things" - usersType = "users" - description = "Description" - - numOfThings = 5 - numOfUsers = 5 - - authoritiesObj = "authorities" - memberRelation = "member" - loginDuration = 30 * time.Minute -) - -var svc auth.Service - -func newService() auth.Service { - repo := mocks.NewKeyRepository() - groupRepo := mocks.NewGroupRepository() - idProvider := uuid.NewMock() - - mockAuthzDB := map[string][]mocks.MockSubjectSet{} - mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: authoritiesObj, Relation: memberRelation}) - ketoMock := mocks.NewKetoMock(mockAuthzDB) - - t := jwt.New(secret) - - return auth.New(repo, groupRepo, idProvider, t, ketoMock, loginDuration) -} - -func startGRPCServer(svc auth.Service, port int) { - listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port)) - server := grpc.NewServer() - mainflux.RegisterAuthServiceServer(server, grpcapi.NewServer(mocktracer.New(), svc)) - go server.Serve(listener) -} - -func TestIssue(t *testing.T) { - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - cases := []struct { - desc string - id string - email string - kind uint32 - err error - code codes.Code - }{ - { - desc: "issue for user with valid token", - id: id, - email: email, - kind: auth.LoginKey, - err: nil, - code: codes.OK, - }, - { - desc: "issue recovery key", - id: id, - email: email, - kind: auth.RecoveryKey, - err: nil, - code: codes.OK, - }, - { - desc: "issue API key unauthenticated", - id: id, - email: email, - kind: auth.APIKey, - err: nil, - code: codes.Unauthenticated, - }, - { - desc: "issue for invalid key type", - id: id, - email: email, - kind: 32, - err: status.Error(codes.InvalidArgument, "received invalid token request"), - code: codes.InvalidArgument, - }, - { - desc: "issue for user that exist", - id: "", - email: "", - kind: auth.APIKey, - err: status.Error(codes.Unauthenticated, "unauthenticated access"), - code: codes.Unauthenticated, - }, - } - - for _, tc := range cases { - _, err := client.Issue(context.Background(), &mainflux.IssueReq{Id: tc.id, Email: tc.email, Type: tc.kind}) - 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())) - } -} - -func TestIdentify(t *testing.T) { - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - _, recoverySecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.RecoveryKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing recovery key expected to succeed: %s", err)) - - _, apiSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), ExpiresAt: time.Now().Add(time.Minute), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing API key expected to succeed: %s", err)) - - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - cases := []struct { - desc string - token string - idt *mainflux.UserIdentity - err error - code codes.Code - }{ - { - desc: "identify user with user token", - token: loginSecret, - idt: &mainflux.UserIdentity{Email: email, Id: id}, - err: nil, - code: codes.OK, - }, - { - desc: "identify user with recovery token", - token: recoverySecret, - idt: &mainflux.UserIdentity{Email: email, Id: id}, - err: nil, - code: codes.OK, - }, - { - desc: "identify user with API token", - token: apiSecret, - idt: &mainflux.UserIdentity{Email: email, Id: id}, - err: nil, - code: codes.OK, - }, - { - desc: "identify user with invalid user token", - token: "invalid", - idt: &mainflux.UserIdentity{}, - err: status.Error(codes.Unauthenticated, "unauthenticated access"), - code: codes.Unauthenticated, - }, - { - desc: "identify user with empty token", - token: "", - idt: &mainflux.UserIdentity{}, - err: status.Error(codes.InvalidArgument, "received invalid token request"), - code: codes.Unauthenticated, - }, - } - - for _, tc := range cases { - idt, err := client.Identify(context.Background(), &mainflux.Token{Value: tc.token}) - if idt != nil { - assert.Equal(t, tc.idt, idt, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.idt, idt)) - } - 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())) - } -} - -func TestAuthorize(t *testing.T) { - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - cases := []struct { - desc string - token string - subject string - object string - relation string - ar *mainflux.AuthorizeRes - err error - code codes.Code - }{ - { - desc: "authorize user with authorized token", - token: loginSecret, - subject: id, - object: authoritiesObj, - relation: memberRelation, - ar: &mainflux.AuthorizeRes{Authorized: true}, - err: nil, - code: codes.OK, - }, - { - desc: "authorize user with unauthorized relation", - token: loginSecret, - subject: id, - object: authoritiesObj, - relation: "unauthorizedRelation", - ar: &mainflux.AuthorizeRes{Authorized: false}, - err: nil, - code: codes.PermissionDenied, - }, - { - desc: "authorize user with unauthorized object", - token: loginSecret, - subject: id, - object: "unauthorizedobject", - relation: memberRelation, - ar: &mainflux.AuthorizeRes{Authorized: false}, - err: nil, - code: codes.PermissionDenied, - }, - { - desc: "authorize user with unauthorized subject", - token: loginSecret, - subject: "unauthorizedSubject", - object: authoritiesObj, - relation: memberRelation, - ar: &mainflux.AuthorizeRes{Authorized: false}, - err: nil, - code: codes.PermissionDenied, - }, - { - desc: "authorize user with invalid ACL", - token: loginSecret, - subject: "", - object: "", - relation: "", - ar: &mainflux.AuthorizeRes{Authorized: false}, - err: nil, - code: codes.InvalidArgument, - }, - } - for _, tc := range cases { - ar, err := client.Authorize(context.Background(), &mainflux.AuthorizeReq{Sub: tc.subject, Obj: tc.object, Act: tc.relation}) - if ar != nil { - assert.Equal(t, tc.ar, ar, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.ar, ar)) - } - - 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())) - } -} - -func TestAddPolicy(t *testing.T) { - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - groupAdminObj := "groupadmin" - - cases := []struct { - desc string - token string - subject string - object string - relation string - ar *mainflux.AddPolicyRes - err error - code codes.Code - }{ - { - desc: "add groupadmin policy to user", - token: loginSecret, - subject: id, - object: groupAdminObj, - relation: memberRelation, - ar: &mainflux.AddPolicyRes{Authorized: true}, - err: nil, - code: codes.OK, - }, - { - desc: "add policy to user with invalid ACL", - token: loginSecret, - subject: "", - object: "", - relation: "", - ar: &mainflux.AddPolicyRes{Authorized: false}, - err: nil, - code: codes.InvalidArgument, - }, - } - for _, tc := range cases { - apr, err := client.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Sub: tc.subject, Obj: tc.object, Act: tc.relation}) - if apr != nil { - assert.Equal(t, tc.ar, apr, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.ar, apr)) - } - - 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())) - } -} - -func TestDeletePolicy(t *testing.T) { - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - readRelation := "read" - thingID := "thing" - - apr, err := client.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Sub: id, Obj: thingID, Act: readRelation}) - assert.Nil(t, err, fmt.Sprintf("Adding read policy to user expected to succeed: %s", err)) - assert.True(t, apr.GetAuthorized(), fmt.Sprintf("Adding read policy expected to make user authorized, expected %v got %v", true, apr.GetAuthorized())) - - cases := []struct { - desc string - token string - subject string - object string - relation string - dpr *mainflux.DeletePolicyRes - code codes.Code - }{ - { - desc: "delete valid policy", - token: loginSecret, - subject: id, - object: thingID, - relation: readRelation, - dpr: &mainflux.DeletePolicyRes{Deleted: true}, - code: codes.OK, - }, - { - desc: "delete invalid policy", - token: loginSecret, - subject: "", - object: "", - relation: "", - dpr: &mainflux.DeletePolicyRes{Deleted: false}, - code: codes.InvalidArgument, - }, - } - for _, tc := range cases { - dpr, err := client.DeletePolicy(context.Background(), &mainflux.DeletePolicyReq{Sub: tc.subject, Obj: tc.object, Act: tc.relation}) - 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())) - assert.Equal(t, tc.dpr.GetDeleted(), dpr.GetDeleted(), fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.dpr.GetDeleted(), dpr.GetDeleted())) - } -} - -func TestMembers(t *testing.T) { - _, token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - group := auth.Group{ - Name: "Mainflux", - Description: description, - } - - var things []string - for i := 0; i < numOfThings; i++ { - thID, err := uuid.New().ID() - assert.Nil(t, err, fmt.Sprintf("Generate thing id expected to succeed: %s", err)) - - err = svc.AddPolicy(context.Background(), auth.PolicyReq{Subject: id, Object: thID, Relation: "owner"}) - assert.Nil(t, err, fmt.Sprintf("Adding a policy expected to succeed: %s", err)) - - things = append(things, thID) - } - - var users []string - for i := 0; i < numOfUsers; i++ { - id, err := uuid.New().ID() - assert.Nil(t, err, fmt.Sprintf("Generate thing id expected to succeed: %s", err)) - - users = append(users, id) - } - - group, err = svc.CreateGroup(context.Background(), token, group) - assert.Nil(t, err, fmt.Sprintf("Creating group expected to succeed: %s", err)) - err = svc.AddPolicy(context.Background(), auth.PolicyReq{Subject: id, Object: group.ID, Relation: "groupadmin"}) - assert.Nil(t, err, fmt.Sprintf("Adding a policy expected to succeed: %s", err)) - - err = svc.Assign(context.Background(), token, group.ID, thingsType, things...) - assert.Nil(t, err, fmt.Sprintf("Assign members to expected to succeed: %s", err)) - - err = svc.Assign(context.Background(), token, group.ID, usersType, users...) - assert.Nil(t, err, fmt.Sprintf("Assign members to group expected to succeed: %s", err)) - - cases := []struct { - desc string - token string - groupID string - groupType string - size int - err error - code codes.Code - }{ - { - desc: "get all things with user token", - groupID: group.ID, - token: token, - groupType: thingsType, - size: numOfThings, - err: nil, - code: codes.OK, - }, - { - desc: "get all users with user token", - groupID: group.ID, - token: token, - groupType: usersType, - size: numOfUsers, - err: nil, - code: codes.OK, - }, - } - - authAddr := fmt.Sprintf("localhost:%d", port) - conn, _ := grpc.Dial(authAddr, grpc.WithInsecure()) - client := grpcapi.NewClient(mocktracer.New(), conn, time.Second) - - for _, tc := range cases { - m, err := client.Members(context.Background(), &mainflux.MembersReq{Token: tc.token, GroupID: tc.groupID, Type: tc.groupType, Offset: 0, Limit: 10}) - e, ok := status.FromError(err) - assert.Equal(t, tc.size, len(m.Members), fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.size, len(m.Members))) - assert.Equal(t, tc.code, e.Code(), fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.code, e.Code())) - assert.True(t, ok, "OK expected to be true") - } -} diff --git a/auth/api/grpc/server.go b/auth/api/grpc/server.go deleted file mode 100644 index c2a6caa8a68..00000000000 --- a/auth/api/grpc/server.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package grpc - -import ( - "context" - - kitot "github.com/go-kit/kit/tracing/opentracing" - kitgrpc "github.com/go-kit/kit/transport/grpc" - "github.com/golang/protobuf/ptypes/empty" - mainflux "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/pkg/errors" - opentracing "github.com/opentracing/opentracing-go" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var _ mainflux.AuthServiceServer = (*grpcServer)(nil) - -type grpcServer struct { - issue kitgrpc.Handler - identify kitgrpc.Handler - authorize kitgrpc.Handler - addPolicy kitgrpc.Handler - deletePolicy kitgrpc.Handler - listPolicies kitgrpc.Handler - assign kitgrpc.Handler - members kitgrpc.Handler - mainflux.UnimplementedAuthServiceServer -} - -// NewServer returns new AuthServiceServer instance. -func NewServer(tracer opentracing.Tracer, svc auth.Service) mainflux.AuthServiceServer { - return &grpcServer{ - issue: kitgrpc.NewServer( - kitot.TraceServer(tracer, "issue")(issueEndpoint(svc)), - decodeIssueRequest, - encodeIssueResponse, - ), - identify: kitgrpc.NewServer( - kitot.TraceServer(tracer, "identify")(identifyEndpoint(svc)), - decodeIdentifyRequest, - encodeIdentifyResponse, - ), - authorize: kitgrpc.NewServer( - kitot.TraceServer(tracer, "authorize")(authorizeEndpoint(svc)), - decodeAuthorizeRequest, - encodeAuthorizeResponse, - ), - addPolicy: kitgrpc.NewServer( - kitot.TraceServer(tracer, "add_policy")(addPolicyEndpoint(svc)), - decodeAddPolicyRequest, - encodeAddPolicyResponse, - ), - deletePolicy: kitgrpc.NewServer( - kitot.TraceServer(tracer, "delete_policy")(deletePolicyEndpoint(svc)), - decodeDeletePolicyRequest, - encodeDeletePolicyResponse, - ), - listPolicies: kitgrpc.NewServer( - kitot.TraceServer(tracer, "list_policies")(listPoliciesEndpoint(svc)), - decodeListPoliciesRequest, - encodeListPoliciesResponse, - ), - assign: kitgrpc.NewServer( - kitot.TraceServer(tracer, "assign")(assignEndpoint(svc)), - decodeAssignRequest, - encodeEmptyResponse, - ), - members: kitgrpc.NewServer( - kitot.TraceServer(tracer, "members")(membersEndpoint(svc)), - decodeMembersRequest, - encodeMembersResponse, - ), - } -} - -func (s *grpcServer) Issue(ctx context.Context, req *mainflux.IssueReq) (*mainflux.Token, error) { - _, res, err := s.issue.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.Token), nil -} - -func (s *grpcServer) Identify(ctx context.Context, token *mainflux.Token) (*mainflux.UserIdentity, error) { - _, res, err := s.identify.ServeGRPC(ctx, token) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.UserIdentity), nil -} - -func (s *grpcServer) Authorize(ctx context.Context, req *mainflux.AuthorizeReq) (*mainflux.AuthorizeRes, error) { - _, res, err := s.authorize.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.AuthorizeRes), nil -} - -func (s *grpcServer) AddPolicy(ctx context.Context, req *mainflux.AddPolicyReq) (*mainflux.AddPolicyRes, error) { - _, res, err := s.addPolicy.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.AddPolicyRes), nil -} - -func (s *grpcServer) DeletePolicy(ctx context.Context, req *mainflux.DeletePolicyReq) (*mainflux.DeletePolicyRes, error) { - _, res, err := s.deletePolicy.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.DeletePolicyRes), nil -} - -func (s *grpcServer) ListPolicies(ctx context.Context, req *mainflux.ListPoliciesReq) (*mainflux.ListPoliciesRes, error) { - _, res, err := s.listPolicies.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.ListPoliciesRes), nil -} - -func (s *grpcServer) Assign(ctx context.Context, token *mainflux.Assignment) (*empty.Empty, error) { - _, res, err := s.assign.ServeGRPC(ctx, token) - if err != nil { - return nil, encodeError(err) - } - return res.(*empty.Empty), nil -} - -func (s *grpcServer) Members(ctx context.Context, req *mainflux.MembersReq) (*mainflux.MembersRes, error) { - _, res, err := s.members.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*mainflux.MembersRes), nil -} - -func decodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.IssueReq) - return issueReq{id: req.GetId(), email: req.GetEmail(), keyType: req.GetType()}, nil -} - -func encodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(issueRes) - return &mainflux.Token{Value: res.value}, nil -} - -func decodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.Token) - return identityReq{token: req.GetValue()}, nil -} - -func encodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(identityRes) - return &mainflux.UserIdentity{Id: res.id, Email: res.email}, nil -} - -func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.AuthorizeReq) - return authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub()}, nil -} - -func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(authorizeRes) - return &mainflux.AuthorizeRes{Authorized: res.authorized}, nil -} - -func decodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.AddPolicyReq) - return policyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil -} - -func encodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(addPolicyRes) - return &mainflux.AddPolicyRes{Authorized: res.authorized}, nil -} - -func decodeAssignRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.Token) - return assignReq{token: req.GetValue()}, nil -} - -func decodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.DeletePolicyReq) - return policyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil -} - -func encodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(deletePolicyRes) - return &mainflux.DeletePolicyRes{Deleted: res.deleted}, nil -} - -func decodeListPoliciesRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.ListPoliciesReq) - return listPoliciesReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil -} - -func encodeListPoliciesResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(listPoliciesRes) - return &mainflux.ListPoliciesRes{Policies: res.policies}, nil -} - -func decodeMembersRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*mainflux.MembersReq) - return membersReq{ - token: req.GetToken(), - groupID: req.GetGroupID(), - memberType: req.GetType(), - offset: req.Offset, - limit: req.Limit, - }, nil -} - -func encodeMembersResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(membersRes) - return &mainflux.MembersRes{ - Total: res.total, - Offset: res.offset, - Limit: res.limit, - Type: res.groupType, - Members: res.members, - }, nil -} - -func encodeEmptyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(emptyRes) - return &empty.Empty{}, encodeError(res.err) -} - -func encodeError(err error) error { - switch { - case errors.Contains(err, nil): - return nil - case errors.Contains(err, errors.ErrMalformedEntity), - err == apiutil.ErrInvalidAuthKey, - err == apiutil.ErrMissingID, - err == apiutil.ErrMissingMemberType, - err == apiutil.ErrMissingPolicySub, - err == apiutil.ErrMissingPolicyObj, - err == apiutil.ErrMissingPolicyAct: - return status.Error(codes.InvalidArgument, err.Error()) - case errors.Contains(err, errors.ErrAuthentication), - errors.Contains(err, auth.ErrKeyExpired), - err == apiutil.ErrMissingEmail, - err == apiutil.ErrBearerToken: - return status.Error(codes.Unauthenticated, err.Error()) - case errors.Contains(err, errors.ErrAuthorization): - return status.Error(codes.PermissionDenied, err.Error()) - default: - return status.Error(codes.Internal, "internal server error") - } -} diff --git a/auth/api/grpc/setup_test.go b/auth/api/grpc/setup_test.go deleted file mode 100644 index 0af08379c45..00000000000 --- a/auth/api/grpc/setup_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package grpc_test - -import ( - "os" - "testing" -) - -func TestMain(m *testing.M) { - svc = newService() - startGRPCServer(svc, port) - - code := m.Run() - - os.Exit(code) -} diff --git a/auth/api/http/doc.go b/auth/api/http/doc.go deleted file mode 100644 index 4a864535348..00000000000 --- a/auth/api/http/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 -package http diff --git a/auth/api/http/groups/endpoint.go b/auth/api/http/groups/endpoint.go deleted file mode 100644 index 5315bb4ba16..00000000000 --- a/auth/api/http/groups/endpoint.go +++ /dev/null @@ -1,370 +0,0 @@ -package groups - -import ( - "context" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/auth" -) - -func createGroupEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(createGroupReq) - if err := req.validate(); err != nil { - return groupRes{}, err - } - - group := auth.Group{ - Name: req.Name, - Description: req.Description, - ParentID: req.ParentID, - Metadata: req.Metadata, - } - - group, err := svc.CreateGroup(ctx, req.token, group) - if err != nil { - return groupRes{}, err - } - - return groupRes{created: true, id: group.ID}, nil - } -} - -func viewGroupEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(groupReq) - if err := req.validate(); err != nil { - return viewGroupRes{}, err - } - - group, err := svc.ViewGroup(ctx, req.token, req.id) - if err != nil { - return viewGroupRes{}, err - } - - res := viewGroupRes{ - ID: group.ID, - Name: group.Name, - Description: group.Description, - Metadata: group.Metadata, - ParentID: group.ParentID, - OwnerID: group.OwnerID, - CreatedAt: group.CreatedAt, - UpdatedAt: group.UpdatedAt, - } - - return res, nil - } -} - -func updateGroupEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(updateGroupReq) - if err := req.validate(); err != nil { - return groupRes{}, err - } - - group := auth.Group{ - ID: req.id, - Name: req.Name, - Description: req.Description, - Metadata: req.Metadata, - } - - _, err := svc.UpdateGroup(ctx, req.token, group) - if err != nil { - return groupRes{}, err - } - - res := groupRes{created: false} - return res, nil - } -} - -func deleteGroupEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(groupReq) - if err := req.validate(); err != nil { - return nil, err - } - - if err := svc.RemoveGroup(ctx, req.token, req.id); err != nil { - return nil, err - } - - return deleteRes{}, nil - } -} - -func listGroupsEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listGroupsReq) - if err := req.validate(); err != nil { - return groupPageRes{}, err - } - pm := auth.PageMetadata{ - Level: req.level, - Metadata: req.metadata, - } - page, err := svc.ListGroups(ctx, req.token, pm) - if err != nil { - return groupPageRes{}, err - } - - if req.tree { - return buildGroupsResponseTree(page), nil - } - - return buildGroupsResponse(page), nil - } -} - -func listMemberships(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listMembershipsReq) - if err := req.validate(); err != nil { - return memberPageRes{}, err - } - - pm := auth.PageMetadata{ - Offset: req.offset, - Limit: req.limit, - Metadata: req.metadata, - } - - page, err := svc.ListMemberships(ctx, req.token, req.id, pm) - if err != nil { - return memberPageRes{}, err - } - - return buildGroupsResponse(page), nil - } -} - -func shareGroupAccessEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(shareGroupAccessReq) - if err := req.validate(); err != nil { - return shareGroupRes{}, err - } - - if err := svc.AssignGroupAccessRights(ctx, req.token, req.ThingGroupID, req.userGroupID); err != nil { - return shareGroupRes{}, err - } - return shareGroupRes{}, nil - } -} - -func listChildrenEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listGroupsReq) - if err := req.validate(); err != nil { - return groupPageRes{}, err - } - - pm := auth.PageMetadata{ - Level: req.level, - Metadata: req.metadata, - } - page, err := svc.ListChildren(ctx, req.token, req.id, pm) - if err != nil { - return groupPageRes{}, err - } - - if req.tree { - return buildGroupsResponseTree(page), nil - } - - return buildGroupsResponse(page), nil - } -} - -func listParentsEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listGroupsReq) - if err := req.validate(); err != nil { - return groupPageRes{}, err - } - pm := auth.PageMetadata{ - Level: req.level, - Metadata: req.metadata, - } - - page, err := svc.ListParents(ctx, req.token, req.id, pm) - if err != nil { - return groupPageRes{}, err - } - - if req.tree { - return buildGroupsResponseTree(page), nil - } - - return buildGroupsResponse(page), nil - } -} - -func assignEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(assignReq) - if err := req.validate(); err != nil { - return nil, err - } - - if err := svc.Assign(ctx, req.token, req.groupID, req.Type, req.Members...); err != nil { - return nil, err - } - - return assignRes{}, nil - } -} - -func unassignEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(unassignReq) - if err := req.validate(); err != nil { - return nil, err - } - - if err := svc.Unassign(ctx, req.token, req.groupID, req.Members...); err != nil { - return nil, err - } - - return unassignRes{}, nil - } -} - -func listMembersEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listMembersReq) - if err := req.validate(); err != nil { - return memberPageRes{}, err - } - - pm := auth.PageMetadata{ - Offset: req.offset, - Limit: req.limit, - Metadata: req.metadata, - } - page, err := svc.ListMembers(ctx, req.token, req.id, req.groupType, pm) - if err != nil { - return memberPageRes{}, err - } - - return buildUsersResponse(page, req.groupType), nil - } -} - -func buildGroupsResponseTree(page auth.GroupPage) groupPageRes { - groupsMap := map[string]*auth.Group{} - // Parents' map keeps its array of children. - parentsMap := map[string][]*auth.Group{} - for i := range page.Groups { - if _, ok := groupsMap[page.Groups[i].ID]; !ok { - groupsMap[page.Groups[i].ID] = &page.Groups[i] - parentsMap[page.Groups[i].ID] = make([]*auth.Group, 0) - } - } - - for _, group := range groupsMap { - if children, ok := parentsMap[group.ParentID]; ok { - children = append(children, group) - parentsMap[group.ParentID] = children - } - } - - res := groupPageRes{ - pageRes: pageRes{ - Limit: page.Limit, - Offset: page.Offset, - Total: page.Total, - Level: page.Level, - }, - Groups: []viewGroupRes{}, - } - - for _, group := range groupsMap { - if children, ok := parentsMap[group.ID]; ok { - group.Children = children - } - - } - - for _, group := range groupsMap { - view := toViewGroupRes(*group) - if children, ok := parentsMap[group.ParentID]; len(children) == 0 || !ok { - res.Groups = append(res.Groups, view) - } - } - - return res -} - -func toViewGroupRes(group auth.Group) viewGroupRes { - view := viewGroupRes{ - ID: group.ID, - ParentID: group.ParentID, - OwnerID: group.OwnerID, - Name: group.Name, - Description: group.Description, - Metadata: group.Metadata, - Level: group.Level, - Path: group.Path, - Children: make([]*viewGroupRes, 0), - CreatedAt: group.CreatedAt, - UpdatedAt: group.UpdatedAt, - } - - for _, ch := range group.Children { - child := toViewGroupRes(*ch) - view.Children = append(view.Children, &child) - } - - return view -} - -func buildGroupsResponse(gp auth.GroupPage) groupPageRes { - res := groupPageRes{ - pageRes: pageRes{ - Total: gp.Total, - Level: gp.Level, - }, - Groups: []viewGroupRes{}, - } - - for _, group := range gp.Groups { - view := viewGroupRes{ - ID: group.ID, - ParentID: group.ParentID, - OwnerID: group.OwnerID, - Name: group.Name, - Description: group.Description, - Metadata: group.Metadata, - Level: group.Level, - Path: group.Path, - CreatedAt: group.CreatedAt, - UpdatedAt: group.UpdatedAt, - } - res.Groups = append(res.Groups, view) - } - - return res -} - -func buildUsersResponse(mp auth.MemberPage, groupType string) memberPageRes { - res := memberPageRes{ - pageRes: pageRes{ - Total: mp.Total, - Offset: mp.Offset, - Limit: mp.Limit, - Name: mp.Name, - }, - Type: groupType, - Members: []string{}, - } - - for _, m := range mp.Members { - res.Members = append(res.Members, m.ID) - } - - return res -} diff --git a/auth/api/http/groups/endpoint_test.go b/auth/api/http/groups/endpoint_test.go deleted file mode 100644 index cf1dc7fed2c..00000000000 --- a/auth/api/http/groups/endpoint_test.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package groups_test - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - httpapi "github.com/mainflux/mainflux/auth/api/http" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/mocks" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" -) - -const ( - contentType = "application/json" - email = "user@example.com" - secret = "secret" - id = "testID" - loginDuration = 30 * time.Minute -) - -type testRequest struct { - client *http.Client - method string - url string - contentType string - token string - body io.Reader -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - return tr.client.Do(req) -} - -func newService() auth.Service { - keys := mocks.NewKeyRepository() - groups := mocks.NewGroupRepository() - idProvider := uuid.NewMock() - t := jwt.New(secret) - policies := mocks.NewKetoMock(map[string][]mocks.MockSubjectSet{}) - return auth.New(keys, groups, idProvider, t, policies, loginDuration) -} - -func newServer(svc auth.Service) *httptest.Server { - logger := logger.NewMock() - mux := httpapi.MakeHandler(svc, mocktracer.New(), logger) - return httptest.NewServer(mux) -} - -func toJSON(data interface{}) string { - jsonData, _ := json.Marshal(data) - return string(jsonData) -} - -func TestShareGroupAccess(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - type shareGroupAccessReq struct { - token string - userGroupID string - ThingGroupID string `json:"thing_group_id"` - } - data := shareGroupAccessReq{token: apiToken, userGroupID: "ug", ThingGroupID: "tg"} - invalidData := shareGroupAccessReq{token: apiToken, userGroupID: "ug", ThingGroupID: ""} - - cases := []struct { - desc string - req string - contentType string - auth string - userGroupID string - status int - }{ - { - desc: "share a user group with thing group", - req: toJSON(data), - contentType: contentType, - auth: apiToken, - userGroupID: "ug", - status: http.StatusOK, - }, - { - desc: "share a user group with invalid thing group", - req: toJSON(invalidData), - contentType: contentType, - auth: apiToken, - userGroupID: "ug", - status: http.StatusBadRequest, - }, - { - desc: "share an invalid user group with thing group", - req: toJSON(data), - contentType: contentType, - auth: apiToken, - userGroupID: "", - status: http.StatusBadRequest, - }, - { - desc: "share an invalid user group with invalid thing group", - req: toJSON(invalidData), - contentType: contentType, - auth: apiToken, - userGroupID: "", - status: http.StatusBadRequest, - }, - { - desc: "share a user group with thing group with invalid content type", - req: toJSON(data), - contentType: "", - auth: apiToken, - userGroupID: "ug", - status: http.StatusUnsupportedMediaType, - }, - { - desc: "share a user group with thing group with invalid token", - req: toJSON(data), - contentType: contentType, - auth: "token", - userGroupID: "ug", - status: http.StatusUnauthorized, - }, - } - - for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/groups/%s/share", ts.URL, tc.userGroupID), - contentType: tc.contentType, - token: tc.auth, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} diff --git a/auth/api/http/groups/requests.go b/auth/api/http/groups/requests.go deleted file mode 100644 index b95c22ebc2c..00000000000 --- a/auth/api/http/groups/requests.go +++ /dev/null @@ -1,191 +0,0 @@ -package groups - -import ( - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" -) - -type createGroupReq struct { - token string - Name string `json:"name,omitempty"` - ParentID string `json:"parent_id,omitempty"` - Description string `json:"description,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` -} - -func (req createGroupReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - if len(req.Name) > maxNameSize || req.Name == "" { - return apiutil.ErrNameSize - } - - return nil -} - -type updateGroupReq struct { - token string - id string - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` -} - -func (req updateGroupReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type listGroupsReq struct { - token string - id string - level uint64 - // - `true` - result is JSON tree representing groups hierarchy, - // - `false` - result is JSON array of groups. - tree bool - metadata auth.GroupMetadata -} - -func (req listGroupsReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.level > auth.MaxLevel || req.level < auth.MinLevel { - return apiutil.ErrMaxLevelExceeded - } - - return nil -} - -type listMembersReq struct { - token string - id string - groupType string - offset uint64 - limit uint64 - tree bool - metadata auth.GroupMetadata -} - -func (req listMembersReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type listMembershipsReq struct { - token string - id string - offset uint64 - limit uint64 - metadata auth.GroupMetadata -} - -func (req listMembershipsReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type assignReq struct { - token string - groupID string - Type string `json:"type,omitempty"` - Members []string `json:"members"` -} - -func (req assignReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.Type == "" { - return apiutil.ErrMissingMemberType - } - - if req.groupID == "" { - return apiutil.ErrMissingID - } - - if len(req.Members) == 0 { - return apiutil.ErrEmptyList - } - - return nil -} - -type shareGroupAccessReq struct { - token string - userGroupID string - ThingGroupID string `json:"thing_group_id"` -} - -func (req shareGroupAccessReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.ThingGroupID == "" || req.userGroupID == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type unassignReq struct { - assignReq -} - -func (req unassignReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.groupID == "" { - return apiutil.ErrMissingID - } - - if len(req.Members) == 0 { - return apiutil.ErrEmptyList - } - - return nil -} - -type groupReq struct { - token string - id string -} - -func (req groupReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} diff --git a/auth/api/http/groups/responses.go b/auth/api/http/groups/responses.go deleted file mode 100644 index bf364bf36be..00000000000 --- a/auth/api/http/groups/responses.go +++ /dev/null @@ -1,174 +0,0 @@ -package groups - -import ( - "fmt" - "net/http" - "time" - - "github.com/mainflux/mainflux" -) - -var ( - _ mainflux.Response = (*memberPageRes)(nil) - _ mainflux.Response = (*groupRes)(nil) - _ mainflux.Response = (*deleteRes)(nil) - _ mainflux.Response = (*assignRes)(nil) - _ mainflux.Response = (*unassignRes)(nil) -) - -type memberPageRes struct { - pageRes - Type string `json:"type"` - Members []string `json:"members"` -} - -func (res memberPageRes) Code() int { - return http.StatusOK -} - -func (res memberPageRes) Headers() map[string]string { - return map[string]string{} -} - -func (res memberPageRes) Empty() bool { - return false -} - -type shareGroupRes struct { -} - -func (res shareGroupRes) Code() int { - return http.StatusOK -} - -func (res shareGroupRes) Headers() map[string]string { - return map[string]string{} -} - -func (res shareGroupRes) Empty() bool { - return false -} - -type viewGroupRes struct { - ID string `json:"id"` - Name string `json:"name"` - OwnerID string `json:"owner_id"` - ParentID string `json:"parent_id,omitempty"` - Description string `json:"description,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` - // Indicates a level in tree hierarchy from first group node - root. - Level int `json:"level"` - // Path in a tree consisting of group ids - // parentID1.parentID2.childID1 - // e.g. 01EXPM5Z8HRGFAEWTETR1X1441.01EXPKW2TVK74S5NWQ979VJ4PJ.01EXPKW2TVK74S5NWQ979VJ4PJ - Path string `json:"path"` - Children []*viewGroupRes `json:"children,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -func (res viewGroupRes) Code() int { - return http.StatusOK -} - -func (res viewGroupRes) Headers() map[string]string { - return map[string]string{} -} - -func (res viewGroupRes) Empty() bool { - return false -} - -type groupRes struct { - id string - created bool -} - -func (res groupRes) Code() int { - if res.created { - return http.StatusCreated - } - - return http.StatusOK -} - -func (res groupRes) Headers() map[string]string { - if res.created { - return map[string]string{ - "Location": fmt.Sprintf("/groups/%s", res.id), - } - } - - return map[string]string{} -} - -func (res groupRes) Empty() bool { - return true -} - -type groupPageRes struct { - pageRes - Groups []viewGroupRes `json:"groups"` -} - -type pageRes struct { - Limit uint64 `json:"limit,omitempty"` - Offset uint64 `json:"offset,omitempty"` - Total uint64 `json:"total"` - Level uint64 `json:"level"` - Name string `json:"name"` -} - -func (res groupPageRes) Code() int { - return http.StatusOK -} - -func (res groupPageRes) Headers() map[string]string { - return map[string]string{} -} - -func (res groupPageRes) Empty() bool { - return false -} - -type deleteRes struct{} - -func (res deleteRes) Code() int { - return http.StatusNoContent -} - -func (res deleteRes) Headers() map[string]string { - return map[string]string{} -} - -func (res deleteRes) Empty() bool { - return true -} - -type assignRes struct{} - -func (res assignRes) Code() int { - return http.StatusOK -} - -func (res assignRes) Headers() map[string]string { - return map[string]string{} -} - -func (res assignRes) Empty() bool { - return true -} - -type unassignRes struct{} - -func (res unassignRes) Code() int { - return http.StatusNoContent -} - -func (res unassignRes) Headers() map[string]string { - return map[string]string{} -} - -func (res unassignRes) Empty() bool { - return true -} diff --git a/auth/api/http/groups/transport.go b/auth/api/http/groups/transport.go deleted file mode 100644 index 49b2afd0e18..00000000000 --- a/auth/api/http/groups/transport.go +++ /dev/null @@ -1,354 +0,0 @@ -package groups - -import ( - "context" - "encoding/json" - "net/http" - "strings" - - kitot "github.com/go-kit/kit/tracing/opentracing" - kithttp "github.com/go-kit/kit/transport/http" - "github.com/go-zoo/bone" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/opentracing/opentracing-go" -) - -const ( - contentType = "application/json" - maxNameSize = 254 - offsetKey = "offset" - limitKey = "limit" - levelKey = "level" - metadataKey = "metadata" - treeKey = "tree" - groupType = "type" - defOffset = 0 - defLimit = 10 - defLevel = 1 -) - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)), - } - mux.Post("/groups", kithttp.NewServer( - kitot.TraceServer(tracer, "create_group")(createGroupEndpoint(svc)), - decodeGroupCreate, - encodeResponse, - opts..., - )) - - mux.Get("/groups/:groupID", kithttp.NewServer( - kitot.TraceServer(tracer, "view_group")(viewGroupEndpoint(svc)), - decodeGroupRequest, - encodeResponse, - opts..., - )) - - mux.Put("/groups/:groupID", kithttp.NewServer( - kitot.TraceServer(tracer, "update_group")(updateGroupEndpoint(svc)), - decodeGroupUpdate, - encodeResponse, - opts..., - )) - - mux.Delete("/groups/:groupID", kithttp.NewServer( - kitot.TraceServer(tracer, "delete_group")(deleteGroupEndpoint(svc)), - decodeGroupRequest, - encodeResponse, - opts..., - )) - - mux.Post("/groups/:subjectGroupID/share", kithttp.NewServer( - kitot.TraceServer(tracer, "share_group_access")(shareGroupAccessEndpoint(svc)), - decodeShareGroupRequest, - encodeResponse, - opts..., - )) - - mux.Get("/groups", kithttp.NewServer( - kitot.TraceServer(tracer, "list_groups")(listGroupsEndpoint(svc)), - decodeListGroupsRequest, - encodeResponse, - opts..., - )) - - mux.Get("/groups/:groupID/children", kithttp.NewServer( - kitot.TraceServer(tracer, "list_children")(listChildrenEndpoint(svc)), - decodeListGroupsRequest, - encodeResponse, - opts..., - )) - - mux.Get("/groups/:groupID/parents", kithttp.NewServer( - kitot.TraceServer(tracer, "list_parents_groups")(listParentsEndpoint(svc)), - decodeListGroupsRequest, - encodeResponse, - opts..., - )) - - mux.Post("/groups/:groupID/members", kithttp.NewServer( - kitot.TraceServer(tracer, "assign")(assignEndpoint(svc)), - decodeAssignRequest, - encodeResponse, - opts..., - )) - - mux.Delete("/groups/:groupID/members", kithttp.NewServer( - kitot.TraceServer(tracer, "unassign")(unassignEndpoint(svc)), - decodeUnassignRequest, - encodeResponse, - opts..., - )) - - mux.Get("/groups/:groupID/members", kithttp.NewServer( - kitot.TraceServer(tracer, "list_members")(listMembersEndpoint(svc)), - decodeListMembersRequest, - encodeResponse, - opts..., - )) - - mux.Get("/members/:memberID/groups", kithttp.NewServer( - kitot.TraceServer(tracer, "list_memberships")(listMemberships(svc)), - decodeListMembershipsRequest, - encodeResponse, - opts..., - )) - - return mux -} - -func decodeShareGroupRequest(ctx context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := shareGroupAccessReq{ - token: apiutil.ExtractBearerToken(r), - userGroupID: bone.GetValue(r, "subjectGroupID"), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeListGroupsRequest(_ context.Context, r *http.Request) (interface{}, error) { - l, err := apiutil.ReadUintQuery(r, levelKey, defLevel) - if err != nil { - return nil, err - } - - m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil) - if err != nil { - return nil, err - } - - t, err := apiutil.ReadBoolQuery(r, treeKey, false) - if err != nil { - return nil, err - } - - req := listGroupsReq{ - token: apiutil.ExtractBearerToken(r), - level: l, - metadata: m, - tree: t, - id: bone.GetValue(r, "groupID"), - } - return req, nil -} - -func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, error) { - o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset) - if err != nil { - return nil, err - } - - l, err := apiutil.ReadUintQuery(r, limitKey, defLimit) - if err != nil { - return nil, err - } - - m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil) - if err != nil { - return nil, err - } - - tree, err := apiutil.ReadBoolQuery(r, treeKey, false) - if err != nil { - return nil, err - } - - t, err := apiutil.ReadStringQuery(r, groupType, "") - if err != nil { - return nil, err - } - - req := listMembersReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "groupID"), - groupType: t, - offset: o, - limit: l, - metadata: m, - tree: tree, - } - return req, nil -} - -func decodeListMembershipsRequest(_ context.Context, r *http.Request) (interface{}, error) { - o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset) - if err != nil { - return nil, err - } - - l, err := apiutil.ReadUintQuery(r, limitKey, defLimit) - if err != nil { - return nil, err - } - - m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil) - if err != nil { - return nil, err - } - - req := listMembershipsReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "memberID"), - offset: o, - limit: l, - metadata: m, - } - - return req, nil -} - -func decodeGroupCreate(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := createGroupReq{token: apiutil.ExtractBearerToken(r)} - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeGroupUpdate(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := updateGroupReq{ - id: bone.GetValue(r, "groupID"), - token: apiutil.ExtractBearerToken(r), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeGroupRequest(_ context.Context, r *http.Request) (interface{}, error) { - req := groupReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "groupID"), - } - - return req, nil -} - -func decodeAssignRequest(_ context.Context, r *http.Request) (interface{}, error) { - req := assignReq{ - token: apiutil.ExtractBearerToken(r), - groupID: bone.GetValue(r, "groupID"), - } - - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeUnassignRequest(_ context.Context, r *http.Request) (interface{}, error) { - req := unassignReq{ - assignReq{ - token: apiutil.ExtractBearerToken(r), - groupID: bone.GetValue(r, "groupID"), - }, - } - - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - w.Header().Set("Content-Type", contentType) - - if ar, ok := response.(mainflux.Response); ok { - for k, v := range ar.Headers() { - w.Header().Set(k, v) - } - - w.WriteHeader(ar.Code()) - - if ar.Empty() { - return nil - } - } - - return json.NewEncoder(w).Encode(response) -} - -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - switch { - case errors.Contains(err, errors.ErrMalformedEntity), - err == apiutil.ErrMissingID, - err == apiutil.ErrEmptyList, - err == apiutil.ErrMissingMemberType, - err == apiutil.ErrNameSize: - w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrAuthentication): - w.WriteHeader(http.StatusUnauthorized) - case errors.Contains(err, errors.ErrNotFound): - w.WriteHeader(http.StatusNotFound) - case errors.Contains(err, errors.ErrConflict): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrAuthorization): - w.WriteHeader(http.StatusForbidden) - case errors.Contains(err, auth.ErrMemberAlreadyAssigned): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrUnsupportedContentType): - w.WriteHeader(http.StatusUnsupportedMediaType) - - case errors.Contains(err, errors.ErrCreateEntity), - errors.Contains(err, errors.ErrUpdateEntity), - errors.Contains(err, errors.ErrViewEntity), - errors.Contains(err, errors.ErrRemoveEntity): - w.WriteHeader(http.StatusInternalServerError) - - default: - w.WriteHeader(http.StatusInternalServerError) - } - - if errorVal, ok := err.(errors.Error); ok { - w.Header().Set("Content-Type", contentType) - if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil { - w.WriteHeader(http.StatusInternalServerError) - } - } -} diff --git a/auth/api/http/keys/endpoint.go b/auth/api/http/keys/endpoint.go deleted file mode 100644 index 437e5f4e36a..00000000000 --- a/auth/api/http/keys/endpoint.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keys - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/auth" -) - -func issueEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(issueKeyReq) - if err := req.validate(); err != nil { - return nil, err - } - - now := time.Now().UTC() - newKey := auth.Key{ - IssuedAt: now, - Type: req.Type, - } - - duration := time.Duration(req.Duration * time.Second) - if duration != 0 { - exp := now.Add(duration) - newKey.ExpiresAt = exp - } - - key, secret, err := svc.Issue(ctx, req.token, newKey) - if err != nil { - return nil, err - } - - res := issueKeyRes{ - ID: key.ID, - Value: secret, - IssuedAt: key.IssuedAt, - } - if !key.ExpiresAt.IsZero() { - res.ExpiresAt = &key.ExpiresAt - } - return res, nil - } -} - -func retrieveEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(keyReq) - - if err := req.validate(); err != nil { - return nil, err - } - - key, err := svc.RetrieveKey(ctx, req.token, req.id) - - if err != nil { - return nil, err - } - ret := retrieveKeyRes{ - ID: key.ID, - IssuerID: key.IssuerID, - Subject: key.Subject, - Type: key.Type, - IssuedAt: key.IssuedAt, - } - if !key.ExpiresAt.IsZero() { - ret.ExpiresAt = &key.ExpiresAt - } - - return ret, nil - } -} - -func revokeEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(keyReq) - - if err := req.validate(); err != nil { - return nil, err - } - - if err := svc.Revoke(ctx, req.token, req.id); err != nil { - return nil, err - } - - return revokeKeyRes{}, nil - } -} diff --git a/auth/api/http/keys/endpoint_test.go b/auth/api/http/keys/endpoint_test.go deleted file mode 100644 index 98818743d84..00000000000 --- a/auth/api/http/keys/endpoint_test.go +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keys_test - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - httpapi "github.com/mainflux/mainflux/auth/api/http" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/mocks" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" -) - -const ( - secret = "secret" - contentType = "application/json" - id = "123e4567-e89b-12d3-a456-000000000001" - email = "user@example.com" - loginDuration = 30 * time.Minute -) - -type issueRequest struct { - Duration time.Duration `json:"duration,omitempty"` - Type uint32 `json:"type,omitempty"` -} - -type testRequest struct { - client *http.Client - method string - url string - contentType string - token string - body io.Reader -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - - req.Header.Set("Referer", "http://localhost") - return tr.client.Do(req) -} - -func newService() auth.Service { - repo := mocks.NewKeyRepository() - groupRepo := mocks.NewGroupRepository() - idProvider := uuid.NewMock() - t := jwt.New(secret) - - mockAuthzDB := map[string][]mocks.MockSubjectSet{} - mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: "authorities", Relation: "member"}) - ketoMock := mocks.NewKetoMock(mockAuthzDB) - - return auth.New(repo, groupRepo, idProvider, t, ketoMock, loginDuration) -} - -func newServer(svc auth.Service) *httptest.Server { - logger := logger.NewMock() - mux := httpapi.MakeHandler(svc, mocktracer.New(), logger) - return httptest.NewServer(mux) -} - -func toJSON(data interface{}) string { - jsonData, _ := json.Marshal(data) - return string(jsonData) -} - -func TestIssue(t *testing.T) { - svc := newService() - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - lk := issueRequest{Type: auth.LoginKey} - ak := issueRequest{Type: auth.APIKey, Duration: time.Hour} - rk := issueRequest{Type: auth.RecoveryKey} - - cases := []struct { - desc string - req string - ct string - token string - status int - }{ - { - desc: "issue login key with empty token", - req: toJSON(lk), - ct: contentType, - token: "", - status: http.StatusUnauthorized, - }, - { - desc: "issue API key", - req: toJSON(ak), - ct: contentType, - token: loginSecret, - status: http.StatusCreated, - }, - { - desc: "issue recovery key", - req: toJSON(rk), - ct: contentType, - token: loginSecret, - status: http.StatusCreated, - }, - { - desc: "issue login key wrong content type", - req: toJSON(lk), - ct: "", - token: loginSecret, - status: http.StatusUnsupportedMediaType, - }, - { - desc: "issue recovery key wrong content type", - req: toJSON(rk), - ct: "", - token: loginSecret, - status: http.StatusUnsupportedMediaType, - }, - { - desc: "issue key with an invalid token", - req: toJSON(ak), - ct: contentType, - token: "wrong", - status: http.StatusUnauthorized, - }, - { - desc: "issue recovery key with empty token", - req: toJSON(rk), - ct: contentType, - token: "", - status: http.StatusUnauthorized, - }, - { - desc: "issue key with invalid request", - req: "{", - ct: contentType, - token: loginSecret, - status: http.StatusBadRequest, - }, - { - desc: "issue key with invalid JSON", - req: "{invalid}", - ct: contentType, - token: loginSecret, - status: http.StatusBadRequest, - }, - { - desc: "issue key with invalid JSON content", - req: `{"Type":{"key":"value"}}`, - ct: contentType, - token: loginSecret, - status: http.StatusBadRequest, - }, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPost, - url: fmt.Sprintf("%s/keys", ts.URL), - contentType: tc.ct, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} - -func TestRetrieve(t *testing.T) { - svc := newService() - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - key := auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), IssuerID: id, Subject: email} - - k, _, err := svc.Issue(context.Background(), loginSecret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - cases := []struct { - desc string - id string - token string - status int - }{ - { - desc: "retrieve an existing key", - id: k.ID, - token: loginSecret, - status: http.StatusOK, - }, - { - desc: "retrieve a non-existing key", - id: "non-existing", - token: loginSecret, - status: http.StatusNotFound, - }, - { - desc: "retrieve a key with an invalid token", - id: k.ID, - token: "wrong", - status: http.StatusUnauthorized, - }, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodGet, - url: fmt.Sprintf("%s/keys/%s", ts.URL, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} - -func TestRevoke(t *testing.T) { - svc := newService() - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - key := auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), IssuerID: id, Subject: email} - - k, _, err := svc.Issue(context.Background(), loginSecret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - cases := []struct { - desc string - id string - token string - status int - }{ - { - desc: "revoke an existing key", - id: k.ID, - token: loginSecret, - status: http.StatusNoContent, - }, - { - desc: "revoke a non-existing key", - id: "non-existing", - token: loginSecret, - status: http.StatusNoContent, - }, - { - desc: "revoke key with invalid token", - id: k.ID, - token: "wrong", - status: http.StatusUnauthorized}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodDelete, - url: fmt.Sprintf("%s/keys/%s", ts.URL, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} diff --git a/auth/api/http/keys/requests.go b/auth/api/http/keys/requests.go deleted file mode 100644 index 2d61d1585e6..00000000000 --- a/auth/api/http/keys/requests.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keys - -import ( - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" -) - -type issueKeyReq struct { - token string - Type uint32 `json:"type,omitempty"` - Duration time.Duration `json:"duration,omitempty"` -} - -// It is not possible to issue Reset key using HTTP API. -func (req issueKeyReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.Type != auth.LoginKey && - req.Type != auth.RecoveryKey && - req.Type != auth.APIKey { - return apiutil.ErrInvalidAPIKey - } - - return nil -} - -type keyReq struct { - token string - id string -} - -func (req keyReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - return nil -} diff --git a/auth/api/http/keys/responses.go b/auth/api/http/keys/responses.go deleted file mode 100644 index 5bd4db6d516..00000000000 --- a/auth/api/http/keys/responses.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keys - -import ( - "net/http" - "time" - - "github.com/mainflux/mainflux" -) - -var ( - _ mainflux.Response = (*issueKeyRes)(nil) - _ mainflux.Response = (*revokeKeyRes)(nil) -) - -type issueKeyRes struct { - ID string `json:"id,omitempty"` - Value string `json:"value,omitempty"` - IssuedAt time.Time `json:"issued_at,omitempty"` - ExpiresAt *time.Time `json:"expires_at,omitempty"` -} - -func (res issueKeyRes) Code() int { - return http.StatusCreated -} - -func (res issueKeyRes) Headers() map[string]string { - return map[string]string{} -} - -func (res issueKeyRes) Empty() bool { - return res.Value == "" -} - -type retrieveKeyRes struct { - ID string `json:"id,omitempty"` - IssuerID string `json:"issuer_id,omitempty"` - Subject string `json:"subject,omitempty"` - Type uint32 `json:"type,omitempty"` - IssuedAt time.Time `json:"issued_at,omitempty"` - ExpiresAt *time.Time `json:"expires_at,omitempty"` -} - -func (res retrieveKeyRes) Code() int { - return http.StatusOK -} - -func (res retrieveKeyRes) Headers() map[string]string { - return map[string]string{} -} - -func (res retrieveKeyRes) Empty() bool { - return false -} - -type revokeKeyRes struct { -} - -func (res revokeKeyRes) Code() int { - return http.StatusNoContent -} - -func (res revokeKeyRes) Headers() map[string]string { - return map[string]string{} -} - -func (res revokeKeyRes) Empty() bool { - return true -} diff --git a/auth/api/http/keys/transport.go b/auth/api/http/keys/transport.go deleted file mode 100644 index 41b507b1c29..00000000000 --- a/auth/api/http/keys/transport.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keys - -import ( - "context" - "encoding/json" - "net/http" - "strings" - - kitot "github.com/go-kit/kit/tracing/opentracing" - kithttp "github.com/go-kit/kit/transport/http" - "github.com/go-zoo/bone" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/opentracing/opentracing-go" -) - -const contentType = "application/json" - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)), - } - mux.Post("/keys", kithttp.NewServer( - kitot.TraceServer(tracer, "issue")(issueEndpoint(svc)), - decodeIssue, - encodeResponse, - opts..., - )) - - mux.Get("/keys/:id", kithttp.NewServer( - kitot.TraceServer(tracer, "retrieve")(retrieveEndpoint(svc)), - decodeKeyReq, - encodeResponse, - opts..., - )) - - mux.Delete("/keys/:id", kithttp.NewServer( - kitot.TraceServer(tracer, "revoke")(revokeEndpoint(svc)), - decodeKeyReq, - encodeResponse, - opts..., - )) - - return mux -} - -func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := issueKeyReq{token: apiutil.ExtractBearerToken(r)} - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeKeyReq(_ context.Context, r *http.Request) (interface{}, error) { - req := keyReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "id"), - } - return req, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - w.Header().Set("Content-Type", contentType) - - if ar, ok := response.(mainflux.Response); ok { - for k, v := range ar.Headers() { - w.Header().Set(k, v) - } - - w.WriteHeader(ar.Code()) - - if ar.Empty() { - return nil - } - } - - return json.NewEncoder(w).Encode(response) -} - -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - switch { - case errors.Contains(err, errors.ErrMalformedEntity), - err == apiutil.ErrMissingID, - err == apiutil.ErrInvalidAPIKey: - w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrAuthentication), - err == apiutil.ErrBearerToken: - w.WriteHeader(http.StatusUnauthorized) - case errors.Contains(err, errors.ErrNotFound): - w.WriteHeader(http.StatusNotFound) - case errors.Contains(err, errors.ErrConflict): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrUnsupportedContentType): - w.WriteHeader(http.StatusUnsupportedMediaType) - default: - w.WriteHeader(http.StatusInternalServerError) - } - - if errorVal, ok := err.(errors.Error); ok { - w.Header().Set("Content-Type", contentType) - if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil { - w.WriteHeader(http.StatusInternalServerError) - } - } -} diff --git a/auth/api/http/policies/endpoint.go b/auth/api/http/policies/endpoint.go deleted file mode 100644 index e6a79617eb9..00000000000 --- a/auth/api/http/policies/endpoint.go +++ /dev/null @@ -1,38 +0,0 @@ -package policies - -import ( - "context" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/auth" -) - -func createPolicyEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(policiesReq) - if err := req.validate(); err != nil { - return createPolicyRes{}, err - } - - if err := svc.AddPolicies(ctx, req.token, req.Object, req.SubjectIDs, req.Policies); err != nil { - return createPolicyRes{}, err - } - - return createPolicyRes{created: true}, nil - } -} - -func deletePoliciesEndpoint(svc auth.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(policiesReq) - if err := req.validate(); err != nil { - return deletePoliciesRes{}, err - } - - if err := svc.DeletePolicies(ctx, req.token, req.Object, req.SubjectIDs, req.Policies); err != nil { - return deletePoliciesRes{}, err - } - - return deletePoliciesRes{deleted: true}, nil - } -} diff --git a/auth/api/http/policies/endpoint_test.go b/auth/api/http/policies/endpoint_test.go deleted file mode 100644 index 26a6558a7c4..00000000000 --- a/auth/api/http/policies/endpoint_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package policies_test - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - httpapi "github.com/mainflux/mainflux/auth/api/http" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/mocks" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" -) - -const ( - secret = "secret" - contentType = "application/json" - id = uuid.Prefix + "-000000000001" - email = "user@example.com" - unauthzID = uuid.Prefix + "-000000000002" - unauthzEmail = "unauthz@example.com" - loginDuration = 30 * time.Minute -) - -type testRequest struct { - client *http.Client - method string - url string - contentType string - token string - body io.Reader -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - - req.Header.Set("Referer", "http://localhost") - return tr.client.Do(req) -} - -func newService() auth.Service { - repo := mocks.NewKeyRepository() - groupRepo := mocks.NewGroupRepository() - idProvider := uuid.NewMock() - t := jwt.New(secret) - - mockAuthzDB := map[string][]mocks.MockSubjectSet{} - mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: "authorities", Relation: "member"}) - mockAuthzDB[unauthzID] = append(mockAuthzDB[unauthzID], mocks.MockSubjectSet{Object: "users", Relation: "member"}) - ketoMock := mocks.NewKetoMock(mockAuthzDB) - - return auth.New(repo, groupRepo, idProvider, t, ketoMock, loginDuration) -} - -func newServer(svc auth.Service) *httptest.Server { - logger := logger.NewMock() - mux := httpapi.MakeHandler(svc, mocktracer.New(), logger) - return httptest.NewServer(mux) -} - -func toJSON(data interface{}) string { - jsonData, _ := json.Marshal(data) - return string(jsonData) -} - -type addPolicyRequest struct { - SubjectIDs []string `json:"subjects"` - Policies []string `json:"policies"` - Object string `json:"object"` -} - -func TestAddPolicies(t *testing.T) { - svc := newService() - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - _, userLoginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: unauthzID, Subject: unauthzEmail}) - assert.Nil(t, err, fmt.Sprintf("Issuing unauthorized user's key expected to succeed: %s", err)) - - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - valid := addPolicyRequest{Object: "obj", Policies: []string{"read"}, SubjectIDs: []string{"user1", "user2"}} - multipleValid := addPolicyRequest{Object: "obj", Policies: []string{"write", "delete"}, SubjectIDs: []string{"user1", "user2"}} - invalidObject := addPolicyRequest{Object: "", Policies: []string{"read"}, SubjectIDs: []string{"user1", "user2"}} - invalidPolicies := addPolicyRequest{Object: "obj", Policies: []string{"read", "invalid"}, SubjectIDs: []string{"user1", "user2"}} - invalidSubjects := addPolicyRequest{Object: "obj", Policies: []string{"read", "access"}, SubjectIDs: []string{"", "user2"}} - - cases := []struct { - desc string - token string - ct string - status int - req string - }{ - { - desc: "Add policies with authorized access", - token: loginSecret, - ct: contentType, - status: http.StatusCreated, - req: toJSON(valid), - }, - { - desc: "Add multiple policies to multiple user", - token: loginSecret, - ct: contentType, - status: http.StatusCreated, - req: toJSON(multipleValid), - }, - { - desc: "Add policies with unauthorized access", - token: userLoginSecret, - ct: contentType, - status: http.StatusForbidden, - req: toJSON(valid), - }, - { - desc: "Add policies with invalid token", - token: "invalid", - ct: contentType, - status: http.StatusUnauthorized, - req: toJSON(valid), - }, - { - desc: "Add policies with empty token", - token: "", - ct: contentType, - status: http.StatusUnauthorized, - req: toJSON(valid), - }, - { - desc: "Add policies with invalid content type", - token: loginSecret, - ct: "text/html", - status: http.StatusUnsupportedMediaType, - req: toJSON(valid), - }, - { - desc: "Add policies with empty content type", - token: loginSecret, - ct: "", - status: http.StatusUnsupportedMediaType, - req: toJSON(valid), - }, - { - desc: "Add policies with invalid object field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidObject), - }, - { - desc: "Add policies with invalid policies field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidPolicies), - }, - { - desc: "Add policies with invalid subjects field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidSubjects), - }, - { - desc: "Add policies with empty request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: "", - }, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPost, - url: fmt.Sprintf("%s/policies", ts.URL), - contentType: tc.ct, - token: tc.token, - body: strings.NewReader(tc.req), - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} - -func TestDeletePolicies(t *testing.T) { - svc := newService() - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err)) - - _, userLoginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: unauthzID, Subject: unauthzEmail}) - assert.Nil(t, err, fmt.Sprintf("Issuing unauthorized user's key expected to succeed: %s", err)) - - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - policies := addPolicyRequest{Object: "obj", Policies: []string{"read", "write", "delete"}, SubjectIDs: []string{"user1", "user2", "user3"}} - err = svc.AddPolicies(context.Background(), loginSecret, policies.Object, policies.SubjectIDs, policies.Policies) - assert.Nil(t, err, fmt.Sprintf("Adding policies expected to succeed: %s", err)) - - validSingleDeleteReq := addPolicyRequest{Object: "obj", Policies: []string{"read"}, SubjectIDs: []string{"user1"}} - validMultipleDeleteReq := addPolicyRequest{Object: "obj", Policies: []string{"write", "delete"}, SubjectIDs: []string{"user2", "user3"}} - invalidObject := addPolicyRequest{Object: "", Policies: []string{"read"}, SubjectIDs: []string{"user1", "user2"}} - invalidPolicies := addPolicyRequest{Object: "obj", Policies: []string{"read", "invalid"}, SubjectIDs: []string{"user1", "user2"}} - invalidSubjects := addPolicyRequest{Object: "obj", Policies: []string{"read", "access"}, SubjectIDs: []string{"", "user2"}} - - cases := []struct { - desc string - token string - ct string - req string - status int - }{ - { - desc: "Delete policies with unauthorized access", - token: userLoginSecret, - ct: contentType, - status: http.StatusForbidden, - req: toJSON(validMultipleDeleteReq), - }, - { - desc: "Delete policies with invalid token", - token: "invalid", - ct: contentType, - status: http.StatusUnauthorized, - req: toJSON(validSingleDeleteReq), - }, - { - desc: "Delete policies with empty token", - token: "", - ct: contentType, - status: http.StatusUnauthorized, - req: toJSON(validSingleDeleteReq), - }, - { - desc: "Delete policies with authorized access", - token: loginSecret, - ct: contentType, - status: http.StatusNoContent, - req: toJSON(validSingleDeleteReq), - }, - { - desc: "Delete multiple policies to multiple user", - token: loginSecret, - ct: contentType, - status: http.StatusNoContent, - req: toJSON(validMultipleDeleteReq), - }, - { - desc: "Delete policies with invalid content type", - token: loginSecret, - ct: "text/html", - status: http.StatusUnsupportedMediaType, - req: toJSON(validMultipleDeleteReq), - }, - { - desc: "Delete policies with empty content type", - token: loginSecret, - ct: "", - status: http.StatusUnsupportedMediaType, - req: toJSON(validMultipleDeleteReq), - }, - { - desc: "Delete policies with invalid object field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidObject), - }, - { - desc: "Delete policies with invalid policies field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidPolicies), - }, - { - desc: "Delete policies with invalid subjects field in request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: toJSON(invalidSubjects), - }, - { - desc: "Delete policies with empty request body", - token: loginSecret, - ct: contentType, - status: http.StatusBadRequest, - req: "", - }, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPut, - url: fmt.Sprintf("%s/policies", ts.URL), - contentType: tc.ct, - token: tc.token, - body: strings.NewReader(tc.req), - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} diff --git a/auth/api/http/policies/requests.go b/auth/api/http/policies/requests.go deleted file mode 100644 index a97de7163b2..00000000000 --- a/auth/api/http/policies/requests.go +++ /dev/null @@ -1,64 +0,0 @@ -package policies - -import "github.com/mainflux/mainflux/internal/apiutil" - -// Action represents an enum for the policies used in the Mainflux. -type Action int - -const ( - Create Action = iota - Read - Write - Delete - Access - Member - Unknown -) - -var actions = map[string]Action{ - "create": Create, - "read": Read, - "write": Write, - "delete": Delete, - "access": Access, - "member": Member, -} - -type policiesReq struct { - token string - SubjectIDs []string `json:"subjects"` - Policies []string `json:"policies"` - Object string `json:"object"` -} - -func (req policiesReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if len(req.SubjectIDs) == 0 { - return apiutil.ErrEmptyList - } - - if len(req.Policies) == 0 { - return apiutil.ErrEmptyList - } - - if req.Object == "" { - return apiutil.ErrMissingPolicyObj - } - - for _, policy := range req.Policies { - if _, ok := actions[policy]; !ok { - return apiutil.ErrMalformedPolicy - } - } - - for _, subID := range req.SubjectIDs { - if subID == "" { - return apiutil.ErrMissingPolicySub - } - } - - return nil -} diff --git a/auth/api/http/policies/responses.go b/auth/api/http/policies/responses.go deleted file mode 100644 index 27fd596ed8e..00000000000 --- a/auth/api/http/policies/responses.go +++ /dev/null @@ -1,43 +0,0 @@ -package policies - -import "net/http" - -type createPolicyRes struct { - created bool -} - -func (res createPolicyRes) Code() int { - if res.created { - return http.StatusCreated - } - - return http.StatusOK -} - -func (res createPolicyRes) Headers() map[string]string { - return map[string]string{} -} - -func (res createPolicyRes) Empty() bool { - return false -} - -type deletePoliciesRes struct { - deleted bool -} - -func (res deletePoliciesRes) Code() int { - if res.deleted { - return http.StatusNoContent - } - - return http.StatusOK -} - -func (res deletePoliciesRes) Headers() map[string]string { - return map[string]string{} -} - -func (res deletePoliciesRes) Empty() bool { - return true -} diff --git a/auth/api/http/policies/transport.go b/auth/api/http/policies/transport.go deleted file mode 100644 index 423d95104c4..00000000000 --- a/auth/api/http/policies/transport.go +++ /dev/null @@ -1,107 +0,0 @@ -package policies - -import ( - "context" - "encoding/json" - "net/http" - "strings" - - kitot "github.com/go-kit/kit/tracing/opentracing" - kithttp "github.com/go-kit/kit/transport/http" - "github.com/go-zoo/bone" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/opentracing/opentracing-go" -) - -const contentType = "application/json" - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)), - } - - mux.Post("/policies", kithttp.NewServer( - kitot.TraceServer(tracer, "create_policy_bulk")(createPolicyEndpoint(svc)), - decodePoliciesRequest, - encodeResponse, - opts..., - )) - - mux.Put("/policies", kithttp.NewServer( - kitot.TraceServer(tracer, "delete_policies")(deletePoliciesEndpoint(svc)), - decodePoliciesRequest, - encodeResponse, - opts..., - )) - - return mux -} - -func decodePoliciesRequest(ctx context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := policiesReq{token: apiutil.ExtractBearerToken(r)} - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - w.Header().Set("Content-Type", contentType) - - if ar, ok := response.(mainflux.Response); ok { - for k, v := range ar.Headers() { - w.Header().Set(k, v) - } - - w.WriteHeader(ar.Code()) - - if ar.Empty() { - return nil - } - } - - return json.NewEncoder(w).Encode(response) -} - -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - switch { - case errors.Contains(err, errors.ErrMalformedEntity), - err == apiutil.ErrEmptyList, - err == apiutil.ErrMissingPolicyObj, - err == apiutil.ErrMissingPolicySub, - err == apiutil.ErrMalformedPolicy: - w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrAuthentication), - err == apiutil.ErrBearerToken: - w.WriteHeader(http.StatusUnauthorized) - case errors.Contains(err, errors.ErrNotFound): - w.WriteHeader(http.StatusNotFound) - case errors.Contains(err, errors.ErrConflict): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrAuthorization): - w.WriteHeader(http.StatusForbidden) - case errors.Contains(err, auth.ErrMemberAlreadyAssigned): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrUnsupportedContentType): - w.WriteHeader(http.StatusUnsupportedMediaType) - default: - w.WriteHeader(http.StatusInternalServerError) - } - - if errorVal, ok := err.(errors.Error); ok { - w.Header().Set("Content-Type", contentType) - if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil { - w.WriteHeader(http.StatusInternalServerError) - } - } -} diff --git a/auth/api/http/transport.go b/auth/api/http/transport.go deleted file mode 100644 index 8e1f0a68fe1..00000000000 --- a/auth/api/http/transport.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 -package http - -import ( - "net/http" - - "github.com/go-zoo/bone" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/auth/api/http/groups" - "github.com/mainflux/mainflux/auth/api/http/keys" - "github.com/mainflux/mainflux/auth/api/http/policies" - "github.com/mainflux/mainflux/logger" - "github.com/opentracing/opentracing-go" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc auth.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler { - mux := bone.New() - mux = keys.MakeHandler(svc, mux, tracer, logger) - mux = groups.MakeHandler(svc, mux, tracer, logger) - mux = policies.MakeHandler(svc, mux, tracer, logger) - mux.GetFunc("/health", mainflux.Health("auth")) - mux.Handle("/metrics", promhttp.Handler()) - return mux -} diff --git a/auth/api/logging.go b/auth/api/logging.go deleted file mode 100644 index df0b589a78f..00000000000 --- a/auth/api/logging.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package api - -import ( - "context" - "fmt" - "time" - - "github.com/mainflux/mainflux/auth" - log "github.com/mainflux/mainflux/logger" -) - -var _ auth.Service = (*loggingMiddleware)(nil) - -type loggingMiddleware struct { - logger log.Logger - svc auth.Service -} - -// LoggingMiddleware adds logging facilities to the core service. -func LoggingMiddleware(svc auth.Service, logger log.Logger) auth.Service { - return &loggingMiddleware{logger, svc} -} - -func (lm *loggingMiddleware) ListPolicies(ctx context.Context, pr auth.PolicyReq) (p auth.PolicyPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_policies took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListPolicies(ctx, pr) -} - -func (lm *loggingMiddleware) Issue(ctx context.Context, token string, newKey auth.Key) (key auth.Key, secret string, err error) { - defer func(begin time.Time) { - d := "infinite duration" - if !key.ExpiresAt.IsZero() { - d = fmt.Sprintf("the key with expiration date %v", key.ExpiresAt) - } - message := fmt.Sprintf("Method issue for %s took %s to complete", d, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Issue(ctx, token, newKey) -} - -func (lm *loggingMiddleware) Revoke(ctx context.Context, token, id string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method revoke for key %s took %s to complete", id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Revoke(ctx, token, id) -} - -func (lm *loggingMiddleware) RetrieveKey(ctx context.Context, token, id string) (key auth.Key, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method retrieve for key %s took %s to complete", id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.RetrieveKey(ctx, token, id) -} - -func (lm *loggingMiddleware) Identify(ctx context.Context, key string) (id auth.Identity, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method identify took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Identify(ctx, key) -} - -func (lm *loggingMiddleware) Authorize(ctx context.Context, pr auth.PolicyReq) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method authorize took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - return lm.svc.Authorize(ctx, pr) -} - -func (lm *loggingMiddleware) AddPolicy(ctx context.Context, pr auth.PolicyReq) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method add_policy took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - return lm.svc.AddPolicy(ctx, pr) -} - -func (lm *loggingMiddleware) AddPolicies(ctx context.Context, token, object string, subjectIDs, relations []string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method create_policy_bulk took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.AddPolicies(ctx, token, object, subjectIDs, relations) -} - -func (lm *loggingMiddleware) DeletePolicy(ctx context.Context, pr auth.PolicyReq) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method delete_policy took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - return lm.svc.DeletePolicy(ctx, pr) -} - -func (lm *loggingMiddleware) DeletePolicies(ctx context.Context, token, object string, subjectIDs, relations []string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method delete_policies took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - return lm.svc.DeletePolicies(ctx, token, object, subjectIDs, relations) -} - -func (lm *loggingMiddleware) CreateGroup(ctx context.Context, token string, group auth.Group) (g auth.Group, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method create_group for token %s and name %s took %s to complete", token, group.Name, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.CreateGroup(ctx, token, group) -} - -func (lm *loggingMiddleware) UpdateGroup(ctx context.Context, token string, group auth.Group) (gr auth.Group, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method update_group for token %s and name %s took %s to complete", token, group.Name, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.UpdateGroup(ctx, token, group) -} - -func (lm *loggingMiddleware) RemoveGroup(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method remove_group for token %s and id %s took %s to complete", token, id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.RemoveGroup(ctx, token, id) -} - -func (lm *loggingMiddleware) ViewGroup(ctx context.Context, token, id string) (group auth.Group, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method view_group for token %s and id %s took %s to complete", token, id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ViewGroup(ctx, token, id) -} - -func (lm *loggingMiddleware) ListGroups(ctx context.Context, token string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_groups for token %s took %s to complete", token, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListGroups(ctx, token, pm) -} - -func (lm *loggingMiddleware) ListChildren(ctx context.Context, token, parentID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_children for token %s and parent %s took %s to complete", token, parentID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListChildren(ctx, token, parentID, pm) -} - -func (lm *loggingMiddleware) ListParents(ctx context.Context, token, childID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_parents for token %s and child %s took for child %s to complete", token, childID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListParents(ctx, token, childID, pm) -} - -func (lm *loggingMiddleware) ListMembers(ctx context.Context, token, groupID, groupType string, pm auth.PageMetadata) (gp auth.MemberPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_members for token %s and group id %s took %s to complete", token, groupID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListMembers(ctx, token, groupID, groupType, pm) -} - -func (lm *loggingMiddleware) ListMemberships(ctx context.Context, token, memberID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_memberships for token %s and member id %s took %s to complete", token, memberID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListMemberships(ctx, token, memberID, pm) -} - -func (lm *loggingMiddleware) Assign(ctx context.Context, token, groupID, groupType string, memberIDs ...string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method assign for token %s and member %s group id %s took %s to complete", token, memberIDs, groupID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Assign(ctx, token, groupID, groupType, memberIDs...) -} - -func (lm *loggingMiddleware) Unassign(ctx context.Context, token string, groupID string, memberIDs ...string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method unassign for token %s and member %s group id %s took %s to complete", token, memberIDs, groupID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Unassign(ctx, token, groupID, memberIDs...) -} - -func (lm *loggingMiddleware) AssignGroupAccessRights(ctx context.Context, token, thingGroupID, userGroupID string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method share_group_access took %s to complete", time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.AssignGroupAccessRights(ctx, token, thingGroupID, userGroupID) -} diff --git a/auth/api/metrics.go b/auth/api/metrics.go deleted file mode 100644 index c07bd94289f..00000000000 --- a/auth/api/metrics.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package api - -import ( - "context" - "time" - - "github.com/go-kit/kit/metrics" - "github.com/mainflux/mainflux/auth" -) - -var _ auth.Service = (*metricsMiddleware)(nil) - -type metricsMiddleware struct { - counter metrics.Counter - latency metrics.Histogram - svc auth.Service -} - -// MetricsMiddleware instruments core service by tracking request count and latency. -func MetricsMiddleware(svc auth.Service, counter metrics.Counter, latency metrics.Histogram) auth.Service { - return &metricsMiddleware{ - counter: counter, - latency: latency, - svc: svc, - } -} - -func (ms *metricsMiddleware) ListPolicies(ctx context.Context, pr auth.PolicyReq) (p auth.PolicyPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_policies").Add(1) - ms.latency.With("method", "list_policies").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListPolicies(ctx, pr) -} - -func (ms *metricsMiddleware) Issue(ctx context.Context, token string, key auth.Key) (auth.Key, string, error) { - defer func(begin time.Time) { - ms.counter.With("method", "issue_key").Add(1) - ms.latency.With("method", "issue_key").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Issue(ctx, token, key) -} - -func (ms *metricsMiddleware) Revoke(ctx context.Context, token, id string) error { - defer func(begin time.Time) { - ms.counter.With("method", "revoke_key").Add(1) - ms.latency.With("method", "revoke_key").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Revoke(ctx, token, id) -} - -func (ms *metricsMiddleware) RetrieveKey(ctx context.Context, token, id string) (auth.Key, error) { - defer func(begin time.Time) { - ms.counter.With("method", "retrieve_key").Add(1) - ms.latency.With("method", "retrieve_key").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.RetrieveKey(ctx, token, id) -} - -func (ms *metricsMiddleware) Identify(ctx context.Context, token string) (auth.Identity, error) { - defer func(begin time.Time) { - ms.counter.With("method", "identify").Add(1) - ms.latency.With("method", "identify").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Identify(ctx, token) -} - -func (ms *metricsMiddleware) Authorize(ctx context.Context, pr auth.PolicyReq) error { - defer func(begin time.Time) { - ms.counter.With("method", "authorize").Add(1) - ms.latency.With("method", "authorize").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.Authorize(ctx, pr) -} - -func (ms *metricsMiddleware) AddPolicy(ctx context.Context, pr auth.PolicyReq) error { - defer func(begin time.Time) { - ms.counter.With("method", "add_policy").Add(1) - ms.latency.With("method", "add_policy").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.AddPolicy(ctx, pr) -} - -func (ms *metricsMiddleware) AddPolicies(ctx context.Context, token, object string, subjectIDs, relations []string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "create_policy_bulk").Add(1) - ms.latency.With("method", "create_policy_bulk").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.AddPolicies(ctx, token, object, subjectIDs, relations) -} - -func (ms *metricsMiddleware) DeletePolicy(ctx context.Context, pr auth.PolicyReq) error { - defer func(begin time.Time) { - ms.counter.With("method", "delete_policy").Add(1) - ms.latency.With("method", "delete_policy").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.DeletePolicy(ctx, pr) -} - -func (ms *metricsMiddleware) DeletePolicies(ctx context.Context, token, object string, subjectIDs, relations []string) error { - defer func(begin time.Time) { - ms.counter.With("method", "delete_policies").Add(1) - ms.latency.With("method", "delete_policies").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.DeletePolicies(ctx, token, object, subjectIDs, relations) -} - -func (ms *metricsMiddleware) CreateGroup(ctx context.Context, token string, group auth.Group) (gr auth.Group, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "create_group").Add(1) - ms.latency.With("method", "create_group").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.CreateGroup(ctx, token, group) -} - -func (ms *metricsMiddleware) UpdateGroup(ctx context.Context, token string, group auth.Group) (gr auth.Group, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "update_group").Add(1) - ms.latency.With("method", "update_group").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.UpdateGroup(ctx, token, group) -} - -func (ms *metricsMiddleware) RemoveGroup(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "remove_group").Add(1) - ms.latency.With("method", "remove_group").Observe(time.Since(begin).Seconds()) - }(time.Now()) - return ms.svc.RemoveGroup(ctx, token, id) -} - -func (ms *metricsMiddleware) ViewGroup(ctx context.Context, token, id string) (group auth.Group, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "view_group").Add(1) - ms.latency.With("method", "view_group").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ViewGroup(ctx, token, id) -} - -func (ms *metricsMiddleware) ListGroups(ctx context.Context, token string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_groups").Add(1) - ms.latency.With("method", "list_groups").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListGroups(ctx, token, pm) -} - -func (ms *metricsMiddleware) ListParents(ctx context.Context, token, childID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "parents").Add(1) - ms.latency.With("method", "parents").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListParents(ctx, token, childID, pm) -} - -func (ms *metricsMiddleware) ListChildren(ctx context.Context, token, parentID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_children").Add(1) - ms.latency.With("method", "list_children").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListChildren(ctx, token, parentID, pm) -} - -func (ms *metricsMiddleware) ListMembers(ctx context.Context, token, groupID, groupType string, pm auth.PageMetadata) (gp auth.MemberPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_members").Add(1) - ms.latency.With("method", "list_members").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListMembers(ctx, token, groupID, groupType, pm) -} - -func (ms *metricsMiddleware) ListMemberships(ctx context.Context, token, memberID string, pm auth.PageMetadata) (gp auth.GroupPage, err error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_memberships").Add(1) - ms.latency.With("method", "list_memberships").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListMemberships(ctx, token, memberID, pm) -} - -func (ms *metricsMiddleware) Assign(ctx context.Context, token, groupID, groupType string, memberIDs ...string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "assign").Add(1) - ms.latency.With("method", "assign").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Assign(ctx, token, groupID, groupType, memberIDs...) -} - -func (ms *metricsMiddleware) Unassign(ctx context.Context, token, groupID string, memberIDs ...string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "unassign").Add(1) - ms.latency.With("method", "unassign").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Unassign(ctx, token, groupID, memberIDs...) -} - -func (ms *metricsMiddleware) AssignGroupAccessRights(ctx context.Context, token, thingGroupID, userGroupID string) error { - defer func(begin time.Time) { - ms.counter.With("method", "share_group_access").Add(1) - ms.latency.With("method", "share_group_access").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.AssignGroupAccessRights(ctx, token, thingGroupID, userGroupID) -} diff --git a/auth/groups.go b/auth/groups.go deleted file mode 100644 index d95b3a39ef7..00000000000 --- a/auth/groups.go +++ /dev/null @@ -1,162 +0,0 @@ -package auth - -import ( - "context" - "errors" - "time" -) - -const ( - // MaxLevel represents the maximum group hierarchy level. - MaxLevel = uint64(5) - // MinLevel represents the minimum group hierarchy level. - MinLevel = uint64(1) -) - -var ( - // ErrAssignToGroup indicates failure to assign member to a group. - ErrAssignToGroup = errors.New("failed to assign member to a group") - - // ErrUnassignFromGroup indicates failure to unassign member from a group. - ErrUnassignFromGroup = errors.New("failed to unassign member from a group") - - // ErrMissingParent indicates that parent can't be found - ErrMissingParent = errors.New("failed to retrieve parent") - - // ErrGroupNotEmpty indicates group is not empty, can't be deleted. - ErrGroupNotEmpty = errors.New("group is not empty") - - // ErrMemberAlreadyAssigned indicates that members is already assigned. - ErrMemberAlreadyAssigned = errors.New("member is already assigned") -) - -// GroupMetadata defines the Metadata type. -type GroupMetadata map[string]interface{} - -// Member represents the member information. -type Member struct { - ID string - Type string -} - -// Group represents the group information. -type Group struct { - ID string - OwnerID string - ParentID string - Name string - Description string - Metadata GroupMetadata - // Indicates a level in tree hierarchy. - // Root node is level 1. - Level int - // Path in a tree consisting of group ids - // parentID1.parentID2.childID1 - // e.g. 01EXPM5Z8HRGFAEWTETR1X1441.01EXPKW2TVK74S5NWQ979VJ4PJ.01EXPKW2TVK74S5NWQ979VJ4PJ - Path string - Children []*Group - CreatedAt time.Time - UpdatedAt time.Time -} - -// PageMetadata contains page metadata that helps navigation. -type PageMetadata struct { - Total uint64 - Offset uint64 - Limit uint64 - Size uint64 - Level uint64 - Name string - Type string - Metadata GroupMetadata -} - -// GroupPage contains page related metadata as well as list of groups that -// belong to this page. -type GroupPage struct { - PageMetadata - Groups []Group -} - -// MemberPage contains page related metadata as well as list of members that -// belong to this page. -type MemberPage struct { - PageMetadata - Members []Member -} - -// GroupService specifies an API that must be fullfiled by the domain service -// implementation, and all of its decorators (e.g. logging & metrics). -type GroupService interface { - // CreateGroup creates new group. - CreateGroup(ctx context.Context, token string, g Group) (Group, error) - - // UpdateGroup updates the group identified by the provided ID. - UpdateGroup(ctx context.Context, token string, g Group) (Group, error) - - // ViewGroup retrieves data about the group identified by ID. - ViewGroup(ctx context.Context, token, id string) (Group, error) - - // ListGroups retrieves groups. - ListGroups(ctx context.Context, token string, pm PageMetadata) (GroupPage, error) - - // ListChildren retrieves groups that are children to group identified by parentID - ListChildren(ctx context.Context, token, parentID string, pm PageMetadata) (GroupPage, error) - - // ListParents retrieves groups that are parent to group identified by childID. - ListParents(ctx context.Context, token, childID string, pm PageMetadata) (GroupPage, error) - - // ListMembers retrieves everything that is assigned to a group identified by groupID. - ListMembers(ctx context.Context, token, groupID, groupType string, pm PageMetadata) (MemberPage, error) - - // ListMemberships retrieves all groups for member that is identified with memberID belongs to. - ListMemberships(ctx context.Context, token, memberID string, pm PageMetadata) (GroupPage, error) - - // RemoveGroup removes the group identified with the provided ID. - RemoveGroup(ctx context.Context, token, id string) error - - // Assign adds a member with memberID into the group identified by groupID. - Assign(ctx context.Context, token, groupID, groupType string, memberIDs ...string) error - - // Unassign removes member with memberID from group identified by groupID. - Unassign(ctx context.Context, token, groupID string, memberIDs ...string) error - - // AssignGroupAccessRights adds access rights on thing groups to user group. - AssignGroupAccessRights(ctx context.Context, token, thingGroupID, userGroupID string) error -} - -// GroupRepository specifies a group persistence API. -type GroupRepository interface { - // Save group - Save(ctx context.Context, g Group) (Group, error) - - // Update a group - Update(ctx context.Context, g Group) (Group, error) - - // Delete a group - Delete(ctx context.Context, id string) error - - // RetrieveByID retrieves group by its id - RetrieveByID(ctx context.Context, id string) (Group, error) - - // RetrieveAll retrieves all groups. - RetrieveAll(ctx context.Context, pm PageMetadata) (GroupPage, error) - - // RetrieveAllParents retrieves all groups that are ancestors to the group with given groupID. - RetrieveAllParents(ctx context.Context, groupID string, pm PageMetadata) (GroupPage, error) - - // RetrieveAllChildren retrieves all children from group with given groupID up to the hierarchy level. - RetrieveAllChildren(ctx context.Context, groupID string, pm PageMetadata) (GroupPage, error) - - // Retrieves list of groups that member belongs to - Memberships(ctx context.Context, memberID string, pm PageMetadata) (GroupPage, error) - - // Members retrieves everything that is assigned to a group identified by groupID. - Members(ctx context.Context, groupID, groupType string, pm PageMetadata) (MemberPage, error) - - // Assign adds a member to group. - Assign(ctx context.Context, groupID, groupType string, memberIDs ...string) error - - // Unassign removes a member from a group - Unassign(ctx context.Context, groupID string, memberIDs ...string) error -} diff --git a/auth/jwt/token_test.go b/auth/jwt/token_test.go deleted file mode 100644 index ada6dae8807..00000000000 --- a/auth/jwt/token_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package jwt_test - -import ( - "fmt" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const secret = "test" - -func key() auth.Key { - exp := time.Now().UTC().Add(10 * time.Minute).Round(time.Second) - return auth.Key{ - ID: "id", - Type: auth.LoginKey, - Subject: "user@email.com", - IssuerID: "", - IssuedAt: time.Now().UTC().Add(-10 * time.Second).Round(time.Second), - ExpiresAt: exp, - } -} - -func TestIssue(t *testing.T) { - tokenizer := jwt.New(secret) - - cases := []struct { - desc string - key auth.Key - err error - }{ - { - desc: "issue new token", - key: key(), - err: nil, - }, - } - - for _, tc := range cases { - _, err := tokenizer.Issue(tc.key) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s, got %s", tc.desc, tc.err, err)) - } -} - -func TestParse(t *testing.T) { - tokenizer := jwt.New(secret) - - token, err := tokenizer.Issue(key()) - require.Nil(t, err, fmt.Sprintf("issuing key expected to succeed: %s", err)) - - apiKey := key() - apiKey.Type = auth.APIKey - apiKey.ExpiresAt = time.Now().UTC().Add(-1 * time.Minute).Round(time.Second) - apiToken, err := tokenizer.Issue(apiKey) - require.Nil(t, err, fmt.Sprintf("issuing user key expected to succeed: %s", err)) - - expKey := key() - expKey.ExpiresAt = time.Now().UTC().Add(-1 * time.Minute).Round(time.Second) - expToken, err := tokenizer.Issue(expKey) - require.Nil(t, err, fmt.Sprintf("issuing expired key expected to succeed: %s", err)) - - cases := []struct { - desc string - key auth.Key - token string - err error - }{ - { - desc: "parse valid key", - key: key(), - token: token, - err: nil, - }, - { - desc: "parse ivalid key", - key: auth.Key{}, - token: "invalid", - err: errors.ErrAuthentication, - }, - { - desc: "parse expired key", - key: auth.Key{}, - token: expToken, - err: auth.ErrKeyExpired, - }, - { - desc: "parse expired API key", - key: apiKey, - token: apiToken, - err: auth.ErrAPIKeyExpired, - }, - } - - for _, tc := range cases { - key, err := tokenizer.Parse(tc.token) - 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)) - } -} diff --git a/auth/jwt/tokenizer.go b/auth/jwt/tokenizer.go deleted file mode 100644 index 29a3231519f..00000000000 --- a/auth/jwt/tokenizer.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package jwt - -import ( - "time" - - "github.com/golang-jwt/jwt/v4" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" -) - -const issuerName = "mainflux.auth" - -type claims struct { - jwt.StandardClaims - IssuerID string `json:"issuer_id,omitempty"` - Type *uint32 `json:"type,omitempty"` -} - -func (c claims) Valid() error { - if c.Type == nil || *c.Type > auth.APIKey || c.Issuer != issuerName { - return errors.ErrMalformedEntity - } - - return c.StandardClaims.Valid() -} - -type tokenizer struct { - secret string -} - -// New returns new JWT Tokenizer. -func New(secret string) auth.Tokenizer { - return tokenizer{secret: secret} -} - -func (svc tokenizer) Issue(key auth.Key) (string, error) { - claims := claims{ - StandardClaims: jwt.StandardClaims{ - Issuer: issuerName, - Subject: key.Subject, - IssuedAt: key.IssuedAt.UTC().Unix(), - }, - IssuerID: key.IssuerID, - Type: &key.Type, - } - - if !key.ExpiresAt.IsZero() { - claims.ExpiresAt = key.ExpiresAt.UTC().Unix() - } - if key.ID != "" { - claims.Id = key.ID - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString([]byte(svc.secret)) -} - -func (svc tokenizer) Parse(token string) (auth.Key, error) { - c := claims{} - _, err := jwt.ParseWithClaims(token, &c, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, errors.ErrAuthentication - } - return []byte(svc.secret), nil - }) - - if err != nil { - if e, ok := err.(*jwt.ValidationError); ok && e.Errors == jwt.ValidationErrorExpired { - // Expired User key needs to be revoked. - if c.Type != nil && *c.Type == auth.APIKey { - return c.toKey(), auth.ErrAPIKeyExpired - } - return auth.Key{}, errors.Wrap(auth.ErrKeyExpired, err) - } - return auth.Key{}, errors.Wrap(errors.ErrAuthentication, err) - } - - return c.toKey(), nil -} - -func (c claims) toKey() auth.Key { - key := auth.Key{ - ID: c.Id, - IssuerID: c.IssuerID, - Subject: c.Subject, - IssuedAt: time.Unix(c.IssuedAt, 0).UTC(), - } - if c.ExpiresAt != 0 { - key.ExpiresAt = time.Unix(c.ExpiresAt, 0).UTC() - } - - // Default type is 0. - if c.Type != nil { - key.Type = *c.Type - } - - return key -} diff --git a/auth/keto/doc.go b/auth/keto/doc.go deleted file mode 100644 index bbb95a7df57..00000000000 --- a/auth/keto/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package keto contains PolicyAgent implementation using Keto. -package keto diff --git a/auth/keto/policies.go b/auth/keto/policies.go deleted file mode 100644 index d2ce28b67f5..00000000000 --- a/auth/keto/policies.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package keto - -import ( - "context" - "regexp" - "strings" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" - acl "github.com/ory/keto/proto/ory/keto/acl/v1alpha1" -) - -const ( - subjectSetRegex = "^.{1,}:.{1,}#.{1,}$" // expected subject set structure is :# - ketoNamespace = "members" -) - -type policyAgent struct { - writer acl.WriteServiceClient - checker acl.CheckServiceClient - reader acl.ReadServiceClient -} - -// NewPolicyAgent returns a gRPC communication functionalities -// to communicate with ORY Keto. -func NewPolicyAgent(checker acl.CheckServiceClient, writer acl.WriteServiceClient, reader acl.ReadServiceClient) auth.PolicyAgent { - return policyAgent{checker: checker, writer: writer, reader: reader} -} - -func (pa policyAgent) CheckPolicy(ctx context.Context, pr auth.PolicyReq) error { - res, err := pa.checker.Check(context.Background(), &acl.CheckRequest{ - Namespace: ketoNamespace, - Object: pr.Object, - Relation: pr.Relation, - Subject: getSubject(pr), - }) - if err != nil { - return errors.Wrap(err, errors.ErrAuthorization) - } - if !res.GetAllowed() { - return errors.ErrAuthorization - } - return nil -} - -func (pa policyAgent) AddPolicy(ctx context.Context, pr auth.PolicyReq) error { - var ss *acl.Subject - switch isSubjectSet(pr.Subject) { - case true: - namespace, object, relation := parseSubjectSet(pr.Subject) - ss = &acl.Subject{ - Ref: &acl.Subject_Set{Set: &acl.SubjectSet{Namespace: namespace, Object: object, Relation: relation}}, - } - default: - ss = &acl.Subject{Ref: &acl.Subject_Id{Id: pr.Subject}} - } - - trt := pa.writer.TransactRelationTuples - _, err := trt(context.Background(), &acl.TransactRelationTuplesRequest{ - RelationTupleDeltas: []*acl.RelationTupleDelta{ - { - Action: acl.RelationTupleDelta_INSERT, - RelationTuple: &acl.RelationTuple{ - Namespace: ketoNamespace, - Object: pr.Object, - Relation: pr.Relation, - Subject: ss, - }, - }, - }, - }) - return err -} - -func (pa policyAgent) DeletePolicy(ctx context.Context, pr auth.PolicyReq) error { - trt := pa.writer.TransactRelationTuples - _, err := trt(context.Background(), &acl.TransactRelationTuplesRequest{ - RelationTupleDeltas: []*acl.RelationTupleDelta{ - { - Action: acl.RelationTupleDelta_DELETE, - RelationTuple: &acl.RelationTuple{ - Namespace: ketoNamespace, - Object: pr.Object, - Relation: pr.Relation, - Subject: &acl.Subject{Ref: &acl.Subject_Id{ - Id: pr.Subject, - }}, - }, - }, - }, - }) - return err -} - -func (pa policyAgent) RetrievePolicies(ctx context.Context, pr auth.PolicyReq) ([]*acl.RelationTuple, error) { - var ss *acl.Subject - switch isSubjectSet(pr.Subject) { - case true: - namespace, object, relation := parseSubjectSet(pr.Subject) - ss = &acl.Subject{ - Ref: &acl.Subject_Set{Set: &acl.SubjectSet{Namespace: namespace, Object: object, Relation: relation}}, - } - default: - ss = &acl.Subject{Ref: &acl.Subject_Id{Id: pr.Subject}} - } - - res, err := pa.reader.ListRelationTuples(ctx, &acl.ListRelationTuplesRequest{ - Query: &acl.ListRelationTuplesRequest_Query{ - Namespace: ketoNamespace, - Relation: pr.Relation, - Subject: ss, - }, - }) - if err != nil { - return []*acl.RelationTuple{}, err - } - - tuple := res.GetRelationTuples() - for res.NextPageToken != "" { - tuple = append(tuple, res.GetRelationTuples()...) - } - - return tuple, nil -} - -// getSubject returns a 'subject' field for ACL(access control lists). -// If the given PolicyReq argument contains a subject as subject set, -// it returns subject set; otherwise, it returns a subject. -func getSubject(pr auth.PolicyReq) *acl.Subject { - if isSubjectSet(pr.Subject) { - return &acl.Subject{ - Ref: &acl.Subject_Set{Set: &acl.SubjectSet{ - Namespace: ketoNamespace, - Object: pr.Object, - Relation: pr.Relation, - }}, - } - } - - return &acl.Subject{Ref: &acl.Subject_Id{Id: pr.Subject}} -} - -// isSubjectSet returns true when given subject is subject set. -// Otherwise, it returns false. -func isSubjectSet(subject string) bool { - r, err := regexp.Compile(subjectSetRegex) - if err != nil { - return false - } - return r.MatchString(subject) -} - -func parseSubjectSet(subjectSet string) (namespace, object, relation string) { - r := strings.Split(subjectSet, ":") - if len(r) != 2 { - return - } - namespace = r[0] - - r = strings.Split(r[1], "#") - if len(r) != 2 { - return - } - - object = r[0] - relation = r[1] - - return -} diff --git a/auth/keto/policies_test.go b/auth/keto/policies_test.go deleted file mode 100644 index aab65aaac8e..00000000000 --- a/auth/keto/policies_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package keto - -import ( - "fmt" - "testing" - - "github.com/mainflux/mainflux/auth" - acl "github.com/ory/keto/proto/ory/keto/acl/v1alpha1" - "github.com/stretchr/testify/assert" -) - -func TestIsSubjectSet(t *testing.T) { - cases := []struct { - desc string - subjectSet string - result bool - }{ - { - desc: "check valid subject set", - subjectSet: "namespace:object#relation", - result: true, - }, - { - desc: "check invalid subject set, missing namespace field", - subjectSet: ":object#relation", - result: false, - }, - { - desc: "check invalid subject set, missing object field", - subjectSet: "namespace:#relation", - result: false, - }, - { - desc: "check invalid subject set, missing relation field", - subjectSet: "namespace:object#", - result: false, - }, - { - desc: "check invalid subject set, empty subject set", - subjectSet: ":#", - result: false, - }, - { - desc: "check invalid subject set, missing subject set identifier", - subjectSet: "namespace:#relation", - result: false, - }, - { - desc: "check invalid subject set, missing object field", - subjectSet: "namespace:object", - result: false, - }, - { - desc: "check invalid subject set, unexpected object field", - subjectSet: "namespace:object@relation", - result: false, - }, - } - - for _, tc := range cases { - iss := isSubjectSet(tc.subjectSet) - assert.Equal(t, iss, tc.result, fmt.Sprintf("%s expected to be %v, got %v\n", tc.desc, tc.result, iss)) - } - -} - -func TestGetSubject(t *testing.T) { - p1 := auth.PolicyReq{Subject: "subject", Object: "object", Relation: "relation"} - s1 := getSubject(p1) - ref1 := s1.GetRef() - _, ok := ref1.(*acl.Subject_Id) - assert.True(t, ok, fmt.Errorf("subject reference of %#v is expected to be (*acl.Subject_Id), got %T", p1, ref1)) - - p2 := auth.PolicyReq{Subject: "members:group#access", Object: "object", Relation: "relation"} - s2 := getSubject(p2) - ref2 := s2.GetRef() - _, ok = ref2.(*acl.Subject_Set) - assert.True(t, ok, fmt.Errorf("subject reference of %#v is expected to be (*acl.Subject_Set), got %T", p2, ref2)) -} diff --git a/auth/keys.go b/auth/keys.go deleted file mode 100644 index 80c71565fc1..00000000000 --- a/auth/keys.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth - -import ( - "context" - "errors" - "time" -) - -var ( - // ErrInvalidKeyIssuedAt indicates that the Key is being used before it's issued. - ErrInvalidKeyIssuedAt = errors.New("invalid issue time") - - // ErrKeyExpired indicates that the Key is expired. - ErrKeyExpired = errors.New("use of expired key") - - // ErrAPIKeyExpired indicates that the Key is expired - // and that the key type is API key. - ErrAPIKeyExpired = errors.New("use of expired API key") -) - -const ( - // LoginKey is temporary User key received on successfull login. - LoginKey uint32 = iota - // RecoveryKey represents a key for resseting password. - RecoveryKey - // APIKey enables the one to act on behalf of the user. - APIKey -) - -// Key represents API key. -type Key struct { - ID string - Type uint32 - IssuerID string - Subject string - IssuedAt time.Time - ExpiresAt time.Time -} - -// Identity contains ID and Email. -type Identity struct { - ID string - Email string -} - -// Expired verifies if the key is expired. -func (k Key) Expired() bool { - if k.Type == APIKey && k.ExpiresAt.IsZero() { - return false - } - return k.ExpiresAt.UTC().Before(time.Now().UTC()) -} - -// KeyRepository specifies Key persistence API. -type KeyRepository interface { - // Save persists the Key. A non-nil error is returned to indicate - // operation failure - Save(context.Context, Key) (string, error) - - // Retrieve retrieves Key by its unique identifier. - Retrieve(context.Context, string, string) (Key, error) - - // Remove removes Key with provided ID. - Remove(context.Context, string, string) error -} diff --git a/auth/keys_test.go b/auth/keys_test.go deleted file mode 100644 index 916cc07fe04..00000000000 --- a/auth/keys_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth_test - -import ( - "fmt" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/stretchr/testify/assert" -) - -func TestExpired(t *testing.T) { - exp := time.Now().Add(5 * time.Minute) - exp1 := time.Now() - cases := []struct { - desc string - key auth.Key - expired bool - }{ - { - desc: "not expired key", - key: auth.Key{ - IssuedAt: time.Now(), - ExpiresAt: exp, - }, - expired: false, - }, - { - desc: "expired key", - key: auth.Key{ - IssuedAt: time.Now().UTC().Add(2 * time.Minute), - ExpiresAt: exp1, - }, - expired: true, - }, - { - desc: "user key with no expiration date", - key: auth.Key{ - IssuedAt: time.Now(), - }, - expired: true, - }, - { - desc: "API key with no expiration date", - key: auth.Key{ - IssuedAt: time.Now(), - Type: auth.APIKey, - }, - expired: false, - }, - } - - for _, tc := range cases { - res := tc.key.Expired() - assert.Equal(t, tc.expired, res, fmt.Sprintf("%s: expected %t got %t\n", tc.desc, tc.expired, res)) - } -} diff --git a/auth/mocks/groups.go b/auth/mocks/groups.go deleted file mode 100644 index 4f2de21636f..00000000000 --- a/auth/mocks/groups.go +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package mocks - -import ( - "context" - "fmt" - "strings" - "sync" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" -) - -var _ auth.GroupRepository = (*groupRepositoryMock)(nil) - -type groupRepositoryMock struct { - mu sync.Mutex - // Map of groups, group id as a key. - // groups map[GroupID]auth.Group - groups map[string]auth.Group - // Map of groups with group id as key that are - // children (i.e. has same parent id) is element - // in children's map where parent id is key. - // children map[ParentID]map[GroupID]auth.Group - children map[string]map[string]auth.Group - // Map of parents' id with child group id as key. - // Each child has one parent. - // parents map[ChildID]ParentID - parents map[string]string - // Map of groups (with group id as key) which - // represent memberships is element in - // memberships' map where member id is a key. - // memberships map[MemberID]map[GroupID]auth.Group - memberships map[string]map[string]auth.Group - // Map of group members where member id is a key - // is an element in the map members where group id is a key. - // members map[type][GroupID]map[MemberID]MemberID - members map[string]map[string]map[string]string -} - -// NewGroupRepository creates in-memory user repository -func NewGroupRepository() auth.GroupRepository { - return &groupRepositoryMock{ - groups: make(map[string]auth.Group), - children: make(map[string]map[string]auth.Group), - parents: make(map[string]string), - memberships: make(map[string]map[string]auth.Group), - members: make(map[string]map[string]map[string]string), - } -} - -func (grm *groupRepositoryMock) Save(ctx context.Context, group auth.Group) (auth.Group, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - if _, ok := grm.groups[group.ID]; ok { - return auth.Group{}, errors.ErrConflict - } - path := group.ID - - if group.ParentID != "" { - parent, ok := grm.groups[group.ParentID] - if !ok { - return auth.Group{}, errors.ErrCreateEntity - } - if _, ok := grm.children[group.ParentID]; !ok { - grm.children[group.ParentID] = make(map[string]auth.Group) - } - grm.children[group.ParentID][group.ID] = group - grm.parents[group.ID] = group.ParentID - path = fmt.Sprintf("%s.%s", parent.Path, path) - } - - group.Path = path - group.Level = len(strings.Split(path, ".")) - - grm.groups[group.ID] = group - return group, nil -} - -func (grm *groupRepositoryMock) Update(ctx context.Context, group auth.Group) (auth.Group, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - up, ok := grm.groups[group.ID] - if !ok { - return auth.Group{}, errors.ErrNotFound - } - up.Name = group.Name - up.Description = group.Description - up.Metadata = group.Metadata - up.UpdatedAt = time.Now() - - grm.groups[group.ID] = up - return up, nil -} - -func (grm *groupRepositoryMock) Delete(ctx context.Context, id string) error { - grm.mu.Lock() - defer grm.mu.Unlock() - if _, ok := grm.groups[id]; !ok { - return errors.ErrNotFound - } - - if len(grm.members[id]) > 0 { - return auth.ErrGroupNotEmpty - } - - // This is not quite exact, it should go in depth - for _, ch := range grm.children[id] { - if len(grm.members[ch.ID]) > 0 { - return auth.ErrGroupNotEmpty - } - } - - // This is not quite exact, it should go in depth - delete(grm.groups, id) - for _, ch := range grm.children[id] { - delete(grm.members, ch.ID) - } - - delete(grm.children, id) - - return nil - -} - -func (grm *groupRepositoryMock) RetrieveByID(ctx context.Context, id string) (auth.Group, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - - val, ok := grm.groups[id] - if !ok { - return auth.Group{}, errors.ErrNotFound - } - return val, nil -} - -func (grm *groupRepositoryMock) RetrieveAll(ctx context.Context, pm auth.PageMetadata) (auth.GroupPage, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - var items []auth.Group - for _, g := range grm.groups { - items = append(items, g) - } - return auth.GroupPage{ - Groups: items, - PageMetadata: auth.PageMetadata{ - Total: uint64(len(items)), - }, - }, nil -} - -func (grm *groupRepositoryMock) Unassign(ctx context.Context, groupID string, memberIDs ...string) error { - grm.mu.Lock() - defer grm.mu.Unlock() - if _, ok := grm.groups[groupID]; !ok { - return errors.ErrNotFound - } - for _, memberID := range memberIDs { - for typ, m := range grm.members[groupID] { - _, ok := m[memberID] - if !ok { - return errors.ErrNotFound - } - delete(grm.members[groupID][typ], memberID) - delete(grm.memberships[memberID], groupID) - } - - } - return nil -} - -func (grm *groupRepositoryMock) Assign(ctx context.Context, groupID, groupType string, memberIDs ...string) error { - grm.mu.Lock() - defer grm.mu.Unlock() - if _, ok := grm.groups[groupID]; !ok { - return errors.ErrNotFound - } - - if _, ok := grm.members[groupID]; !ok { - grm.members[groupID] = make(map[string]map[string]string) - } - - for _, memberID := range memberIDs { - if _, ok := grm.members[groupID][groupType]; !ok { - grm.members[groupID][groupType] = make(map[string]string) - } - if _, ok := grm.memberships[memberID]; !ok { - grm.memberships[memberID] = make(map[string]auth.Group) - } - - grm.members[groupID][groupType][memberID] = memberID - grm.memberships[memberID][groupID] = grm.groups[groupID] - } - return nil - -} - -func (grm *groupRepositoryMock) Memberships(ctx context.Context, memberID string, pm auth.PageMetadata) (auth.GroupPage, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - var items []auth.Group - - first := uint64(pm.Offset) - last := first + uint64(pm.Limit) - - i := uint64(0) - for _, g := range grm.memberships[memberID] { - if i >= first && i < last { - items = append(items, g) - } - i++ - } - - return auth.GroupPage{ - Groups: items, - PageMetadata: auth.PageMetadata{ - Limit: pm.Limit, - Offset: pm.Offset, - Total: uint64(len(items)), - }, - }, nil -} - -func (grm *groupRepositoryMock) Members(ctx context.Context, groupID, groupType string, pm auth.PageMetadata) (auth.MemberPage, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - var items []auth.Member - members, ok := grm.members[groupID][groupType] - if !ok { - return auth.MemberPage{}, errors.ErrNotFound - } - - first := uint64(pm.Offset) - last := first + uint64(pm.Limit) - - i := uint64(0) - for _, g := range members { - if i >= first && i < last { - items = append(items, auth.Member{ID: g, Type: groupType}) - } - i++ - } - return auth.MemberPage{ - Members: items, - PageMetadata: auth.PageMetadata{ - Total: uint64(len(items)), - }, - }, nil -} - -func (grm *groupRepositoryMock) RetrieveAllParents(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - if groupID == "" { - return auth.GroupPage{}, nil - } - - group, ok := grm.groups[groupID] - if !ok { - return auth.GroupPage{}, errors.ErrNotFound - } - - groups := make([]auth.Group, 0) - groups, err := grm.getParents(groups, group) - if err != nil { - return auth.GroupPage{}, err - } - - return auth.GroupPage{ - Groups: groups, - PageMetadata: auth.PageMetadata{ - Total: uint64(len(groups)), - }, - }, nil -} - -func (grm *groupRepositoryMock) getParents(groups []auth.Group, group auth.Group) ([]auth.Group, error) { - groups = append(groups, group) - parentID, ok := grm.parents[group.ID] - if !ok && parentID == "" { - return groups, nil - } - parent, ok := grm.groups[parentID] - if !ok { - panic(fmt.Sprintf("parent with id: %s not found", parentID)) - } - return grm.getParents(groups, parent) -} - -func (grm *groupRepositoryMock) RetrieveAllChildren(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - grm.mu.Lock() - defer grm.mu.Unlock() - group, ok := grm.groups[groupID] - if !ok { - return auth.GroupPage{}, nil - } - - groups := make([]auth.Group, 0) - groups = append(groups, group) - for ch := range grm.parents { - g, ok := grm.groups[ch] - if !ok { - panic(fmt.Sprintf("child with id %s not found", ch)) - } - groups = append(groups, g) - } - - return auth.GroupPage{ - Groups: groups, - PageMetadata: auth.PageMetadata{ - Total: uint64(len(groups)), - Offset: pm.Offset, - Limit: pm.Limit, - }, - }, nil -} diff --git a/auth/mocks/keys.go b/auth/mocks/keys.go deleted file mode 100644 index cbf23598a0c..00000000000 --- a/auth/mocks/keys.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package mocks - -import ( - "context" - "sync" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" -) - -var _ auth.KeyRepository = (*keyRepositoryMock)(nil) - -type keyRepositoryMock struct { - mu sync.Mutex - keys map[string]auth.Key -} - -// NewKeyRepository creates in-memory user repository -func NewKeyRepository() auth.KeyRepository { - return &keyRepositoryMock{ - keys: make(map[string]auth.Key), - } -} - -func (krm *keyRepositoryMock) Save(ctx context.Context, key auth.Key) (string, error) { - krm.mu.Lock() - defer krm.mu.Unlock() - - if _, ok := krm.keys[key.ID]; ok { - return "", errors.ErrConflict - } - - krm.keys[key.ID] = key - return key.ID, nil -} -func (krm *keyRepositoryMock) Retrieve(ctx context.Context, issuerID, id string) (auth.Key, error) { - krm.mu.Lock() - defer krm.mu.Unlock() - - if key, ok := krm.keys[id]; ok && key.IssuerID == issuerID { - return key, nil - } - - return auth.Key{}, errors.ErrNotFound -} -func (krm *keyRepositoryMock) Remove(ctx context.Context, issuerID, id string) error { - krm.mu.Lock() - defer krm.mu.Unlock() - if key, ok := krm.keys[id]; ok && key.IssuerID == issuerID { - delete(krm.keys, id) - } - return nil -} diff --git a/auth/mocks/policies.go b/auth/mocks/policies.go deleted file mode 100644 index 6213c03b9a8..00000000000 --- a/auth/mocks/policies.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package mocks - -import ( - "context" - "sync" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" - acl "github.com/ory/keto/proto/ory/keto/acl/v1alpha1" -) - -type MockSubjectSet struct { - Object string - Relation string -} - -type policyAgentMock struct { - mu sync.Mutex - // authzDb stores 'subject' as a key, and subject policies as a value. - authzDB map[string][]MockSubjectSet -} - -// NewKetoMock returns a mock service for Keto. -// This mock is not implemented yet. -func NewKetoMock(db map[string][]MockSubjectSet) auth.PolicyAgent { - return &policyAgentMock{authzDB: db} -} - -func (pa *policyAgentMock) CheckPolicy(ctx context.Context, pr auth.PolicyReq) error { - pa.mu.Lock() - defer pa.mu.Unlock() - - ssList := pa.authzDB[pr.Subject] - for _, ss := range ssList { - if ss.Object == pr.Object && ss.Relation == pr.Relation { - return nil - } - } - return errors.ErrAuthorization -} - -func (pa *policyAgentMock) AddPolicy(ctx context.Context, pr auth.PolicyReq) error { - pa.mu.Lock() - defer pa.mu.Unlock() - - pa.authzDB[pr.Subject] = append(pa.authzDB[pr.Subject], MockSubjectSet{Object: pr.Object, Relation: pr.Relation}) - return nil -} - -func (pa *policyAgentMock) DeletePolicy(ctx context.Context, pr auth.PolicyReq) error { - pa.mu.Lock() - defer pa.mu.Unlock() - - ssList := pa.authzDB[pr.Subject] - for k, ss := range ssList { - if ss.Object == pr.Object && ss.Relation == pr.Relation { - ssList[k] = MockSubjectSet{} - } - } - return nil -} - -func (pa *policyAgentMock) RetrievePolicies(ctx context.Context, pr auth.PolicyReq) ([]*acl.RelationTuple, error) { - pa.mu.Lock() - defer pa.mu.Unlock() - - ssList := pa.authzDB[pr.Subject] - tuple := []*acl.RelationTuple{} - for _, ss := range ssList { - if ss.Relation == pr.Relation { - tuple = append(tuple, &acl.RelationTuple{Object: ss.Object, Relation: ss.Relation}) - } - } - return tuple, nil -} diff --git a/auth/policies.go b/auth/policies.go deleted file mode 100644 index 4a7ab1e53cd..00000000000 --- a/auth/policies.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth - -import ( - "context" - - acl "github.com/ory/keto/proto/ory/keto/acl/v1alpha1" -) - -// PolicyReq represents an argument struct for making a policy related -// function calls. -type PolicyReq struct { - Subject string - Object string - Relation string -} - -type PolicyPage struct { - Policies []string -} - -// Authz represents a authorization service. It exposes -// functionalities through `auth` to perform authorization. -type Authz interface { - // Authorize checks authorization of the given `subject`. Basically, - // Authorize verifies that Is `subject` allowed to `relation` on - // `object`. Authorize returns a non-nil error if the subject has - // no relation on the object (which simply means the operation is - // denied). - Authorize(ctx context.Context, pr PolicyReq) error - - // AddPolicy creates a policy for the given subject, so that, after - // AddPolicy, `subject` has a `relation` on `object`. Returns a non-nil - // error in case of failures. - AddPolicy(ctx context.Context, pr PolicyReq) error - - // AddPolicies adds new policies for given subjects. This method is - // only allowed to use as an admin. - AddPolicies(ctx context.Context, token, object string, subjectIDs, relations []string) error - - // DeletePolicy removes a policy. - DeletePolicy(ctx context.Context, pr PolicyReq) error - - // DeletePolicies deletes policies for given subjects. This method is - // only allowed to use as an admin. - DeletePolicies(ctx context.Context, token, object string, subjectIDs, relations []string) error - - // ListPolicies lists policies based on the given PolicyReq structure. - ListPolicies(ctx context.Context, pr PolicyReq) (PolicyPage, error) -} - -// PolicyAgent facilitates the communication to authorization -// services and implements Authz functionalities for certain -// authorization services (e.g. ORY Keto). -type PolicyAgent interface { - // CheckPolicy checks if the subject has a relation on the object. - // It returns a non-nil error if the subject has no relation on - // the object (which simply means the operation is denied). - CheckPolicy(ctx context.Context, pr PolicyReq) error - - // AddPolicy creates a policy for the given subject, so that, after - // AddPolicy, `subject` has a `relation` on `object`. Returns a non-nil - // error in case of failures. - AddPolicy(ctx context.Context, pr PolicyReq) error - - // DeletePolicy removes a policy. - DeletePolicy(ctx context.Context, pr PolicyReq) error - - RetrievePolicies(ctx context.Context, pr PolicyReq) ([]*acl.RelationTuple, error) -} diff --git a/auth/postgres/doc.go b/auth/postgres/doc.go deleted file mode 100644 index 6bce8d090b3..00000000000 --- a/auth/postgres/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package postgres contains Key repository implementations using -// PostgreSQL as the underlying database. -package postgres diff --git a/auth/postgres/groups.go b/auth/postgres/groups.go deleted file mode 100644 index 79ba3d01f6a..00000000000 --- a/auth/postgres/groups.go +++ /dev/null @@ -1,744 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import ( - "context" - "database/sql" - "database/sql/driver" - "encoding/json" - "fmt" - "time" - - "github.com/gofrs/uuid" - "github.com/jackc/pgerrcode" - "github.com/jackc/pgx/v5/pgconn" - "github.com/jmoiron/sqlx" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" -) - -var ( - errStringToUUID = errors.New("error converting string to uuid") - errGetTotal = errors.New("failed to get total number of groups") - errCreateMetadataQuery = errors.New("failed to create query for metadata") - groupIDFkeyy = "group_relations_group_id_fkey" -) - -var _ auth.GroupRepository = (*groupRepository)(nil) - -type groupRepository struct { - db Database -} - -// NewGroupRepo instantiates a PostgreSQL implementation of group -// repository. -func NewGroupRepo(db Database) auth.GroupRepository { - return &groupRepository{ - db: db, - } -} - -func (gr groupRepository) Save(ctx context.Context, g auth.Group) (auth.Group, error) { - // For root group path is initialized with id - q := `INSERT INTO groups (name, description, id, path, owner_id, metadata, created_at, updated_at) - VALUES (:name, :description, :id, :id, :owner_id, :metadata, :created_at, :updated_at) - RETURNING id, name, owner_id, parent_id, description, metadata, path, nlevel(path) as level, created_at, updated_at` - if g.ParentID != "" { - // Path is constructed in insert_group_tr - init.go - q = `INSERT INTO groups (name, description, id, owner_id, parent_id, metadata, created_at, updated_at) - VALUES ( :name, :description, :id, :owner_id, :parent_id, :metadata, :created_at, :updated_at) - RETURNING id, name, owner_id, parent_id, description, metadata, path, nlevel(path) as level, created_at, updated_at` - } - - dbg, err := toDBGroup(g) - if err != nil { - return auth.Group{}, err - } - - row, err := gr.db.NamedQueryContext(ctx, q, dbg) - if err != nil { - pgErr, ok := err.(*pgconn.PgError) - if ok { - switch pgErr.Code { - case pgerrcode.InvalidTextRepresentation: - return auth.Group{}, errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.ForeignKeyViolation: - return auth.Group{}, errors.Wrap(errors.ErrCreateEntity, err) - case pgerrcode.UniqueViolation: - return auth.Group{}, errors.Wrap(errors.ErrConflict, err) - case pgerrcode.StringDataRightTruncationDataException: - return auth.Group{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - } - - return auth.Group{}, errors.Wrap(errors.ErrCreateEntity, err) - } - - defer row.Close() - row.Next() - dbg = dbGroup{} - if err := row.StructScan(&dbg); err != nil { - return auth.Group{}, err - } - - return toGroup(dbg) -} - -func (gr groupRepository) Update(ctx context.Context, g auth.Group) (auth.Group, error) { - q := `UPDATE groups SET name = :name, description = :description, metadata = :metadata, updated_at = :updated_at WHERE id = :id - RETURNING id, name, owner_id, parent_id, description, metadata, path, nlevel(path) as level, created_at, updated_at` - - dbu, err := toDBGroup(g) - if err != nil { - return auth.Group{}, errors.Wrap(errors.ErrUpdateEntity, err) - } - - row, err := gr.db.NamedQueryContext(ctx, q, dbu) - if err != nil { - pgErr, ok := err.(*pgconn.PgError) - if ok { - switch pgErr.Code { - case pgerrcode.InvalidTextRepresentation: - return auth.Group{}, errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.UniqueViolation: - return auth.Group{}, errors.Wrap(errors.ErrConflict, err) - case pgerrcode.StringDataRightTruncationDataException: - return auth.Group{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - } - return auth.Group{}, errors.Wrap(errors.ErrUpdateEntity, err) - } - - defer row.Close() - row.Next() - dbu = dbGroup{} - if err := row.StructScan(&dbu); err != nil { - return g, errors.Wrap(errors.ErrUpdateEntity, err) - } - - return toGroup(dbu) -} - -func (gr groupRepository) Delete(ctx context.Context, groupID string) error { - qd := `DELETE FROM groups WHERE id = :id` - group := auth.Group{ - ID: groupID, - } - dbg, err := toDBGroup(group) - if err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - res, err := gr.db.NamedExecContext(ctx, qd, dbg) - if err != nil { - pqErr, ok := err.(*pgconn.PgError) - if ok { - switch pqErr.Code { - case pgerrcode.InvalidTextRepresentation: - return errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.ForeignKeyViolation: - switch pqErr.ConstraintName { - case groupIDFkeyy: - return errors.Wrap(auth.ErrGroupNotEmpty, err) - } - return errors.Wrap(errors.ErrConflict, err) - } - } - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - cnt, err := res.RowsAffected() - if err != nil { - return errors.Wrap(errors.ErrRemoveEntity, err) - } - - if cnt != 1 { - return errors.Wrap(errors.ErrRemoveEntity, err) - } - return nil -} - -func (gr groupRepository) RetrieveByID(ctx context.Context, id string) (auth.Group, error) { - dbu := dbGroup{ - ID: id, - } - q := `SELECT id, name, owner_id, parent_id, description, metadata, path, nlevel(path) as level, created_at, updated_at FROM groups WHERE id = $1` - if err := gr.db.QueryRowxContext(ctx, q, id).StructScan(&dbu); err != nil { - if err == sql.ErrNoRows { - return auth.Group{}, errors.Wrap(errors.ErrNotFound, err) - - } - return auth.Group{}, errors.Wrap(errors.ErrViewEntity, err) - } - return toGroup(dbu) -} - -func (gr groupRepository) RetrieveAll(ctx context.Context, pm auth.PageMetadata) (auth.GroupPage, error) { - _, metaQuery, err := getGroupsMetadataQuery("groups", pm.Metadata) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveAll, err) - } - - var mq string - if metaQuery != "" { - mq = fmt.Sprintf(" AND %s", metaQuery) - } - - q := fmt.Sprintf(`SELECT id, owner_id, parent_id, name, description, metadata, path, nlevel(path) as level, created_at, updated_at FROM groups - WHERE nlevel(path) <= :level %s ORDER BY path`, mq) - - dbPage, err := toDBGroupPage("", "", pm) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveAll, err) - } - - rows, err := gr.db.NamedQueryContext(ctx, q, dbPage) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveAll, err) - } - defer rows.Close() - - items, err := gr.processRows(rows) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveAll, err) - } - - cq := "SELECT COUNT(*) FROM groups" - if metaQuery != "" { - cq = fmt.Sprintf(" %s WHERE %s", cq, metaQuery) - } - - total, err := total(ctx, gr.db, cq, dbPage) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveAll, err) - } - - page := auth.GroupPage{ - Groups: items, - PageMetadata: auth.PageMetadata{ - Total: total, - Size: uint64(len(items)), - }, - } - - return page, nil -} - -func (gr groupRepository) RetrieveAllParents(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - q := `SELECT g.id, g.name, g.owner_id, g.parent_id, g.description, g.metadata, g.path, nlevel(g.path) as level, g.created_at, g.updated_at - FROM groups parent, groups g - WHERE parent.id = :id AND g.path @> parent.path AND nlevel(parent.path) - nlevel(g.path) <= :level` - cq := `SELECT COUNT(*) FROM groups parent, groups g WHERE parent.id = :id AND g.path @> parent.path` - - gp, err := gr.retrieve(ctx, groupID, q, cq, pm) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveParents, err) - } - return gp, nil -} - -func (gr groupRepository) RetrieveAllChildren(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - q := `SELECT g.id, g.name, g.owner_id, g.parent_id, g.description, g.metadata, g.path, nlevel(g.path) as level, g.created_at, g.updated_at - FROM groups parent, groups g - WHERE parent.id = :id AND g.path <@ parent.path AND nlevel(g.path) - nlevel(parent.path) < :level` - - cq := `SELECT COUNT(*) FROM groups parent, groups g WHERE parent.id = :id AND g.path <@ parent.path ` - gp, err := gr.retrieve(ctx, groupID, q, cq, pm) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveChildren, err) - } - return gp, nil -} - -func (gr groupRepository) retrieve(ctx context.Context, groupID, retQuery, cntQuery string, pm auth.PageMetadata) (auth.GroupPage, error) { - if groupID == "" { - return auth.GroupPage{}, nil - } - _, mq, err := getGroupsMetadataQuery("g", pm.Metadata) - if err != nil { - return auth.GroupPage{}, err - } - if mq != "" { - mq = fmt.Sprintf("AND %s", mq) - } - - retQuery = fmt.Sprintf(`%s %s`, retQuery, mq) - cntQuery = fmt.Sprintf(`%s %s`, cntQuery, mq) - - dbPage, err := toDBGroupPage(groupID, "", pm) - if err != nil { - return auth.GroupPage{}, err - } - - rows, err := gr.db.NamedQueryContext(ctx, retQuery, dbPage) - if err != nil { - return auth.GroupPage{}, err - } - defer rows.Close() - - items, err := gr.processRows(rows) - if err != nil { - return auth.GroupPage{}, err - } - - total, err := total(ctx, gr.db, cntQuery, dbPage) - if err != nil { - return auth.GroupPage{}, err - } - - page := auth.GroupPage{ - Groups: items, - PageMetadata: auth.PageMetadata{ - Level: pm.Level, - Total: total, - Size: uint64(len(items)), - }, - } - - return page, nil - -} - -func (gr groupRepository) Members(ctx context.Context, groupID, groupType string, pm auth.PageMetadata) (auth.MemberPage, error) { - _, mq, err := getGroupsMetadataQuery("groups", pm.Metadata) - if err != nil { - return auth.MemberPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembers, err) - } - - q := fmt.Sprintf(`SELECT gr.member_id, gr.group_id, gr.type, gr.created_at, gr.updated_at FROM group_relations gr - WHERE gr.group_id = :group_id AND gr.type = :type %s`, mq) - - if groupType == "" { - q = fmt.Sprintf(`SELECT gr.member_id, gr.group_id, gr.type, gr.created_at, gr.updated_at FROM group_relations gr - WHERE gr.group_id = :group_id %s`, mq) - } - - params, err := toDBMemberPage("", groupID, groupType, pm) - if err != nil { - return auth.MemberPage{}, err - } - - rows, err := gr.db.NamedQueryContext(ctx, q, params) - if err != nil { - return auth.MemberPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembers, err) - } - defer rows.Close() - - var items []auth.Member - for rows.Next() { - member := dbMember{} - if err := rows.StructScan(&member); err != nil { - return auth.MemberPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembers, err) - } - - if err != nil { - return auth.MemberPage{}, err - } - - items = append(items, auth.Member{ID: member.MemberID, Type: member.Type}) - } - - cq := fmt.Sprintf(`SELECT COUNT(*) FROM groups g, group_relations gr - WHERE gr.group_id = :group_id AND gr.group_id = g.id AND gr.type = :type %s;`, mq) - - total, err := total(ctx, gr.db, cq, params) - if err != nil { - return auth.MemberPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembers, err) - } - - page := auth.MemberPage{ - Members: items, - PageMetadata: auth.PageMetadata{ - Total: total, - Offset: pm.Offset, - Limit: pm.Limit, - Size: uint64(len(items)), - }, - } - - return page, nil -} - -func (gr groupRepository) Memberships(ctx context.Context, memberID string, pm auth.PageMetadata) (auth.GroupPage, error) { - _, mq, err := getGroupsMetadataQuery("groups", pm.Metadata) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembership, err) - } - - if mq != "" { - mq = fmt.Sprintf("AND %s", mq) - } - q := fmt.Sprintf(`SELECT g.id, g.owner_id, g.parent_id, g.name, g.description, g.metadata - FROM group_relations gr, groups g - WHERE gr.group_id = g.id and gr.member_id = :member_id - %s ORDER BY id LIMIT :limit OFFSET :offset;`, mq) - - params, err := toDBMemberPage(memberID, "", "", pm) - if err != nil { - return auth.GroupPage{}, err - } - - rows, err := gr.db.NamedQueryContext(ctx, q, params) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembership, err) - } - defer rows.Close() - - var items []auth.Group - for rows.Next() { - dbg := dbGroup{} - if err := rows.StructScan(&dbg); err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembership, err) - } - gr, err := toGroup(dbg) - if err != nil { - return auth.GroupPage{}, err - } - items = append(items, gr) - } - - cq := fmt.Sprintf(`SELECT COUNT(*) FROM group_relations gr, groups g - WHERE gr.group_id = g.id and gr.member_id = :member_id %s `, mq) - - total, err := total(ctx, gr.db, cq, params) - if err != nil { - return auth.GroupPage{}, errors.Wrap(auth.ErrFailedToRetrieveMembership, err) - } - - page := auth.GroupPage{ - Groups: items, - PageMetadata: auth.PageMetadata{ - Total: total, - Offset: pm.Offset, - Limit: pm.Limit, - Size: uint64(len(items)), - }, - } - - return page, nil -} - -func (gr groupRepository) Assign(ctx context.Context, groupID, groupType string, ids ...string) error { - tx, err := gr.db.BeginTxx(ctx, nil) - if err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - - qIns := `INSERT INTO group_relations (group_id, member_id, type, created_at, updated_at) - VALUES(:group_id, :member_id, :type, :created_at, :updated_at)` - - for _, id := range ids { - dbg, err := toDBGroupRelation(id, groupID, groupType) - if err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - created := time.Now() - dbg.CreatedAt = created - dbg.UpdatedAt = created - - if _, err := tx.NamedExecContext(ctx, qIns, dbg); err != nil { - tx.Rollback() - pgErr, ok := err.(*pgconn.PgError) - if ok { - switch pgErr.Code { - case pgerrcode.InvalidTextRepresentation: - return errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.ForeignKeyViolation: - return errors.Wrap(errors.ErrConflict, errors.New(pgErr.Detail)) - case pgerrcode.UniqueViolation: - return errors.Wrap(auth.ErrMemberAlreadyAssigned, errors.New(pgErr.Detail)) - } - } - - return errors.Wrap(auth.ErrAssignToGroup, err) - } - } - - if err = tx.Commit(); err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - - return nil -} - -func (gr groupRepository) Unassign(ctx context.Context, groupID string, ids ...string) error { - tx, err := gr.db.BeginTxx(ctx, nil) - if err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - - qDel := `DELETE from group_relations WHERE group_id = :group_id AND member_id = :member_id` - - for _, id := range ids { - dbg, err := toDBGroupRelation(id, groupID, "") - if err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - - if _, err := tx.NamedExecContext(ctx, qDel, dbg); err != nil { - tx.Rollback() - pgErr, ok := err.(*pgconn.PgError) - if ok { - switch pgErr.Code { - case pgerrcode.InvalidTextRepresentation: - return errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.UniqueViolation: - return errors.Wrap(errors.ErrConflict, err) - } - } - - return errors.Wrap(auth.ErrAssignToGroup, err) - } - } - - if err = tx.Commit(); err != nil { - return errors.Wrap(auth.ErrAssignToGroup, err) - } - - return nil -} - -type dbMember struct { - MemberID string `db:"member_id"` - GroupID string `db:"group_id"` - Type string `db:"type"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` -} - -type dbGroup struct { - ID string `db:"id"` - ParentID sql.NullString `db:"parent_id"` - OwnerID uuid.NullUUID `db:"owner_id"` - Name string `db:"name"` - Description string `db:"description"` - Metadata dbMetadata `db:"metadata"` - Level int `db:"level"` - Path string `db:"path"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` -} - -type dbGroupPage struct { - ID string `db:"id"` - ParentID string `db:"parent_id"` - OwnerID uuid.NullUUID `db:"owner_id"` - Metadata dbMetadata `db:"metadata"` - Path string `db:"path"` - Level uint64 `db:"level"` - Total uint64 `db:"total"` - Limit uint64 `db:"limit"` - Offset uint64 `db:"offset"` -} - -type dbMemberPage struct { - GroupID string `db:"group_id"` - MemberID string `db:"member_id"` - Type string `db:"type"` - Metadata dbMetadata `db:"metadata"` - Limit uint64 `db:"limit"` - Offset uint64 `db:"offset"` - Size uint64 -} - -func toUUID(id string) (uuid.NullUUID, error) { - var uid uuid.NullUUID - if id == "" { - return uuid.NullUUID{UUID: uuid.Nil, Valid: false}, nil - } - err := uid.Scan(id) - return uid, err -} - -func toString(id uuid.NullUUID) (string, error) { - if id.Valid { - return id.UUID.String(), nil - } - if id.UUID == uuid.Nil { - return "", nil - } - return "", errStringToUUID -} - -func toDBGroup(g auth.Group) (dbGroup, error) { - ownerID, err := toUUID(g.OwnerID) - if err != nil { - return dbGroup{}, err - } - - var parentID sql.NullString - if g.ParentID != "" { - parentID = sql.NullString{String: g.ParentID, Valid: true} - } - - meta := dbMetadata(g.Metadata) - - return dbGroup{ - ID: g.ID, - Name: g.Name, - ParentID: parentID, - OwnerID: ownerID, - Description: g.Description, - Metadata: meta, - Path: g.Path, - CreatedAt: g.CreatedAt, - UpdatedAt: g.UpdatedAt, - }, nil -} - -func toDBGroupPage(id, path string, pm auth.PageMetadata) (dbGroupPage, error) { - level := auth.MaxLevel - if pm.Level < auth.MaxLevel { - level = pm.Level - } - return dbGroupPage{ - Metadata: dbMetadata(pm.Metadata), - ID: id, - Path: path, - Level: level, - Total: pm.Total, - Offset: pm.Offset, - Limit: pm.Limit, - }, nil -} - -func toDBMemberPage(memberID, groupID, groupType string, pm auth.PageMetadata) (dbMemberPage, error) { - return dbMemberPage{ - GroupID: groupID, - MemberID: memberID, - Type: groupType, - Metadata: dbMetadata(pm.Metadata), - Offset: pm.Offset, - Limit: pm.Limit, - }, nil -} - -func toGroup(dbu dbGroup) (auth.Group, error) { - ownerID, err := toString(dbu.OwnerID) - if err != nil { - return auth.Group{}, err - } - - return auth.Group{ - ID: dbu.ID, - Name: dbu.Name, - ParentID: dbu.ParentID.String, - OwnerID: ownerID, - Description: dbu.Description, - Metadata: auth.GroupMetadata(dbu.Metadata), - Level: dbu.Level, - Path: dbu.Path, - UpdatedAt: dbu.UpdatedAt, - CreatedAt: dbu.CreatedAt, - }, nil -} - -type dbGroupRelation struct { - GroupID sql.NullString `db:"group_id"` - MemberID sql.NullString `db:"member_id"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` - Type string `db:"type"` -} - -func toDBGroupRelation(memberID, groupID, groupType string) (dbGroupRelation, error) { - var grID sql.NullString - if groupID != "" { - grID = sql.NullString{String: groupID, Valid: true} - } - - var mID sql.NullString - if memberID != "" { - mID = sql.NullString{String: memberID, Valid: true} - } - - return dbGroupRelation{ - GroupID: grID, - MemberID: mID, - Type: groupType, - }, nil -} - -func getGroupsMetadataQuery(db string, m auth.GroupMetadata) (mb []byte, mq string, err error) { - if len(m) > 0 { - mq = `metadata @> :metadata` - if db != "" { - mq = db + "." + mq - } - - b, err := json.Marshal(m) - if err != nil { - return nil, "", errors.Wrap(err, errCreateMetadataQuery) - } - mb = b - } - return mb, mq, nil -} - -func (gr groupRepository) processRows(rows *sqlx.Rows) ([]auth.Group, error) { - var items []auth.Group - for rows.Next() { - dbg := dbGroup{} - if err := rows.StructScan(&dbg); err != nil { - return items, err - } - group, err := toGroup(dbg) - if err != nil { - return items, err - } - items = append(items, group) - } - return items, nil -} - -func total(ctx context.Context, db Database, query string, params interface{}) (uint64, error) { - rows, err := db.NamedQueryContext(ctx, query, params) - if err != nil { - return 0, errors.Wrap(errGetTotal, err) - } - defer rows.Close() - total := uint64(0) - if rows.Next() { - if err := rows.Scan(&total); err != nil { - return 0, errors.Wrap(errGetTotal, err) - } - } - return total, nil -} - -// dbMetadata type for handling metadata properly in database/sql -type dbMetadata map[string]interface{} - -// Scan - Implement the database/sql scanner interface -func (m *dbMetadata) Scan(value interface{}) error { - if value == nil { - return nil - } - - b, ok := value.([]byte) - if !ok { - return errors.ErrScanMetadata - } - - if err := json.Unmarshal(b, m); err != nil { - return err - } - - return nil -} - -// Value Implements valuer -func (m dbMetadata) Value() (driver.Value, error) { - if len(m) == 0 { - return nil, nil - } - - b, err := json.Marshal(m) - if err != nil { - return nil, err - } - return b, err -} diff --git a/auth/postgres/groups_test.go b/auth/postgres/groups_test.go deleted file mode 100644 index 39cf4a5cbb1..00000000000 --- a/auth/postgres/groups_test.go +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres_test - -import ( - "context" - "fmt" - "strings" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/auth/postgres" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - maxNameSize = 254 - maxDescSize = 1024 - groupName = "Mainflux" - description = "description" -) - -var ( - invalidName = strings.Repeat("m", maxNameSize+1) - invalidDesc = strings.Repeat("m", maxDescSize+1) - metadata = auth.GroupMetadata{ - "admin": "true", - } -) - -func generateGroupID(t *testing.T) string { - grpID, err := ulidProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - return grpID -} - -func TestGroupSave(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - usrID, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - wrongID, err := ulidProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - grpID := generateGroupID(t) - - cases := []struct { - desc string - group auth.Group - err error - }{ - { - desc: "create new group", - group: auth.Group{ - ID: grpID, - OwnerID: usrID, - Name: groupName, - }, - err: nil, - }, - { - desc: "create new group with existing name", - group: auth.Group{ - ID: grpID, - OwnerID: usrID, - Name: groupName, - }, - err: errors.ErrConflict, - }, - { - desc: "create group with invalid name", - group: auth.Group{ - ID: generateGroupID(t), - OwnerID: usrID, - Name: invalidName, - }, - err: errors.ErrMalformedEntity, - }, - { - desc: "create group with invalid description", - group: auth.Group{ - ID: generateGroupID(t), - OwnerID: usrID, - Name: groupName, - Description: invalidDesc, - }, - err: errors.ErrMalformedEntity, - }, - { - desc: "create group with parent", - group: auth.Group{ - ID: generateGroupID(t), - ParentID: grpID, - OwnerID: usrID, - Name: "withParent", - }, - err: nil, - }, - { - desc: "create group with parent and existing name", - group: auth.Group{ - ID: generateGroupID(t), - ParentID: grpID, - OwnerID: usrID, - Name: groupName, - }, - err: nil, - }, - { - desc: "create group with wrong parent", - group: auth.Group{ - ID: generateGroupID(t), - ParentID: wrongID, - OwnerID: usrID, - Name: "wrongParent", - }, - err: errors.ErrCreateEntity, - }, - } - - for _, tc := range cases { - _, err := groupRepo.Save(context.Background(), tc.group) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } - -} - -func TestGroupRetrieveByID(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - require.Nil(t, err, fmt.Sprintf("group id unexpected error: %s", err)) - group1 := auth.Group{ - ID: generateGroupID(t), - Name: groupName + "TestGroupRetrieveByID1", - OwnerID: uid, - } - - _, err = groupRepo.Save(context.Background(), group1) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - retrieved, err := groupRepo.RetrieveByID(context.Background(), group1.ID) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - assert.True(t, retrieved.ID == group1.ID, fmt.Sprintf("Save group, ID: expected %s got %s\n", group1.ID, retrieved.ID)) - - // Round to milliseconds as otherwise saving and retriving from DB - // adds rounding error. - creationTime := time.Now().UTC().Round(time.Millisecond) - group2 := auth.Group{ - ID: generateGroupID(t), - Name: groupName + "TestGroupRetrieveByID", - OwnerID: uid, - ParentID: group1.ID, - CreatedAt: creationTime, - UpdatedAt: creationTime, - Description: description, - Metadata: metadata, - } - - _, err = groupRepo.Save(context.Background(), group2) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - retrieved, err = groupRepo.RetrieveByID(context.Background(), group2.ID) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - assert.True(t, retrieved.ID == group2.ID, fmt.Sprintf("Save group, ID: expected %s got %s\n", group2.ID, retrieved.ID)) - assert.True(t, retrieved.CreatedAt.Equal(creationTime), fmt.Sprintf("Save group, CreatedAt: expected %s got %s\n", creationTime, retrieved.CreatedAt)) - assert.True(t, retrieved.UpdatedAt.Equal(creationTime), fmt.Sprintf("Save group, UpdatedAt: expected %s got %s\n", creationTime, retrieved.UpdatedAt)) - assert.True(t, retrieved.Level == 2, fmt.Sprintf("Save group, Level: expected %d got %d\n", retrieved.Level, 2)) - assert.True(t, retrieved.ParentID == group1.ID, fmt.Sprintf("Save group, Level: expected %s got %s\n", group1.ID, retrieved.ParentID)) - assert.True(t, retrieved.Description == description, fmt.Sprintf("Save group, Description: expected %v got %v\n", retrieved.Description, description)) - assert.True(t, retrieved.Path == fmt.Sprintf("%s.%s", group1.ID, group2.ID), fmt.Sprintf("Save group, Path: expected %s got %s\n", fmt.Sprintf("%s.%s", group1.ID, group2.ID), retrieved.Path)) - - retrieved, err = groupRepo.RetrieveByID(context.Background(), generateGroupID(t)) - assert.True(t, errors.Contains(err, errors.ErrNotFound), fmt.Sprintf("Retrieve group: expected %s got %s\n", errors.ErrNotFound, err)) -} - -func TestGroupUpdate(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - updateTime := time.Now().UTC() - groupID := generateGroupID(t) - - group := auth.Group{ - ID: groupID, - Name: groupName + "TestGroupUpdate", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - Description: description, - Metadata: metadata, - } - - _, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - retrieved, err := groupRepo.RetrieveByID(context.Background(), group.ID) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - cases := []struct { - desc string - groupUpdate auth.Group - groupExpected auth.Group - err error - }{ - { - desc: "update group for existing id", - groupUpdate: auth.Group{ - ID: groupID, - Name: groupName + "Updated", - UpdatedAt: updateTime, - Metadata: auth.GroupMetadata{"admin": "false"}, - }, - groupExpected: auth.Group{ - Name: groupName + "Updated", - UpdatedAt: updateTime, - Metadata: auth.GroupMetadata{"admin": "false"}, - CreatedAt: retrieved.CreatedAt, - Path: retrieved.Path, - ParentID: retrieved.ParentID, - ID: retrieved.ID, - Level: retrieved.Level, - }, - err: nil, - }, - { - desc: "update group for non-existing id", - groupUpdate: auth.Group{ - ID: "wrong", - Name: groupName + "-2", - }, - err: errors.ErrUpdateEntity, - }, - { - desc: "update group for invalid name", - groupUpdate: auth.Group{ - ID: groupID, - Name: invalidName, - }, - err: errors.ErrMalformedEntity, - }, - { - desc: "update group for invalid description", - groupUpdate: auth.Group{ - ID: groupID, - Description: invalidDesc, - }, - err: errors.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - updated, err := groupRepo.Update(context.Background(), tc.groupUpdate) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - if tc.desc == "update group for existing id" { - assert.True(t, updated.Level == tc.groupExpected.Level, fmt.Sprintf("%s:Level: expected %d got %d\n", tc.desc, tc.groupExpected.Level, updated.Level)) - assert.True(t, updated.Name == tc.groupExpected.Name, fmt.Sprintf("%s:Name: expected %s got %s\n", tc.desc, tc.groupExpected.Name, updated.Name)) - assert.True(t, updated.Metadata["admin"] == tc.groupExpected.Metadata["admin"], fmt.Sprintf("%s:Level: expected %d got %d\n", tc.desc, tc.groupExpected.Metadata["admin"], updated.Metadata["admin"])) - } - } -} - -func TestGroupDelete(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - groupParent := auth.Group{ - ID: generateGroupID(t), - Name: groupName + "Updated", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - groupParent, err = groupRepo.Save(context.Background(), groupParent) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - creationTime = time.Now().UTC() - groupChild1 := auth.Group{ - ID: generateGroupID(t), - ParentID: groupParent.ID, - Name: groupName + "child1", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - creationTime = time.Now().UTC() - groupChild2 := auth.Group{ - ID: generateGroupID(t), - ParentID: groupParent.ID, - Name: groupName + "child2", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - meta := auth.PageMetadata{ - Level: auth.MaxLevel, - } - - groupChild1, err = groupRepo.Save(context.Background(), groupChild1) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - groupChild2, err = groupRepo.Save(context.Background(), groupChild2) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - gp, err := groupRepo.RetrieveAllChildren(context.Background(), groupParent.ID, meta) - assert.True(t, errors.Contains(err, nil), fmt.Sprintf("Retrieve children for parent: expected %v got %v\n", nil, err)) - assert.True(t, gp.Total == 3, fmt.Sprintf("Number of children + parent: expected %d got %d\n", 3, gp.Total)) - - thingID, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("thing id create unexpected error: %s", err)) - - err = groupRepo.Assign(context.Background(), groupChild1.ID, "things", thingID) - require.Nil(t, err, fmt.Sprintf("thing assign got unexpected error: %s", err)) - - err = groupRepo.Delete(context.Background(), groupChild1.ID) - assert.True(t, errors.Contains(err, auth.ErrGroupNotEmpty), fmt.Sprintf("delete non empty group: expected %v got %v\n", auth.ErrGroupNotEmpty, err)) - - err = groupRepo.Delete(context.Background(), groupChild2.ID) - assert.True(t, errors.Contains(err, nil), fmt.Sprintf("delete empty group: expected %v got %v\n", nil, err)) - - err = groupRepo.Delete(context.Background(), groupParent.ID) - assert.True(t, errors.Contains(err, auth.ErrGroupNotEmpty), fmt.Sprintf("delete parent with children with members: expected %v got %v\n", auth.ErrGroupNotEmpty, err)) - - gp, err = groupRepo.RetrieveAllChildren(context.Background(), groupParent.ID, meta) - assert.True(t, errors.Contains(err, nil), fmt.Sprintf("retrieve children after one child removed: expected %v got %v\n", nil, err)) - assert.True(t, gp.Total == 2, fmt.Sprintf("number of children + parent: expected %d got %d\n", 2, gp.Total)) - - err = groupRepo.Unassign(context.Background(), groupChild1.ID, thingID) - require.Nil(t, err, fmt.Sprintf("failed to remove thing from a group error: %s", err)) - - err = groupRepo.Delete(context.Background(), groupParent.ID) - assert.True(t, errors.Contains(err, nil), fmt.Sprintf("delete parent with children with no members: expected %v got %v\n", nil, err)) - - _, err = groupRepo.RetrieveByID(context.Background(), groupChild1.ID) - assert.True(t, errors.Contains(err, errors.ErrNotFound), fmt.Sprintf("retrieve child after parent removed: expected %v got %v\n", nil, err)) -} - -func TestRetrieveAll(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - metadata := auth.PageMetadata{ - Metadata: auth.GroupMetadata{ - "field": "value", - }, - Level: auth.MaxLevel, - } - wrongMeta := auth.PageMetadata{ - Metadata: auth.GroupMetadata{ - "wrong": "wrong", - }, - Level: auth.MaxLevel, - } - - metaNum := uint64(3) - - n := uint64(auth.MaxLevel) - parentID := "" - for i := uint64(0); i < n; i++ { - creationTime := time.Now().UTC() - group := auth.Group{ - ID: generateGroupID(t), - Name: fmt.Sprintf("%s-%d", groupName, i), - OwnerID: uid, - ParentID: parentID, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - // Create Groups with metadata. - if i < metaNum { - group.Metadata = metadata.Metadata - } - - _, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = group.ID - } - - cases := map[string]struct { - Size uint64 - Metadata auth.PageMetadata - }{ - "retrieve all groups": { - Metadata: auth.PageMetadata{ - Total: n, - Limit: n, - Level: auth.MaxLevel, - }, - Size: n, - }, - "retrieve groups with existing metadata": { - Metadata: auth.PageMetadata{ - Total: metaNum, - Limit: n, - Level: auth.MaxLevel, - Metadata: metadata.Metadata, - }, - Size: metaNum, - }, - "retrieve groups with non-existing metadata": { - Metadata: auth.PageMetadata{ - Total: uint64(0), - Limit: n, - Level: auth.MaxLevel, - Metadata: wrongMeta.Metadata, - }, - Size: uint64(0), - }, - "retrieve groups with hierarchy level depth": { - Metadata: auth.PageMetadata{ - Total: uint64(metaNum), - Limit: n, - Level: auth.MaxLevel, - Metadata: metadata.Metadata, - }, - Size: uint64(metaNum), - }, - "retrieve groups with hierarchy level depth and existing metadata": { - Metadata: auth.PageMetadata{ - Total: uint64(metaNum), - Limit: n, - Level: auth.MaxLevel, - Metadata: metadata.Metadata, - }, - Size: uint64(metaNum), - }, - } - - for desc, tc := range cases { - page, err := groupRepo.RetrieveAll(context.Background(), tc.Metadata) - size := len(page.Groups) - assert.Equal(t, tc.Size, uint64(size), fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.Size, size)) - assert.Equal(t, tc.Metadata.Total, page.Total, fmt.Sprintf("%s: expected total %d got %d\n", desc, tc.Metadata.Total, page.Total)) - assert.Nil(t, err, fmt.Sprintf("%s: expected no error got %d\n", desc, err)) - } -} - -func TestRetrieveAllParents(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - metadata := auth.GroupMetadata{ - "field": "value", - } - wrongMeta := auth.GroupMetadata{ - "wrong": "wrong", - } - - p, err := groupRepo.RetrieveAll(context.Background(), auth.PageMetadata{Level: auth.MaxLevel}) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - assert.Equal(t, uint64(0), p.Total, fmt.Sprintf("expected total %d got %d\n", 0, p.Total)) - - metaNum := uint64(3) - - n := uint64(10) - parentID := "" - parentMiddle := "" - for i := uint64(0); i < n; i++ { - creationTime := time.Now().UTC() - group := auth.Group{ - ID: generateGroupID(t), - Name: fmt.Sprintf("%s-%d", groupName, i), - OwnerID: uid, - ParentID: parentID, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - // Create Groups with metadata. - if n-i <= metaNum { - group.Metadata = metadata - } - if i == n/2 { - parentMiddle = group.ID - } - _, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = group.ID - } - - cases := map[string]struct { - level uint64 - parentID string - Size uint64 - Total uint64 - Metadata auth.GroupMetadata - }{ - "retrieve all parents": { - Total: n, - Size: auth.MaxLevel + 1, - level: auth.MaxLevel, - parentID: parentID, - }, - "retrieve groups with existing metadata": { - Total: metaNum, - Size: metaNum, - Metadata: metadata, - parentID: parentID, - level: auth.MaxLevel, - }, - "retrieve groups with non-existing metadata": { - Total: uint64(0), - Metadata: wrongMeta, - Size: uint64(0), - level: auth.MaxLevel, - parentID: parentID, - }, - "retrieve groups with hierarchy level depth": { - Total: n, - Size: 2 + 1, - level: uint64(2), - parentID: parentID, - }, - "retrieve groups with hierarchy level depth and existing metadata": { - Total: metaNum, - Size: metaNum, - level: 3, - Metadata: metadata, - parentID: parentID, - }, - "retrieve parent groups from children in the middle": { - Total: n/2 + 1, - Size: n/2 + 1, - level: auth.MaxLevel, - parentID: parentMiddle, - }, - } - - for desc, tc := range cases { - page, err := groupRepo.RetrieveAllParents(context.Background(), tc.parentID, auth.PageMetadata{Level: tc.level, Metadata: tc.Metadata}) - size := len(page.Groups) - assert.Equal(t, tc.Size, uint64(size), fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.Size, size)) - assert.Equal(t, tc.Total, page.Total, fmt.Sprintf("%s: expected total %d got %d\n", desc, tc.Total, page.Total)) - assert.Nil(t, err, fmt.Sprintf("%s: expected no error got %d\n", desc, err)) - } -} - -func TestRetrieveAllChildren(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - metadata := auth.GroupMetadata{ - "field": "value", - } - wrongMeta := auth.GroupMetadata{ - "wrong": "wrong", - } - - metaNum := uint64(3) - - n := uint64(10) - groupID := generateGroupID(t) - firstParentID := groupID - parentID := "" - parentMiddle := "" - for i := uint64(0); i < n; i++ { - creationTime := time.Now().UTC() - group := auth.Group{ - ID: groupID, - Name: fmt.Sprintf("%s-%d", groupName, i), - OwnerID: uid, - ParentID: parentID, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - // Create Groups with metadata. - if i < metaNum { - group.Metadata = metadata - } - if i == n/2 { - parentMiddle = group.ID - } - _, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = group.ID - groupID = generateGroupID(t) - } - - p, err := groupRepo.RetrieveAll(context.Background(), auth.PageMetadata{Level: auth.MaxLevel}) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - assert.Equal(t, n, p.Total, fmt.Sprintf("expected total %d got %d\n", n, p.Total)) - - cases := map[string]struct { - parentID string - size uint64 - total uint64 - metadata auth.PageMetadata - }{ - "retrieve all children": { - size: auth.MaxLevel, - total: n, - metadata: auth.PageMetadata{ - Level: auth.MaxLevel, - }, - parentID: firstParentID, - }, - "retrieve groups with existing metadata": { - size: metaNum, - total: metaNum, - metadata: auth.PageMetadata{ - Level: auth.MaxLevel, - Metadata: metadata, - }, - parentID: firstParentID, - }, - "retrieve groups with non-existing metadata": { - total: 0, - size: 0, - metadata: auth.PageMetadata{ - Level: auth.MaxLevel, - Metadata: wrongMeta, - }, - parentID: firstParentID, - }, - "retrieve groups with hierarchy level depth": { - total: n, - size: 2, - metadata: auth.PageMetadata{ - Level: 2, - }, - parentID: firstParentID, - }, - "retrieve groups with hierarchy level depth and existing metadata": { - total: metaNum, - size: metaNum, - metadata: auth.PageMetadata{ - Level: 3, - Metadata: metadata, - }, - parentID: firstParentID, - }, - "retrieve parent groups from children in the middle": { - total: n / 2, - size: n / 2, - metadata: auth.PageMetadata{ - Level: auth.MaxLevel, - }, - parentID: parentMiddle, - }, - } - - for desc, tc := range cases { - page, err := groupRepo.RetrieveAllChildren(context.Background(), tc.parentID, tc.metadata) - size := len(page.Groups) - assert.Equal(t, tc.size, uint64(size), fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.size, size)) - assert.Equal(t, tc.total, page.Total, fmt.Sprintf("%s: expected total %d got %d\n", desc, tc.total, page.Total)) - assert.Nil(t, err, fmt.Sprintf("%s: expected no error got %d\n", desc, err)) - } -} - -func TestAssign(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - group := auth.Group{ - ID: generateGroupID(t), - Name: groupName + "Updated", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - pm := auth.PageMetadata{ - Offset: 0, - Limit: 10, - } - - group, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - mid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - err = groupRepo.Assign(context.Background(), group.ID, "things", mid) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - - mp, err := groupRepo.Members(context.Background(), group.ID, "things", pm) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total)) - - err = groupRepo.Assign(context.Background(), group.ID, "things", mid) - assert.True(t, errors.Contains(err, auth.ErrMemberAlreadyAssigned), fmt.Sprintf("assign member again: expected %v got %v\n", auth.ErrMemberAlreadyAssigned, err)) -} - -func TestUnassign(t *testing.T) { - t.Cleanup(func() { cleanUp(t) }) - dbMiddleware := postgres.NewDatabase(db) - groupRepo := postgres.NewGroupRepo(dbMiddleware) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - group := auth.Group{ - ID: generateGroupID(t), - Name: groupName + "Updated", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - pm := auth.PageMetadata{ - Offset: 0, - Limit: 10, - } - - group, err = groupRepo.Save(context.Background(), group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - mid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - err = groupRepo.Assign(context.Background(), group.ID, "things", mid) - require.Nil(t, err, fmt.Sprintf("member assign unexpected error: %s", err)) - - mid, err = idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - err = groupRepo.Assign(context.Background(), group.ID, "things", mid) - require.Nil(t, err, fmt.Sprintf("member assign unexpected error: %s", err)) - - mp, err := groupRepo.Members(context.Background(), group.ID, "things", pm) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - assert.True(t, mp.Total == 2, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 2, mp.Total)) - - err = groupRepo.Unassign(context.Background(), group.ID, mid) - require.Nil(t, err, fmt.Sprintf("member unassign save unexpected error: %s", err)) - - mp, err = groupRepo.Members(context.Background(), group.ID, "things", pm) - require.Nil(t, err, fmt.Sprintf("members retrieve unexpected error: %s", err)) - assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total)) -} - -func cleanUp(t *testing.T) { - _, err := db.Exec("delete from group_relations") - require.Nil(t, err, fmt.Sprintf("clean relations unexpected error: %s", err)) - _, err = db.Exec("delete from groups") - require.Nil(t, err, fmt.Sprintf("clean groups unexpected error: %s", err)) -} diff --git a/auth/postgres/init.go b/auth/postgres/init.go deleted file mode 100644 index fc6992f5361..00000000000 --- a/auth/postgres/init.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import migrate "github.com/rubenv/sql-migrate" - -// Migration of Auth service -func Migration() *migrate.MemoryMigrationSource { - return &migrate.MemoryMigrationSource{ - Migrations: []*migrate.Migration{ - { - Id: "auth_1", - Up: []string{ - `CREATE TABLE IF NOT EXISTS keys ( - id VARCHAR(254) NOT NULL, - type SMALLINT, - subject VARCHAR(254) NOT NULL, - issuer_id UUID NOT NULL, - issued_at TIMESTAMP NOT NULL, - expires_at TIMESTAMP, - PRIMARY KEY (id, issuer_id) - )`, - `CREATE EXTENSION IF NOT EXISTS LTREE`, - `CREATE TABLE IF NOT EXISTS groups ( - id VARCHAR(254) UNIQUE NOT NULL, - parent_id VARCHAR(254), - owner_id VARCHAR(254), - name VARCHAR(254) NOT NULL, - description VARCHAR(1024), - metadata JSONB, - path LTREE, - created_at TIMESTAMPTZ, - updated_at TIMESTAMPTZ, - UNIQUE (owner_id, name, parent_id), - FOREIGN KEY (parent_id) REFERENCES groups (id) ON DELETE CASCADE - )`, - `CREATE TABLE IF NOT EXISTS group_relations ( - member_id VARCHAR(254) NOT NULL, - group_id VARCHAR(254) NOT NULL, - type VARCHAR(254), - created_at TIMESTAMPTZ, - updated_at TIMESTAMPTZ, - FOREIGN KEY (group_id) REFERENCES groups (id), - PRIMARY KEY (member_id, group_id) - )`, - `CREATE INDEX path_gist_idx ON groups USING GIST (path);`, - `CREATE OR REPLACE FUNCTION inherit_group() - RETURNS trigger - LANGUAGE PLPGSQL - AS - $$ - BEGIN - IF NEW.parent_id IS NULL OR NEW.parent_id = '' THEN - RETURN NEW; - END IF; - IF NOT EXISTS (SELECT id FROM groups WHERE id = NEW.parent_id) THEN - RAISE EXCEPTION 'wrong parent id'; - END IF; - SELECT text2ltree(ltree2text(path) || '.' || NEW.id) INTO NEW.path FROM groups WHERE id = NEW.parent_id; - RETURN NEW; - END; - $$`, - `CREATE TRIGGER inherit_group_tr - BEFORE INSERT - ON groups - FOR EACH ROW - EXECUTE PROCEDURE inherit_group();`, - }, - Down: []string{ - `DROP TABLE IF EXISTS keys`, - `DROP EXTENSION IF EXISTS LTREE`, - `DROP TABLE IF EXISTS groups`, - `DROP TABLE IF EXISTS group_relations`, - `DROP FUNCTION IF EXISTS inherit_group`, - `DROP TRIGGER IF EXISTS inherit_group_tr ON groups`, - }, - }, - }, - } -} diff --git a/auth/postgres/key.go b/auth/postgres/key.go deleted file mode 100644 index 0a82ea42abb..00000000000 --- a/auth/postgres/key.go +++ /dev/null @@ -1,115 +0,0 @@ -package postgres - -import ( - "context" - "database/sql" - "time" - - "github.com/jackc/pgerrcode" - "github.com/jackc/pgx/v5/pgconn" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/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 _ auth.KeyRepository = (*repo)(nil) - -type repo struct { - db Database -} - -// New instantiates a PostgreSQL implementation of key repository. -func New(db Database) auth.KeyRepository { - return &repo{ - db: db, - } -} - -func (kr repo) Save(ctx context.Context, key auth.Key) (string, error) { - q := `INSERT INTO keys (id, type, issuer_id, subject, issued_at, expires_at) - VALUES (:id, :type, :issuer_id, :subject, :issued_at, :expires_at)` - - dbKey := toDBKey(key) - if _, err := kr.db.NamedExecContext(ctx, q, dbKey); err != nil { - - if pgErr, ok := err.(*pgconn.PgError); ok && pgErr.Code == pgerrcode.UniqueViolation { - return "", errors.Wrap(errors.ErrConflict, err) - } - - return "", errors.Wrap(errSave, err) - } - - return dbKey.ID, nil -} - -func (kr repo) Retrieve(ctx context.Context, issuerID, id string) (auth.Key, error) { - q := `SELECT id, type, issuer_id, subject, issued_at, expires_at FROM keys WHERE issuer_id = $1 AND id = $2` - key := dbKey{} - if err := kr.db.QueryRowxContext(ctx, q, issuerID, id).StructScan(&key); err != nil { - pgErr, ok := err.(*pgconn.PgError) - if err == sql.ErrNoRows || ok && pgerrcode.InvalidTextRepresentation == pgErr.Code { - return auth.Key{}, errors.Wrap(errors.ErrNotFound, err) - } - - return auth.Key{}, errors.Wrap(errRetrieve, err) - } - - return toKey(key), nil -} - -func (kr repo) Remove(ctx context.Context, issuerID, id string) error { - q := `DELETE FROM keys WHERE issuer_id = :issuer_id AND id = :id` - key := dbKey{ - ID: id, - IssuerID: issuerID, - } - if _, err := kr.db.NamedExecContext(ctx, q, key); err != nil { - return errors.Wrap(errDelete, err) - } - - return nil -} - -type dbKey struct { - ID string `db:"id"` - Type uint32 `db:"type"` - IssuerID string `db:"issuer_id"` - Subject string `db:"subject"` - Revoked bool `db:"revoked"` - IssuedAt time.Time `db:"issued_at"` - ExpiresAt sql.NullTime `db:"expires_at"` -} - -func toDBKey(key auth.Key) dbKey { - ret := dbKey{ - ID: key.ID, - Type: key.Type, - IssuerID: key.IssuerID, - Subject: key.Subject, - IssuedAt: key.IssuedAt, - } - if !key.ExpiresAt.IsZero() { - ret.ExpiresAt = sql.NullTime{Time: key.ExpiresAt, Valid: true} - } - - return ret -} - -func toKey(key dbKey) auth.Key { - ret := auth.Key{ - ID: key.ID, - Type: key.Type, - IssuerID: key.IssuerID, - Subject: key.Subject, - IssuedAt: key.IssuedAt, - } - if key.ExpiresAt.Valid { - ret.ExpiresAt = key.ExpiresAt.Time - } - - return ret -} diff --git a/auth/postgres/key_test.go b/auth/postgres/key_test.go deleted file mode 100644 index db2d095a0ac..00000000000 --- a/auth/postgres/key_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres_test - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/auth/postgres" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/ulid" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const email = "user-save@example.com" - -var ( - expTime = time.Now().Add(5 * time.Minute) - idProvider = uuid.New() - ulidProvider = ulid.New() -) - -func TestKeySave(t *testing.T) { - dbMiddleware := postgres.NewDatabase(db) - repo := postgres.New(dbMiddleware) - - id, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - cases := []struct { - desc string - key auth.Key - err error - }{ - { - desc: "save a new key", - key: auth.Key{ - Subject: email, - IssuedAt: time.Now(), - ExpiresAt: expTime, - ID: id, - IssuerID: id, - }, - err: nil, - }, - { - desc: "save with duplicate id", - key: auth.Key{ - Subject: email, - IssuedAt: time.Now(), - ExpiresAt: expTime, - ID: id, - IssuerID: id, - }, - err: errors.ErrConflict, - }, - } - - for _, tc := range cases { - _, err := repo.Save(context.Background(), tc.key) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestKeyRetrieve(t *testing.T) { - dbMiddleware := postgres.NewDatabase(db) - repo := postgres.New(dbMiddleware) - - id, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - key := auth.Key{ - Subject: email, - IssuedAt: time.Now(), - ExpiresAt: expTime, - ID: id, - IssuerID: id, - } - _, err = repo.Save(context.Background(), key) - assert.Nil(t, err, fmt.Sprintf("Storing Key expected to succeed: %s", err)) - cases := []struct { - desc string - id string - owner string - err error - }{ - { - desc: "retrieve an existing key", - id: key.ID, - owner: key.IssuerID, - err: nil, - }, - { - desc: "retrieve key with empty issuer id", - id: key.ID, - owner: "", - err: errors.ErrNotFound, - }, - { - desc: "retrieve non-existent key", - id: "", - owner: key.IssuerID, - err: errors.ErrNotFound, - }, - } - - for _, tc := range cases { - _, err := repo.Retrieve(context.Background(), tc.owner, tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestKeyRemove(t *testing.T) { - dbMiddleware := postgres.NewDatabase(db) - repo := postgres.New(dbMiddleware) - - id, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - key := auth.Key{ - Subject: email, - IssuedAt: time.Now(), - ExpiresAt: expTime, - ID: id, - IssuerID: id, - } - _, err = repo.Save(opentracing.ContextWithSpan(context.Background(), opentracing.StartSpan("")), key) - assert.Nil(t, err, fmt.Sprintf("Storing Key expected to succeed: %s", err)) - cases := []struct { - desc string - id string - owner string - err error - }{ - { - desc: "remove an existing key", - id: key.ID, - owner: key.IssuerID, - err: nil, - }, - { - desc: "remove key that does not exist", - id: key.ID, - owner: key.IssuerID, - err: nil, - }, - } - - for _, tc := range cases { - err := repo.Remove(context.Background(), tc.owner, tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} diff --git a/auth/postgres/setup_test.go b/auth/postgres/setup_test.go deleted file mode 100644 index d76bc174b7d..00000000000 --- a/auth/postgres/setup_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package postgres_test contains tests for PostgreSQL repository -// implementations. -package postgres_test - -import ( - "database/sql" - "fmt" - "log" - "os" - "testing" - - "github.com/jmoiron/sqlx" - authRepo "github.com/mainflux/mainflux/auth/postgres" - pgClient "github.com/mainflux/mainflux/internal/clients/postgres" - dockertest "github.com/ory/dockertest/v3" -) - -var db *sqlx.DB - -func TestMain(m *testing.M) { - pool, err := dockertest.NewPool("") - if err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - cfg := []string{ - "POSTGRES_USER=test", - "POSTGRES_PASSWORD=test", - "POSTGRES_DB=test", - } - container, err := pool.Run("postgres", "13.3-alpine", cfg) - if err != nil { - log.Fatalf("Could not start container: %s", err) - } - - port := container.GetPort("5432/tcp") - - if err := pool.Retry(func() error { - url := fmt.Sprintf("host=localhost port=%s user=test dbname=test password=test sslmode=disable", port) - db, err := sql.Open("pgx", url) - if err != nil { - return err - } - return db.Ping() - }); err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - dbConfig := pgClient.Config{ - Host: "localhost", - Port: port, - User: "test", - Pass: "test", - Name: "test", - SSLMode: "disable", - SSLCert: "", - SSLKey: "", - SSLRootCert: "", - } - - if db, err = pgClient.SetupDB(dbConfig, *authRepo.Migration()); err != nil { - log.Fatalf("Could not setup test DB connection: %s", err) - } - - code := m.Run() - - // Defers will not be run when using os.Exit - db.Close() - if err := pool.Purge(container); err != nil { - log.Fatalf("Could not purge container: %s", err) - } - - os.Exit(code) -} diff --git a/auth/postgres/tracing.go b/auth/postgres/tracing.go deleted file mode 100644 index 6fe90a89c55..00000000000 --- a/auth/postgres/tracing.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import ( - "context" - "database/sql" - - "github.com/jmoiron/sqlx" - "github.com/opentracing/opentracing-go" -) - -var _ Database = (*database)(nil) - -type database struct { - db *sqlx.DB -} - -// Database provides a database interface -type Database interface { - NamedExecContext(context.Context, string, interface{}) (sql.Result, error) - QueryRowxContext(context.Context, string, ...interface{}) *sqlx.Row - QueryxContext(context.Context, string, ...interface{}) (*sqlx.Rows, error) - NamedQueryContext(context.Context, string, interface{}) (*sqlx.Rows, error) - BeginTxx(ctx context.Context, opts *sql.TxOptions) (*sqlx.Tx, error) -} - -// NewDatabase creates a ThingDatabase instance -func NewDatabase(db *sqlx.DB) Database { - return &database{ - db: db, - } -} - -func (d database) NamedQueryContext(ctx context.Context, query string, args interface{}) (*sqlx.Rows, error) { - addSpanTags(ctx, query) - return d.db.NamedQueryContext(ctx, query, args) -} - -func (d database) NamedExecContext(ctx context.Context, query string, args interface{}) (sql.Result, error) { - addSpanTags(ctx, query) - return d.db.NamedExecContext(ctx, query, args) -} - -func (d database) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row { - addSpanTags(ctx, query) - return d.db.QueryRowxContext(ctx, query, args...) -} - -func (d database) QueryxContext(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error) { - addSpanTags(ctx, query) - return d.db.QueryxContext(ctx, query, args...) -} - -func (d database) BeginTxx(ctx context.Context, opts *sql.TxOptions) (*sqlx.Tx, error) { - span := opentracing.SpanFromContext(ctx) - if span != nil { - span.SetTag("span.kind", "client") - span.SetTag("peer.service", "postgres") - span.SetTag("db.type", "sql") - } - return d.db.BeginTxx(ctx, opts) -} - -func addSpanTags(ctx context.Context, query string) { - span := opentracing.SpanFromContext(ctx) - if span != nil { - span.SetTag("sql.statement", query) - span.SetTag("span.kind", "client") - span.SetTag("peer.service", "postgres") - span.SetTag("db.type", "sql") - } -} diff --git a/auth/service.go b/auth/service.go deleted file mode 100644 index 546ad4a786e..00000000000 --- a/auth/service.go +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth - -import ( - "context" - "fmt" - "time" - - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/ulid" -) - -const ( - recoveryDuration = 5 * time.Minute - thingsGroupType = "things" - - authoritiesObject = "authorities" - memberRelation = "member" -) - -var ( - // ErrFailedToRetrieveMembers failed to retrieve group members. - ErrFailedToRetrieveMembers = errors.New("failed to retrieve group members") - - // ErrFailedToRetrieveMembership failed to retrieve memberships - ErrFailedToRetrieveMembership = errors.New("failed to retrieve memberships") - - // ErrFailedToRetrieveAll failed to retrieve groups. - ErrFailedToRetrieveAll = errors.New("failed to retrieve all groups") - - // ErrFailedToRetrieveParents failed to retrieve groups. - ErrFailedToRetrieveParents = errors.New("failed to retrieve all groups") - - // ErrFailedToRetrieveChildren failed to retrieve groups. - ErrFailedToRetrieveChildren = errors.New("failed to retrieve all groups") - - errIssueUser = errors.New("failed to issue new login 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") -) - -// Authn specifies an API that must be fullfiled by the domain service -// implementation, and all of its decorators (e.g. logging & metrics). -// Token is a string value of the actual Key and is used to authenticate -// an Auth service request. -type Authn interface { - // Issue issues a new Key, returning its token value alongside. - Issue(ctx context.Context, token string, key Key) (Key, string, error) - - // Revoke removes the Key with the provided id that is - // issued by the user identified by the provided key. - Revoke(ctx context.Context, token, id string) error - - // RetrieveKey retrieves data for the Key identified by the provided - // ID, that is issued by the user identified by the provided key. - RetrieveKey(ctx context.Context, token, id string) (Key, error) - - // Identify validates token token. If token is valid, content - // is returned. If token is invalid, or invocation failed for some - // other reason, non-nil error value is returned in response. - Identify(ctx context.Context, token string) (Identity, error) -} - -// Service specifies an API that must be fulfilled by the domain service -// implementation, and all of its decorators (e.g. logging & metrics). -// Token is a string value of the actual Key and is used to authenticate -// an Auth service request. -type Service interface { - Authn - Authz - - // GroupService implements groups API, creating groups, assigning members - GroupService -} - -var _ Service = (*service)(nil) - -type service struct { - keys KeyRepository - groups GroupRepository - idProvider mainflux.IDProvider - ulidProvider mainflux.IDProvider - agent PolicyAgent - tokenizer Tokenizer - loginDuration time.Duration -} - -// New instantiates the auth service implementation. -func New(keys KeyRepository, groups GroupRepository, idp mainflux.IDProvider, tokenizer Tokenizer, policyAgent PolicyAgent, duration time.Duration) Service { - return &service{ - tokenizer: tokenizer, - keys: keys, - groups: groups, - idProvider: idp, - ulidProvider: ulid.New(), - agent: policyAgent, - loginDuration: duration, - } -} - -func (svc service) Issue(ctx context.Context, token string, key Key) (Key, string, error) { - if key.IssuedAt.IsZero() { - return Key{}, "", ErrInvalidKeyIssuedAt - } - switch key.Type { - case APIKey: - return svc.userKey(ctx, token, key) - case RecoveryKey: - return svc.tmpKey(recoveryDuration, key) - default: - return svc.tmpKey(svc.loginDuration, key) - } -} - -func (svc service) Revoke(ctx context.Context, token, id string) error { - issuerID, _, err := svc.login(token) - if err != nil { - return errors.Wrap(errRevoke, err) - } - if err := svc.keys.Remove(ctx, issuerID, id); err != nil { - return errors.Wrap(errRevoke, err) - } - return nil -} - -func (svc service) RetrieveKey(ctx context.Context, token, id string) (Key, error) { - issuerID, _, err := svc.login(token) - if err != nil { - return Key{}, errors.Wrap(errRetrieve, err) - } - - return svc.keys.Retrieve(ctx, issuerID, id) -} - -func (svc service) Identify(ctx context.Context, token string) (Identity, error) { - key, err := svc.tokenizer.Parse(token) - if err == ErrAPIKeyExpired { - err = svc.keys.Remove(ctx, key.IssuerID, key.ID) - return Identity{}, errors.Wrap(ErrAPIKeyExpired, err) - } - if err != nil { - return Identity{}, errors.Wrap(errIdentify, err) - } - - switch key.Type { - case RecoveryKey, LoginKey: - return Identity{ID: key.IssuerID, Email: key.Subject}, nil - case APIKey: - _, err := svc.keys.Retrieve(context.TODO(), key.IssuerID, key.ID) - if err != nil { - return Identity{}, errors.ErrAuthentication - } - return Identity{ID: key.IssuerID, Email: key.Subject}, nil - default: - return Identity{}, errors.ErrAuthentication - } -} - -func (svc service) Authorize(ctx context.Context, pr PolicyReq) error { - return svc.agent.CheckPolicy(ctx, pr) -} - -func (svc service) AddPolicy(ctx context.Context, pr PolicyReq) error { - return svc.agent.AddPolicy(ctx, pr) -} - -func (svc service) AddPolicies(ctx context.Context, token, object string, subjectIDs, relations []string) error { - user, err := svc.Identify(ctx, token) - if err != nil { - return err - } - - if err := svc.Authorize(ctx, PolicyReq{Object: authoritiesObject, Relation: memberRelation, Subject: user.ID}); err != nil { - return err - } - - var errs error - for _, subjectID := range subjectIDs { - for _, relation := range relations { - if err := svc.AddPolicy(ctx, PolicyReq{Object: object, Relation: relation, Subject: subjectID}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot add '%s' policy on object '%s' for subject '%s': %s", relation, object, subjectID, err), errs) - } - } - } - return errs -} - -func (svc service) DeletePolicy(ctx context.Context, pr PolicyReq) error { - return svc.agent.DeletePolicy(ctx, pr) -} - -func (svc service) DeletePolicies(ctx context.Context, token, object string, subjectIDs, relations []string) error { - user, err := svc.Identify(ctx, token) - if err != nil { - return err - } - - // Check if the user identified by token is the admin. - if err := svc.Authorize(ctx, PolicyReq{Object: authoritiesObject, Relation: memberRelation, Subject: user.ID}); err != nil { - return err - } - - var errs error - for _, subjectID := range subjectIDs { - for _, relation := range relations { - if err := svc.DeletePolicy(ctx, PolicyReq{Object: object, Relation: relation, Subject: subjectID}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot delete '%s' policy on object '%s' for subject '%s': %s", relation, object, subjectID, err), errs) - } - } - } - return errs -} - -func (svc service) AssignGroupAccessRights(ctx context.Context, token, thingGroupID, userGroupID string) error { - if _, err := svc.Identify(ctx, token); err != nil { - return err - } - return svc.agent.AddPolicy(ctx, PolicyReq{Object: thingGroupID, Relation: memberRelation, Subject: fmt.Sprintf("%s:%s#%s", "members", userGroupID, memberRelation)}) -} - -func (svc service) ListPolicies(ctx context.Context, pr PolicyReq) (PolicyPage, error) { - res, err := svc.agent.RetrievePolicies(ctx, pr) - if err != nil { - return PolicyPage{}, err - } - var page PolicyPage - for _, tuple := range res { - page.Policies = append(page.Policies, tuple.GetObject()) - } - return page, err -} - -func (svc service) tmpKey(duration time.Duration, key Key) (Key, string, error) { - key.ExpiresAt = key.IssuedAt.Add(duration) - secret, err := svc.tokenizer.Issue(key) - if err != nil { - return Key{}, "", errors.Wrap(errIssueTmp, err) - } - - return key, secret, nil -} - -func (svc service) userKey(ctx context.Context, token string, key Key) (Key, string, error) { - id, sub, err := svc.login(token) - if err != nil { - return Key{}, "", errors.Wrap(errIssueUser, err) - } - - key.IssuerID = id - if key.Subject == "" { - key.Subject = sub - } - - keyID, err := svc.idProvider.ID() - if err != nil { - return Key{}, "", errors.Wrap(errIssueUser, err) - } - key.ID = keyID - - if _, err := svc.keys.Save(ctx, key); err != nil { - return Key{}, "", errors.Wrap(errIssueUser, err) - } - - secret, err := svc.tokenizer.Issue(key) - if err != nil { - return Key{}, "", errors.Wrap(errIssueUser, err) - } - - return key, secret, nil -} - -func (svc service) login(token string) (string, string, error) { - key, err := svc.tokenizer.Parse(token) - if err != nil { - return "", "", err - } - // Only login key token is valid for login. - if key.Type != LoginKey || key.IssuerID == "" { - return "", "", errors.ErrAuthentication - } - - return key.IssuerID, key.Subject, nil -} - -func (svc service) CreateGroup(ctx context.Context, token string, group Group) (Group, error) { - user, err := svc.Identify(ctx, token) - if err != nil { - return Group{}, err - } - - ulid, err := svc.ulidProvider.ID() - if err != nil { - return Group{}, err - } - - timestamp := getTimestmap() - group.UpdatedAt = timestamp - group.CreatedAt = timestamp - - group.ID = ulid - group.OwnerID = user.ID - - group, err = svc.groups.Save(ctx, group) - if err != nil { - return Group{}, err - } - - if err := svc.agent.AddPolicy(ctx, PolicyReq{Object: group.ID, Relation: memberRelation, Subject: user.ID}); err != nil { - return Group{}, err - } - - return group, nil -} - -func (svc service) ListGroups(ctx context.Context, token string, pm PageMetadata) (GroupPage, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return GroupPage{}, err - } - return svc.groups.RetrieveAll(ctx, pm) -} - -func (svc service) ListParents(ctx context.Context, token string, childID string, pm PageMetadata) (GroupPage, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return GroupPage{}, err - } - return svc.groups.RetrieveAllParents(ctx, childID, pm) -} - -func (svc service) ListChildren(ctx context.Context, token string, parentID string, pm PageMetadata) (GroupPage, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return GroupPage{}, err - } - return svc.groups.RetrieveAllChildren(ctx, parentID, pm) -} - -func (svc service) ListMembers(ctx context.Context, token string, groupID, groupType string, pm PageMetadata) (MemberPage, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return MemberPage{}, err - } - mp, err := svc.groups.Members(ctx, groupID, groupType, pm) - if err != nil { - return MemberPage{}, errors.Wrap(ErrFailedToRetrieveMembers, err) - } - return mp, nil -} - -func (svc service) RemoveGroup(ctx context.Context, token, id string) error { - if _, err := svc.Identify(ctx, token); err != nil { - return err - } - return svc.groups.Delete(ctx, id) -} - -func (svc service) UpdateGroup(ctx context.Context, token string, group Group) (Group, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return Group{}, err - } - - group.UpdatedAt = getTimestmap() - return svc.groups.Update(ctx, group) -} - -func (svc service) ViewGroup(ctx context.Context, token, id string) (Group, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return Group{}, err - } - return svc.groups.RetrieveByID(ctx, id) -} - -func (svc service) Assign(ctx context.Context, token string, groupID, groupType string, memberIDs ...string) error { - if _, err := svc.Identify(ctx, token); err != nil { - return err - } - - if err := svc.groups.Assign(ctx, groupID, groupType, memberIDs...); err != nil { - return err - } - - if groupType == thingsGroupType { - ss := fmt.Sprintf("%s:%s#%s", "members", groupID, memberRelation) - var errs error - for _, memberID := range memberIDs { - for _, action := range []string{"read", "write", "delete"} { - if err := svc.agent.AddPolicy(ctx, PolicyReq{Object: memberID, Relation: action, Subject: ss}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot add thing: '%s' to thing group: '%s'", memberID, groupID), errs) - } - } - } - return errs - } - - var errs error - for _, memberID := range memberIDs { - if err := svc.agent.AddPolicy(ctx, PolicyReq{Object: groupID, Relation: memberRelation, Subject: memberID}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot add user: '%s' to user group: '%s'", memberID, groupID), errs) - } - } - return errs -} - -func (svc service) Unassign(ctx context.Context, token string, groupID string, memberIDs ...string) error { - if _, err := svc.Identify(ctx, token); err != nil { - return err - } - - ss := fmt.Sprintf("%s:%s#%s", "members", groupID, memberRelation) - var errs error - for _, memberID := range memberIDs { - // If the member is a user, #member@memberID must be deleted. - if err := svc.agent.DeletePolicy(ctx, PolicyReq{Object: groupID, Relation: memberRelation, Subject: memberID}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot delete a membership of member '%s' from group '%s'", memberID, groupID), errs) - } - - // If the member is a Thing, memberID#read|write|delete@(members:groupID#member) must be deleted. - for _, action := range []string{"read", "write", "delete"} { - if err := svc.agent.DeletePolicy(ctx, PolicyReq{Object: memberID, Relation: action, Subject: ss}); err != nil { - errs = errors.Wrap(fmt.Errorf("cannot delete '%s' policy from member '%s'", action, memberID), errs) - } - } - } - - err := svc.groups.Unassign(ctx, groupID, memberIDs...) - return errors.Wrap(err, errs) -} - -func (svc service) ListMemberships(ctx context.Context, token string, memberID string, pm PageMetadata) (GroupPage, error) { - if _, err := svc.Identify(ctx, token); err != nil { - return GroupPage{}, err - } - return svc.groups.Memberships(ctx, memberID, pm) -} - -func getTimestmap() time.Time { - return time.Now().UTC().Round(time.Millisecond) -} diff --git a/auth/service_test.go b/auth/service_test.go deleted file mode 100644 index 9954e37ca6d..00000000000 --- a/auth/service_test.go +++ /dev/null @@ -1,1269 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth_test - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/mocks" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var idProvider = uuid.New() - -const ( - secret = "secret" - email = "test@example.com" - id = "testID" - groupName = "mfx" - description = "Description" - - memberRelation = "member" - authoritiesObj = "authorities" - loginDuration = 30 * time.Minute -) - -func newService() auth.Service { - repo := mocks.NewKeyRepository() - groupRepo := mocks.NewGroupRepository() - idProvider := uuid.NewMock() - - mockAuthzDB := map[string][]mocks.MockSubjectSet{} - mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: authoritiesObj, Relation: memberRelation}) - ketoMock := mocks.NewKetoMock(mockAuthzDB) - - t := jwt.New(secret) - return auth.New(repo, groupRepo, idProvider, t, ketoMock, loginDuration) -} - -func TestIssue(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - cases := []struct { - desc string - key auth.Key - token string - err error - }{ - { - desc: "issue login key", - key: auth.Key{ - Type: auth.LoginKey, - IssuedAt: time.Now(), - }, - token: secret, - err: nil, - }, - { - desc: "issue login key with no time", - key: auth.Key{ - Type: auth.LoginKey, - }, - token: secret, - err: auth.ErrInvalidKeyIssuedAt, - }, - { - desc: "issue API key", - key: auth.Key{ - Type: auth.APIKey, - IssuedAt: time.Now(), - }, - token: secret, - err: nil, - }, - { - desc: "issue API key with an invalid token", - key: auth.Key{ - Type: auth.APIKey, - IssuedAt: time.Now(), - }, - token: "invalid", - err: errors.ErrAuthentication, - }, - { - desc: "issue API key with no time", - key: auth.Key{ - Type: auth.APIKey, - }, - token: secret, - err: auth.ErrInvalidKeyIssuedAt, - }, - { - desc: "issue recovery key", - key: auth.Key{ - Type: auth.RecoveryKey, - IssuedAt: time.Now(), - }, - token: "", - err: nil, - }, - { - desc: "issue recovery with no issue time", - key: auth.Key{ - Type: auth.RecoveryKey, - }, - token: secret, - err: auth.ErrInvalidKeyIssuedAt, - }, - } - - for _, tc := range cases { - _, _, err := svc.Issue(context.Background(), tc.token, tc.key) - 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) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - key := auth.Key{ - Type: auth.APIKey, - IssuedAt: time.Now(), - IssuerID: id, - Subject: email, - } - newKey, _, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - cases := []struct { - desc string - id string - token string - err error - }{ - { - desc: "revoke login key", - id: newKey.ID, - token: secret, - err: nil, - }, - { - desc: "revoke non-existing login key", - id: newKey.ID, - token: secret, - err: nil, - }, - { - desc: "revoke with empty login key", - id: newKey.ID, - token: "", - err: errors.ErrAuthentication, - }, - } - - for _, tc := range cases { - err := svc.Revoke(context.Background(), tc.token, tc.id) - 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) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), Subject: email, IssuerID: id}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, userToken, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - apiKey, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing login's key expected to succeed: %s", err)) - - _, resetToken, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.RecoveryKey, IssuedAt: time.Now()}) - assert.Nil(t, err, fmt.Sprintf("Issuing reset key expected to succeed: %s", err)) - - cases := []struct { - desc string - id string - token string - err error - }{ - { - desc: "retrieve login key", - id: apiKey.ID, - token: userToken, - err: nil, - }, - { - desc: "retrieve non-existing login key", - id: "invalid", - token: userToken, - err: errors.ErrNotFound, - }, - { - desc: "retrieve with wrong login key", - id: apiKey.ID, - token: "wrong", - err: errors.ErrAuthentication, - }, - { - desc: "retrieve with API token", - id: apiKey.ID, - token: apiToken, - err: errors.ErrAuthentication, - }, - { - desc: "retrieve with reset token", - id: apiKey.ID, - token: resetToken, - err: errors.ErrAuthentication, - }, - } - - for _, tc := range cases { - _, err := svc.RetrieveKey(context.Background(), tc.token, tc.id) - 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) { - svc := newService() - - _, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - _, recoverySecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.RecoveryKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing reset key expected to succeed: %s", err)) - - _, apiSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: auth.APIKey, IssuerID: id, Subject: email, IssuedAt: time.Now(), ExpiresAt: time.Now().Add(time.Minute)}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - exp1 := time.Now().Add(-2 * time.Second) - _, expSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), ExpiresAt: exp1}) - assert.Nil(t, err, fmt.Sprintf("Issuing expired login key expected to succeed: %s", err)) - - _, invalidSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: 22, IssuedAt: time.Now()}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - cases := []struct { - desc string - key string - idt auth.Identity - err error - }{ - { - desc: "identify login key", - key: loginSecret, - idt: auth.Identity{id, email}, - err: nil, - }, - { - desc: "identify recovery key", - key: recoverySecret, - idt: auth.Identity{id, email}, - err: nil, - }, - { - desc: "identify API key", - key: apiSecret, - idt: auth.Identity{id, email}, - err: nil, - }, - { - desc: "identify expired API key", - key: expSecret, - idt: auth.Identity{}, - err: auth.ErrAPIKeyExpired, - }, - { - desc: "identify expired key", - key: invalidSecret, - idt: auth.Identity{}, - err: errors.ErrAuthentication, - }, - { - desc: "identify invalid key", - key: "invalid", - idt: auth.Identity{}, - err: errors.ErrAuthentication, - }, - } - - for _, tc := range cases { - idt, err := svc.Identify(context.Background(), tc.key) - 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.idt, idt, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.idt, idt)) - } -} - -func TestCreateGroup(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Name: "Group", - Description: description, - } - - parentGroup := auth.Group{ - Name: "ParentGroup", - Description: description, - } - - parent, err := svc.CreateGroup(context.Background(), apiToken, parentGroup) - assert.Nil(t, err, fmt.Sprintf("Creating parent group expected to succeed: %s", err)) - - err = svc.Authorize(context.Background(), auth.PolicyReq{Object: parent.ID, Relation: memberRelation, Subject: id}) - assert.Nil(t, err, fmt.Sprintf("Checking parent group owner's policy expected to succeed: %s", err)) - - cases := []struct { - desc string - group auth.Group - err error - }{ - { - desc: "create new group", - group: group, - err: nil, - }, - { - desc: "create group with existing name", - group: group, - err: nil, - }, - { - desc: "create group with parent", - group: auth.Group{ - Name: groupName, - ParentID: parent.ID, - }, - err: nil, - }, - { - desc: "create group with invalid parent", - group: auth.Group{ - Name: groupName, - ParentID: "xxxxxxxxxx", - }, - err: errors.ErrCreateEntity, - }, - } - - for _, tc := range cases { - g, err := svc.CreateGroup(context.Background(), apiToken, tc.group) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - - if err == nil { - authzErr := svc.Authorize(context.Background(), auth.PolicyReq{Object: g.ID, Relation: memberRelation, Subject: g.OwnerID}) - assert.Nil(t, authzErr, fmt.Sprintf("%s - Checking group owner's policy expected to succeed: %s", tc.desc, authzErr)) - } - } -} - -func TestUpdateGroup(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Name: "Group", - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - - group, err = svc.CreateGroup(context.Background(), apiToken, group) - assert.Nil(t, err, fmt.Sprintf("Creating parent group failed: %s", err)) - - cases := []struct { - desc string - group auth.Group - err error - }{ - { - desc: "update group", - group: auth.Group{ - ID: group.ID, - Name: "NewName", - Description: "NewDescription", - Metadata: auth.GroupMetadata{ - "field": "value2", - }, - }, - err: nil, - }, - } - - for _, tc := range cases { - g, err := svc.UpdateGroup(context.Background(), apiToken, tc.group) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - assert.Equal(t, g.ID, tc.group.ID, fmt.Sprintf("ID: expected %s got %s\n", g.ID, tc.group.ID)) - assert.Equal(t, g.Name, tc.group.Name, fmt.Sprintf("Name: expected %s got %s\n", g.Name, tc.group.Name)) - assert.Equal(t, g.Description, tc.group.Description, fmt.Sprintf("Description: expected %s got %s\n", g.Description, tc.group.Description)) - assert.Equal(t, g.Metadata["field"], g.Metadata["field"], fmt.Sprintf("Metadata: expected %s got %s\n", g.Metadata, tc.group.Metadata)) - } - -} - -func TestViewGroup(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Name: "Group", - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - - group, err = svc.CreateGroup(context.Background(), apiToken, group) - assert.Nil(t, err, fmt.Sprintf("Creating parent group failed: %s", err)) - - cases := []struct { - desc string - token string - groupID string - err error - }{ - { - - desc: "view group", - token: apiToken, - groupID: group.ID, - err: nil, - }, - { - desc: "view group with invalid token", - token: "wrongtoken", - groupID: group.ID, - err: errors.ErrAuthentication, - }, - { - desc: "view group for wrong id", - token: apiToken, - groupID: "wrong", - err: errors.ErrNotFound, - }, - } - - for _, tc := range cases { - _, err := svc.ViewGroup(context.Background(), tc.token, tc.groupID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestListGroups(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - n := uint64(10) - parentID := "" - for i := uint64(0); i < n; i++ { - group.Name = fmt.Sprintf("Group%d", i) - group.ParentID = parentID - g, err := svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = g.ID - } - - cases := map[string]struct { - token string - level uint64 - size uint64 - metadata auth.GroupMetadata - err error - }{ - "list all groups": { - token: apiToken, - level: 5, - size: n, - err: nil, - }, - "list groups for level 1": { - token: apiToken, - level: 1, - size: n, - err: nil, - }, - "list all groups with wrong token": { - token: "wrongToken", - level: 5, - size: 0, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - page, err := svc.ListGroups(context.Background(), tc.token, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata}) - size := uint64(len(page.Groups)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } - -} - -func TestListChildren(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - n := uint64(10) - parentID := "" - groupIDs := make([]string, n) - for i := uint64(0); i < n; i++ { - group.Name = fmt.Sprintf("Group%d", i) - group.ParentID = parentID - g, err := svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = g.ID - groupIDs[i] = g.ID - } - - cases := map[string]struct { - token string - level uint64 - size uint64 - id string - metadata auth.GroupMetadata - err error - }{ - "list all children": { - token: apiToken, - level: 5, - id: groupIDs[0], - size: n, - err: nil, - }, - "list all groups with wrong token": { - token: "wrongToken", - level: 5, - size: 0, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - page, err := svc.ListChildren(context.Background(), tc.token, tc.id, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata}) - size := uint64(len(page.Groups)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestListParents(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - n := uint64(10) - parentID := "" - groupIDs := make([]string, n) - for i := uint64(0); i < n; i++ { - group.Name = fmt.Sprintf("Group%d", i) - group.ParentID = parentID - g, err := svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - parentID = g.ID - groupIDs[i] = g.ID - } - - cases := map[string]struct { - token string - level uint64 - size uint64 - id string - metadata auth.GroupMetadata - err error - }{ - "list all parents": { - token: apiToken, - level: 5, - id: groupIDs[n-1], - size: n, - err: nil, - }, - "list all parents with wrong token": { - token: "wrongToken", - level: 5, - size: 0, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - page, err := svc.ListParents(context.Background(), tc.token, tc.id, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata}) - size := uint64(len(page.Groups)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestListMembers(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - g, err := svc.CreateGroup(context.Background(), apiToken, group) - assert.Nil(t, err, fmt.Sprintf("Creating group expected to succeed: %s", err)) - group.ID = g.ID - - n := uint64(10) - for i := uint64(0); i < n; i++ { - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - - err = svc.Assign(context.Background(), apiToken, group.ID, "things", uid) - require.Nil(t, err, fmt.Sprintf("Assign member expected to succeed: %s\n", err)) - } - - cases := map[string]struct { - token string - size uint64 - offset uint64 - limit uint64 - group auth.Group - metadata auth.GroupMetadata - err error - }{ - "list all members": { - token: apiToken, - offset: 0, - limit: n, - group: group, - size: n, - err: nil, - }, - "list half members": { - token: apiToken, - offset: n / 2, - limit: n, - group: group, - size: n / 2, - err: nil, - }, - "list all members with wrong token": { - token: "wrongToken", - offset: 0, - limit: n, - size: 0, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - page, err := svc.ListMembers(context.Background(), tc.token, tc.group.ID, "things", auth.PageMetadata{Offset: tc.offset, Limit: tc.limit, Metadata: tc.metadata}) - size := uint64(len(page.Members)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } - -} - -func TestListMemberships(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - group := auth.Group{ - Description: description, - Metadata: auth.GroupMetadata{ - "field": "value", - }, - } - - memberID, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - - n := uint64(10) - for i := uint64(0); i < n; i++ { - group.Name = fmt.Sprintf("Group%d", i) - g, err := svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) - - _ = svc.AddPolicy(context.Background(), auth.PolicyReq{Subject: id, Object: memberID, Relation: "owner"}) - err = svc.Assign(context.Background(), apiToken, g.ID, "things", memberID) - require.Nil(t, err, fmt.Sprintf("Assign member expected to succeed: %s\n", err)) - } - - cases := map[string]struct { - token string - size uint64 - offset uint64 - limit uint64 - group auth.Group - metadata auth.GroupMetadata - err error - }{ - "list all members": { - token: apiToken, - offset: 0, - limit: n, - group: group, - size: n, - err: nil, - }, - "list half members": { - token: apiToken, - offset: n / 2, - limit: n, - group: group, - size: n / 2, - err: nil, - }, - "list all members with wrong token": { - token: "wrongToken", - offset: 0, - limit: n, - size: 0, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - page, err := svc.ListMemberships(context.Background(), tc.token, memberID, auth.PageMetadata{Limit: tc.limit, Offset: tc.offset, Metadata: tc.metadata}) - size := uint64(len(page.Groups)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestRemoveGroup(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - group := auth.Group{ - Name: groupName, - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - group, err = svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - err = svc.RemoveGroup(context.Background(), "wrongToken", group.ID) - assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) - - err = svc.RemoveGroup(context.Background(), apiToken, "wrongID") - assert.True(t, errors.Contains(err, errors.ErrNotFound), fmt.Sprintf("Remove group with wrong id: expected %v got %v", errors.ErrNotFound, err)) - - gp, err := svc.ListGroups(context.Background(), apiToken, auth.PageMetadata{Level: auth.MaxLevel}) - require.Nil(t, err, fmt.Sprintf("list groups unexpected error: %s", err)) - assert.True(t, gp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, gp.Total)) - - err = svc.RemoveGroup(context.Background(), apiToken, group.ID) - assert.True(t, errors.Contains(err, nil), fmt.Sprintf("Unauthorized access: expected %v got %v", nil, err)) - - gp, err = svc.ListGroups(context.Background(), apiToken, auth.PageMetadata{Level: auth.MaxLevel}) - require.Nil(t, err, fmt.Sprintf("list groups save unexpected error: %s", err)) - assert.True(t, gp.Total == 0, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 0, gp.Total)) - -} - -func TestAssign(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - group := auth.Group{ - Name: groupName + "Updated", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - group, err = svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - mid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - err = svc.Assign(context.Background(), apiToken, group.ID, "things", mid) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - - // check access control policies things members. - subjectSet := fmt.Sprintf("%s:%s#%s", "members", group.ID, memberRelation) - err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "read", Subject: subjectSet}) - require.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, "read", mid, err)) - err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "write", Subject: subjectSet}) - require.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, "write", mid, err)) - err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "delete", Subject: subjectSet}) - require.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, "delete", mid, err)) - - mp, err := svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Offset: 0, Limit: 10}) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total)) - - err = svc.Assign(context.Background(), "wrongToken", group.ID, "things", mid) - assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) - -} - -func TestUnassign(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - creationTime := time.Now().UTC() - group := auth.Group{ - Name: groupName + "Updated", - OwnerID: uid, - CreatedAt: creationTime, - UpdatedAt: creationTime, - } - - group, err = svc.CreateGroup(context.Background(), apiToken, group) - require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) - - mid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - err = svc.Assign(context.Background(), apiToken, group.ID, "things", mid) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - - mp, err := svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Limit: 10, Offset: 0}) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total)) - - err = svc.Unassign(context.Background(), apiToken, group.ID, mid) - require.Nil(t, err, fmt.Sprintf("member unassign save unexpected error: %s", err)) - - mp, err = svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Limit: 10, Offset: 0}) - require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err)) - assert.True(t, mp.Total == 0, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 0, mp.Total)) - - err = svc.Unassign(context.Background(), "wrongToken", group.ID, mid) - assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) - - err = svc.Unassign(context.Background(), apiToken, group.ID, mid) - assert.True(t, errors.Contains(err, errors.ErrNotFound), fmt.Sprintf("Unauthorized access: expected %v got %v", nil, err)) -} - -func TestAuthorize(t *testing.T) { - svc := newService() - - pr := auth.PolicyReq{Object: authoritiesObj, Relation: memberRelation, Subject: id} - err := svc.Authorize(context.Background(), pr) - require.Nil(t, err, fmt.Sprintf("authorizing initial %v policy expected to succeed: %s", pr, err)) -} - -func TestAddPolicy(t *testing.T) { - svc := newService() - - pr := auth.PolicyReq{Object: "obj", Relation: "rel", Subject: "sub"} - err := svc.AddPolicy(context.Background(), pr) - require.Nil(t, err, fmt.Sprintf("adding %v policy expected to succeed: %v", pr, err)) - - err = svc.Authorize(context.Background(), pr) - require.Nil(t, err, fmt.Sprintf("checking shared %v policy expected to be succeed: %#v", pr, err)) -} - -func TestDeletePolicy(t *testing.T) { - svc := newService() - - pr := auth.PolicyReq{Object: authoritiesObj, Relation: memberRelation, Subject: id} - err := svc.DeletePolicy(context.Background(), pr) - require.Nil(t, err, fmt.Sprintf("deleting %v policy expected to succeed: %s", pr, err)) -} - -func TestAssignAccessRights(t *testing.T) { - svc := newService() - - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - userGroupID := "user-group" - thingGroupID := "thing-group" - err = svc.AssignGroupAccessRights(context.Background(), apiToken, thingGroupID, userGroupID) - require.Nil(t, err, fmt.Sprintf("sharing the user group with thing group expected to succeed: %v", err)) - - err = svc.Authorize(context.Background(), auth.PolicyReq{Object: thingGroupID, Relation: memberRelation, Subject: fmt.Sprintf("%s:%s#%s", "members", userGroupID, memberRelation)}) - require.Nil(t, err, fmt.Sprintf("checking shared group access policy expected to be succeed: %#v", err)) -} - -func TestAddPolicies(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - thingID, err := idProvider.ID() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tmpID := "tmpid" - readPolicy := "read" - writePolicy := "write" - deletePolicy := "delete" - - // Add read policy to users. - err = svc.AddPolicies(context.Background(), apiToken, thingID, []string{id, tmpID}, []string{readPolicy}) - assert.Nil(t, err, fmt.Sprintf("adding policies expected to succeed: %s", err)) - - // Add write and delete policies to users. - err = svc.AddPolicies(context.Background(), apiToken, thingID, []string{id, tmpID}, []string{writePolicy, deletePolicy}) - assert.Nil(t, err, fmt.Sprintf("adding multiple policies expected to succeed: %s", err)) - - cases := []struct { - desc string - policy auth.PolicyReq - err error - }{ - { - desc: "check valid 'read' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: readPolicy, Subject: id}, - err: nil, - }, - { - desc: "check valid 'write' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: writePolicy, Subject: id}, - err: nil, - }, - { - desc: "check valid 'delete' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: deletePolicy, Subject: id}, - err: nil, - }, - { - desc: "check valid 'read' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: readPolicy, Subject: tmpID}, - err: nil, - }, - { - desc: "check valid 'write' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: writePolicy, Subject: tmpID}, - err: nil, - }, - { - desc: "check valid 'delete' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: deletePolicy, Subject: tmpID}, - err: nil, - }, - { - desc: "check invalid 'access' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: "access", Subject: id}, - err: errors.ErrAuthorization, - }, - { - desc: "check invalid 'access' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: "access", Subject: tmpID}, - err: errors.ErrAuthorization, - }, - } - - for _, tc := range cases { - err := svc.Authorize(context.Background(), tc.policy) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %v, got %v", tc.desc, tc.err, err)) - } -} - -func TestDeletePolicies(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - thingID, err := idProvider.ID() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tmpID := "tmpid" - readPolicy := "read" - writePolicy := "write" - deletePolicy := "delete" - memberPolicy := "member" - - // Add read, write and delete policies to users. - err = svc.AddPolicies(context.Background(), apiToken, thingID, []string{id, tmpID}, []string{readPolicy, writePolicy, deletePolicy, memberPolicy}) - assert.Nil(t, err, fmt.Sprintf("adding policies expected to succeed: %s", err)) - - // Delete multiple policies from single user. - err = svc.DeletePolicies(context.Background(), apiToken, thingID, []string{id}, []string{readPolicy, writePolicy}) - assert.Nil(t, err, fmt.Sprintf("deleting policies from single user expected to succeed: %s", err)) - - // Delete multiple policies from multiple user. - err = svc.DeletePolicies(context.Background(), apiToken, thingID, []string{id, tmpID}, []string{deletePolicy, memberPolicy}) - assert.Nil(t, err, fmt.Sprintf("deleting policies from multiple user expected to succeed: %s", err)) - - cases := []struct { - desc string - policy auth.PolicyReq - err error - }{ - { - desc: "check non-existing 'read' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: readPolicy, Subject: id}, - err: errors.ErrAuthorization, - }, - { - desc: "check non-existing 'write' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: writePolicy, Subject: id}, - err: errors.ErrAuthorization, - }, - { - desc: "check non-existing 'delete' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: deletePolicy, Subject: id}, - err: errors.ErrAuthorization, - }, - { - desc: "check non-existing 'member' policy of user with id", - policy: auth.PolicyReq{Object: thingID, Relation: memberPolicy, Subject: id}, - err: errors.ErrAuthorization, - }, - { - desc: "check non-existing 'delete' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: deletePolicy, Subject: tmpID}, - err: errors.ErrAuthorization, - }, - { - desc: "check non-existing 'member' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: memberPolicy, Subject: tmpID}, - err: errors.ErrAuthorization, - }, - { - desc: "check valid 'read' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: readPolicy, Subject: tmpID}, - err: nil, - }, - { - desc: "check valid 'write' policy of user with tmpid", - policy: auth.PolicyReq{Object: thingID, Relation: writePolicy, Subject: tmpID}, - err: nil, - }, - } - - for _, tc := range cases { - err := svc.Authorize(context.Background(), tc.policy) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %v, got %v", tc.desc, tc.err, err)) - } -} - -func TestListPolicies(t *testing.T) { - svc := newService() - _, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.LoginKey, IssuedAt: time.Now(), IssuerID: id, Subject: email}) - assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err)) - - key := auth.Key{ - ID: "id", - Type: auth.APIKey, - IssuerID: id, - Subject: email, - IssuedAt: time.Now(), - } - - _, apiToken, err := svc.Issue(context.Background(), secret, key) - assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err)) - - readPolicy := "read" - pageLen := 15 - - // Add arbitrary policies to the user. - for i := 0; i < pageLen; i++ { - err = svc.AddPolicies(context.Background(), apiToken, fmt.Sprintf("thing-%d", i), []string{id}, []string{readPolicy}) - assert.Nil(t, err, fmt.Sprintf("adding policies expected to succeed: %s", err)) - } - - page, err := svc.ListPolicies(context.Background(), auth.PolicyReq{Subject: id, Relation: readPolicy}) - assert.Nil(t, err, fmt.Sprintf("listing policies expected to succeed: %s", err)) - assert.Equal(t, pageLen, len(page.Policies), fmt.Sprintf("unexpected listing page size, expected %d, got %d: %v", pageLen, len(page.Policies), err)) - -} diff --git a/auth/tokenizer.go b/auth/tokenizer.go deleted file mode 100644 index d8bd4f731ab..00000000000 --- a/auth/tokenizer.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package auth - -// Tokenizer specifies API for encoding and decoding between string and Key. -type Tokenizer interface { - // Issue converts API Key to its string representation. - Issue(Key) (string, error) - - // Parse extracts API Key data from string token. - Parse(string) (Key, error) -} diff --git a/auth/tracing/groups.go b/auth/tracing/groups.go deleted file mode 100644 index 80b53ca2ef1..00000000000 --- a/auth/tracing/groups.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package tracing contains middlewares that will add spans to existing traces. -package tracing - -import ( - "context" - - "github.com/mainflux/mainflux/auth" - opentracing "github.com/opentracing/opentracing-go" -) - -const ( - assign = "assign" - saveGroup = "save_group" - deleteGroup = "delete_group" - updateGroup = "update_group" - retrieveByID = "retrieve_by_id" - retrieveAllParents = "retrieve_all_parents" - retrieveAllChildren = "retrieve_all_children" - retrieveAll = "retrieve_all_groups" - memberships = "memberships" - members = "members" - unassign = "unassign" -) - -var _ auth.GroupRepository = (*groupRepositoryMiddleware)(nil) - -type groupRepositoryMiddleware struct { - tracer opentracing.Tracer - repo auth.GroupRepository -} - -// GroupRepositoryMiddleware tracks request and their latency, and adds spans to context. -func GroupRepositoryMiddleware(tracer opentracing.Tracer, gr auth.GroupRepository) auth.GroupRepository { - return groupRepositoryMiddleware{ - tracer: tracer, - repo: gr, - } -} - -func (grm groupRepositoryMiddleware) Save(ctx context.Context, g auth.Group) (auth.Group, error) { - span := createSpan(ctx, grm.tracer, saveGroup) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Save(ctx, g) -} - -func (grm groupRepositoryMiddleware) Update(ctx context.Context, g auth.Group) (auth.Group, error) { - span := createSpan(ctx, grm.tracer, updateGroup) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Update(ctx, g) -} - -func (grm groupRepositoryMiddleware) Delete(ctx context.Context, groupID string) error { - span := createSpan(ctx, grm.tracer, deleteGroup) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Delete(ctx, groupID) -} - -func (grm groupRepositoryMiddleware) RetrieveByID(ctx context.Context, id string) (auth.Group, error) { - span := createSpan(ctx, grm.tracer, retrieveByID) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.RetrieveByID(ctx, id) -} - -func (grm groupRepositoryMiddleware) RetrieveAllParents(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - span := createSpan(ctx, grm.tracer, retrieveAllParents) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.RetrieveAllParents(ctx, groupID, pm) -} - -func (grm groupRepositoryMiddleware) RetrieveAllChildren(ctx context.Context, groupID string, pm auth.PageMetadata) (auth.GroupPage, error) { - span := createSpan(ctx, grm.tracer, retrieveAllChildren) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.RetrieveAllChildren(ctx, groupID, pm) -} - -func (grm groupRepositoryMiddleware) RetrieveAll(ctx context.Context, pm auth.PageMetadata) (auth.GroupPage, error) { - span := createSpan(ctx, grm.tracer, retrieveAll) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.RetrieveAll(ctx, pm) -} - -func (grm groupRepositoryMiddleware) Memberships(ctx context.Context, memberID string, pm auth.PageMetadata) (auth.GroupPage, error) { - span := createSpan(ctx, grm.tracer, memberships) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Memberships(ctx, memberID, pm) -} - -func (grm groupRepositoryMiddleware) Members(ctx context.Context, groupID, groupType string, pm auth.PageMetadata) (auth.MemberPage, error) { - span := createSpan(ctx, grm.tracer, members) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Members(ctx, groupID, groupType, pm) -} - -func (grm groupRepositoryMiddleware) Assign(ctx context.Context, groupID, groupType string, memberIDs ...string) error { - span := createSpan(ctx, grm.tracer, assign) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Assign(ctx, groupID, groupType, memberIDs...) -} - -func (grm groupRepositoryMiddleware) Unassign(ctx context.Context, groupID string, memberIDs ...string) error { - span := createSpan(ctx, grm.tracer, unassign) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return grm.repo.Unassign(ctx, groupID, memberIDs...) -} diff --git a/auth/tracing/keys.go b/auth/tracing/keys.go deleted file mode 100644 index 36755a0661b..00000000000 --- a/auth/tracing/keys.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package tracing contains middlewares that will add spans -// to existing traces. -package tracing - -import ( - "context" - - "github.com/mainflux/mainflux/auth" - opentracing "github.com/opentracing/opentracing-go" -) - -const ( - saveOp = "save" - retrieveOp = "retrieve_by_id" - revokeOp = "remove" -) - -var _ auth.KeyRepository = (*keyRepositoryMiddleware)(nil) - -// keyRepositoryMiddleware tracks request and their latency, and adds spans -// to context. -type keyRepositoryMiddleware struct { - tracer opentracing.Tracer - repo auth.KeyRepository -} - -// New tracks request and their latency, and adds spans -// to context. -func New(repo auth.KeyRepository, tracer opentracing.Tracer) auth.KeyRepository { - return keyRepositoryMiddleware{ - tracer: tracer, - repo: repo, - } -} - - -func (krm keyRepositoryMiddleware) Save(ctx context.Context, key auth.Key) (string, error) { - span := createSpan(ctx, krm.tracer, saveOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return krm.repo.Save(ctx, key) -} - -func (krm keyRepositoryMiddleware) Retrieve(ctx context.Context, owner, id string) (auth.Key, error) { - span := createSpan(ctx, krm.tracer, retrieveOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return krm.repo.Retrieve(ctx, owner, id) -} - -func (krm keyRepositoryMiddleware) Remove(ctx context.Context, owner, id string) error { - span := createSpan(ctx, krm.tracer, revokeOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return krm.repo.Remove(ctx, owner, id) -} - -func createSpan(ctx context.Context, tracer opentracing.Tracer, opName string) opentracing.Span { - if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil { - return tracer.StartSpan( - opName, - opentracing.ChildOf(parentSpan.Context()), - ) - } - - return tracer.StartSpan(opName) -} diff --git a/bootstrap/api/endpoint_test.go b/bootstrap/api/endpoint_test.go index 30d8f6a652b..9063fd4dc95 100644 --- a/bootstrap/api/endpoint_test.go +++ b/bootstrap/api/endpoint_test.go @@ -19,10 +19,10 @@ import ( "strings" "testing" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/bootstrap" bsapi "github.com/mainflux/mainflux/bootstrap/api" "github.com/mainflux/mainflux/bootstrap/mocks" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" @@ -163,7 +163,7 @@ func dec(in []byte) ([]byte, error) { return in, nil } -func newService(auth mainflux.AuthServiceClient, url string) bootstrap.Service { +func newService(auth policies.AuthServiceClient, url string) bootstrap.Service { things := mocks.NewConfigsRepository() config := mfsdk.Config{ ThingsURL: url, @@ -186,7 +186,7 @@ func generateChannels() map[string]things.Channel { return channels } -func newThingsService(auth mainflux.AuthServiceClient) things.Service { +func newThingsService(auth policies.AuthServiceClient) things.Service { return mocks.NewThingsService(map[string]things.Thing{}, generateChannels(), auth) } diff --git a/bootstrap/mocks/things.go b/bootstrap/mocks/things.go index 96aeef8437a..090d8d52ce3 100644 --- a/bootstrap/mocks/things.go +++ b/bootstrap/mocks/things.go @@ -8,7 +8,7 @@ import ( "strconv" "sync" - "github.com/mainflux/mainflux" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/things" ) @@ -20,13 +20,13 @@ type mainfluxThings struct { counter uint64 things map[string]things.Thing channels map[string]things.Channel - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient connections map[string][]string } // NewThingsService returns Mainflux Things service mock. // Only methods used by SDK are mocked. -func NewThingsService(things map[string]things.Thing, channels map[string]things.Channel, auth mainflux.AuthServiceClient) things.Service { +func NewThingsService(things map[string]things.Thing, channels map[string]things.Channel, auth policies.AuthServiceClient) things.Service { return &mainfluxThings{ things: things, channels: channels, @@ -39,7 +39,7 @@ func (svc *mainfluxThings) CreateThings(_ context.Context, owner string, ths ... svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return []things.Thing{}, errors.ErrAuthentication } @@ -58,7 +58,7 @@ func (svc *mainfluxThings) ViewThing(_ context.Context, owner, id string) (thing svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return things.Thing{}, errors.ErrAuthentication } @@ -75,7 +75,7 @@ func (svc *mainfluxThings) Connect(_ context.Context, owner string, chIDs, thIDs svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return errors.ErrAuthentication } @@ -93,7 +93,7 @@ func (svc *mainfluxThings) Disconnect(_ context.Context, owner string, chIDs, th svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return errors.ErrAuthentication } @@ -128,7 +128,7 @@ func (svc *mainfluxThings) RemoveThing(_ context.Context, owner, id string) erro svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return errors.ErrAuthentication } @@ -185,7 +185,7 @@ func (svc *mainfluxThings) CreateChannels(_ context.Context, owner string, chs . svc.mu.Lock() defer svc.mu.Unlock() - userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) + userID, err := svc.auth.Identify(context.Background(), &policies.Token{Value: owner}) if err != nil { return []things.Channel{}, errors.ErrAuthentication } @@ -227,7 +227,7 @@ func (svc *mainfluxThings) Identify(context.Context, string) (string, error) { panic("not implemented") } -func (svc *mainfluxThings) ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) error { +func (svc *mainfluxThings) ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) error { panic("not implemented") } diff --git a/bootstrap/mocks/users.go b/bootstrap/mocks/users.go index 54942d69e7f..66cd43b614a 100644 --- a/bootstrap/mocks/users.go +++ b/bootstrap/mocks/users.go @@ -6,60 +6,49 @@ package mocks import ( "context" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/pkg/errors" "google.golang.org/grpc" ) -var _ mainflux.AuthServiceClient = (*serviceMock)(nil) +var _ policies.AuthServiceClient = (*serviceMock)(nil) type serviceMock struct { users map[string]string } // NewAuthClient creates mock of users service. -func NewAuthClient(users map[string]string) mainflux.AuthServiceClient { +func NewAuthClient(users map[string]string) policies.AuthServiceClient { return &serviceMock{users} } -func (svc serviceMock) Identify(ctx context.Context, in *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { +func (svc serviceMock) Identify(ctx context.Context, in *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { if id, ok := svc.users[in.Value]; ok { - return &mainflux.UserIdentity{Email: id, Id: id}, nil + return &policies.UserIdentity{Email: id, Id: id}, nil } return nil, errors.ErrAuthentication } -func (svc serviceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { +func (svc serviceMock) Issue(ctx context.Context, in *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { if id, ok := svc.users[in.GetEmail()]; ok { switch in.Type { default: - return &mainflux.Token{Value: id}, nil + return &policies.Token{Value: id}, nil } } return nil, errors.ErrAuthentication } -func (svc serviceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { +func (svc serviceMock) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { panic("not implemented") } -func (svc serviceMock) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { +func (svc serviceMock) AddPolicy(ctx context.Context, req *policies.AddPolicyReq, _ ...grpc.CallOption) (r *policies.AddPolicyRes, err error) { panic("not implemented") } - -func (svc serviceMock) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { - panic("not implemented") -} - -func (svc serviceMock) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { +func (svc serviceMock) DeletePolicy(ctx context.Context, req *policies.DeletePolicyReq, _ ...grpc.CallOption) (r *policies.DeletePolicyRes, err error) { panic("not implemented") } - -func (svc serviceMock) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - panic("not implemented") -} - -func (svc serviceMock) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { +func (svc serviceMock) ListPolicies(ctx context.Context, req *policies.ListPoliciesReq, _ ...grpc.CallOption) (r *policies.ListPoliciesRes, err error) { panic("not implemented") } diff --git a/bootstrap/redis/producer/streams_test.go b/bootstrap/redis/producer/streams_test.go index 24fe34df416..f4c5499ddb3 100644 --- a/bootstrap/redis/producer/streams_test.go +++ b/bootstrap/redis/producer/streams_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/go-redis/redis/v8" - "github.com/mainflux/mainflux" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" "github.com/opentracing/opentracing-go/mocktracer" @@ -63,7 +63,7 @@ var ( } ) -func newService(auth mainflux.AuthServiceClient, url string) bootstrap.Service { +func newService(auth policies.AuthServiceClient, url string) bootstrap.Service { configs := mocks.NewConfigsRepository() config := mfsdk.Config{ ThingsURL: url, @@ -73,7 +73,7 @@ func newService(auth mainflux.AuthServiceClient, url string) bootstrap.Service { return bootstrap.New(auth, configs, sdk, encKey) } -func newThingsService(auth mainflux.AuthServiceClient) things.Service { +func newThingsService(auth policies.AuthServiceClient) things.Service { channels := make(map[string]things.Channel, channelsNum) for i := 0; i < channelsNum; i++ { id := strconv.Itoa(i + 1) diff --git a/bootstrap/service.go b/bootstrap/service.go index fc5675b4a66..282b4e456df 100644 --- a/bootstrap/service.go +++ b/bootstrap/service.go @@ -10,7 +10,7 @@ import ( "encoding/hex" "time" - "github.com/mainflux/mainflux" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/pkg/errors" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" ) @@ -102,14 +102,14 @@ type ConfigReader interface { } type bootstrapService struct { - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient configs ConfigRepository sdk mfsdk.SDK encKey []byte } // New returns new Bootstrap service. -func New(auth mainflux.AuthServiceClient, configs ConfigRepository, sdk mfsdk.SDK, encKey []byte) Service { +func New(auth policies.AuthServiceClient, configs ConfigRepository, sdk mfsdk.SDK, encKey []byte) Service { return &bootstrapService{ configs: configs, sdk: sdk, @@ -365,7 +365,7 @@ func (bs bootstrapService) identify(token string) (string, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - res, err := bs.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := bs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return "", errors.ErrAuthentication } diff --git a/bootstrap/service_test.go b/bootstrap/service_test.go index 04ba330902c..0b92752adf8 100644 --- a/bootstrap/service_test.go +++ b/bootstrap/service_test.go @@ -18,9 +18,9 @@ import ( "github.com/opentracing/opentracing-go/mocktracer" "github.com/gofrs/uuid" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/bootstrap" "github.com/mainflux/mainflux/bootstrap/mocks" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" @@ -55,7 +55,7 @@ var ( } ) -func newService(auth mainflux.AuthServiceClient, url string) bootstrap.Service { +func newService(auth policies.AuthServiceClient, url string) bootstrap.Service { things := mocks.NewConfigsRepository() config := mfsdk.Config{ ThingsURL: url, @@ -65,7 +65,7 @@ func newService(auth mainflux.AuthServiceClient, url string) bootstrap.Service { return bootstrap.New(auth, things, sdk, encKey) } -func newThingsService(auth mainflux.AuthServiceClient) things.Service { +func newThingsService(auth policies.AuthServiceClient) things.Service { channels := make(map[string]things.Channel, channelsNum) for i := 0; i < channelsNum; i++ { id := strconv.Itoa(i + 1) diff --git a/certs/postgres/certs.go b/certs/postgres/certs.go index d91bfd6532b..be7b1588b9b 100644 --- a/certs/postgres/certs.go +++ b/certs/postgres/certs.go @@ -11,7 +11,6 @@ import ( "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5/pgconn" - "github.com/jmoiron/sqlx" "github.com/mainflux/mainflux/certs" "github.com/mainflux/mainflux/logger" diff --git a/certs/service.go b/certs/service.go index deabf727fce..7631934f387 100644 --- a/certs/service.go +++ b/certs/service.go @@ -7,8 +7,8 @@ import ( "context" "time" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/certs/pki" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/pkg/errors" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" ) @@ -45,14 +45,14 @@ type Service interface { } type certsService struct { - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient certsRepo Repository sdk mfsdk.SDK pki pki.Agent } // New returns new Certs service -func New(auth mainflux.AuthServiceClient, certs Repository, sdk mfsdk.SDK, pki pki.Agent) Service { +func New(auth policies.AuthServiceClient, certs Repository, sdk mfsdk.SDK, pki pki.Agent) Service { return &certsService{ certsRepo: certs, sdk: sdk, @@ -80,7 +80,7 @@ type Cert struct { } func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, ttl string) (Cert, error) { - owner, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token}) + owner, err := cs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Cert{}, err } @@ -113,7 +113,7 @@ func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, tt func (cs *certsService) RevokeCert(ctx context.Context, token, thingID string) (Revoke, error) { var revoke Revoke - u, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token}) + u, err := cs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return revoke, err } @@ -144,7 +144,7 @@ func (cs *certsService) RevokeCert(ctx context.Context, token, thingID string) ( } func (cs *certsService) ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (Page, error) { - u, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token}) + u, err := cs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Page{}, err } @@ -167,7 +167,7 @@ func (cs *certsService) ListCerts(ctx context.Context, token, thingID string, of } func (cs *certsService) ListSerials(ctx context.Context, token, thingID string, offset, limit uint64) (Page, error) { - u, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token}) + u, err := cs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Page{}, err } @@ -176,7 +176,7 @@ func (cs *certsService) ListSerials(ctx context.Context, token, thingID string, } func (cs *certsService) ViewCert(ctx context.Context, token, serialID string) (Cert, error) { - u, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token}) + u, err := cs.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Cert{}, err } diff --git a/certs/service_test.go b/certs/service_test.go index ab564729c8b..e3b9dbd4b2c 100644 --- a/certs/service_test.go +++ b/certs/service_test.go @@ -16,10 +16,10 @@ import ( "testing" "time" - "github.com/mainflux/mainflux" bsmocks "github.com/mainflux/mainflux/bootstrap/mocks" "github.com/mainflux/mainflux/certs" "github.com/mainflux/mainflux/certs/mocks" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" @@ -52,8 +52,9 @@ func newService(tokens map[string]string) (certs.Service, error) { ac := bsmocks.NewAuthClient(map[string]string{token: email}) server := newThingsServer(newThingsService(ac)) - policies := []thmocks.MockSubjectSet{{Object: "users", Relation: "member"}} - auth := thmocks.NewAuthService(tokens, map[string][]thmocks.MockSubjectSet{email: policies}) + policies := []thmocks.MockSubjectSet{{Subject: "token", Relation: things.AdminRelationKey}} + auth := thmocks.NewAuthService(tokens, map[string][]thmocks.MockSubjectSet{token: policies}) + config := mfsdk.Config{ ThingsURL: server.URL, } @@ -76,7 +77,7 @@ func newService(tokens map[string]string) (certs.Service, error) { return certs.New(auth, repo, sdk, pki), nil } -func newThingsService(auth mainflux.AuthServiceClient) things.Service { +func newThingsService(auth policies.AuthServiceClient) things.Service { ths := make(map[string]things.Thing, thingsNum) for i := 0; i < thingsNum; i++ { id := strconv.Itoa(i + 1) diff --git a/cli/keys.go b/cli/keys.go deleted file mode 100644 index c08052a85ba..00000000000 --- a/cli/keys.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package cli - -import ( - "time" - - "github.com/spf13/cobra" -) - -var cmdAPIKeys = []cobra.Command{ - { - Use: "issue ", - Short: "Issue key", - Long: `Issues a new Key`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { - logUsage(cmd.Use) - return - } - - d, err := time.ParseDuration(args[0]) - if err != nil { - logError(err) - return - } - - resp, err := sdk.Issue(d, args[1]) - if err != nil { - logError(err) - return - } - - logJSON(resp) - }, - }, - { - Use: "revoke ", - Short: "Revoke key", - Long: `Removes API key from database`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { - logUsage(cmd.Use) - return - } - - if err := sdk.Revoke(args[0], args[1]); err != nil { - logError(err) - return - } - - logOK() - }, - }, - { - Use: "retrieve ", - Short: "Retrieve key", - Long: `Retrieves API key with given id`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { - logUsage(cmd.Use) - return - } - - rk, err := sdk.RetrieveKey(args[0], args[1]) - if err != nil { - logError(err) - return - } - - logJSON(rk) - }, - }, -} - -// NewKeysCmd returns keys command. -func NewKeysCmd() *cobra.Command { - cmd := cobra.Command{ - Use: "keys [issue | revoke | retrieve]", - Short: "Keys management", - Long: `Keys management: issue, revoke, or retrieve API key.`, - } - - for i := range cmdAPIKeys { - cmd.AddCommand(&cmdAPIKeys[i]) - } - - return &cmd -} diff --git a/cli/provision.go b/cli/provision.go index ce8f453694a..b6383bc69ca 100644 --- a/cli/provision.go +++ b/cli/provision.go @@ -122,8 +122,10 @@ var cmdProvision = []cobra.Command{ un := fmt.Sprintf("%s@email.com", namesgenerator.GetRandomName(0)) // Create test user user := mfxsdk.User{ - Email: un, - Password: "12345678", + Credentials: mfxsdk.Credentials{ + Identity: un, + Secret: "12345678", + }, } if _, err := sdk.CreateUser(user, ""); err != nil { logError(err) diff --git a/cli/users.go b/cli/users.go index e7aa57a0f5c..18d80f67f00 100644 --- a/cli/users.go +++ b/cli/users.go @@ -7,6 +7,7 @@ import ( "encoding/json" mfxsdk "github.com/mainflux/mainflux/pkg/sdk/go" + "github.com/mainflux/mainflux/users/clients" "github.com/spf13/cobra" ) @@ -25,8 +26,11 @@ var cmdUsers = []cobra.Command{ } user := mfxsdk.User{ - Email: args[0], - Password: args[1], + Credentials: mfxsdk.Credentials{ + Identity: args[0], + Secret: args[1], + }, + Status: clients.EnabledStatus.String(), } id, err := sdk.CreateUser(user, args[2]) if err != nil { @@ -89,8 +93,10 @@ var cmdUsers = []cobra.Command{ } user := mfxsdk.User{ - Email: args[0], - Password: args[1], + Credentials: mfxsdk.Credentials{ + Identity: args[0], + Secret: args[1], + }, } token, err := sdk.CreateToken(user) if err != nil { @@ -127,16 +133,16 @@ var cmdUsers = []cobra.Command{ }, }, { - Use: "password ", + Use: "password ", Short: "Update password", Long: `Update user password`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsage(cmd.Use) return } - if err := sdk.UpdatePassword(args[0], args[1], args[2]); err != nil { + if err := sdk.UpdatePassword(args[0], args[1], args[2], args[3]); err != nil { logError(err) return } diff --git a/clients/README.md b/clients/README.md deleted file mode 100644 index 3458839cfb1..00000000000 --- a/clients/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Clients - -Repository for Clients service for handling generic clients diff --git a/clients/policies/api/grpc/client.go b/clients/policies/api/grpc/client.go deleted file mode 100644 index db50eb2756b..00000000000 --- a/clients/policies/api/grpc/client.go +++ /dev/null @@ -1,66 +0,0 @@ -package grpc - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - kitgrpc "github.com/go-kit/kit/transport/grpc" - "github.com/mainflux/mainflux/clients/policies" - opentracing "github.com/opentracing/opentracing-go" - "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" - "google.golang.org/grpc" -) - -const svcName = "policies.AuthService" - -var _ policies.AuthServiceClient = (*grpcClient)(nil) - -type grpcClient struct { - authorize endpoint.Endpoint - timeout time.Duration -} - -// NewClient returns new gRPC client instance. -func NewClient(tracer opentracing.Tracer, conn *grpc.ClientConn, timeout time.Duration) policies.AuthServiceClient { - return &grpcClient{ - authorize: otelkit.EndpointMiddleware(otelkit.WithOperation("authorize"))(kitgrpc.NewClient( - conn, - svcName, - "Authorize", - encodeAuthorizeRequest, - decodeAuthorizeResponse, - policies.AuthorizeRes{}, - ).Endpoint()), - - timeout: timeout, - } -} - -func (client grpcClient) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { - ctx, close := context.WithTimeout(ctx, client.timeout) - defer close() - - res, err := client.authorize(ctx, authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub(), EntityType: req.GetEntityType()}) - if err != nil { - return &policies.AuthorizeRes{}, err - } - - ar := res.(authorizeRes) - return &policies.AuthorizeRes{Authorized: ar.authorized}, err -} - -func decodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(*policies.AuthorizeRes) - return authorizeRes{authorized: res.Authorized}, nil -} - -func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(authReq) - return &policies.AuthorizeReq{ - Sub: req.Sub, - Obj: req.Obj, - Act: req.Act, - EntityType: req.EntityType, - }, nil -} diff --git a/clients/policies/api/grpc/endpoint.go b/clients/policies/api/grpc/endpoint.go deleted file mode 100644 index 7da15d1d0d1..00000000000 --- a/clients/policies/api/grpc/endpoint.go +++ /dev/null @@ -1,24 +0,0 @@ -package grpc - -import ( - "context" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/clients/policies" -) - -func authorizeEndpoint(svc policies.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(authReq) - - if err := req.validate(); err != nil { - return authorizeRes{}, err - } - - err := svc.Authorize(ctx, req.EntityType, policies.Policy{Subject: req.Sub, Object: req.Obj, Actions: []string{req.Act}}) - if err != nil { - return authorizeRes{}, err - } - return authorizeRes{authorized: true}, err - } -} diff --git a/clients/policies/api/grpc/requests.go b/clients/policies/api/grpc/requests.go deleted file mode 100644 index 8a4cd4d3059..00000000000 --- a/clients/policies/api/grpc/requests.go +++ /dev/null @@ -1,33 +0,0 @@ -package grpc - -import ( - "github.com/mainflux/mainflux/internal/apiutil" -) - -// authReq represents authorization request. It contains: -// 1. subject - an action invoker (client) -// 2. object - an entity over which action will be executed (client, group, computation, dataset) -// 3. action - type of action that will be executed (read/write) -type authReq struct { - Sub string - Obj string - Act string - EntityType string -} - -func (req authReq) validate() error { - if req.Sub == "" { - return apiutil.ErrMissingPolicySub - } - if req.Obj == "" { - return apiutil.ErrMissingPolicyObj - } - if req.Act == "" { - return apiutil.ErrMissingPolicyAct - } - if req.EntityType == "" { - return apiutil.ErrMissingPolicyEntityType - } - - return nil -} diff --git a/clients/policies/api/grpc/responses.go b/clients/policies/api/grpc/responses.go deleted file mode 100644 index fd0fba28a0c..00000000000 --- a/clients/policies/api/grpc/responses.go +++ /dev/null @@ -1,5 +0,0 @@ -package grpc - -type authorizeRes struct { - authorized bool -} diff --git a/clients/policies/api/grpc/transport.go b/clients/policies/api/grpc/transport.go deleted file mode 100644 index b30af2754d6..00000000000 --- a/clients/policies/api/grpc/transport.go +++ /dev/null @@ -1,73 +0,0 @@ -package grpc - -import ( - "context" - - kitgrpc "github.com/go-kit/kit/transport/grpc" - "github.com/mainflux/mainflux/clients/policies" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/pkg/errors" - "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var _ policies.AuthServiceServer = (*grpcServer)(nil) - -type grpcServer struct { - authorize kitgrpc.Handler - policies.UnimplementedAuthServiceServer -} - -// NewServer returns new AuthServiceServer instance. -func NewServer(svc policies.Service) policies.AuthServiceServer { - return &grpcServer{ - authorize: kitgrpc.NewServer( - otelkit.EndpointMiddleware(otelkit.WithOperation("authorize"))(authorizeEndpoint(svc)), - decodeAuthorizeRequest, - encodeAuthorizeResponse, - ), - } -} - -func (s *grpcServer) Authorize(ctx context.Context, req *policies.AuthorizeReq) (*policies.AuthorizeRes, error) { - _, res, err := s.authorize.ServeGRPC(ctx, req) - if err != nil { - return nil, encodeError(err) - } - return res.(*policies.AuthorizeRes), nil -} - -func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*policies.AuthorizeReq) - return authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub(), EntityType: req.GetEntityType()}, nil -} - -func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { - res := grpcRes.(authorizeRes) - return &policies.AuthorizeRes{Authorized: res.authorized}, nil -} - -func encodeError(err error) error { - switch { - case errors.Contains(err, nil): - return nil - case errors.Contains(err, errors.ErrMalformedEntity), - err == apiutil.ErrInvalidAuthKey, - err == apiutil.ErrMissingID, - err == apiutil.ErrMissingPolicySub, - err == apiutil.ErrMissingPolicyObj, - err == apiutil.ErrMissingPolicyAct, - err == apiutil.ErrMalformedPolicy, - err == apiutil.ErrMissingPolicyOwner, - err == apiutil.ErrHigherPolicyRank: - return status.Error(codes.InvalidArgument, err.Error()) - case errors.Contains(err, errors.ErrAuthentication), - err == apiutil.ErrBearerToken: - return status.Error(codes.Unauthenticated, err.Error()) - case errors.Contains(err, errors.ErrAuthorization): - return status.Error(codes.PermissionDenied, err.Error()) - default: - return status.Error(codes.Internal, "internal server error") - } -} diff --git a/clients/policies/clientauth.pb.go b/clients/policies/clientauth.pb.go deleted file mode 100644 index 9e0f46403f0..00000000000 --- a/clients/policies/clientauth.pb.go +++ /dev/null @@ -1,241 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.12 -// source: clients/policies/clientauth.proto - -package policies - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type AuthorizeReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Sub string `protobuf:"bytes,1,opt,name=sub,proto3" json:"sub,omitempty"` - Obj string `protobuf:"bytes,2,opt,name=obj,proto3" json:"obj,omitempty"` - Act string `protobuf:"bytes,3,opt,name=act,proto3" json:"act,omitempty"` - EntityType string `protobuf:"bytes,4,opt,name=entityType,proto3" json:"entityType,omitempty"` -} - -func (x *AuthorizeReq) Reset() { - *x = AuthorizeReq{} - if protoimpl.UnsafeEnabled { - mi := &file_clients_policies_clientauth_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AuthorizeReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AuthorizeReq) ProtoMessage() {} - -func (x *AuthorizeReq) ProtoReflect() protoreflect.Message { - mi := &file_clients_policies_clientauth_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AuthorizeReq.ProtoReflect.Descriptor instead. -func (*AuthorizeReq) Descriptor() ([]byte, []int) { - return file_clients_policies_clientauth_proto_rawDescGZIP(), []int{0} -} - -func (x *AuthorizeReq) GetSub() string { - if x != nil { - return x.Sub - } - return "" -} - -func (x *AuthorizeReq) GetObj() string { - if x != nil { - return x.Obj - } - return "" -} - -func (x *AuthorizeReq) GetAct() string { - if x != nil { - return x.Act - } - return "" -} - -func (x *AuthorizeReq) GetEntityType() string { - if x != nil { - return x.EntityType - } - return "" -} - -type AuthorizeRes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"` -} - -func (x *AuthorizeRes) Reset() { - *x = AuthorizeRes{} - if protoimpl.UnsafeEnabled { - mi := &file_clients_policies_clientauth_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AuthorizeRes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AuthorizeRes) ProtoMessage() {} - -func (x *AuthorizeRes) ProtoReflect() protoreflect.Message { - mi := &file_clients_policies_clientauth_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AuthorizeRes.ProtoReflect.Descriptor instead. -func (*AuthorizeRes) Descriptor() ([]byte, []int) { - return file_clients_policies_clientauth_proto_rawDescGZIP(), []int{1} -} - -func (x *AuthorizeRes) GetAuthorized() bool { - if x != nil { - return x.Authorized - } - return false -} - -var File_clients_policies_clientauth_proto protoreflect.FileDescriptor - -var file_clients_policies_clientauth_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, - 0x0c, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, - 0x03, 0x73, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x75, 0x62, 0x12, - 0x10, 0x0a, 0x03, 0x6f, 0x62, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x62, - 0x6a, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x2e, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, - 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x65, 0x64, 0x32, 0x4c, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, - 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x22, - 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_clients_policies_clientauth_proto_rawDescOnce sync.Once - file_clients_policies_clientauth_proto_rawDescData = file_clients_policies_clientauth_proto_rawDesc -) - -func file_clients_policies_clientauth_proto_rawDescGZIP() []byte { - file_clients_policies_clientauth_proto_rawDescOnce.Do(func() { - file_clients_policies_clientauth_proto_rawDescData = protoimpl.X.CompressGZIP(file_clients_policies_clientauth_proto_rawDescData) - }) - return file_clients_policies_clientauth_proto_rawDescData -} - -var file_clients_policies_clientauth_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_clients_policies_clientauth_proto_goTypes = []interface{}{ - (*AuthorizeReq)(nil), // 0: policies.AuthorizeReq - (*AuthorizeRes)(nil), // 1: policies.AuthorizeRes -} -var file_clients_policies_clientauth_proto_depIdxs = []int32{ - 0, // 0: policies.AuthService.Authorize:input_type -> policies.AuthorizeReq - 1, // 1: policies.AuthService.Authorize:output_type -> policies.AuthorizeRes - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_clients_policies_clientauth_proto_init() } -func file_clients_policies_clientauth_proto_init() { - if File_clients_policies_clientauth_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_clients_policies_clientauth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthorizeReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_clients_policies_clientauth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthorizeRes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_clients_policies_clientauth_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_clients_policies_clientauth_proto_goTypes, - DependencyIndexes: file_clients_policies_clientauth_proto_depIdxs, - MessageInfos: file_clients_policies_clientauth_proto_msgTypes, - }.Build() - File_clients_policies_clientauth_proto = out.File - file_clients_policies_clientauth_proto_rawDesc = nil - file_clients_policies_clientauth_proto_goTypes = nil - file_clients_policies_clientauth_proto_depIdxs = nil -} diff --git a/clients/policies/clientauth.proto b/clients/policies/clientauth.proto deleted file mode 100644 index 625b832af7d..00000000000 --- a/clients/policies/clientauth.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; - -package policies; - -option go_package = "./policies"; - -service AuthService { - rpc Authorize(AuthorizeReq) returns (AuthorizeRes) {} -} - -message AuthorizeReq { - string sub = 1; - string obj = 2; - string act = 3; - string entityType = 4; -} -message AuthorizeRes { - bool authorized = 1; -} diff --git a/clients/policies/clientauth_grpc.pb.go b/clients/policies/clientauth_grpc.pb.go deleted file mode 100644 index e2006745a09..00000000000 --- a/clients/policies/clientauth_grpc.pb.go +++ /dev/null @@ -1,105 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 -// source: clients/policies/clientauth.proto - -package policies - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// AuthServiceClient is the client API for AuthService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type AuthServiceClient interface { - Authorize(ctx context.Context, in *AuthorizeReq, opts ...grpc.CallOption) (*AuthorizeRes, error) -} - -type authServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient { - return &authServiceClient{cc} -} - -func (c *authServiceClient) Authorize(ctx context.Context, in *AuthorizeReq, opts ...grpc.CallOption) (*AuthorizeRes, error) { - out := new(AuthorizeRes) - err := c.cc.Invoke(ctx, "/policies.AuthService/Authorize", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// AuthServiceServer is the server API for AuthService service. -// All implementations must embed UnimplementedAuthServiceServer -// for forward compatibility -type AuthServiceServer interface { - Authorize(context.Context, *AuthorizeReq) (*AuthorizeRes, error) - mustEmbedUnimplementedAuthServiceServer() -} - -// UnimplementedAuthServiceServer must be embedded to have forward compatible implementations. -type UnimplementedAuthServiceServer struct { -} - -func (UnimplementedAuthServiceServer) Authorize(context.Context, *AuthorizeReq) (*AuthorizeRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Authorize not implemented") -} -func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {} - -// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to AuthServiceServer will -// result in compilation errors. -type UnsafeAuthServiceServer interface { - mustEmbedUnimplementedAuthServiceServer() -} - -func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) { - s.RegisterService(&AuthService_ServiceDesc, srv) -} - -func _AuthService_Authorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AuthorizeReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AuthServiceServer).Authorize(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/policies.AuthService/Authorize", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AuthServiceServer).Authorize(ctx, req.(*AuthorizeReq)) - } - return interceptor(ctx, in, info, handler) -} - -// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var AuthService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "policies.AuthService", - HandlerType: (*AuthServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Authorize", - Handler: _AuthService_Authorize_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "clients/policies/clientauth.proto", -} diff --git a/clients/postgres/init.go b/clients/postgres/init.go deleted file mode 100644 index a333c281ca6..00000000000 --- a/clients/postgres/init.go +++ /dev/null @@ -1,93 +0,0 @@ -package postgres - -import ( - "fmt" - - _ "github.com/jackc/pgx/v5/stdlib" // required for SQL access - "github.com/jmoiron/sqlx" - migrate "github.com/rubenv/sql-migrate" -) - -// Config defines the options that are used when connecting to a PostgreSQL instance -type Config struct { - Host string - Port string - User string - Pass string - Name string - SSLMode string - SSLCert string - SSLKey string - SSLRootCert string -} - -// Connect creates a connection to the PostgreSQL instance and applies any -// unapplied database migrations. A non-nil error is returned to indicate -// failure. -func Connect(cfg Config) (*sqlx.DB, error) { - url := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s", cfg.Host, cfg.Port, cfg.User, cfg.Name, cfg.Pass, cfg.SSLMode, cfg.SSLCert, cfg.SSLKey, cfg.SSLRootCert) - db, err := sqlx.Open("pgx", url) - if err != nil { - return nil, err - } - - if err := migrateDB(db); err != nil { - return nil, err - } - return db, nil -} - -func migrateDB(db *sqlx.DB) error { - migrations := &migrate.MemoryMigrationSource{ - Migrations: []*migrate.Migration{ - { - Id: "clients_01", - Up: []string{ - `CREATE TABLE IF NOT EXISTS clients ( - id VARCHAR(254) PRIMARY KEY, - name VARCHAR(254), - owner VARCHAR(254), - identity VARCHAR(254) UNIQUE NOT NULL, - secret TEXT NOT NULL, - tags TEXT[], - metadata JSONB, - created_at TIMESTAMP, - updated_at TIMESTAMP, - status SMALLINT NOT NULL CHECK (status >= 0) DEFAULT 1 - )`, - `CREATE TABLE IF NOT EXISTS groups ( - id VARCHAR(254) PRIMARY KEY, - parent_id VARCHAR(254), - owner_id VARCHAR(254) NOT NULL, - name VARCHAR(254) NOT NULL, - description VARCHAR(1024), - metadata JSONB, - created_at TIMESTAMP, - updated_at TIMESTAMP, - status SMALLINT NOT NULL CHECK (status >= 0) DEFAULT 1, - UNIQUE (owner_id, name), - FOREIGN KEY (parent_id) REFERENCES groups (id) ON DELETE CASCADE - )`, - `CREATE TABLE IF NOT EXISTS policies ( - owner_id VARCHAR(254) NOT NULL, - subject VARCHAR(254) NOT NULL, - object VARCHAR(254) NOT NULL, - actions TEXT[] NOT NULL, - created_at TIMESTAMP, - updated_at TIMESTAMP, - FOREIGN KEY (subject) REFERENCES clients (id), - PRIMARY KEY (subject, object, actions) - )`, - }, - Down: []string{ - `DROP TABLE IF EXISTS clients`, - `DROP TABLE IF EXISTS groups`, - `DROP TABLE IF EXISTS memberships`, - }, - }, - }, - } - - _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up) - return err -} diff --git a/cmd/auth/main.go b/cmd/auth/main.go deleted file mode 100644 index 573a4d8bd94..00000000000 --- a/cmd/auth/main.go +++ /dev/null @@ -1,163 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "os" - "time" - - "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - api "github.com/mainflux/mainflux/auth/api" - grpcapi "github.com/mainflux/mainflux/auth/api/grpc" - httpapi "github.com/mainflux/mainflux/auth/api/http" - "github.com/mainflux/mainflux/auth/jwt" - "github.com/mainflux/mainflux/auth/keto" - authPg "github.com/mainflux/mainflux/auth/postgres" - "github.com/mainflux/mainflux/auth/tracing" - "github.com/mainflux/mainflux/internal" - grpcClient "github.com/mainflux/mainflux/internal/clients/grpc" - jaegerClient "github.com/mainflux/mainflux/internal/clients/jaeger" - pgClient "github.com/mainflux/mainflux/internal/clients/postgres" - "github.com/mainflux/mainflux/internal/env" - "github.com/mainflux/mainflux/internal/server" - grpcserver "github.com/mainflux/mainflux/internal/server/grpc" - httpserver "github.com/mainflux/mainflux/internal/server/http" - mflog "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/opentracing/opentracing-go" - acl "github.com/ory/keto/proto/ory/keto/acl/v1alpha1" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc" -) - -const ( - svcName = "auth" - envPrefix = "MF_AUTH_" - envPrefixHttp = "MF_AUTH_HTTP_" - envPrefixGrpc = "MF_AUTH_GRPC_" - defDB = "auth" - defSvcHttpPort = "8180" - defSvcGrpcPort = "8181" -) - -type config struct { - LogLevel string `env:"MF_AUTH_LOG_LEVEL" envDefault:"info"` - Secret string `env:"MF_AUTH_SECRET" envDefault:"auth"` - KetoReadHost string `env:"MF_KETO_READ_REMOTE_HOST" envDefault:"mainflux-keto"` - KetoReadPort string `env:"MF_KETO_READ_REMOTE_PORT" envDefault:"4466"` - KetoWriteHost string `env:"MF_KETO_WRITE_REMOTE_HOST" envDefault:"mainflux-keto"` - KetoWritePort string `env:"MF_KETO_WRITE_REMOTE_PORT" envDefault:"4467"` - LoginDuration time.Duration `env:"MF_AUTH_LOGIN_TOKEN_DURATION" envDefault:"10h"` - JaegerURL string `env:"MF_JAEGER_URL" envDefault:"localhost:6831"` -} - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - g, ctx := errgroup.WithContext(ctx) - - // Create auth service configurations - cfg := config{} - if err := env.Parse(&cfg); err != nil { - log.Fatalf("failed to load %s configuration : %s", svcName, err) - } - - logger, err := mflog.New(os.Stdout, cfg.LogLevel) - if err != nil { - log.Fatalf("failed to init logger: %s", err) - } - - // Create new postgres client - dbConfig := pgClient.Config{Name: defDB} - db, err := pgClient.SetupWithConfig(envPrefix, *authPg.Migration(), dbConfig) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to setup postgres database : %s", err)) - } - defer db.Close() - - // Create new tracer for database - dbTracer, dbCloser, err := jaegerClient.NewTracer("auth_db", cfg.JaegerURL) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to init Jaeger: %s", err)) - } - defer dbCloser.Close() - - // Create new keto reader grpc client - readerConn, _, err := grpcClient.Connect(grpcClient.Config{ClientTLS: false, URL: fmt.Sprintf("%s:%s", cfg.KetoReadHost, cfg.KetoReadPort)}) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to connect to keto gRPC: %s", err)) - } - - // Create new keto writer grpc client - writerConn, _, err := grpcClient.Connect(grpcClient.Config{ClientTLS: false, URL: fmt.Sprintf("%s:%s", cfg.KetoWriteHost, cfg.KetoWritePort)}) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to connect to keto gRPC: %s", err)) - } - - svc := newService(db, dbTracer, cfg.Secret, logger, readerConn, writerConn, cfg.LoginDuration) - - // Create new HTTP Server - tracer, closer, err := jaegerClient.NewTracer("auth", cfg.JaegerURL) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to init Jaeger: %s", err)) - } - defer closer.Close() - - httpServerConfig := server.Config{Port: defSvcHttpPort} - - if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { - logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) - } - - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, httpapi.MakeHandler(svc, tracer, logger), logger) - - // Create new grpc server - grpcServerConfig := server.Config{Port: defSvcGrpcPort} - - if err := env.Parse(&grpcServerConfig, env.Options{Prefix: envPrefixGrpc, AltPrefix: envPrefix}); err != nil { - logger.Fatal(fmt.Sprintf("failed to load %s gRPC server configuration : %s", svcName, err)) - } - registerAuthServiceServer := func(srv *grpc.Server) { - mainflux.RegisterAuthServiceServer(srv, grpcapi.NewServer(tracer, svc)) - } - - gs := grpcserver.New(ctx, cancel, svcName, grpcServerConfig, registerAuthServiceServer, logger) - - // Start servers - g.Go(func() error { - return hs.Start() - }) - g.Go(func() error { - return gs.Start() - }) - - g.Go(func() error { - return server.StopSignalHandler(ctx, cancel, logger, svcName, hs, gs) - }) - if err := g.Wait(); err != nil { - logger.Error(fmt.Sprintf("Authentication service terminated: %s", err)) - } -} - -func newService(db *sqlx.DB, tracer opentracing.Tracer, secret string, logger mflog.Logger, readerConn, writerConn *grpc.ClientConn, duration time.Duration) auth.Service { - database := authPg.NewDatabase(db) - keysRepo := tracing.New(authPg.New(database), tracer) - - groupsRepo := authPg.NewGroupRepo(database) - groupsRepo = tracing.GroupRepositoryMiddleware(tracer, groupsRepo) - - pa := keto.NewPolicyAgent(acl.NewCheckServiceClient(readerConn), acl.NewWriteServiceClient(writerConn), acl.NewReadServiceClient(readerConn)) - - idProvider := uuid.New() - t := jwt.New(secret) - - svc := auth.New(keysRepo, groupsRepo, idProvider, t, pa, duration) - svc = api.LoggingMiddleware(svc, logger) - - counter, latency := internal.MakeMetrics(svcName, "api") - svc = api.MetricsMiddleware(svc, counter, latency) - - return svc -} diff --git a/cmd/bootstrap/main.go b/cmd/bootstrap/main.go index c4a729425c4..afec74b6376 100644 --- a/cmd/bootstrap/main.go +++ b/cmd/bootstrap/main.go @@ -8,11 +8,6 @@ import ( "log" "os" - r "github.com/go-redis/redis/v8" - "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/bootstrap" - api "github.com/mainflux/mainflux/bootstrap/api" bootstrapPg "github.com/mainflux/mainflux/bootstrap/postgres" rediscons "github.com/mainflux/mainflux/bootstrap/redis/consumer" redisprod "github.com/mainflux/mainflux/bootstrap/redis/producer" @@ -25,7 +20,13 @@ import ( httpserver "github.com/mainflux/mainflux/internal/server/http" mflog "github.com/mainflux/mainflux/logger" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" + "github.com/mainflux/mainflux/users/policies" "golang.org/x/sync/errgroup" + + r "github.com/go-redis/redis/v8" + "github.com/jmoiron/sqlx" + "github.com/mainflux/mainflux/bootstrap" + api "github.com/mainflux/mainflux/bootstrap/api" ) const ( @@ -115,7 +116,7 @@ func main() { } } -func newService(auth mainflux.AuthServiceClient, db *sqlx.DB, logger mflog.Logger, esClient *r.Client, cfg config) bootstrap.Service { +func newService(auth policies.AuthServiceClient, db *sqlx.DB, logger mflog.Logger, esClient *r.Client, cfg config) bootstrap.Service { repoConfig := bootstrapPg.NewConfigRepository(db, logger) config := mfsdk.Config{ diff --git a/cmd/cassandra-reader/main.go b/cmd/cassandra-reader/main.go index 3efee2fae88..d80ddba193d 100644 --- a/cmd/cassandra-reader/main.go +++ b/cmd/cassandra-reader/main.go @@ -85,7 +85,7 @@ func main() { logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName, logger), logger) + hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName), logger) // Start servers g.Go(func() error { diff --git a/cmd/certs/main.go b/cmd/certs/main.go index fb7c3dc62d3..43962f88a91 100644 --- a/cmd/certs/main.go +++ b/cmd/certs/main.go @@ -10,8 +10,6 @@ import ( "log" "os" - "github.com/go-redis/redis/v8" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/certs" "github.com/mainflux/mainflux/certs/api" vault "github.com/mainflux/mainflux/certs/pki" @@ -21,6 +19,7 @@ import ( "github.com/mainflux/mainflux/internal/server" httpserver "github.com/mainflux/mainflux/internal/server/http" mflog "github.com/mainflux/mainflux/logger" + "github.com/mainflux/mainflux/users/policies" "golang.org/x/sync/errgroup" "github.com/jmoiron/sqlx" @@ -107,7 +106,7 @@ func main() { defer authHandler.Close() logger.Info("Successfully connected to auth grpc server " + authHandler.Secure()) - svc := newService(auth, db, logger, nil, tlsCert, caCert, cfg, pkiClient) + svc := newService(auth, db, logger, tlsCert, caCert, cfg, pkiClient) httpServerConfig := server.Config{Port: defSvcHttpPort} if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { @@ -128,7 +127,7 @@ func main() { } } -func newService(auth mainflux.AuthServiceClient, db *sqlx.DB, logger mflog.Logger, esClient *redis.Client, tlsCert tls.Certificate, x509Cert *x509.Certificate, cfg config, pkiAgent vault.Agent) certs.Service { +func newService(auth policies.AuthServiceClient, db *sqlx.DB, logger mflog.Logger, tlsCert tls.Certificate, x509Cert *x509.Certificate, cfg config, pkiAgent vault.Agent) certs.Service { certsRepo := certsPg.NewRepository(db, logger) config := mfsdk.Config{ CertsURL: cfg.CertsURL, diff --git a/cmd/cli/main.go b/cmd/cli/main.go index c7351a40ae9..6c2cf9889a8 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -50,7 +50,6 @@ func main() { provisionCmd := cli.NewProvisionCmd() bootstrapCmd := cli.NewBootstrapCmd() certsCmd := cli.NewCertsCmd() - keysCmd := cli.NewKeysCmd() // Root Commands rootCmd.AddCommand(healthCmd) @@ -62,7 +61,6 @@ func main() { rootCmd.AddCommand(provisionCmd) rootCmd.AddCommand(bootstrapCmd) rootCmd.AddCommand(certsCmd) - rootCmd.AddCommand(keysCmd) // Root Flags rootCmd.PersistentFlags().StringVarP( diff --git a/cmd/clients/main.go b/cmd/clients/main.go deleted file mode 100644 index 1c3d0dac3dd..00000000000 --- a/cmd/clients/main.go +++ /dev/null @@ -1,409 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "net" - "net/http" - "os" - "time" - - kitprometheus "github.com/go-kit/kit/metrics/prometheus" - "github.com/go-zoo/bone" - "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/clients" - capi "github.com/mainflux/mainflux/clients/clients/api" - cpostgres "github.com/mainflux/mainflux/clients/clients/postgres" - ctracing "github.com/mainflux/mainflux/clients/clients/tracing" - "github.com/mainflux/mainflux/clients/groups" - gapi "github.com/mainflux/mainflux/clients/groups/api" - gpostgres "github.com/mainflux/mainflux/clients/groups/postgres" - gtracing "github.com/mainflux/mainflux/clients/groups/tracing" - "github.com/mainflux/mainflux/clients/hasher" - "github.com/mainflux/mainflux/clients/jwt" - "github.com/mainflux/mainflux/clients/policies" - grpcapi "github.com/mainflux/mainflux/clients/policies/api/grpc" - papi "github.com/mainflux/mainflux/clients/policies/api/http" - ppostgres "github.com/mainflux/mainflux/clients/policies/postgres" - ppracing "github.com/mainflux/mainflux/clients/policies/tracing" - "github.com/mainflux/mainflux/clients/postgres" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - stdprometheus "github.com/prometheus/client_golang/prometheus" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/jaeger" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/resource" - tracesdk "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.12.0" - "go.opentelemetry.io/otel/trace" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/reflection" -) - -const ( - svcName = "clients" - stopWaitTime = 5 * time.Second - - defLogLevel = "debug" - defSecretKey = "clientsecret" - defAdminIdentity = "admin@example.com" - defAdminSecret = "12345678" - defDBHost = "localhost" - defDBPort = "5432" - defDBUser = "mainflux" - defDBPass = "mainflux" - defDB = "clients" - defDBSSLMode = "disable" - defDBSSLCert = "" - defDBSSLKey = "" - defDBSSLRootCert = "" - defHTTPPort = "9191" - defGRPCPort = "9192" - defServerCert = "" - defServerKey = "" - defJaegerURL = "http://localhost:6831" - - envLogLevel = "MF_CLIENTS_LOG_LEVEL" - envSecretKey = "MF_CLIENTS_SECRET_KEY" - envAdminIdentity = "MF_CLIENTS_ADMIN_EMAIL" - envAdminSecret = "MF_CLIENTS_ADMIN_PASSWORD" - envDBHost = "MF_CLIENTS_DB_HOST" - envDBPort = "MF_CLIENTS_DB_PORT" - envDBUser = "MF_CLIENTS_DB_USER" - envDBPass = "MF_CLIENTS_DB_PASS" - envDB = "MF_CLIENTS_DB" - envDBSSLMode = "MF_CLIENTS_DB_SSL_MODE" - envDBSSLCert = "MF_CLIENTS_DB_SSL_CERT" - envDBSSLKey = "MF_CLIENTS_DB_SSL_KEY" - envDBSSLRootCert = "MF_CLIENTS_DB_SSL_ROOT_CERT" - envHTTPPort = "MF_CLIENTS_HTTP_PORT" - envGRPCPort = "MF_CLIENTS_GRPC_PORT" - envServerCert = "MF_CLIENTS_SERVER_CERT" - envServerKey = "MF_CLIENTS_SERVER_KEY" - envJaegerURL = "MF_CLIENTS_JAEGER_URL" -) - -type config struct { - logLevel string - secretKey string - adminIdentity string - adminSecret string - dbConfig postgres.Config - httpPort string - grpcPort string - serverCert string - serverKey string - jaegerURL string -} - -func main() { - cfg := loadConfig() - ctx, cancel := context.WithCancel(context.Background()) - g, ctx := errgroup.WithContext(ctx) - - logger, err := logger.New(os.Stdout, cfg.logLevel) - if err != nil { - log.Fatalf(err.Error()) - } - db := connectToDB(cfg.dbConfig, logger) - defer db.Close() - - tp, err := initJaeger(svcName, cfg.jaegerURL) - if err != nil { - logger.Error(fmt.Sprintf("Failed to init Jaeger: %s", err)) - } - defer func() { - if err := tp.Shutdown(context.Background()); err != nil { - logger.Error(fmt.Sprintf("Error shutting down tracer provider: %v", err)) - } - }() - tracer := otel.Tracer(svcName) - - csvc, gsvc, psvc := newService(db, tracer, cfg, logger) - - g.Go(func() error { - return startHTTPServer(ctx, csvc, gsvc, psvc, cfg.httpPort, cfg.serverCert, cfg.serverKey, logger) - }) - g.Go(func() error { - return startGRPCServer(ctx, psvc, cfg.grpcPort, cfg.serverCert, cfg.serverKey, logger) - }) - - g.Go(func() error { - if sig := errors.SignalHandler(ctx); sig != nil { - cancel() - logger.Info(fmt.Sprintf("%s service shutdown by signal: %s", svcName, sig)) - } - return nil - }) - - if err := g.Wait(); err != nil { - logger.Error(fmt.Sprintf("%s service terminated: %s", svcName, err)) - } -} - -func loadConfig() config { - dbConfig := postgres.Config{ - Host: mainflux.Env(envDBHost, defDBHost), - Port: mainflux.Env(envDBPort, defDBPort), - User: mainflux.Env(envDBUser, defDBUser), - Pass: mainflux.Env(envDBPass, defDBPass), - Name: mainflux.Env(envDB, defDB), - SSLMode: mainflux.Env(envDBSSLMode, defDBSSLMode), - SSLCert: mainflux.Env(envDBSSLCert, defDBSSLCert), - SSLKey: mainflux.Env(envDBSSLKey, defDBSSLKey), - SSLRootCert: mainflux.Env(envDBSSLRootCert, defDBSSLRootCert), - } - - return config{ - logLevel: mainflux.Env(envLogLevel, defLogLevel), - secretKey: mainflux.Env(envSecretKey, defSecretKey), - adminIdentity: mainflux.Env(envAdminIdentity, defAdminIdentity), - adminSecret: mainflux.Env(envAdminSecret, defAdminSecret), - dbConfig: dbConfig, - httpPort: mainflux.Env(envHTTPPort, defHTTPPort), - grpcPort: mainflux.Env(envGRPCPort, defGRPCPort), - serverCert: mainflux.Env(envServerCert, defServerCert), - serverKey: mainflux.Env(envServerKey, defServerKey), - jaegerURL: mainflux.Env(envJaegerURL, defJaegerURL), - } - -} - -func initJaeger(svcName, url string) (*tracesdk.TracerProvider, error) { - exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url))) - if err != nil { - return nil, err - } - tp := tracesdk.NewTracerProvider( - tracesdk.WithSampler(tracesdk.AlwaysSample()), - tracesdk.WithBatcher(exporter), - tracesdk.WithSpanProcessor(tracesdk.NewBatchSpanProcessor(exporter)), - tracesdk.WithResource(resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(svcName), - )), - ) - otel.SetTracerProvider(tp) - otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) - - return tp, nil -} - -func connectToDB(dbConfig postgres.Config, logger logger.Logger) *sqlx.DB { - db, err := postgres.Connect(dbConfig) - if err != nil { - logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err)) - os.Exit(1) - } - return db -} - -func newService(db *sqlx.DB, tracer trace.Tracer, c config, logger logger.Logger) (clients.Service, groups.GroupService, policies.PolicyService) { - database := postgres.NewDatabase(db, tracer) - cRepo := cpostgres.NewClientRepo(database) - gRepo := gpostgres.NewGroupRepo(database) - pRepo := ppostgres.NewPolicyRepo(database) - - idp := uuid.New() - hsr := hasher.New() - - tokenizer := jwt.NewTokenRepo([]byte(c.secretKey)) - tokenizer = jwt.NewTokenRepoMiddleware(tokenizer, tracer) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, hsr, idp) - gsvc := groups.NewService(gRepo, pRepo, tokenizer, idp) - psvc := policies.NewService(pRepo, tokenizer, idp) - - csvc = ctracing.TracingMiddleware(csvc, tracer) - csvc = capi.LoggingMiddleware(csvc, logger) - csvc = capi.MetricsMiddleware( - csvc, - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: svcName, - Subsystem: "api", - Name: "request_count", - Help: "Number of requests received.", - }, []string{"method"}), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: svcName, - Subsystem: "api", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, []string{"method"}), - ) - - gsvc = gtracing.TracingMiddleware(gsvc, tracer) - gsvc = gapi.LoggingMiddleware(gsvc, logger) - gsvc = gapi.MetricsMiddleware( - gsvc, - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "clients_groups", - Subsystem: "api", - Name: "request_count", - Help: "Number of requests received.", - }, []string{"method"}), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "clients_groups", - Subsystem: "api", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, []string{"method"}), - ) - - psvc = ppracing.TracingMiddleware(psvc, tracer) - psvc = papi.LoggingMiddleware(psvc, logger) - psvc = papi.MetricsMiddleware( - psvc, - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "client_policies", - Subsystem: "api", - Name: "request_count", - Help: "Number of requests received.", - }, []string{"method"}), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "client_policies", - Subsystem: "api", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, []string{"method"}), - ) - - if err := createAdmin(c, cRepo, hsr, csvc); err != nil { - logger.Error(fmt.Sprintf("Failed to create admin client: %s", err)) - os.Exit(1) - } - return csvc, gsvc, psvc -} - -func startHTTPServer(ctx context.Context, csvc clients.Service, gsvc groups.Service, psvc policies.Service, port string, certFile string, keyFile string, logger logger.Logger) error { - p := fmt.Sprintf(":%s", port) - errCh := make(chan error) - m := bone.New() - capi.MakeClientsHandler(csvc, m, logger) - gapi.MakeGroupsHandler(gsvc, m, logger) - papi.MakePolicyHandler(psvc, m, logger) - server := &http.Server{Addr: p, Handler: m} - - switch { - case certFile != "" || keyFile != "": - logger.Info(fmt.Sprintf("Clients service started using https, cert %s key %s, exposed port %s", certFile, keyFile, port)) - go func() { - errCh <- server.ListenAndServeTLS(certFile, keyFile) - }() - default: - logger.Info(fmt.Sprintf("Clients service started using http, exposed port %s", port)) - go func() { - errCh <- server.ListenAndServe() - }() - } - - select { - case <-ctx.Done(): - ctxShutdown, cancelShutdown := context.WithTimeout(context.Background(), stopWaitTime) - defer cancelShutdown() - if err := server.Shutdown(ctxShutdown); err != nil { - logger.Error(fmt.Sprintf("Clients service error occurred during shutdown at %s: %s", p, err)) - return fmt.Errorf("clients service occurred during shutdown at %s: %w", p, err) - } - logger.Info(fmt.Sprintf("Clients service shutdown of http at %s", p)) - return nil - case err := <-errCh: - return err - } - -} - -func startGRPCServer(ctx context.Context, svc policies.Service, port string, certFile string, keyFile string, logger logger.Logger) error { - p := fmt.Sprintf(":%s", port) - errCh := make(chan error) - - listener, err := net.Listen("tcp", p) - if err != nil { - return fmt.Errorf("failed to listen on port %s: %w", port, err) - } - - var server *grpc.Server - switch { - case certFile != "" || keyFile != "": - creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) - if err != nil { - return fmt.Errorf("failed to load auth certificates: %w", err) - } - logger.Info(fmt.Sprintf("Clients gRPC service started using https on port %s with cert %s key %s", port, certFile, keyFile)) - server = grpc.NewServer(grpc.Creds(creds)) - default: - logger.Info(fmt.Sprintf("Clients gRPC service started using http on port %s", port)) - server = grpc.NewServer() - } - - reflection.Register(server) - policies.RegisterAuthServiceServer(server, grpcapi.NewServer(svc)) - logger.Info(fmt.Sprintf("Clients gRPC service started, exposed port %s", port)) - go func() { - errCh <- server.Serve(listener) - }() - - select { - case <-ctx.Done(): - c := make(chan bool) - go func() { - defer close(c) - server.GracefulStop() - }() - select { - case <-c: - case <-time.After(stopWaitTime): - } - logger.Info(fmt.Sprintf("Authentication gRPC service shutdown at %s", p)) - return nil - case err := <-errCh: - return err - } -} - -func createAdmin(c config, crepo clients.ClientRepository, hsr clients.Hasher, svc clients.Service) error { - id, err := uuid.New().ID() - if err != nil { - return err - } - hash, err := hsr.Hash(c.adminSecret) - if err != nil { - return err - } - - client := clients.Client{ - ID: id, - Name: "admin", - Credentials: clients.Credentials{ - Identity: c.adminIdentity, - Secret: hash, - }, - Metadata: clients.Metadata{ - "role": "admin", - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - Status: clients.EnabledStatus, - } - - if _, err := crepo.RetrieveByIdentity(context.Background(), client.Credentials.Identity); err == nil { - return nil - } - - // Create an admin - if _, err = crepo.Save(context.Background(), client); err != nil { - return err - } - _, err = svc.IssueToken(context.Background(), c.adminIdentity, c.adminSecret) - if err != nil { - return err - } - - return nil -} diff --git a/cmd/influxdb-reader/main.go b/cmd/influxdb-reader/main.go index c30545e4cf6..0bb631fcdd0 100644 --- a/cmd/influxdb-reader/main.go +++ b/cmd/influxdb-reader/main.go @@ -78,7 +78,7 @@ func main() { if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName, logger), logger) + hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName), logger) g.Go(func() error { return hs.Start() diff --git a/cmd/mongodb-reader/main.go b/cmd/mongodb-reader/main.go index 247f1047898..95cbaf437e6 100644 --- a/cmd/mongodb-reader/main.go +++ b/cmd/mongodb-reader/main.go @@ -76,7 +76,7 @@ func main() { if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName, logger), logger) + hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName), logger) g.Go(func() error { return hs.Start() diff --git a/cmd/postgres-reader/main.go b/cmd/postgres-reader/main.go index 1fa3643e616..e6aa2ce4606 100644 --- a/cmd/postgres-reader/main.go +++ b/cmd/postgres-reader/main.go @@ -81,7 +81,7 @@ func main() { if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName, logger), logger) + hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName), logger) g.Go(func() error { return hs.Start() diff --git a/cmd/smpp-notifier/main.go b/cmd/smpp-notifier/main.go index 2575d84ec42..a8746651e3d 100644 --- a/cmd/smpp-notifier/main.go +++ b/cmd/smpp-notifier/main.go @@ -10,7 +10,6 @@ import ( "os" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/consumers" "github.com/mainflux/mainflux/consumers/notifiers" "github.com/mainflux/mainflux/consumers/notifiers/api" @@ -19,6 +18,7 @@ import ( "github.com/mainflux/mainflux/internal/env" "github.com/mainflux/mainflux/internal/server" httpserver "github.com/mainflux/mainflux/internal/server/http" + "github.com/mainflux/mainflux/users/policies" "golang.org/x/sync/errgroup" mfsmpp "github.com/mainflux/mainflux/consumers/notifiers/smpp" @@ -125,7 +125,7 @@ func main() { } -func newService(db *sqlx.DB, tracer opentracing.Tracer, auth mainflux.AuthServiceClient, c config, sc mfsmpp.Config, logger mflog.Logger) notifiers.Service { +func newService(db *sqlx.DB, tracer opentracing.Tracer, auth policies.AuthServiceClient, c config, sc mfsmpp.Config, logger mflog.Logger) notifiers.Service { database := notifierPg.NewDatabase(db) repo := tracing.New(notifierPg.New(database), tracer) idp := ulid.New() diff --git a/cmd/smtp-notifier/main.go b/cmd/smtp-notifier/main.go index d4959afa033..bb228305678 100644 --- a/cmd/smtp-notifier/main.go +++ b/cmd/smtp-notifier/main.go @@ -10,7 +10,6 @@ import ( "os" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/consumers" "github.com/mainflux/mainflux/consumers/notifiers" "github.com/mainflux/mainflux/consumers/notifiers/api" @@ -28,6 +27,7 @@ import ( mflog "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/messaging/brokers" "github.com/mainflux/mainflux/pkg/ulid" + "github.com/mainflux/mainflux/users/policies" opentracing "github.com/opentracing/opentracing-go" "golang.org/x/sync/errgroup" ) @@ -125,7 +125,7 @@ func main() { } -func newService(db *sqlx.DB, tracer opentracing.Tracer, auth mainflux.AuthServiceClient, c config, ec email.Config, logger mflog.Logger) notifiers.Service { +func newService(db *sqlx.DB, tracer opentracing.Tracer, auth policies.AuthServiceClient, c config, ec email.Config, logger mflog.Logger) notifiers.Service { database := notifierPg.NewDatabase(db) repo := tracing.New(notifierPg.New(database), tracer) idp := ulid.New() diff --git a/cmd/things/main.go b/cmd/things/main.go index 785064d8dc5..83419600d20 100644 --- a/cmd/things/main.go +++ b/cmd/things/main.go @@ -31,6 +31,7 @@ import ( thingsPg "github.com/mainflux/mainflux/things/postgres" rediscache "github.com/mainflux/mainflux/things/redis" "github.com/mainflux/mainflux/things/tracing" + "github.com/mainflux/mainflux/users/policies" opentracing "github.com/opentracing/opentracing-go" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -171,7 +172,7 @@ func main() { } } -func newService(auth mainflux.AuthServiceClient, dbTracer opentracing.Tracer, cacheTracer opentracing.Tracer, db *sqlx.DB, cacheClient *redis.Client, esClient *redis.Client, logger mflog.Logger) things.Service { +func newService(auth policies.AuthServiceClient, dbTracer opentracing.Tracer, cacheTracer opentracing.Tracer, db *sqlx.DB, cacheClient *redis.Client, esClient *redis.Client, logger mflog.Logger) things.Service { database := thingsPg.NewDatabase(db) thingsRepo := thingsPg.NewThingRepository(database) diff --git a/cmd/timescale-reader/main.go b/cmd/timescale-reader/main.go index a2c0b780a19..4bf0c44534c 100644 --- a/cmd/timescale-reader/main.go +++ b/cmd/timescale-reader/main.go @@ -81,7 +81,7 @@ func main() { if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName, logger), logger) + hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, tc, auth, svcName), logger) g.Go(func() error { return hs.Start() diff --git a/cmd/twins/main.go b/cmd/twins/main.go index c815e6d0bce..245e06b0138 100644 --- a/cmd/twins/main.go +++ b/cmd/twins/main.go @@ -10,7 +10,6 @@ import ( "os" "github.com/go-redis/redis/v8" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/internal" authClient "github.com/mainflux/mainflux/internal/clients/grpc/auth" jaegerClient "github.com/mainflux/mainflux/internal/clients/jaeger" @@ -30,6 +29,7 @@ import ( twmongodb "github.com/mainflux/mainflux/twins/mongodb" rediscache "github.com/mainflux/mainflux/twins/redis" "github.com/mainflux/mainflux/twins/tracing" + "github.com/mainflux/mainflux/users/policies" opentracing "github.com/opentracing/opentracing-go" "go.mongodb.org/mongo-driver/mongo" "golang.org/x/sync/errgroup" @@ -90,7 +90,7 @@ func main() { } defer dbCloser.Close() - var auth mainflux.AuthServiceClient + var auth policies.AuthServiceClient switch cfg.StandaloneEmail != "" && cfg.StandaloneToken != "" { case true: auth = localusers.NewAuthService(cfg.StandaloneEmail, cfg.StandaloneToken) @@ -137,7 +137,7 @@ func main() { } } -func newService(id string, ps messaging.PubSub, chanID string, users mainflux.AuthServiceClient, dbTracer opentracing.Tracer, db *mongo.Database, cacheTracer opentracing.Tracer, cacheClient *redis.Client, logger mflog.Logger) twins.Service { +func newService(id string, ps messaging.PubSub, chanID string, users policies.AuthServiceClient, dbTracer opentracing.Tracer, db *mongo.Database, cacheTracer opentracing.Tracer, cacheClient *redis.Client, logger mflog.Logger) twins.Service { twinRepo := twmongodb.NewTwinRepository(db) twinRepo = tracing.TwinRepositoryMiddleware(dbTracer, twinRepo) diff --git a/cmd/users/main.go b/cmd/users/main.go index b47337a3703..306f48b3aae 100644 --- a/cmd/users/main.go +++ b/cmd/users/main.go @@ -9,46 +9,65 @@ import ( "log" "os" "regexp" + "time" + "github.com/go-zoo/bone" + "github.com/jmoiron/sqlx" "github.com/mainflux/mainflux/internal" - authClient "github.com/mainflux/mainflux/internal/clients/grpc/auth" pgClient "github.com/mainflux/mainflux/internal/clients/postgres" "github.com/mainflux/mainflux/internal/email" "github.com/mainflux/mainflux/internal/env" "github.com/mainflux/mainflux/internal/server" + grpcserver "github.com/mainflux/mainflux/internal/server/grpc" httpserver "github.com/mainflux/mainflux/internal/server/http" - "github.com/mainflux/mainflux/pkg/errors" + mflog "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - "github.com/mainflux/mainflux/users/bcrypt" - "github.com/mainflux/mainflux/users/emailer" - "github.com/mainflux/mainflux/users/tracing" + "github.com/mainflux/mainflux/users/clients" + capi "github.com/mainflux/mainflux/users/clients/api" + "github.com/mainflux/mainflux/users/clients/emailer" + cpostgres "github.com/mainflux/mainflux/users/clients/postgres" + ctracing "github.com/mainflux/mainflux/users/clients/tracing" + "github.com/mainflux/mainflux/users/groups" + gapi "github.com/mainflux/mainflux/users/groups/api" + gpostgres "github.com/mainflux/mainflux/users/groups/postgres" + gtracing "github.com/mainflux/mainflux/users/groups/tracing" + "github.com/mainflux/mainflux/users/hasher" + "github.com/mainflux/mainflux/users/jwt" + "github.com/mainflux/mainflux/users/policies" + grpcapi "github.com/mainflux/mainflux/users/policies/api/grpc" + papi "github.com/mainflux/mainflux/users/policies/api/http" + ppostgres "github.com/mainflux/mainflux/users/policies/postgres" + ptracing "github.com/mainflux/mainflux/users/policies/tracing" + "github.com/mainflux/mainflux/users/postgres" + clientsPg "github.com/mainflux/mainflux/users/postgres" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/jaeger" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + tracesdk "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" + "go.opentelemetry.io/otel/trace" "golang.org/x/sync/errgroup" - - "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux" - jaegerClient "github.com/mainflux/mainflux/internal/clients/jaeger" - mflog "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/users/api" - usersPg "github.com/mainflux/mainflux/users/postgres" - opentracing "github.com/opentracing/opentracing-go" + "google.golang.org/grpc" ) const ( svcName = "users" envPrefix = "MF_USERS_" envPrefixHttp = "MF_USERS_HTTP_" + envPrefixGrpc = "MF_USERS_GRPC_" defDB = "users" - defSvcHttpPort = "8180" + defSvcHttpPort = "9191" + defSvcGrpcPort = "9192" ) type config struct { LogLevel string `env:"MF_USERS_LOG_LEVEL" envDefault:"info"` + SecretKey string `env:"MF_USERS_SECRET_KEY" envDefault:"secret"` AdminEmail string `env:"MF_USERS_ADMIN_EMAIL" envDefault:""` AdminPassword string `env:"MF_USERS_ADMIN_PASSWORD" envDefault:""` PassRegexText string `env:"MF_USERS_PASS_REGEX" envDefault:"^.{8,}$"` - SelfRegister bool `env:"MF_USERS_ALLOW_SELF_REGISTER" envDefault:"true"` - ResetURL string `env:"MF_TOKEN_RESET_ENDPOINT" envDefault:"email.tmpl"` + ResetURL string `env:"MF_TOKEN_RESET_ENDPOINT" envDefault:"/reset-request"` JaegerURL string `env:"MF_JAEGER_URL" envDefault:"localhost:6831"` PassRegex *regexp.Regexp } @@ -59,12 +78,7 @@ func main() { cfg := config{} if err := env.Parse(&cfg); err != nil { - log.Fatalf("failed to load %s configuration : %s", svcName, err) - } - - logger, err := mflog.New(os.Stdout, cfg.LogLevel) - if err != nil { - log.Fatalf("failed to init logger: %s", err) + log.Fatalf("failed to load %s configuration : %s", svcName, err.Error()) } passRegex, err := regexp.Compile(cfg.PassRegexText) if err != nil { @@ -72,51 +86,65 @@ func main() { } cfg.PassRegex = passRegex + logger, err := mflog.New(os.Stdout, cfg.LogLevel) + if err != nil { + logger.Fatal(fmt.Sprintf("failed to init logger: %s", err.Error())) + } + ec := email.Config{} if err := env.Parse(&ec); err != nil { - logger.Fatal(fmt.Sprintf("failed to load email configuration : %s", err)) + logger.Fatal(fmt.Sprintf("failed to load email configuration : %s", err.Error())) } dbConfig := pgClient.Config{Name: defDB} - db, err := pgClient.SetupWithConfig(envPrefix, *usersPg.Migration(), dbConfig) + db, err := pgClient.SetupWithConfig(envPrefix, *clientsPg.Migration(), dbConfig) if err != nil { logger.Fatal(err.Error()) } defer db.Close() - auth, authHandler, err := authClient.Setup(envPrefix, cfg.JaegerURL) - if err != nil { - logger.Fatal(err.Error()) - } - defer authHandler.Close() - logger.Info("Successfully connected to auth grpc server " + authHandler.Secure()) - - dbTracer, dbCloser, err := jaegerClient.NewTracer("auth_db", cfg.JaegerURL) + tp, err := initJaeger(svcName, cfg.JaegerURL) if err != nil { logger.Fatal(fmt.Sprintf("failed to init Jaeger: %s", err)) } - defer dbCloser.Close() + defer func() { + if err := tp.Shutdown(context.Background()); err != nil { + logger.Error(fmt.Sprintf("Error shutting down tracer provider: %v", err)) + } + }() + tracer := otel.Tracer(svcName) - svc := newService(db, dbTracer, auth, cfg, ec, logger) - - tracer, closer, err := jaegerClient.NewTracer("users", cfg.JaegerURL) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to init Jaeger: %s", err)) - } - defer closer.Close() + csvc, gsvc, psvc := newService(db, tracer, cfg, ec, logger) httpServerConfig := server.Config{Port: defSvcHttpPort} if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { - logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) + logger.Fatal(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err.Error())) + } + m := bone.New() + hsc := httpserver.New(ctx, cancel, svcName, httpServerConfig, capi.MakeClientsHandler(csvc, m, logger), logger) + hsg := httpserver.New(ctx, cancel, svcName, httpServerConfig, gapi.MakeGroupsHandler(gsvc, m, logger), logger) + hsp := httpserver.New(ctx, cancel, svcName, httpServerConfig, papi.MakePolicyHandler(psvc, m, logger), logger) + + // Create new grpc server + registerAuthServiceServer := func(srv *grpc.Server) { + policies.RegisterAuthServiceServer(srv, grpcapi.NewServer(csvc, psvc)) + + } + grpcServerConfig := server.Config{Port: defSvcGrpcPort} + if err := env.Parse(&grpcServerConfig, env.Options{Prefix: envPrefixGrpc, AltPrefix: envPrefix}); err != nil { + log.Fatalf("failed to load %s gRPC server configuration : %s", svcName, err.Error()) } - hs := httpserver.New(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(svc, tracer, logger), logger) + gs := grpcserver.New(ctx, cancel, svcName, grpcServerConfig, registerAuthServiceServer, logger) g.Go(func() error { - return hs.Start() + return hsc.Start() + }) + g.Go(func() error { + return gs.Start() }) g.Go(func() error { - return server.StopSignalHandler(ctx, cancel, logger, svcName, hs) + return server.StopSignalHandler(ctx, cancel, logger, svcName, hsc, hsg, hsp, gs) }) if err := g.Wait(); err != nil { @@ -124,103 +152,105 @@ func main() { } } -func newService(db *sqlx.DB, tracer opentracing.Tracer, auth mainflux.AuthServiceClient, c config, ec email.Config, logger mflog.Logger) users.Service { - database := usersPg.NewDatabase(db) - hasher := bcrypt.New() - userRepo := tracing.UserRepositoryMiddleware(usersPg.NewUserRepo(database), tracer) +func initJaeger(svcName, url string) (*tracesdk.TracerProvider, error) { + exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url))) + if err != nil { + return nil, err + } + tp := tracesdk.NewTracerProvider( + tracesdk.WithSampler(tracesdk.AlwaysSample()), + tracesdk.WithBatcher(exporter), + tracesdk.WithSpanProcessor(tracesdk.NewBatchSpanProcessor(exporter)), + tracesdk.WithResource(resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceNameKey.String(svcName), + )), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) + + return tp, nil +} + +func newService(db *sqlx.DB, tracer trace.Tracer, c config, ec email.Config, logger mflog.Logger) (clients.Service, groups.GroupService, policies.PolicyService) { + database := postgres.NewDatabase(db, tracer) + cRepo := cpostgres.NewClientRepo(database) + gRepo := gpostgres.NewGroupRepo(database) + pRepo := ppostgres.NewPolicyRepo(database) + + idp := uuid.New() + hsr := hasher.New() + + tokenizer := jwt.NewTokenRepo([]byte(c.SecretKey)) + tokenizer = jwt.NewTokenRepoMiddleware(tokenizer, tracer) emailer, err := emailer.New(c.ResetURL, &ec) if err != nil { - logger.Error(fmt.Sprintf("Failed to configure e-mailing util: %s", err)) + logger.Error(fmt.Sprintf("Failed to configure e-mailing util: %s", err.Error())) } + csvc := clients.NewService(cRepo, pRepo, tokenizer, emailer, hsr, idp, c.PassRegex) + gsvc := groups.NewService(gRepo, pRepo, tokenizer, idp) + psvc := policies.NewService(pRepo, tokenizer, idp) - idProvider := uuid.New() - - svc := users.New(userRepo, hasher, auth, emailer, idProvider, c.PassRegex) - svc = api.LoggingMiddleware(svc, logger) + csvc = ctracing.TracingMiddleware(csvc, tracer) + csvc = capi.LoggingMiddleware(csvc, logger) counter, latency := internal.MakeMetrics(svcName, "api") - svc = api.MetricsMiddleware(svc, counter, latency) - - if err := createAdmin(svc, userRepo, c, auth); err != nil { - logger.Fatal(fmt.Sprintf("failed to create admin user: %s", err)) - } - - switch c.SelfRegister { - case true: - // If MF_USERS_ALLOW_SELF_REGISTER environment variable is "true", - // everybody can create a new user. Here, check the existence of that - // policy. If the policy does not exist, create it; otherwise, there is - // no need to do anything further. - _, err := auth.Authorize(context.Background(), &mainflux.AuthorizeReq{Obj: "user", Act: "create", Sub: "*"}) - if err != nil { - // Add a policy that allows anybody to create a user - apr, err := auth.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Obj: "user", Act: "create", Sub: "*"}) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to add the policy related to MF_USERS_ALLOW_SELF_REGISTER: %s", err)) - } - if !apr.GetAuthorized() { - logger.Fatal(fmt.Sprintf("failed to authorized the policy result related to MF_USERS_ALLOW_SELF_REGISTER: " + errors.ErrAuthorization.Error())) - } - } - default: - // If MF_USERS_ALLOW_SELF_REGISTER environment variable is "false", - // everybody cannot create a new user. Therefore, delete a policy that - // allows everybody to create a new user. - dpr, err := auth.DeletePolicy(context.Background(), &mainflux.DeletePolicyReq{Obj: "user", Act: "create", Sub: "*"}) - if err != nil { - logger.Fatal(fmt.Sprintf("failed to delete a policy: %s", err)) - } - if !dpr.GetDeleted() { - logger.Fatal("deleting a policy expected to succeed.") - } - } + csvc = capi.MetricsMiddleware(csvc, counter, latency) - return svc -} + gsvc = gtracing.TracingMiddleware(gsvc, tracer) + gsvc = gapi.LoggingMiddleware(gsvc, logger) + counter, latency = internal.MakeMetrics("groups", "api") + gsvc = gapi.MetricsMiddleware(gsvc, counter, latency) -func createAdmin(svc users.Service, userRepo users.UserRepository, c config, auth mainflux.AuthServiceClient) error { - user := users.User{ - Email: c.AdminEmail, - Password: c.AdminPassword, - } - - if admin, err := userRepo.RetrieveByEmail(context.Background(), user.Email); err == nil { - // The admin is already created. Check existence of the admin policy. - _, err := auth.Authorize(context.Background(), &mainflux.AuthorizeReq{Obj: "authorities", Act: "member", Sub: admin.ID}) - if err != nil { - apr, err := auth.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Obj: "authorities", Act: "member", Sub: admin.ID}) - if err != nil { - return err - } - if !apr.GetAuthorized() { - return errors.ErrAuthorization - } - } - return nil + psvc = ptracing.TracingMiddleware(psvc, tracer) + psvc = papi.LoggingMiddleware(psvc, logger) + counter, latency = internal.MakeMetrics("policies", "api") + psvc = papi.MetricsMiddleware(psvc, counter, latency) + + if err := createAdmin(c, cRepo, hsr, csvc); err != nil { + logger.Error(fmt.Sprintf("Failed to create admin client: %s", err)) } + return csvc, gsvc, psvc +} - // Add a policy that allows anybody to create a user - apr, err := auth.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Obj: "user", Act: "create", Sub: "*"}) +func createAdmin(c config, crepo clients.ClientRepository, hsr clients.Hasher, svc clients.Service) error { + id, err := uuid.New().ID() if err != nil { return err } - if !apr.GetAuthorized() { - return errors.ErrAuthorization + hash, err := hsr.Hash(c.AdminPassword) + if err != nil { + return err + } + + client := clients.Client{ + ID: id, + Name: "admin", + Credentials: clients.Credentials{ + Identity: c.AdminEmail, + Secret: hash, + }, + Metadata: clients.Metadata{ + "role": "admin", + }, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + Role: clients.AdminRole, + Status: clients.EnabledStatus, + } + + if _, err := crepo.RetrieveByIdentity(context.Background(), client.Credentials.Identity); err == nil { + return nil } // Create an admin - uid, err := svc.Register(context.Background(), "", user) - if err != nil { + if _, err = crepo.Save(context.Background(), client); err != nil { return err } - - apr, err = auth.AddPolicy(context.Background(), &mainflux.AddPolicyReq{Obj: "authorities", Act: "member", Sub: uid}) + _, err = svc.IssueToken(context.Background(), c.AdminEmail, c.AdminPassword) if err != nil { return err } - if !apr.GetAuthorized() { - return errors.ErrAuthorization - } return nil } diff --git a/consumers/notifiers/mocks/auth.go b/consumers/notifiers/mocks/auth.go index 3d590098ad2..5253742fca5 100644 --- a/consumers/notifiers/mocks/auth.go +++ b/consumers/notifiers/mocks/auth.go @@ -6,60 +6,51 @@ package mocks import ( "context" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "google.golang.org/grpc" ) -var _ mainflux.AuthServiceClient = (*authServiceMock)(nil) +var _ policies.AuthServiceClient = (*authServiceMock)(nil) type authServiceMock struct { users map[string]string } // NewAuth creates mock of auth service. -func NewAuth(users map[string]string) mainflux.AuthServiceClient { +func NewAuth(users map[string]string) policies.AuthServiceClient { return &authServiceMock{users} } -func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { +func (svc authServiceMock) Identify(ctx context.Context, in *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { if id, ok := svc.users[in.Value]; ok { - return &mainflux.UserIdentity{Id: id, Email: id}, nil + return &policies.UserIdentity{Id: id, Email: id}, nil } return nil, errors.ErrAuthentication } -func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { +func (svc authServiceMock) Issue(ctx context.Context, in *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { if id, ok := svc.users[in.GetEmail()]; ok { switch in.Type { default: - return &mainflux.Token{Value: id}, nil + return &policies.Token{Value: id}, nil } } return nil, errors.ErrAuthentication } -func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { +func (svc authServiceMock) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { panic("not implemented") } -func (svc authServiceMock) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { +func (svc authServiceMock) AddPolicy(ctx context.Context, in *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { panic("not implemented") } -func (svc authServiceMock) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { +func (svc authServiceMock) DeletePolicy(ctx context.Context, in *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { panic("not implemented") } -func (svc authServiceMock) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { - panic("not implemented") -} - -func (svc authServiceMock) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - panic("not implemented") -} - -func (svc authServiceMock) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { +func (svc authServiceMock) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { panic("not implemented") } diff --git a/consumers/notifiers/postgres/setup_test.go b/consumers/notifiers/postgres/setup_test.go index 2ee238c4468..fa94d020085 100644 --- a/consumers/notifiers/postgres/setup_test.go +++ b/consumers/notifiers/postgres/setup_test.go @@ -11,6 +11,7 @@ import ( "os" "testing" + _ "github.com/jackc/pgx/v5/stdlib" // required for SQL access "github.com/jmoiron/sqlx" "github.com/mainflux/mainflux/consumers/notifiers/postgres" pgClient "github.com/mainflux/mainflux/internal/clients/postgres" diff --git a/consumers/notifiers/service.go b/consumers/notifiers/service.go index c40fb004f59..38fe9e72a07 100644 --- a/consumers/notifiers/service.go +++ b/consumers/notifiers/service.go @@ -11,6 +11,7 @@ import ( "github.com/mainflux/mainflux/consumers" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/messaging" + "github.com/mainflux/mainflux/users/policies" ) var ( @@ -39,7 +40,7 @@ type Service interface { var _ Service = (*notifierService)(nil) type notifierService struct { - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient subs SubscriptionsRepository idp mainflux.IDProvider notifier Notifier @@ -47,7 +48,7 @@ type notifierService struct { } // New instantiates the subscriptions service implementation. -func New(auth mainflux.AuthServiceClient, subs SubscriptionsRepository, idp mainflux.IDProvider, notifier Notifier, from string) Service { +func New(auth policies.AuthServiceClient, subs SubscriptionsRepository, idp mainflux.IDProvider, notifier Notifier, from string) Service { return ¬ifierService{ auth: auth, subs: subs, @@ -58,7 +59,7 @@ func New(auth mainflux.AuthServiceClient, subs SubscriptionsRepository, idp main } func (ns *notifierService) CreateSubscription(ctx context.Context, token string, sub Subscription) (string, error) { - res, err := ns.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ns.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return "", err } @@ -72,7 +73,7 @@ func (ns *notifierService) CreateSubscription(ctx context.Context, token string, } func (ns *notifierService) ViewSubscription(ctx context.Context, token, id string) (Subscription, error) { - if _, err := ns.auth.Identify(ctx, &mainflux.Token{Value: token}); err != nil { + if _, err := ns.auth.Identify(ctx, &policies.Token{Value: token}); err != nil { return Subscription{}, err } @@ -80,7 +81,7 @@ func (ns *notifierService) ViewSubscription(ctx context.Context, token, id strin } func (ns *notifierService) ListSubscriptions(ctx context.Context, token string, pm PageMetadata) (Page, error) { - if _, err := ns.auth.Identify(ctx, &mainflux.Token{Value: token}); err != nil { + if _, err := ns.auth.Identify(ctx, &policies.Token{Value: token}); err != nil { return Page{}, err } @@ -88,7 +89,7 @@ func (ns *notifierService) ListSubscriptions(ctx context.Context, token string, } func (ns *notifierService) RemoveSubscription(ctx context.Context, token, id string) error { - if _, err := ns.auth.Identify(ctx, &mainflux.Token{Value: token}); err != nil { + if _, err := ns.auth.Identify(ctx, &policies.Token{Value: token}); err != nil { return err } diff --git a/docker/.env b/docker/.env index ab4639c2440..5cc8161fbf1 100644 --- a/docker/.env +++ b/docker/.env @@ -85,16 +85,27 @@ MF_KETO_DB=keto ### Users MF_USERS_LOG_LEVEL=debug -MF_USERS_HTTP_PORT=8180 +MF_USERS_DB_HOST=clients-db MF_USERS_DB_PORT=5432 MF_USERS_DB_USER=mainflux MF_USERS_DB_PASS=mainflux MF_USERS_DB=users +MF_USERS_DB_SSL_MODE= +MF_USERS_DB_SSL_CERT= +MF_USERS_DB_SSL_KEY= +MF_USERS_DB_SSL_ROOT_CERT= +MF_USERS_HTTP_PORT=9191 +MF_USERS_GRPC_PORT=9192 +MF_USERS_GRPC_URL=users:9192 +MF_USERS_GRPC_TIMEOUT=1s +MF_USERS_SERVER_CERT= +MF_USERS_SERVER_KEY= +MF_USERS_SECRET_KEY=HyE2D4RUt9nnKG6v8zKEqAp6g6ka8hhZsqUpzgKvnwpXrNVQSH MF_USERS_ADMIN_EMAIL=admin@example.com MF_USERS_ADMIN_PASSWORD=12345678 +MF_USERS_JAEGER_URL=http://jaeger:14268/api/traces MF_USERS_RESET_PWD_TEMPLATE=users.tmpl MF_USERS_PASS_REGEX=^.{8,}$$ -MF_USERS_ALLOW_SELF_REGISTER=true ### Email utility MF_EMAIL_HOST=smtp.mailtrap.io diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 176126068f6..378c5ebd2e0 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -8,66 +8,14 @@ networks: driver: bridge volumes: - mainflux-clients-db-volume: - mainflux-auth-db-volume: mainflux-users-db-volume: mainflux-things-db-volume: mainflux-keto-db-volume: - mainflux-auth-redis-volume: + mainflux-users-redis-volume: mainflux-es-redis-volume: mainflux-mqtt-broker-volume: services: - keto: - image: oryd/keto:v0.6.0-alpha.3 - container_name: mainflux-keto - ports: - - ${MF_KETO_READ_REMOTE_PORT}:${MF_KETO_READ_REMOTE_PORT} - - ${MF_KETO_WRITE_REMOTE_PORT}:${MF_KETO_WRITE_REMOTE_PORT} - environment: - - DSN=postgresql://${MF_KETO_DB_USER}:${MF_KETO_DB_PASS}@keto-db:${MF_KETO_DB_PORT}/${MF_KETO_DB}?sslmode=disable - command: serve -c /home/ory/keto.yml - restart: on-failure - volumes: - - type: bind - source: ./keto - target: /home/ory - networks: - - mainflux-base-net - depends_on: - - keto-db - - keto-migrate: - image: oryd/keto:v0.6.0-alpha.3 - container_name: mainflux-keto-migrate - environment: - - KETO_WRITE_REMOTE=keto:${MF_KETO_WRITE_REMOTE_PORT} - - KETO_READ_REMOTE=keto:${MF_KETO_READ_REMOTE_PORT} - - DSN=postgresql://${MF_KETO_DB_USER}:${MF_KETO_DB_PASS}@keto-db:${MF_KETO_DB_PORT}/${MF_KETO_DB}?sslmode=disable - volumes: - - type: bind - source: ./keto - target: /home/ory - command: migrate up --all-namespaces -c /home/ory/keto.yml --yes - restart: on-failure - networks: - - mainflux-base-net - depends_on: - - keto-db - - keto-db: - image: postgres:13.3-alpine - container_name: mainflux-keto-db - restart: on-failure - environment: - POSTGRES_USER: ${MF_KETO_DB_USER} - POSTGRES_PASSWORD: ${MF_KETO_DB_PASS} - POSTGRES_DB: ${MF_KETO_DB} - networks: - - mainflux-base-net - volumes: - - mainflux-keto-db-volume:/var/lib/postgresql/data - nginx: image: nginx:1.23.3-alpine container_name: mainflux-nginx @@ -108,99 +56,6 @@ services: ports: - 4222:4222 - auth-db: - image: postgres:13.3-alpine - container_name: mainflux-auth-db - restart: on-failure - environment: - POSTGRES_USER: ${MF_AUTH_DB_USER} - POSTGRES_PASSWORD: ${MF_AUTH_DB_PASS} - POSTGRES_DB: ${MF_AUTH_DB} - networks: - - mainflux-base-net - volumes: - - mainflux-auth-db-volume:/var/lib/postgresql/data - - auth: - image: mainflux/auth:${MF_RELEASE_TAG} - container_name: mainflux-auth - depends_on: - - auth-db - - keto - expose: - - ${MF_AUTH_GRPC_PORT} - restart: on-failure - environment: - MF_AUTH_LOG_LEVEL: ${MF_AUTH_LOG_LEVEL} - MF_AUTH_DB_HOST: auth-db - MF_AUTH_DB_PORT: ${MF_AUTH_DB_PORT} - MF_AUTH_DB_USER: ${MF_AUTH_DB_USER} - MF_AUTH_DB_PASS: ${MF_AUTH_DB_PASS} - MF_AUTH_DB: ${MF_AUTH_DB} - MF_AUTH_HTTP_PORT: ${MF_AUTH_HTTP_PORT} - MF_AUTH_GRPC_PORT: ${MF_AUTH_GRPC_PORT} - MF_AUTH_SECRET: ${MF_AUTH_SECRET} - MF_AUTH_LOGIN_TOKEN_DURATION: ${MF_AUTH_LOGIN_TOKEN_DURATION} - MF_JAEGER_URL: ${MF_JAEGER_URL} - MF_KETO_READ_REMOTE_HOST: ${MF_KETO_READ_REMOTE_HOST} - MF_KETO_READ_REMOTE_PORT: ${MF_KETO_READ_REMOTE_PORT} - MF_KETO_WRITE_REMOTE_HOST: ${MF_KETO_WRITE_REMOTE_HOST} - MF_KETO_WRITE_REMOTE_PORT: ${MF_KETO_WRITE_REMOTE_PORT} - ports: - - ${MF_AUTH_HTTP_PORT}:${MF_AUTH_HTTP_PORT} - - ${MF_AUTH_GRPC_PORT}:${MF_AUTH_GRPC_PORT} - networks: - - mainflux-base-net - - users-db: - image: postgres:13.3-alpine - container_name: mainflux-users-db - restart: on-failure - environment: - POSTGRES_USER: ${MF_USERS_DB_USER} - POSTGRES_PASSWORD: ${MF_USERS_DB_PASS} - POSTGRES_DB: ${MF_USERS_DB} - networks: - - mainflux-base-net - volumes: - - mainflux-users-db-volume:/var/lib/postgresql/data - - users: - image: mainflux/users:${MF_RELEASE_TAG} - container_name: mainflux-users - volumes: - - ./templates/${MF_USERS_RESET_PWD_TEMPLATE}:/${MF_EMAIL_TEMPLATE} - depends_on: - - users-db - - auth - restart: on-failure - environment: - MF_USERS_LOG_LEVEL: ${MF_USERS_LOG_LEVEL} - MF_USERS_DB_HOST: users-db - MF_USERS_DB_PORT: ${MF_USERS_DB_PORT} - MF_USERS_DB_USER: ${MF_USERS_DB_USER} - MF_USERS_DB_PASS: ${MF_USERS_DB_PASS} - MF_USERS_DB: ${MF_USERS_DB} - MF_USERS_HTTP_PORT: ${MF_USERS_HTTP_PORT} - MF_JAEGER_URL: ${MF_JAEGER_URL} - MF_EMAIL_HOST: ${MF_EMAIL_HOST} - MF_EMAIL_PORT: ${MF_EMAIL_PORT} - MF_EMAIL_USERNAME: ${MF_EMAIL_USERNAME} - MF_EMAIL_PASSWORD: ${MF_EMAIL_PASSWORD} - MF_EMAIL_FROM_ADDRESS: ${MF_EMAIL_FROM_ADDRESS} - MF_EMAIL_FROM_NAME: ${MF_EMAIL_FROM_NAME} - MF_EMAIL_TEMPLATE: ${MF_EMAIL_TEMPLATE} - MF_TOKEN_RESET_ENDPOINT: ${MF_TOKEN_RESET_ENDPOINT} - MF_AUTH_GRPC_URL: ${MF_AUTH_GRPC_URL} - MF_AUTH_GRPC_TIMEOUT: ${MF_AUTH_GRPC_TIMEOUT} - MF_USERS_ADMIN_EMAIL: ${MF_USERS_ADMIN_EMAIL} - MF_USERS_ADMIN_PASSWORD: ${MF_USERS_ADMIN_PASSWORD} - MF_USERS_ALLOW_SELF_REGISTER: ${MF_USERS_ALLOW_SELF_REGISTER} - ports: - - ${MF_USERS_HTTP_PORT}:${MF_USERS_HTTP_PORT} - networks: - - mainflux-base-net - things-db: image: postgres:13.3-alpine container_name: mainflux-things-db @@ -214,21 +69,12 @@ services: volumes: - mainflux-things-db-volume:/var/lib/postgresql/data - auth-redis: - image: redis:6.2.2-alpine - container_name: mainflux-auth-redis - restart: on-failure - networks: - - mainflux-base-net - volumes: - - mainflux-auth-redis-volume:/data - things: image: mainflux/things:${MF_RELEASE_TAG} container_name: mainflux-things depends_on: - things-db - - auth + - users restart: on-failure environment: MF_THINGS_LOG_LEVEL: ${MF_THINGS_LOG_LEVEL} @@ -237,13 +83,12 @@ services: MF_THINGS_DB_USER: ${MF_THINGS_DB_USER} MF_THINGS_DB_PASS: ${MF_THINGS_DB_PASS} MF_THINGS_DB: ${MF_THINGS_DB} - MF_THINGS_CACHE_URL: auth-redis:${MF_REDIS_TCP_PORT} + MF_THINGS_CACHE_URL: users-redis:${MF_REDIS_TCP_PORT} MF_THINGS_ES_URL: es-redis:${MF_REDIS_TCP_PORT} MF_THINGS_HTTP_PORT: ${MF_THINGS_HTTP_PORT} MF_THINGS_AUTH_HTTP_PORT: ${MF_THINGS_AUTH_HTTP_PORT} MF_THINGS_AUTH_GRPC_PORT: ${MF_THINGS_AUTH_GRPC_PORT} - MF_JAEGER_URL: ${MF_JAEGER_URL} - MF_AUTH_GRPC_URL: ${MF_AUTH_GRPC_URL} + MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT: ${MF_AUTH_GRPC_TIMEOUT} ports: - ${MF_THINGS_HTTP_PORT}:${MF_THINGS_HTTP_PORT} @@ -252,46 +97,60 @@ services: networks: - mainflux-base-net - clients-db: + users-db: image: postgres:15.1-alpine - container_name: mainflux-clients-db + container_name: mainflux-users-db restart: on-failure environment: - POSTGRES_USER: ${MF_CLIENTS_DB_USER} - POSTGRES_PASSWORD: ${MF_CLIENTS_DB_PASS} - POSTGRES_DB: ${MF_CLIENTS_DB} + POSTGRES_USER: ${MF_USERS_DB_USER} + POSTGRES_PASSWORD: ${MF_USERS_DB_PASS} + POSTGRES_DB: ${MF_USERS_DB} + networks: + - mainflux-base-net + volumes: + - mainflux-users-db-volume:/var/lib/postgresql/data + + users-redis: + image: redis:6.2.2-alpine + container_name: mainflux-users-redis + restart: on-failure networks: - mainflux-base-net volumes: - - mainflux-clients-db-volume:/var/lib/postgresql/data + - mainflux-users-redis-volume:/data - clients: - image: mainflux/clients:${MF_RELEASE_TAG} - container_name: mainflux-clients + users: + image: mainflux/users:${MF_RELEASE_TAG} + container_name: mainflux-users depends_on: - - clients-db + - users-db restart: on-failure environment: - MF_CLIENTS_LOG_LEVEL: ${MF_CLIENTS_LOG_LEVEL} - MF_CLIENTS_DB_HOST: clients-db - MF_CLIENTS_DB_PORT: ${MF_CLIENTS_DB_PORT} - MF_CLIENTS_DB_USER: ${MF_CLIENTS_DB_USER} - MF_CLIENTS_DB_PASS: ${MF_CLIENTS_DB_PASS} - MF_CLIENTS_DB: ${MF_CLIENTS_DB} - MF_CLIENTS_DB_SSL_MODE: ${MF_CLIENTS_DB_SSL_MODE} - MF_CLIENTS_DB_SSL_CERT: ${MF_CLIENTS_DB_SSL_CERT} - MF_CLIENTS_DB_SSL_KEY: ${MF_CLIENTS_DB_SSL_KEY} - MF_CLIENTS_DB_SSL_ROOT_CERT: ${MF_CLIENTS_DB_SSL_ROOT_CERT} - MF_CLIENTS_HTTP_PORT: ${MF_CLIENTS_HTTP_PORT} - MF_CLIENTS_GRPC_PORT: ${MF_CLIENTS_GRPC_PORT} - MF_CLIENTS_JAEGER_URL: ${MF_CLIENTS_JAEGER_URL} - MF_CLIENTS_GRPC_URL: ${MF_CLIENTS_GRPC_URL} - MF_CLIENTS_GRPC_TIMEOUT: ${MF_CLIENTS_GRPC_TIMEOUT} - MF_CLIENTS_SERVER_CERT: ${MF_CLIENTS_SERVER_CERT} - MF_CLIENTS_SERVER_KEY: ${MF_CLIENTS_SERVER_KEY} + MF_USERS_LOG_LEVEL: ${MF_USERS_LOG_LEVEL} + MF_USERS_DB_HOST: users-db + MF_USERS_DB_PORT: ${MF_USERS_DB_PORT} + MF_USERS_DB_USER: ${MF_USERS_DB_USER} + MF_USERS_DB_PASS: ${MF_USERS_DB_PASS} + MF_USERS_DB: ${MF_USERS_DB} + MF_USERS_DB_SSL_MODE: ${MF_USERS_DB_SSL_MODE} + MF_USERS_DB_SSL_CERT: ${MF_USERS_DB_SSL_CERT} + MF_USERS_DB_SSL_KEY: ${MF_USERS_DB_SSL_KEY} + MF_USERS_DB_SSL_ROOT_CERT: ${MF_USERS_DB_SSL_ROOT_CERT} + MF_USERS_HTTP_PORT: ${MF_USERS_HTTP_PORT} + MF_USERS_GRPC_PORT: ${MF_USERS_GRPC_PORT} + MF_JAEGER_URL: ${MF_USERS_JAEGER_URL} + MF_USERS_GRPC_URL: ${MF_USERS_GRPC_URL} + MF_USERS_GRPC_TIMEOUT: ${MF_USERS_GRPC_TIMEOUT} + MF_USERS_SERVER_CERT: ${MF_USERS_SERVER_CERT} + MF_USERS_SERVER_KEY: ${MF_USERS_SERVER_KEY} + MF_USERS_SECRET_KEY: ${MF_USERS_SECRET_KEY} + MF_USERS_ADMIN_EMAIL: ${MF_USERS_ADMIN_EMAIL} + MF_USERS_ADMIN_PASSWORD: ${MF_USERS_ADMIN_PASSWORD} + MF_USERS_RESET_PWD_TEMPLATE: ${MF_USERS_RESET_PWD_TEMPLATE} + MF_USERS_PASS_REGEX: ${MF_USERS_PASS_REGEX} ports: - - ${MF_CLIENTS_HTTP_PORT}:${MF_CLIENTS_HTTP_PORT} - - ${MF_CLIENTS_GRPC_PORT}:${MF_CLIENTS_GRPC_PORT} + - ${MF_USERS_HTTP_PORT}:${MF_USERS_HTTP_PORT} + - ${MF_USERS_GRPC_PORT}:${MF_USERS_GRPC_PORT} networks: - mainflux-base-net @@ -340,7 +199,7 @@ services: MF_JAEGER_URL: ${MF_JAEGER_URL} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_AUTH_CACHE_URL: auth-redis:${MF_REDIS_TCP_PORT} + MF_AUTH_CACHE_URL: users-redis:${MF_REDIS_TCP_PORT} networks: - mainflux-base-net diff --git a/docker/nginx/nginx-key.conf b/docker/nginx/nginx-key.conf index 28b916ddf6a..b158da06e2d 100644 --- a/docker/nginx/nginx-key.conf +++ b/docker/nginx/nginx-key.conf @@ -86,24 +86,9 @@ http { location ~ ^/(groups|members|keys) { include snippets/proxy-headers.conf; add_header Access-Control-Expose-Headers Location; - proxy_pass http://auth:${MF_AUTH_HTTP_PORT}; - } - - # Proxy pass to clients service - location ~ ^/(clients) { - include snippets/proxy-headers.conf; - proxy_pass http://clients:${MF_CLIENTS_HTTP_PORT}; - } - - location ^~ /clients/groups { - include snippets/proxy-headers.conf; - proxy_pass http://clients:${MF_CLIENTS_HTTP_PORT}/groups; + proxy_pass http://users:${MF_USERS_HTTP_PORT}; } - location ^~ /clients/policies { - include snippets/proxy-headers.conf; - proxy_pass http://clients:${MF_CLIENTS_HTTP_PORT}/policies; - } location /health { include snippets/proxy-headers.conf; diff --git a/docker/nginx/nginx-x509.conf b/docker/nginx/nginx-x509.conf index 453f02dbdb6..7f2065b057e 100644 --- a/docker/nginx/nginx-x509.conf +++ b/docker/nginx/nginx-x509.conf @@ -94,7 +94,7 @@ http { location ~ ^/(groups|members|keys) { include snippets/proxy-headers.conf; add_header Access-Control-Expose-Headers Location; - proxy_pass http://auth:${MF_AUTH_HTTP_PORT}; + proxy_pass http://users:${MF_AUTH_HTTP_PORT}; } # Proxy pass to clients service diff --git a/go.mod b/go.mod index 29b58c93833..185bc5ae42a 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/go-zoo/bone v1.3.0 github.com/gocql/gocql v1.2.1 github.com/gofrs/uuid v4.3.0+incompatible - github.com/golang-jwt/jwt/v4 v4.4.2 github.com/golang/protobuf v1.5.2 github.com/gopcua/opcua v0.1.6 github.com/gorilla/websocket v1.5.0 @@ -34,7 +33,6 @@ require ( github.com/oklog/ulid/v2 v2.1.0 github.com/opentracing/opentracing-go v1.2.0 github.com/ory/dockertest/v3 v3.9.1 - github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9 github.com/pelletier/go-toml v1.9.5 github.com/plgd-dev/go-coap/v2 v2.6.0 github.com/prometheus/client_golang v1.13.0 diff --git a/go.sum b/go.sum index f8cdacaa41e..113252c1b16 100644 --- a/go.sum +++ b/go.sum @@ -220,8 +220,6 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -593,8 +591,6 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY= github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= -github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9 h1:gP86NkMkUlqMOTjFQ8lt8T1HbHtCJGGeeeh/6c+nla0= -github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9/go.mod h1:8IoeBQqIRKWU5L6dTKQTlTwVhlUawpqSBJZWfLLN4FM= github.com/panjf2000/ants/v2 v2.4.3/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= @@ -1221,7 +1217,6 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210503173045-b96a97608f20/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 h1:GEgb2jF5zxsFJpJfg9RoDDWm7tiwc/DDSTE2BtLUkXU= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= @@ -1244,7 +1239,6 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= diff --git a/internal/api/common.go b/internal/api/common.go index 460aa14ac12..2e9d6dae1ab 100644 --- a/internal/api/common.go +++ b/internal/api/common.go @@ -7,11 +7,11 @@ import ( "net/http" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/groups" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/groups" + "github.com/mainflux/mainflux/users/postgres" ) const ( diff --git a/internal/apiutil/errors.go b/internal/apiutil/errors.go index 140e4a8b24b..b1d61555fe3 100644 --- a/internal/apiutil/errors.go +++ b/internal/apiutil/errors.go @@ -33,6 +33,9 @@ var ( // ErrInvalidStatus indicates an invalid user account status. ErrInvalidStatus = errors.New("invalid user account status") + // ErrInvalidRole indicates that an invalid role. + ErrInvalidRole = errors.New("invalid client role") + // ErrLimitSize indicates that an invalid limit. ErrLimitSize = errors.New("invalid limit size") diff --git a/internal/clients/grpc/auth/client.go b/internal/clients/grpc/auth/client.go index 58b2bcf3c2d..ed6f0efe37e 100644 --- a/internal/clients/grpc/auth/client.go +++ b/internal/clients/grpc/auth/client.go @@ -1,11 +1,11 @@ package auth import ( - "github.com/mainflux/mainflux" - authapi "github.com/mainflux/mainflux/auth/api/grpc" grpcClient "github.com/mainflux/mainflux/internal/clients/grpc" "github.com/mainflux/mainflux/internal/env" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" + authapi "github.com/mainflux/mainflux/users/policies/api/grpc" ) const envAuthGrpcPrefix = "MF_AUTH_GRPC_" @@ -13,7 +13,7 @@ const envAuthGrpcPrefix = "MF_AUTH_GRPC_" var errGrpcConfig = errors.New("failed to load grpc configuration") // Setup loads Auth gRPC configuration from environment variable and creates new Auth gRPC API -func Setup(envPrefix, jaegerURL string) (mainflux.AuthServiceClient, grpcClient.ClientHandler, error) { +func Setup(envPrefix, jaegerURL string) (policies.AuthServiceClient, grpcClient.ClientHandler, error) { config := grpcClient.Config{} if err := env.Parse(&config, env.Options{Prefix: envAuthGrpcPrefix, AltPrefix: envPrefix}); err != nil { return nil, nil, errors.Wrap(errGrpcConfig, err) @@ -24,5 +24,5 @@ func Setup(envPrefix, jaegerURL string) (mainflux.AuthServiceClient, grpcClient. return nil, nil, err } - return authapi.NewClient(c.Tracer, c.ClientConn, config.Timeout), ch, nil + return authapi.NewClient(c.ClientConn, config.Timeout), ch, nil } diff --git a/pkg/sdk/go/keys.go b/pkg/sdk/go/keys.go deleted file mode 100644 index 64a9d757057..00000000000 --- a/pkg/sdk/go/keys.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package sdk - -import ( - "encoding/json" - "fmt" - "net/http" - "time" - - "github.com/mainflux/mainflux/pkg/errors" -) - -type keyReq struct { - Type uint32 `json:"type,omitempty"` - Duration time.Duration `json:"duration,omitempty"` -} - -const keysEndpoint = "keys" - -const ( - // LoginKey is temporary User key received on successfull login. - LoginKey uint32 = iota - // RecoveryKey represents a key for resseting password. - RecoveryKey - // APIKey enables the one to act on behalf of the user. - APIKey -) - -func (sdk mfSDK) Issue(d time.Duration, token string) (KeyRes, errors.SDKError) { - datareq := keyReq{Type: APIKey, Duration: d} - data, err := json.Marshal(datareq) - if err != nil { - return KeyRes{}, errors.NewSDKError(err) - } - - url := fmt.Sprintf("%s/%s", sdk.authURL, keysEndpoint) - - _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), data, http.StatusCreated) - if sdkerr != nil { - return KeyRes{}, sdkerr - } - - var key KeyRes - if err := json.Unmarshal(body, &key); err != nil { - return KeyRes{}, errors.NewSDKError(err) - } - - return key, nil -} - -func (sdk mfSDK) Revoke(id, token string) errors.SDKError { - url := fmt.Sprintf("%s/%s/%s", sdk.authURL, keysEndpoint, id) - _, _, err := sdk.processRequest(http.MethodDelete, url, token, string(CTJSON), nil, http.StatusNoContent) - return err -} - -func (sdk mfSDK) RetrieveKey(id, token string) (retrieveKeyRes, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s", sdk.authURL, keysEndpoint, id) - _, body, err := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK) - if err != nil { - return retrieveKeyRes{}, err - } - - var key retrieveKeyRes - if err := json.Unmarshal(body, &key); err != nil { - return retrieveKeyRes{}, errors.NewSDKError(err) - } - - return key, nil -} diff --git a/pkg/sdk/go/metadata.go b/pkg/sdk/go/metadata.go new file mode 100644 index 00000000000..26206d1429f --- /dev/null +++ b/pkg/sdk/go/metadata.go @@ -0,0 +1,3 @@ +package sdk + +type Metadata map[string]interface{} diff --git a/pkg/sdk/go/requests.go b/pkg/sdk/go/requests.go index 1ca437a12f1..5631a5b1584 100644 --- a/pkg/sdk/go/requests.go +++ b/pkg/sdk/go/requests.go @@ -19,3 +19,8 @@ type ConnectionIDs struct { ChannelIDs []string `json:"channel_ids"` ThingIDs []string `json:"thing_ids"` } + +type tokenReq struct { + Identity string `json:"identity"` + Secret string `json:"secret"` +} diff --git a/pkg/sdk/go/responses.go b/pkg/sdk/go/responses.go index 2317b9161c5..13583bf0040 100644 --- a/pkg/sdk/go/responses.go +++ b/pkg/sdk/go/responses.go @@ -11,7 +11,9 @@ import ( ) type tokenRes struct { - Token string `json:"token,omitempty"` + AccessToken string `json:"access_token,omitempty"` + RefreshToken string `json:"refresh_token,omitempty"` + AccessType string `json:"access_type,omitempty"` } type createThingsRes struct { @@ -80,26 +82,6 @@ func (res KeyRes) Empty() bool { return res.Value == "" } -type retrieveKeyRes struct { - ID string `json:"id,omitempty"` - IssuerID string `json:"issuer_id,omitempty"` - Subject string `json:"subject,omitempty"` - IssuedAt time.Time `json:"issued_at,omitempty"` - ExpiresAt *time.Time `json:"expires_at,omitempty"` -} - -func (res retrieveKeyRes) Code() int { - return http.StatusOK -} - -func (res retrieveKeyRes) Headers() map[string]string { - return map[string]string{} -} - -func (res retrieveKeyRes) Empty() bool { - return false -} - type revokeCertsRes struct { RevocationTime time.Time `json:"revocation_time"` } diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index 4ecfb7350c5..e5c7e6ba5e1 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -36,14 +36,48 @@ type ContentType string var _ SDK = (*mfSDK)(nil) +var ( + // ErrFailedCreation indicates that entity creation failed. + ErrFailedCreation = errors.New("failed to create entity in the db") + + // ErrFailedList indicates that entities list failed. + ErrFailedList = errors.New("failed to list entities") + + // ErrFailedUpdate indicates that entity update failed. + ErrFailedUpdate = errors.New("failed to update entity") + + // ErrFailedFetch indicates that fetching of entity data failed. + ErrFailedFetch = errors.New("failed to fetch entity") + + // ErrFailedRemoval indicates that entity removal failed. + ErrFailedRemoval = errors.New("failed to remove entity") + + // ErrFailedEnable indicates that client enable failed. + ErrFailedEnable = errors.New("failed to enable client") + + // ErrFailedDisable indicates that client disable failed. + ErrFailedDisable = errors.New("failed to disable client") +) + // User represents mainflux user its credentials. type User struct { - ID string `json:"id,omitempty"` - Email string `json:"email,omitempty"` - Groups []string `json:"groups,omitempty"` - Password string `json:"password,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Credentials Credentials `json:"credentials,omitempty"` + Tags []string `json:"tags,omitempty"` + Owner string `json:"owner,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Status string `json:"status,omitempty"` +} + +// Credentials represent client credentials: it contains +// "identity" which can be a username, email, generated name; +// and "secret" which can be a password or access token. +type Credentials struct { + Identity string `json:"identity"` // username or generated login ID + Secret string `json:"secret"` // password or token } + type PageMetadata struct { Total uint64 `json:"total"` Offset uint64 `json:"offset"` @@ -55,6 +89,8 @@ type PageMetadata struct { Disconnected bool `json:"disconnected,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` Status string `json:"status,omitempty"` + Action string + Tag string } // Group represents mainflux users group. @@ -107,8 +143,20 @@ type SDK interface { // UpdateUser updates existing user. UpdateUser(user User, token string) errors.SDKError + // UpdateUserTags updates the user's tags. + UpdateUserTags(user User, token string) errors.SDKError + + // UpdateUserIdentity updates the user's identity + UpdateUserIdentity(user User, token string) errors.SDKError + + // UpdateUserOwner updates the user's owner. + UpdateUserOwner(user User, token string) errors.SDKError + // UpdatePassword updates user password. - UpdatePassword(oldPass, newPass, token string) errors.SDKError + UpdatePassword(id, oldPass, newPass, token string) errors.SDKError + + // ListMembers retrieves everything that is assigned to a group identified by groupID. + ListMembers(groupID string, meta PageMetadata, token string) (MembersPage, errors.SDKError) // EnableUser changes the status of the user to enabled. EnableUser(id, token string) errors.SDKError @@ -243,15 +291,6 @@ type SDK interface { // RevokeCert revokes certificate for thing with thingID RevokeCert(thingID, token string) (time.Time, errors.SDKError) - - // Issue issues a new key, returning its token value alongside. - Issue(duration time.Duration, token string) (KeyRes, errors.SDKError) - - // Revoke removes the key with the provided ID that is issued by the user identified by the provided key. - Revoke(id, token string) errors.SDKError - - // RetrieveKey retrieves data for the key identified by the provided ID, that is issued by the user identified by the provided key. - RetrieveKey(id, token string) (retrieveKeyRes, errors.SDKError) } type mfSDK struct { diff --git a/pkg/sdk/go/setup_test.go b/pkg/sdk/go/setup_test.go new file mode 100644 index 00000000000..481d52e6549 --- /dev/null +++ b/pkg/sdk/go/setup_test.go @@ -0,0 +1,22 @@ +package sdk_test + +import ( + "os" + "testing" +) + +const ( + Identity = "identity" + token = "token" +) + +var ( + limit uint64 = 5 + offset uint64 = 0 + total uint64 = 200 +) + +func TestMain(m *testing.M) { + exitCode := m.Run() + os.Exit(exitCode) +} diff --git a/pkg/sdk/go/things_test.go b/pkg/sdk/go/things_test.go index 46c0d5195c3..f115babcf92 100644 --- a/pkg/sdk/go/things_test.go +++ b/pkg/sdk/go/things_test.go @@ -28,7 +28,6 @@ const ( email = "user@example.com" adminEmail = "admin@example.com" otherEmail = "other_user@example.com" - token = "token" otherToken = "other_token" wrongValue = "wrong_value" badKey = "999" @@ -43,10 +42,8 @@ var ( ) func newThingsService(tokens map[string]string) things.Service { - userPolicy := mocks.MockSubjectSet{Object: "users", Relation: "member"} - adminPolicy := mocks.MockSubjectSet{Object: "authorities", Relation: "member"} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{ - adminEmail: {userPolicy, adminPolicy}, email: {userPolicy}}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) @@ -548,7 +545,7 @@ func TestUpdateThing(t *testing.T) { Metadata: metadata, }, token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusForbidden), + err: errors.NewSDKErrorWithStatus(errors.ErrNotFound, http.StatusNotFound), }, { desc: "update channel with an empty id", @@ -618,7 +615,7 @@ func TestDeleteThing(t *testing.T) { desc: "delete non-existing thing", thingID: "2", token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrNotFound, http.StatusNotFound), + err: nil, }, { desc: "delete thing with invalid id", diff --git a/pkg/sdk/go/users.go b/pkg/sdk/go/users.go index 474c7fff312..db092952319 100644 --- a/pkg/sdk/go/users.go +++ b/pkg/sdk/go/users.go @@ -1,6 +1,3 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - package sdk import ( @@ -13,17 +10,40 @@ import ( ) const ( - usersEndpoint = "users" - tokensEndpoint = "tokens" - passwordEndpoint = "password" - membersEndpoint = "members" + usersEndpoint = "users" + enableEndpoint = "enable" + disableEndpoint = "disable" + tokensEndpoint = "tokens/issue" + membersEndpoint = "members" ) -func (sdk mfSDK) CreateUser(u User, token string) (string, errors.SDKError) { - data, err := json.Marshal(u) +// MembershipsPage contains page related metadata as well as list of memberships that +// belong to this page. +type MembershipsPage struct { + PageMetadata + Memberships []Group +} + +// updateClientSecretReq is used to update the client secret +type updateClientSecretReq struct { + OldSecret string `json:"old_secret,omitempty"` + NewSecret string `json:"new_secret,omitempty"` +} + +// updateClientIdentityReq is used to update the client identity +type updateClientIdentityReq struct { + token string + id string + Identity string `json:"identity,omitempty"` +} + +// CreateClient creates a new client returning its id. +func (sdk mfSDK) CreateUser(user User, token string) (string, errors.SDKError) { + data, err := json.Marshal(user) if err != nil { return "", errors.NewSDKError(err) } + url := fmt.Sprintf("%s/%s", sdk.usersURL, usersEndpoint) headers, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), data, http.StatusCreated) @@ -35,100 +55,175 @@ func (sdk mfSDK) CreateUser(u User, token string) (string, errors.SDKError) { return id, nil } -func (sdk mfSDK) User(userID, token string) (User, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, usersEndpoint, userID) - - _, body, err := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK) +// Users returns page of users. +func (sdk mfSDK) Users(pm PageMetadata, token string) (UsersPage, errors.SDKError) { + url, err := sdk.withQueryParams(sdk.usersURL, usersEndpoint, pm) if err != nil { - return User{}, err + return UsersPage{}, errors.NewSDKError(err) } - var u User - if err := json.Unmarshal(body, &u); err != nil { - return User{}, errors.NewSDKError(err) + _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK) + if sdkerr != nil { + return UsersPage{}, sdkerr } - return u, nil + var cp UsersPage + if err := json.Unmarshal(body, &cp); err != nil { + return UsersPage{}, errors.NewSDKError(err) + } + + return cp, nil } -func (sdk mfSDK) Users(pm PageMetadata, token string) (UsersPage, errors.SDKError) { - var url string - var err error +// ListMembers retrieves everything that is assigned to a group identified by groupID. +func (sdk mfSDK) ListMembers(groupID string, meta PageMetadata, token string) (MembersPage, errors.SDKError) { + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", groupsEndpoint, groupID, membersEndpoint), meta) + if err != nil { + return MembersPage{}, errors.NewSDKError(err) + } - if url, err = sdk.withQueryParams(sdk.usersURL, usersEndpoint, pm); err != nil { - return UsersPage{}, errors.NewSDKError(err) + _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK) + if sdkerr != nil { + return MembersPage{}, sdkerr } + var mp MembersPage + if err := json.Unmarshal(body, &mp); err != nil { + return MembersPage{}, errors.NewSDKError(err) + } + + return mp, nil +} + +// User returns user object by id. +func (sdk mfSDK) User(id, token string) (User, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, usersEndpoint, id) + _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK) if sdkerr != nil { - return UsersPage{}, sdkerr + return User{}, sdkerr } - var up UsersPage - if err := json.Unmarshal(body, &up); err != nil { - return UsersPage{}, errors.NewSDKError(err) + var user User + if err := json.Unmarshal(body, &user); err != nil { + return User{}, errors.NewSDKError(err) } - return up, nil + return user, nil } -func (sdk mfSDK) CreateToken(user User) (string, errors.SDKError) { +// UpdateUser updates existing user. +func (sdk mfSDK) UpdateUser(user User, token string) errors.SDKError { data, err := json.Marshal(user) if err != nil { - return "", errors.NewSDKError(err) + return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.usersURL, tokensEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, usersEndpoint, user.ID) - _, body, sdkerr := sdk.processRequest(http.MethodPost, url, "", string(CTJSON), data, http.StatusCreated) - if sdkerr != nil { - return "", sdkerr - } + _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusOK) - var tr tokenRes - if err := json.Unmarshal(body, &tr); err != nil { - return "", errors.NewSDKError(err) + return sdkerr +} + +// UpdateUserTags updates the user's tags. +func (sdk mfSDK) UpdateUserTags(user User, token string) errors.SDKError { + data, err := json.Marshal(user) + if err != nil { + return errors.NewSDKError(err) } - return tr.Token, nil + url := fmt.Sprintf("%s/%s/%s/tags", sdk.usersURL, usersEndpoint, user.ID) + + _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusOK) + + return sdkerr } -func (sdk mfSDK) UpdateUser(u User, token string) errors.SDKError { - data, err := json.Marshal(u) +// UpdateUserIdentity updates the user's identity +func (sdk mfSDK) UpdateUserIdentity(user User, token string) errors.SDKError { + ucir := updateClientIdentityReq{token: token, id: user.ID, Identity: user.Credentials.Identity} + + data, err := json.Marshal(ucir) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.usersURL, usersEndpoint) + url := fmt.Sprintf("%s/%s/%s/identity", sdk.usersURL, usersEndpoint, user.ID) + + _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusOK) - _, _, sdkerr := sdk.processRequest(http.MethodPut, url, token, string(CTJSON), data, http.StatusOK) return sdkerr } -func (sdk mfSDK) UpdatePassword(oldPass, newPass, token string) errors.SDKError { - ur := UserPasswordReq{ - OldPassword: oldPass, - Password: newPass, +// UpdatePassword updates user password. +func (sdk mfSDK) UpdatePassword(id, oldPass, newPass, token string) errors.SDKError { + var ucsr = updateClientSecretReq{OldSecret: oldPass, NewSecret: newPass} + + data, err := json.Marshal(ucsr) + if err != nil { + return errors.NewSDKError(err) } - data, err := json.Marshal(ur) + + url := fmt.Sprintf("%s/%s/%s/secret", sdk.usersURL, usersEndpoint, id) + + _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusOK) + + return sdkerr +} + +// UpdateUserOwner updates the user's owner. +func (sdk mfSDK) UpdateUserOwner(user User, token string) errors.SDKError { + data, err := json.Marshal(user) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.usersURL, passwordEndpoint) + url := fmt.Sprintf("%s/%s/%s/owner", sdk.usersURL, usersEndpoint, user.ID) + + _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusOK) - _, _, sdkerr := sdk.processRequest(http.MethodPatch, url, token, string(CTJSON), data, http.StatusCreated) return sdkerr } +// EnableUser changes the status of the user to enabled. func (sdk mfSDK) EnableUser(id, token string) errors.SDKError { - url := fmt.Sprintf("%s/%s/%s/enable", sdk.usersURL, usersEndpoint, id) - _, _, err := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), nil, http.StatusNoContent) - return err + return sdk.changeClientStatus(token, id, enableEndpoint) } +// DisableUser changes the status of the user to disabled. func (sdk mfSDK) DisableUser(id, token string) errors.SDKError { - url := fmt.Sprintf("%s/%s/%s/disable", sdk.usersURL, usersEndpoint, id) - _, _, err := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), nil, http.StatusNoContent) - return err + return sdk.changeClientStatus(token, id, disableEndpoint) +} + +func (sdk mfSDK) changeClientStatus(token, id, status string) errors.SDKError { + url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, usersEndpoint, id, status) + _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), nil, http.StatusOK) + + return sdkerr +} + +// CreateToken receives credentials and returns user token. +func (sdk mfSDK) CreateToken(user User) (string, errors.SDKError) { + var treq = tokenReq{ + Identity: user.Credentials.Identity, + Secret: user.Credentials.Secret, + } + data, err := json.Marshal(treq) + if err != nil { + return "", errors.NewSDKError(err) + } + + url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, usersEndpoint, tokensEndpoint) + + _, body, sdkerr := sdk.processRequest(http.MethodPost, url, "", string(CTJSON), data, http.StatusCreated) + if sdkerr != nil { + return "", sdkerr + } + var tr tokenRes + if err := json.Unmarshal(body, &tr); err != nil { + return "", errors.NewSDKError(err) + } + + return tr.AccessToken, nil } diff --git a/pkg/sdk/go/users_test.go b/pkg/sdk/go/users_test.go deleted file mode 100644 index a81fefa9478..00000000000 --- a/pkg/sdk/go/users_test.go +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package sdk_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "regexp" - "testing" - - "github.com/mainflux/mainflux" - mfauth "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - sdk "github.com/mainflux/mainflux/pkg/sdk/go" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - "github.com/mainflux/mainflux/users/api" - "github.com/mainflux/mainflux/users/mocks" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - invalidEmail = "userexample.com" -) - -var ( - passRegex = regexp.MustCompile("^.{8,}$") - limit uint64 = 5 - offset uint64 = 0 - total uint64 = 200 -) - -func newUserService() users.Service { - usersRepo := mocks.NewUserRepository() - hasher := mocks.NewHasher() - userEmail := "user@example.com" - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[userEmail] = append(mockAuthzDB[userEmail], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{userEmail: userEmail}, mockAuthzDB) - - emailer := mocks.NewEmailer() - idProvider := uuid.New() - - return users.New(usersRepo, hasher, auth, emailer, idProvider, passRegex) -} - -func newUserServer(svc users.Service) *httptest.Server { - logger := logger.NewMock() - mux := api.MakeHandler(svc, mocktracer.New(), logger) - return httptest.NewServer(mux) -} - -func TestCreateUser(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - - mainfluxSDK := sdk.NewSDK(sdkConf) - cases := []struct { - desc string - user sdk.User - token string - err errors.SDKError - }{ - { - desc: "register new user", - user: user, - token: token, - err: nil, - }, - { - desc: "register existing user", - user: user, - token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrConflict, http.StatusConflict), - }, - { - desc: "register user with invalid email address", - user: sdk.User{Email: invalidEmail, Password: "password"}, - token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrMalformedEntity, http.StatusBadRequest), - }, - { - desc: "register user with empty password", - user: sdk.User{Email: "user2@example.com", Password: ""}, - token: token, - err: errors.NewSDKErrorWithStatus(users.ErrPasswordFormat, http.StatusBadRequest), - }, - { - desc: "register user without password", - user: sdk.User{Email: "user2@example.com"}, - token: token, - err: errors.NewSDKErrorWithStatus(users.ErrPasswordFormat, http.StatusBadRequest), - }, - { - desc: "register user without email", - user: sdk.User{Password: "password"}, - token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrMalformedEntity, http.StatusBadRequest), - }, - { - desc: "register empty user", - user: sdk.User{}, - token: token, - err: errors.NewSDKErrorWithStatus(errors.ErrMalformedEntity, http.StatusBadRequest), - }, - } - - for _, tc := range cases { - _, err := mainfluxSDK.CreateUser(tc.user, tc.token) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - } -} - -func TestUser(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - mainfluxSDK := sdk.NewSDK(sdkConf) - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - userID, err := mainfluxSDK.CreateUser(user, token) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - usertoken, err := mainfluxSDK.CreateToken(user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - user.ID = userID - user.Password = "" - - cases := []struct { - desc string - userID string - token string - err errors.SDKError - response sdk.User - }{ - { - desc: "get existing user", - userID: userID, - token: usertoken, - err: nil, - response: user, - }, - { - desc: "get non-existent user", - userID: "43", - token: usertoken, - err: errors.NewSDKErrorWithStatus(errors.ErrNotFound, http.StatusNotFound), - response: sdk.User{}, - }, - - { - desc: "get user with invalid token", - userID: userID, - token: wrongValue, - err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized), - response: sdk.User{}, - }, - } - for _, tc := range cases { - respUs, err := mainfluxSDK.User(tc.userID, tc.token) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) - assert.Equal(t, tc.response, respUs, fmt.Sprintf("%s: expected response user %s, got %s", tc.desc, tc.response, respUs)) - } -} - -func TestUsers(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - mainfluxSDK := sdk.NewSDK(sdkConf) - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - - var users []sdk.User - - for i := 10; i < 100; i++ { - email := fmt.Sprintf("user%d@example.com", i) - password := fmt.Sprintf("password%d", i) - metadata := map[string]interface{}{"name": fmt.Sprintf("user%d", i)} - us := sdk.User{Email: email, Password: password, Metadata: metadata} - userID, err := mainfluxSDK.CreateUser(us, token) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - us.ID = userID - us.Password = "" - users = append(users, us) - } - - cases := []struct { - desc string - token string - offset uint64 - limit uint64 - err errors.SDKError - response []sdk.User - email string - metadata map[string]interface{} - }{ - { - desc: "get a list of users", - token: token, - offset: offset, - limit: limit, - err: nil, - email: "", - response: users[offset:limit], - }, - { - desc: "get a list of users with invalid token", - token: wrongValue, - offset: offset, - limit: limit, - err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized), - email: "", - response: nil, - }, - { - desc: "get a list of users with empty token", - token: "", - offset: offset, - limit: limit, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - email: "", - response: nil, - }, - { - desc: "get a list of users with zero limit", - token: token, - offset: offset, - limit: 0, - err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusBadRequest), - email: "", - response: nil, - }, - { - desc: "get a list of users with limit greater than max", - token: token, - offset: offset, - limit: 110, - err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusBadRequest), - email: "", - response: []sdk.User(nil), - }, - { - desc: "get a list of users with same email address", - token: token, - offset: 0, - limit: 1, - err: nil, - email: "user99@example.com", - metadata: make(map[string]interface{}), - response: []sdk.User{users[89]}, - }, - { - desc: "get a list of users with same email address and metadata", - token: token, - offset: 0, - limit: 1, - err: nil, - email: "user99@example.com", - metadata: map[string]interface{}{ - "name": "user99", - }, - response: []sdk.User{users[89]}, - }, - } - for _, tc := range cases { - filter := sdk.PageMetadata{ - Email: tc.email, - Total: total, - Offset: uint64(tc.offset), - Limit: uint64(tc.limit), - Metadata: tc.metadata, - } - page, err := mainfluxSDK.Users(filter, tc.token) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) - assert.Equal(t, tc.response, page.Users, fmt.Sprintf("%s: expected response user %s, got %s", tc.desc, tc.response, page.Users)) - } -} - -func TestCreateToken(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - mainfluxSDK := sdk.NewSDK(sdkConf) - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - _, err := mainfluxSDK.CreateUser(user, token) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := []struct { - desc string - user sdk.User - token string - err errors.SDKError - }{ - { - desc: "create token for user", - user: user, - token: token, - err: nil, - }, - { - desc: "create token for non existing user", - user: sdk.User{Email: "user2@example.com", Password: "password"}, - token: "", - err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "create user with empty email", - user: sdk.User{Email: "", Password: "password"}, - token: "", - err: errors.NewSDKErrorWithStatus(errors.ErrMalformedEntity, http.StatusBadRequest), - }, - } - for _, tc := range cases { - token, err := mainfluxSDK.CreateToken(tc.user) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) - assert.Equal(t, tc.token, token, fmt.Sprintf("%s: expected response: %s, got: %s", tc.desc, token, tc.token)) - } -} - -func TestUpdateUser(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - mainfluxSDK := sdk.NewSDK(sdkConf) - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - userID, err := mainfluxSDK.CreateUser(user, token) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - usertoken, err := mainfluxSDK.CreateToken(user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := []struct { - desc string - user sdk.User - token string - err errors.SDKError - }{ - { - desc: "update email for user", - user: sdk.User{ID: userID, Email: "user2@example.com", Password: "password"}, - token: usertoken, - err: nil, - }, - { - desc: "update email for user with invalid token", - user: sdk.User{ID: userID, Email: "user2@example.com", Password: "password"}, - token: wrongValue, - err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "update email for user with empty token", - user: sdk.User{ID: userID, Email: "user2@example.com", Password: "password"}, - token: "", - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "update metadata for user", - user: sdk.User{ID: userID, Metadata: metadata, Password: "password"}, - token: usertoken, - err: nil, - }, - } - for _, tc := range cases { - err := mainfluxSDK.UpdateUser(tc.user, tc.token) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) - } -} - -func TestUpdatePassword(t *testing.T) { - svc := newUserService() - ts := newUserServer(svc) - defer ts.Close() - sdkConf := sdk.Config{ - UsersURL: ts.URL, - MsgContentType: contentType, - TLSVerification: false, - } - - mainfluxSDK := sdk.NewSDK(sdkConf) - user := sdk.User{Email: "user@example.com", Password: "password"} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: mfauth.APIKey}) - token := tkn.GetValue() - _, err := mainfluxSDK.CreateUser(user, token) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - usertoken, err := mainfluxSDK.CreateToken(user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := []struct { - desc string - oldPass string - newPass string - token string - err errors.SDKError - }{ - { - desc: "update password for user", - oldPass: "password", - newPass: "password123", - token: usertoken, - err: nil, - }, - { - desc: "update password for user with invalid token", - oldPass: "password", - newPass: "password123", - token: wrongValue, - err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "update password for user with empty token", - oldPass: "password", - newPass: "password123", - token: "", - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - } - for _, tc := range cases { - err := mainfluxSDK.UpdatePassword(tc.oldPass, tc.newPass, tc.token) - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) - } -} diff --git a/provision/service.go b/provision/service.go index bb50cefe7f6..acef9009c55 100644 --- a/provision/service.go +++ b/provision/service.go @@ -283,8 +283,10 @@ func (ps *provisionService) createTokenIfEmpty(token string) (string, error) { } u := SDK.User{ - Email: ps.conf.Server.MfUser, - Password: ps.conf.Server.MfPass, + Credentials: SDK.Credentials{ + Identity: ps.conf.Server.MfUser, + Secret: ps.conf.Server.MfPass, + }, } token, err := ps.sdk.CreateToken(u) if err != nil { diff --git a/readers/api/endpoint.go b/readers/api/endpoint.go index fb25327789b..c769a2886ae 100644 --- a/readers/api/endpoint.go +++ b/readers/api/endpoint.go @@ -10,9 +10,10 @@ import ( "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/readers" + "github.com/mainflux/mainflux/users/policies" ) -func listMessagesEndpoint(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient) endpoint.Endpoint { +func listMessagesEndpoint(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac policies.AuthServiceClient) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(listMessagesReq) diff --git a/readers/api/endpoint_test.go b/readers/api/endpoint_test.go index 74e3737256f..3f46f6f387e 100644 --- a/readers/api/endpoint_test.go +++ b/readers/api/endpoint_test.go @@ -13,13 +13,14 @@ import ( "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/transformers/senml" "github.com/mainflux/mainflux/pkg/uuid" "github.com/mainflux/mainflux/readers" "github.com/mainflux/mainflux/readers/api" "github.com/mainflux/mainflux/readers/mocks" - authmocks "github.com/mainflux/mainflux/users/mocks" + "github.com/mainflux/mainflux/things" + authmocks "github.com/mainflux/mainflux/users/clients/mocks" + "github.com/mainflux/mainflux/users/policies" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -48,9 +49,8 @@ var ( idProvider = uuid.New() ) -func newServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient) *httptest.Server { - logger := logger.NewMock() - mux := api.MakeHandler(repo, tc, ac, svcName, logger) +func newServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, ac policies.AuthServiceClient) *httptest.Server { + mux := api.MakeHandler(repo, tc, ac, svcName) return httptest.NewServer(mux) } @@ -132,7 +132,8 @@ func TestReadAll(t *testing.T) { thSvc := mocks.NewThingsService(map[string]string{email: chanID}) mockAuthzDB := map[string][]authmocks.SubjectSet{} - mockAuthzDB[email] = append(mockAuthzDB[email], authmocks.SubjectSet{Object: "authorities", Relation: "member"}) + mockAuthzDB["token"] = append(mockAuthzDB[email], authmocks.SubjectSet{Subject: "token", Relation: things.AdminRelationKey}) + usrSvc := authmocks.NewAuthService(map[string]string{userToken: email}, mockAuthzDB) repo := mocks.NewMessageRepository(chanID, fromSenml(messages)) diff --git a/readers/api/transport.go b/readers/api/transport.go index 012db8861e9..401efd67771 100644 --- a/readers/api/transport.go +++ b/readers/api/transport.go @@ -12,9 +12,9 @@ import ( "github.com/go-zoo/bone" "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/readers" + "github.com/mainflux/mainflux/users/policies" "github.com/prometheus/client_golang/prometheus/promhttp" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -44,14 +44,10 @@ const ( var ( errThingAccess = errors.New("thing has no permission") errUserAccess = errors.New("user has no permission") - thingsAuth mainflux.ThingsServiceClient - usersAuth mainflux.AuthServiceClient ) // MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient, svcName string, logger logger.Logger) http.Handler { - thingsAuth = tc - usersAuth = ac +func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac policies.AuthServiceClient, svcName string) http.Handler { opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(encodeError), @@ -71,7 +67,7 @@ func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, return mux } -func decodeList(ctx context.Context, r *http.Request) (interface{}, error) { +func decodeList(_ context.Context, r *http.Request) (interface{}, error) { offset, err := apiutil.ReadUintQuery(r, offsetKey, defOffset) if err != nil { return nil, err @@ -215,10 +211,10 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { } } -func authorize(ctx context.Context, req listMessagesReq, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient) (err error) { +func authorize(ctx context.Context, req listMessagesReq, tc mainflux.ThingsServiceClient, ac policies.AuthServiceClient) (err error) { switch { case req.token != "": - user, err := usersAuth.Identify(ctx, &mainflux.Token{Value: req.token}) + user, err := ac.Identify(ctx, &policies.Token{Value: req.token}) if err != nil { e, ok := status.FromError(err) if ok && e.Code() == codes.PermissionDenied { @@ -226,7 +222,7 @@ func authorize(ctx context.Context, req listMessagesReq, tc mainflux.ThingsServi } return err } - if _, err = thingsAuth.IsChannelOwner(ctx, &mainflux.ChannelOwnerReq{Owner: user.Email, ChanID: req.chanID}); err != nil { + if _, err = tc.IsChannelOwner(ctx, &mainflux.ChannelOwnerReq{Owner: user.Email, ChanID: req.chanID}); err != nil { e, ok := status.FromError(err) if ok && e.Code() == codes.PermissionDenied { return errors.Wrap(errUserAccess, err) @@ -235,7 +231,7 @@ func authorize(ctx context.Context, req listMessagesReq, tc mainflux.ThingsServi } return nil default: - if _, err := thingsAuth.CanAccessByKey(ctx, &mainflux.AccessByKeyReq{Token: req.key, ChanID: req.chanID}); err != nil { + if _, err := tc.CanAccessByKey(ctx, &mainflux.AccessByKeyReq{Token: req.key, ChanID: req.chanID}); err != nil { return errors.Wrap(errThingAccess, err) } return nil diff --git a/things/api/auth/grpc/setup_test.go b/things/api/auth/grpc/setup_test.go index 7ba2942ce24..3981993aabc 100644 --- a/things/api/auth/grpc/setup_test.go +++ b/things/api/auth/grpc/setup_test.go @@ -42,8 +42,8 @@ func startServer() { } func newService(tokens map[string]string) things.Service { - policies := []mocks.MockSubjectSet{{Object: "users", Relation: "member"}} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{email: policies}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) diff --git a/things/api/auth/http/endpoint_test.go b/things/api/auth/http/endpoint_test.go index 294ea0b08c9..a2cc27f272f 100644 --- a/things/api/auth/http/endpoint_test.go +++ b/things/api/auth/http/endpoint_test.go @@ -67,8 +67,8 @@ func toJSON(data interface{}) string { } func newService(tokens map[string]string) things.Service { - policies := []mocks.MockSubjectSet{{Object: "users", Relation: "member"}} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{email: policies}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) diff --git a/things/api/logging.go b/things/api/logging.go index cf0ddb1c072..a562305f426 100644 --- a/things/api/logging.go +++ b/things/api/logging.go @@ -52,7 +52,7 @@ func (lm *loggingMiddleware) UpdateThing(ctx context.Context, token string, thin return lm.svc.UpdateThing(ctx, token, thing) } -func (lm *loggingMiddleware) ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) (err error) { +func (lm *loggingMiddleware) ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) (err error) { defer func(begin time.Time) { message := fmt.Sprintf("Method share_thing for token %s and thing %s took %s to complete", token, thingID, time.Since(begin)) if err != nil { @@ -62,7 +62,7 @@ func (lm *loggingMiddleware) ShareThing(ctx context.Context, token, thingID stri lm.logger.Info(fmt.Sprintf("%s without errors.", message)) }(time.Now()) - return lm.svc.ShareThing(ctx, token, thingID, actions, userIDs) + return lm.svc.ShareThing(ctx, token, thingID, actions, userID) } func (lm *loggingMiddleware) UpdateKey(ctx context.Context, token, id, key string) (err error) { diff --git a/things/api/metrics.go b/things/api/metrics.go index 5aad2998fd6..12c35d97905 100644 --- a/things/api/metrics.go +++ b/things/api/metrics.go @@ -48,13 +48,13 @@ func (ms *metricsMiddleware) UpdateThing(ctx context.Context, token string, thin return ms.svc.UpdateThing(ctx, token, thing) } -func (ms *metricsMiddleware) ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) error { +func (ms *metricsMiddleware) ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) error { defer func(begin time.Time) { ms.counter.With("method", "share_thing").Add(1) ms.latency.With("method", "share_thing").Observe(time.Since(begin).Seconds()) }(time.Now()) - return ms.svc.ShareThing(ctx, token, thingID, actions, userIDs) + return ms.svc.ShareThing(ctx, token, thingID, actions, userID) } func (ms *metricsMiddleware) UpdateKey(ctx context.Context, token, id, key string) error { diff --git a/things/api/things/http/endpoint.go b/things/api/things/http/endpoint.go index 850b72b58db..697309072f6 100644 --- a/things/api/things/http/endpoint.go +++ b/things/api/things/http/endpoint.go @@ -89,7 +89,7 @@ func shareThingEndpoint(svc things.Service) endpoint.Endpoint { return nil, err } - if err := svc.ShareThing(ctx, req.token, req.thingID, req.Policies, req.UserIDs); err != nil { + if err := svc.ShareThing(ctx, req.token, req.thingID, req.Policies, req.UserID); err != nil { return nil, err } diff --git a/things/api/things/http/endpoint_test.go b/things/api/things/http/endpoint_test.go index 5e0f05b908d..93f472cd8da 100644 --- a/things/api/things/http/endpoint_test.go +++ b/things/api/things/http/endpoint_test.go @@ -85,10 +85,8 @@ func (tr testRequest) make() (*http.Response, error) { } func newService(tokens map[string]string) things.Service { - userPolicy := mocks.MockSubjectSet{Object: "users", Relation: "member"} - adminPolicy := mocks.MockSubjectSet{Object: "authorities", Relation: "member"} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{ - adminEmail: {userPolicy, adminPolicy}, email: {userPolicy}}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) @@ -374,7 +372,7 @@ func TestUpdateThing(t *testing.T) { id: strconv.FormatUint(wrongID, 10), contentType: contentType, auth: token, - status: http.StatusForbidden, + status: http.StatusNotFound, }, { desc: "update thing with invalid id", @@ -382,7 +380,7 @@ func TestUpdateThing(t *testing.T) { id: "invalid", contentType: contentType, auth: token, - status: http.StatusForbidden, + status: http.StatusNotFound, }, { desc: "update thing with invalid user token", @@ -450,18 +448,18 @@ func TestUpdateThing(t *testing.T) { func TestShareThing(t *testing.T) { token2 := "token2" - svc := newService(map[string]string{token: email, token2: "user@ex.com"}) + svc := newService(map[string]string{token: email, token2: "token2"}) ts := newServer(svc) defer ts.Close() type shareThingReq struct { - UserIDs []string `json:"user_ids"` + UserID string `json:"user_id"` Policies []string `json:"policies"` } - data := toJSON(shareThingReq{UserIDs: []string{"token2"}, Policies: []string{"read"}}) + data := toJSON(shareThingReq{UserID: "token2", Policies: []string{"read"}}) invalidData := toJSON(shareThingReq{}) - invalidPolicies := toJSON(shareThingReq{UserIDs: []string{"token2"}, Policies: []string{"wrong"}}) + invalidPolicies := toJSON(shareThingReq{UserID: "token2", Policies: []string{"wrong"}}) ths, err := svc.CreateThings(context.Background(), token, thing) require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) @@ -537,7 +535,7 @@ func TestShareThing(t *testing.T) { thingID: th.ID, contentType: contentType, token: "invalid", - status: http.StatusUnauthorized, + status: http.StatusForbidden, }, { desc: "share a thing with unauthorized access", @@ -1376,7 +1374,7 @@ func TestRemoveThing(t *testing.T) { desc: "delete non-existent thing", id: strconv.FormatUint(wrongID, 10), auth: token, - status: http.StatusNotFound, + status: http.StatusNoContent, }, { desc: "delete thing with invalid token", diff --git a/things/api/things/http/requests.go b/things/api/things/http/requests.go index 2e63e8f1703..d6ab552f947 100644 --- a/things/api/things/http/requests.go +++ b/things/api/things/http/requests.go @@ -87,7 +87,7 @@ func (req createThingsReq) validate() error { type shareThingReq struct { token string thingID string - UserIDs []string `json:"user_ids"` + UserID string `json:"user_id"` Policies []string `json:"policies"` } @@ -96,7 +96,7 @@ func (req shareThingReq) validate() error { return apiutil.ErrBearerToken } - if req.thingID == "" || len(req.UserIDs) == 0 { + if req.thingID == "" || req.UserID == "" { return apiutil.ErrMissingID } diff --git a/things/mocks/auth.go b/things/mocks/auth.go index 258652c2bc4..64186580647 100644 --- a/things/mocks/auth.go +++ b/things/mocks/auth.go @@ -6,17 +6,16 @@ package mocks import ( "context" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "google.golang.org/grpc" ) -var _ mainflux.AuthServiceClient = (*authServiceMock)(nil) +var _ policies.AuthServiceClient = (*authServiceMock)(nil) type MockSubjectSet struct { - Object string - Relation string + Subject string + Relation []string } type authServiceMock struct { @@ -24,64 +23,58 @@ type authServiceMock struct { policies map[string][]MockSubjectSet } -func (svc authServiceMock) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { - res := mainflux.ListPoliciesRes{} +func (svc authServiceMock) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { + res := policies.ListPoliciesRes{} for key := range svc.policies { - res.Policies = append(res.Policies, key) + res.Objects = append(res.Objects, key) } return &res, nil } // NewAuthService creates mock of users service. -func NewAuthService(users map[string]string, policies map[string][]MockSubjectSet) mainflux.AuthServiceClient { +func NewAuthService(users map[string]string, policies map[string][]MockSubjectSet) policies.AuthServiceClient { return &authServiceMock{users, policies} } -func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { +func (svc authServiceMock) Identify(ctx context.Context, in *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { if id, ok := svc.users[in.Value]; ok { - return &mainflux.UserIdentity{Id: id, Email: id}, nil + return &policies.UserIdentity{Id: id, Email: id}, nil } return nil, errors.ErrAuthentication } -func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { +func (svc authServiceMock) Issue(ctx context.Context, in *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { if id, ok := svc.users[in.GetEmail()]; ok { switch in.Type { default: - return &mainflux.Token{Value: id}, nil + return &policies.Token{Value: id}, nil } } return nil, errors.ErrAuthentication } -func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { +func (svc authServiceMock) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { for _, policy := range svc.policies[req.GetSub()] { - if policy.Relation == req.GetAct() && policy.Object == req.GetObj() { - return &mainflux.AuthorizeRes{Authorized: true}, nil + for _, r := range policy.Relation { + if r == req.GetAct() && policy.Subject == req.GetSub() { + return &policies.AuthorizeRes{Authorized: true}, nil + } } } return nil, errors.ErrAuthorization } -func (svc authServiceMock) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { - if in.GetAct() == "" || in.GetObj() == "" || in.GetSub() == "" { - return &mainflux.AddPolicyRes{}, errors.ErrMalformedEntity +func (svc authServiceMock) AddPolicy(ctx context.Context, in *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { + if len(in.GetAct()) == 0 || in.GetObj() == "" || in.GetSub() == "" { + return &policies.AddPolicyRes{}, errors.ErrMalformedEntity } - obj := in.GetObj() - svc.policies[in.GetSub()] = append(svc.policies[in.GetSub()], MockSubjectSet{Object: obj, Relation: in.GetAct()}) - return &mainflux.AddPolicyRes{Authorized: true}, nil + sub := in.GetSub() + svc.policies[in.GetSub()] = append(svc.policies[in.GetSub()], MockSubjectSet{Subject: sub, Relation: in.GetAct()}) + return &policies.AddPolicyRes{Authorized: true}, nil } -func (svc authServiceMock) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { +func (svc authServiceMock) DeletePolicy(ctx context.Context, in *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { // Not implemented yet - return &mainflux.DeletePolicyRes{Deleted: true}, nil -} - -func (svc authServiceMock) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - panic("not implemented") -} - -func (svc authServiceMock) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { - panic("not implemented") + return &policies.DeletePolicyRes{Deleted: true}, nil } diff --git a/things/postgres/setup_test.go b/things/postgres/setup_test.go index 823fea10282..60f04559a6f 100644 --- a/things/postgres/setup_test.go +++ b/things/postgres/setup_test.go @@ -11,6 +11,7 @@ import ( "os" "testing" + _ "github.com/jackc/pgx/v5/stdlib" // required for SQL access "github.com/jmoiron/sqlx" pgClient "github.com/mainflux/mainflux/internal/clients/postgres" "github.com/mainflux/mainflux/things/postgres" diff --git a/things/redis/streams.go b/things/redis/streams.go index 8132b2fe2b2..8a5e3b4b8de 100644 --- a/things/redis/streams.go +++ b/things/redis/streams.go @@ -82,8 +82,8 @@ func (es eventStore) UpdateKey(ctx context.Context, token, id, key string) error return es.svc.UpdateKey(ctx, token, id, key) } -func (es eventStore) ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) error { - return es.svc.ShareThing(ctx, token, thingID, actions, userIDs) +func (es eventStore) ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) error { + return es.svc.ShareThing(ctx, token, thingID, actions, userID) } func (es eventStore) ViewThing(ctx context.Context, token, id string) (things.Thing, error) { diff --git a/things/redis/streams_test.go b/things/redis/streams_test.go index bfce4853ef3..ea027b3f84c 100644 --- a/things/redis/streams_test.go +++ b/things/redis/streams_test.go @@ -40,10 +40,8 @@ const ( ) func newService(tokens map[string]string) things.Service { - userPolicy := mocks.MockSubjectSet{Object: "users", Relation: "member"} - adminPolicy := mocks.MockSubjectSet{Object: "authorities", Relation: "member"} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{ - adminEmail: {userPolicy, adminPolicy}, email: {userPolicy}}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) diff --git a/things/service.go b/things/service.go index ef98c2da3ce..e5c076d5dd3 100644 --- a/things/service.go +++ b/things/service.go @@ -5,23 +5,27 @@ package things import ( "context" - "fmt" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/ulid" ) const ( - usersObjectKey = "users" - authoritiesObject = "authorities" - memberRelationKey = "member" - readRelationKey = "read" - writeRelationKey = "write" - deleteRelationKey = "delete" + thingsObjectKey = "things" + createKey = "c_add" + updateRelationKey = "c_update" + listRelationKey = "c_list" + deleteRelationKey = "c_delete" + readRelationKey = "m_read" + writeRelationKey = "m_write" + entityType = "group" ) +var AdminRelationKey = []string{createKey, updateRelationKey, listRelationKey, deleteRelationKey, readRelationKey, writeRelationKey} + // Service specifies an API that must be fulfilled by the domain service // implementation, and all of its decorators (e.g. logging & metrics). type Service interface { @@ -35,7 +39,7 @@ type Service interface { // ShareThing gives actions associated with the thing to the given user IDs. // The requester user identified by the token has to have a "write" relation // on the thing in order to share the thing. - ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) error + ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) error // UpdateKey updates key value of the existing thing. A non-nil error is // returned to indicate operation failure. @@ -124,7 +128,7 @@ type PageMetadata struct { var _ Service = (*thingsService)(nil) type thingsService struct { - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient things ThingRepository channels ChannelRepository channelCache ChannelCache @@ -134,7 +138,7 @@ type thingsService struct { } // New instantiates the things service implementation. -func New(auth mainflux.AuthServiceClient, things ThingRepository, channels ChannelRepository, ccache ChannelCache, tcache ThingCache, idp mainflux.IDProvider) Service { +func New(auth policies.AuthServiceClient, things ThingRepository, channels ChannelRepository, ccache ChannelCache, tcache ThingCache, idp mainflux.IDProvider) Service { return &thingsService{ auth: auth, things: things, @@ -147,18 +151,17 @@ func New(auth mainflux.AuthServiceClient, things ThingRepository, channels Chann } func (ts *thingsService) CreateThings(ctx context.Context, token string, things ...Thing) ([]Thing, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return []Thing{}, err } - - if err := ts.authorize(ctx, res.GetId(), usersObjectKey, memberRelationKey); err != nil { + if err := ts.authorize(ctx, token, thingsObjectKey, createKey); err != nil { return []Thing{}, err } ths := []Thing{} for _, thing := range things { - th, err := ts.createThing(ctx, &thing, res) + th, err := ts.createThing(ctx, token, &thing, res) if err != nil { return []Thing{}, err @@ -170,7 +173,7 @@ func (ts *thingsService) CreateThings(ctx context.Context, token string, things } // createThing saves the Thing and adds identity as an owner(Read, Write, Delete policies) of the Thing. -func (ts *thingsService) createThing(ctx context.Context, thing *Thing, identity *mainflux.UserIdentity) (Thing, error) { +func (ts *thingsService) createThing(ctx context.Context, token string, thing *Thing, identity *policies.UserIdentity) (Thing, error) { thing.Owner = identity.GetEmail() if thing.ID == "" { @@ -198,8 +201,7 @@ func (ts *thingsService) createThing(ctx context.Context, thing *Thing, identity return Thing{}, errors.ErrCreateEntity } - ss := fmt.Sprintf("%s:%s#%s", "members", authoritiesObject, memberRelationKey) - if err := ts.claimOwnership(ctx, ths[0].ID, []string{readRelationKey, writeRelationKey, deleteRelationKey}, []string{identity.GetId(), ss}); err != nil { + if err := ts.claimOwnership(ctx, token, ths[0].ID, AdminRelationKey, identity.GetId()); err != nil { return Thing{}, err } @@ -207,15 +209,13 @@ func (ts *thingsService) createThing(ctx context.Context, thing *Thing, identity } func (ts *thingsService) UpdateThing(ctx context.Context, token string, thing Thing) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return err } - if err := ts.authorize(ctx, res.GetId(), thing.ID, writeRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return err - } + if err := ts.authorize(ctx, token, thing.ID, updateRelationKey); err != nil { + return err } thing.Owner = res.GetEmail() @@ -223,47 +223,39 @@ func (ts *thingsService) UpdateThing(ctx context.Context, token string, thing Th return ts.things.Update(ctx, thing) } -func (ts *thingsService) ShareThing(ctx context.Context, token, thingID string, actions, userIDs []string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) - if err != nil { +func (ts *thingsService) ShareThing(ctx context.Context, token, thingID string, actions []string, userID string) error { + if err := ts.authorize(ctx, token, thingID, updateRelationKey); err != nil { return err } - if err := ts.authorize(ctx, res.GetId(), thingID, writeRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return err - } - } - - return ts.claimOwnership(ctx, thingID, actions, userIDs) + return ts.claimOwnership(ctx, token, thingID, actions, userID) } -func (ts *thingsService) claimOwnership(ctx context.Context, objectID string, actions, userIDs []string) error { - var errs error - for _, userID := range userIDs { - for _, action := range actions { - apr, err := ts.auth.AddPolicy(ctx, &mainflux.AddPolicyReq{Obj: objectID, Act: action, Sub: userID}) - if err != nil { - errs = errors.Wrap(fmt.Errorf("cannot claim ownership on object '%s' by user '%s': %s", objectID, userID, err), errs) - } - if !apr.GetAuthorized() { - errs = errors.Wrap(fmt.Errorf("cannot claim ownership on object '%s' by user '%s': unauthorized", objectID, userID), errs) - } - } +func (ts *thingsService) claimOwnership(ctx context.Context, token, objectID string, actions []string, subject string) error { + req := &policies.AddPolicyReq{ + Token: token, + Sub: subject, + Obj: objectID, + Act: actions, } - return errs + res, err := ts.auth.AddPolicy(ctx, req) + if err != nil { + return errors.Wrap(errors.ErrAuthorization, err) + } + if !res.GetAuthorized() { + return errors.ErrAuthorization + } + return nil } func (ts *thingsService) UpdateKey(ctx context.Context, token, id, key string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), id, writeRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, id, updateRelationKey); err != nil { + return err } owner := res.GetEmail() @@ -272,29 +264,27 @@ func (ts *thingsService) UpdateKey(ctx context.Context, token, id, key string) e } func (ts *thingsService) ViewThing(ctx context.Context, token, id string) (Thing, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Thing{}, errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), id, readRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return Thing{}, errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, id, listRelationKey); err != nil { + return Thing{}, errors.Wrap(errors.ErrNotFound, err) } return ts.things.RetrieveByID(ctx, res.GetEmail(), id) } func (ts *thingsService) ListThings(ctx context.Context, token string, pm PageMetadata) (Page, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Page{}, errors.Wrap(errors.ErrAuthentication, err) } subject := res.GetId() // If the user is admin, fetch all things from database. - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err == nil { + if err := ts.authorize(ctx, token, "", listRelationKey); err == nil { pm.FetchSharedThings = true page, err := ts.things.RetrieveAll(ctx, res.GetEmail(), pm) if err != nil { @@ -307,14 +297,14 @@ func (ts *thingsService) ListThings(ctx context.Context, token string, pm PageMe // If user provides 'shared' key, fetch things from policies. Otherwise, // fetch things from the database based on thing's 'owner' field. if pm.FetchSharedThings { - req := &mainflux.ListPoliciesReq{Act: "read", Sub: subject} + req := &policies.ListPoliciesReq{Act: listRelationKey, Sub: subject} lpr, err := ts.auth.ListPolicies(ctx, req) if err != nil { return Page{}, err } var page Page - for _, thingID := range lpr.Policies { + for _, thingID := range lpr.Objects { page.Things = append(page.Things, Thing{ID: thingID}) } return page, nil @@ -330,7 +320,7 @@ func (ts *thingsService) ListThings(ctx context.Context, token string, pm PageMe } func (ts *thingsService) ListThingsByChannel(ctx context.Context, token, chID string, pm PageMetadata) (Page, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Page{}, errors.Wrap(errors.ErrAuthentication, err) } @@ -339,16 +329,14 @@ func (ts *thingsService) ListThingsByChannel(ctx context.Context, token, chID st } func (ts *thingsService) RemoveThing(ctx context.Context, token, id string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), id, deleteRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, id, deleteRelationKey); err != nil { + return errors.Wrap(errors.ErrNotFound, err) } if err := ts.thingCache.Remove(ctx, id); err != nil { @@ -358,14 +346,14 @@ func (ts *thingsService) RemoveThing(ctx context.Context, token, id string) erro } func (ts *thingsService) CreateChannels(ctx context.Context, token string, channels ...Channel) ([]Channel, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return []Channel{}, errors.Wrap(errors.ErrAuthentication, err) } chs := []Channel{} for _, channel := range channels { - ch, err := ts.createChannel(ctx, &channel, res) + ch, err := ts.createChannel(ctx, token, &channel, res) if err != nil { return []Channel{}, err } @@ -374,7 +362,7 @@ func (ts *thingsService) CreateChannels(ctx context.Context, token string, chann return chs, nil } -func (ts *thingsService) createChannel(ctx context.Context, channel *Channel, identity *mainflux.UserIdentity) (Channel, error) { +func (ts *thingsService) createChannel(ctx context.Context, token string, channel *Channel, identity *policies.UserIdentity) (Channel, error) { if channel.ID == "" { chID, err := ts.idProvider.ID() if err != nil { @@ -392,23 +380,20 @@ func (ts *thingsService) createChannel(ctx context.Context, channel *Channel, id return Channel{}, errors.ErrCreateEntity } - ss := fmt.Sprintf("%s:%s#%s", "members", authoritiesObject, memberRelationKey) - if err := ts.claimOwnership(ctx, chs[0].ID, []string{readRelationKey, writeRelationKey, deleteRelationKey}, []string{identity.GetId(), ss}); err != nil { + if err := ts.claimOwnership(ctx, token, chs[0].ID, AdminRelationKey, identity.GetId()); err != nil { return Channel{}, err } return chs[0], nil } func (ts *thingsService) UpdateChannel(ctx context.Context, token string, channel Channel) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), channel.ID, writeRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, channel.ID, updateRelationKey); err != nil { + return errors.Wrap(errors.ErrNotFound, err) } channel.Owner = res.GetEmail() @@ -416,28 +401,26 @@ func (ts *thingsService) UpdateChannel(ctx context.Context, token string, channe } func (ts *thingsService) ViewChannel(ctx context.Context, token, id string) (Channel, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Channel{}, errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), id, readRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return Channel{}, errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, id, listRelationKey); err != nil { + return Channel{}, errors.Wrap(errors.ErrNotFound, err) } return ts.channels.RetrieveByID(ctx, res.GetEmail(), id) } func (ts *thingsService) ListChannels(ctx context.Context, token string, pm PageMetadata) (ChannelsPage, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return ChannelsPage{}, errors.Wrap(errors.ErrAuthentication, err) } // If the user is admin, fetch all channels from the database. - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err == nil { + if err := ts.authorize(ctx, token, "", listRelationKey); err == nil { pm.FetchSharedThings = true page, err := ts.channels.RetrieveAll(ctx, res.GetEmail(), pm) if err != nil { @@ -451,7 +434,7 @@ func (ts *thingsService) ListChannels(ctx context.Context, token string, pm Page } func (ts *thingsService) ListChannelsByThing(ctx context.Context, token, thID string, pm PageMetadata) (ChannelsPage, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return ChannelsPage{}, errors.Wrap(errors.ErrAuthentication, err) } @@ -460,15 +443,13 @@ func (ts *thingsService) ListChannelsByThing(ctx context.Context, token, thID st } func (ts *thingsService) RemoveChannel(ctx context.Context, token, id string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } - if err := ts.authorize(ctx, res.GetId(), id, deleteRelationKey); err != nil { - if err := ts.authorize(ctx, res.GetId(), authoritiesObject, memberRelationKey); err != nil { - return errors.Wrap(errors.ErrNotFound, err) - } + if err := ts.authorize(ctx, token, id, deleteRelationKey); err != nil { + return errors.Wrap(errors.ErrNotFound, err) } if err := ts.channelCache.Remove(ctx, id); err != nil { @@ -479,7 +460,7 @@ func (ts *thingsService) RemoveChannel(ctx context.Context, token, id string) er } func (ts *thingsService) Connect(ctx context.Context, token string, chIDs, thIDs []string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } @@ -488,7 +469,7 @@ func (ts *thingsService) Connect(ctx context.Context, token string, chIDs, thIDs } func (ts *thingsService) Disconnect(ctx context.Context, token string, chIDs, thIDs []string) error { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.Wrap(errors.ErrAuthentication, err) } @@ -576,39 +557,15 @@ func (ts *thingsService) hasThing(ctx context.Context, chanID, thingKey string) } func (ts *thingsService) ListMembers(ctx context.Context, token, groupID string, pm PageMetadata) (Page, error) { - if _, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}); err != nil { - return Page{}, err - } - - res, err := ts.members(ctx, token, groupID, "things", pm.Offset, pm.Limit) - if err != nil { - return Page{}, nil - } - - return ts.things.RetrieveByIDs(ctx, res, pm) -} - -func (ts *thingsService) members(ctx context.Context, token, groupID, groupType string, limit, offset uint64) ([]string, error) { - req := mainflux.MembersReq{ - Token: token, - GroupID: groupID, - Offset: offset, - Limit: limit, - Type: groupType, - } - - res, err := ts.auth.Members(ctx, &req) - if err != nil { - return nil, nil - } - return res.Members, nil + panic("unimplemented - to be implemented on clients integration") } func (ts *thingsService) authorize(ctx context.Context, subject, object string, relation string) error { - req := &mainflux.AuthorizeReq{ - Sub: subject, - Obj: object, - Act: relation, + req := &policies.AuthorizeReq{ + EntityType: entityType, + Sub: subject, + Obj: object, + Act: relation, } res, err := ts.auth.Authorize(ctx, req) if err != nil { diff --git a/things/service_test.go b/things/service_test.go index 94cdbb24f05..477a689be54 100644 --- a/things/service_test.go +++ b/things/service_test.go @@ -38,10 +38,8 @@ var ( ) func newService(tokens map[string]string) things.Service { - userPolicy := mocks.MockSubjectSet{Object: "users", Relation: "member"} - adminPolicy := mocks.MockSubjectSet{Object: "authorities", Relation: "member"} - auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{ - adminEmail: {userPolicy, adminPolicy}, email: {userPolicy}}) + adminPolicy := mocks.MockSubjectSet{Subject: "token", Relation: things.AdminRelationKey} + auth := mocks.NewAuthService(tokens, map[string][]mocks.MockSubjectSet{token: {adminPolicy}}) conns := make(chan mocks.Connection) thingsRepo := mocks.NewThingRepository(conns) channelsRepo := mocks.NewChannelRepository(thingsRepo, conns) @@ -57,6 +55,7 @@ func TestInit(t *testing.T) { thingList[i].Name = fmt.Sprintf("name-%d", i+1) thingList[i].ID = fmt.Sprintf("%s%012d", prefix, i+1) thingList[i].Key = fmt.Sprintf("%s1%011d", prefix, i+1) + thingList[i].Owner = token } } @@ -130,7 +129,7 @@ func TestUpdateThing(t *testing.T) { desc: "update non-existing thing", thing: other, token: token, - err: errors.ErrAuthorization, + err: errors.ErrNotFound, }, } @@ -173,7 +172,7 @@ func TestUpdateKey(t *testing.T) { token: token, id: wrongID, key: wrongValue, - err: errors.ErrAuthorization, + err: errors.ErrNotFound, }, } @@ -195,7 +194,7 @@ func TestShareThing(t *testing.T) { token string thingID string policies []string - userIDs []string + userID string err error }{ { @@ -203,7 +202,7 @@ func TestShareThing(t *testing.T) { token: token, thingID: th.ID, policies: policies, - userIDs: []string{email2}, + userID: email2, err: nil, }, { @@ -211,7 +210,7 @@ func TestShareThing(t *testing.T) { token: token2, thingID: th.ID, policies: policies, - userIDs: []string{email2}, + userID: email2, err: errors.ErrAuthorization, }, { @@ -219,21 +218,21 @@ func TestShareThing(t *testing.T) { token: wrongValue, thingID: th.ID, policies: policies, - userIDs: []string{email2}, - err: errors.ErrAuthentication, + userID: email2, + err: errors.ErrAuthorization, }, { desc: "share a thing with partially invalid policies", token: token, thingID: th.ID, policies: []string{"", "read"}, - userIDs: []string{email2}, - err: fmt.Errorf("cannot claim ownership on object '%s' by user '%s': %s", th.ID, email2, errors.ErrMalformedEntity), + userID: email2, + err: nil, }, } for _, tc := range cases { - err := svc.ShareThing(context.Background(), tc.token, tc.thingID, tc.policies, tc.userIDs) + err := svc.ShareThing(context.Background(), tc.token, tc.thingID, tc.policies, tc.userID) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) } @@ -571,7 +570,9 @@ func TestListThingsByChannel(t *testing.T) { assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) // Check if Things by Channel list have been sorted properly - testSortThings(t, tc.pageMetadata, page.Things) + if len(page.Things) > 0 { + testSortThings(t, tc.pageMetadata, page.Things) + } } } @@ -609,7 +610,7 @@ func TestRemoveThing(t *testing.T) { desc: "remove non-existing thing", id: wrongID, token: token, - err: errors.ErrAuthorization, + err: nil, }, } diff --git a/things/standalone/standalone.go b/things/standalone/standalone.go index 8af807ca0b9..1a9ce4a3382 100644 --- a/things/standalone/standalone.go +++ b/things/standalone/standalone.go @@ -6,15 +6,14 @@ package standalone import ( "context" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "google.golang.org/grpc" ) var errUnsupported = errors.New("not supported in standalone mode") -var _ mainflux.AuthServiceClient = (*singleUserRepo)(nil) +var _ policies.AuthServiceClient = (*singleUserRepo)(nil) type singleUserRepo struct { email string @@ -22,58 +21,50 @@ type singleUserRepo struct { } // NewAuthService creates single user repository for constrained environments. -func NewAuthService(email, token string) mainflux.AuthServiceClient { +func NewAuthService(email, token string) policies.AuthServiceClient { return singleUserRepo{ email: email, token: token, } } -func (repo singleUserRepo) Issue(ctx context.Context, req *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { +func (repo singleUserRepo) Issue(ctx context.Context, req *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { if repo.token != req.GetEmail() { return nil, errors.ErrAuthentication } - return &mainflux.Token{Value: repo.token}, nil + return &policies.Token{Value: repo.token}, nil } -func (repo singleUserRepo) Identify(ctx context.Context, token *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { +func (repo singleUserRepo) Identify(ctx context.Context, token *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { if repo.token != token.GetValue() { return nil, errors.ErrAuthentication } - return &mainflux.UserIdentity{Id: repo.email, Email: repo.email}, nil + return &policies.UserIdentity{Id: repo.email, Email: repo.email}, nil } -func (repo singleUserRepo) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { +func (repo singleUserRepo) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { if repo.email != req.Sub { - return &mainflux.AuthorizeRes{}, errUnsupported + return &policies.AuthorizeRes{}, errUnsupported } - return &mainflux.AuthorizeRes{Authorized: true}, nil + return &policies.AuthorizeRes{Authorized: true}, nil } -func (repo singleUserRepo) AddPolicy(ctx context.Context, req *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { +func (repo singleUserRepo) AddPolicy(ctx context.Context, req *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { if repo.email != req.Sub { - return &mainflux.AddPolicyRes{}, errUnsupported + return &policies.AddPolicyRes{}, errUnsupported } - return &mainflux.AddPolicyRes{Authorized: true}, nil + return &policies.AddPolicyRes{Authorized: true}, nil } -func (repo singleUserRepo) DeletePolicy(ctx context.Context, req *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { +func (repo singleUserRepo) DeletePolicy(ctx context.Context, req *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { if repo.email != req.Sub { - return &mainflux.DeletePolicyRes{}, errUnsupported + return &policies.DeletePolicyRes{}, errUnsupported } - return &mainflux.DeletePolicyRes{Deleted: true}, nil + return &policies.DeletePolicyRes{Deleted: true}, nil } -func (repo singleUserRepo) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { - return &mainflux.ListPoliciesRes{}, errUnsupported -} - -func (repo singleUserRepo) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - return &mainflux.MembersRes{}, errUnsupported -} - -func (repo singleUserRepo) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { - return &empty.Empty{}, errUnsupported +func (repo singleUserRepo) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { + return &policies.ListPoliciesRes{}, errUnsupported } diff --git a/things/standalone/standalone_test.go b/things/standalone/standalone_test.go index 48ca5374b07..b77296a07ea 100644 --- a/things/standalone/standalone_test.go +++ b/things/standalone/standalone_test.go @@ -8,9 +8,9 @@ import ( "fmt" "testing" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/things/standalone" + "github.com/mainflux/mainflux/users/policies" "github.com/stretchr/testify/assert" ) @@ -40,7 +40,7 @@ func TestIdentify(t *testing.T) { } for desc, tc := range cases { - id, err := svc.Identify(context.Background(), &mainflux.Token{Value: tc.token}) + id, err := svc.Identify(context.Background(), &policies.Token{Value: tc.token}) assert.Equal(t, tc.id, id.GetEmail(), fmt.Sprintf("%s: expected %s, got %s", desc, tc.id, id.GetEmail())) assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s, got %s", desc, tc.err, err)) } @@ -67,7 +67,7 @@ func TestIssue(t *testing.T) { } for desc, tc := range cases { - id, err := svc.Issue(context.Background(), &mainflux.IssueReq{Id: tc.id, Email: tc.token, Type: 0}) + id, err := svc.Issue(context.Background(), &policies.IssueReq{Id: tc.id, Email: tc.token, Type: 0}) assert.Equal(t, tc.id, id.GetValue(), fmt.Sprintf("%s: expected %s, got %s", desc, tc.id, id.GetValue())) assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s, got %s", desc, tc.err, err)) } diff --git a/tools/provision/provision.go b/tools/provision/provision.go index 98353f3eaab..d5763228f3e 100644 --- a/tools/provision/provision.go +++ b/tools/provision/provision.go @@ -73,13 +73,15 @@ func Provision(conf Config) { s := sdk.NewSDK(sdkConf) user := sdk.User{ - Email: conf.Username, - Password: conf.Password, + Credentials: sdk.Credentials{ + Identity: conf.Username, + Secret: conf.Password, + }, } - if user.Email == "" { - user.Email = fmt.Sprintf("%s@email.com", namesgenerator.GetRandomName(0)) - user.Password = defPass + if user.Credentials.Identity == "" { + user.Credentials.Identity = fmt.Sprintf("%s@email.com", namesgenerator.GetRandomName(0)) + user.Credentials.Secret = defPass } // Create new user diff --git a/twins/api/http/endpoint_states_test.go b/twins/api/http/endpoint_states_test.go index 360781f4995..613b1a01680 100644 --- a/twins/api/http/endpoint_states_test.go +++ b/twins/api/http/endpoint_states_test.go @@ -51,7 +51,7 @@ func TestListStates(t *testing.T) { attr := def.Attributes[0] var recs = make([]senml.Record, numRecs) - mocks.CreateSenML(numRecs, recs) + mocks.CreateSenML(recs) message, err := mocks.CreateMessage(attr, recs) require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) err = svc.SaveStates(message) diff --git a/twins/mocks/auth.go b/twins/mocks/auth.go index 3b015e072cc..03103a72bcf 100644 --- a/twins/mocks/auth.go +++ b/twins/mocks/auth.go @@ -6,54 +6,45 @@ package mocks import ( "context" - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "google.golang.org/grpc" ) -var _ mainflux.AuthServiceClient = (*authServiceClient)(nil) +var _ policies.AuthServiceClient = (*authServiceClient)(nil) type authServiceClient struct { users map[string]string } -func (svc authServiceClient) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { +func (svc authServiceClient) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { panic("not implemented") } // NewAuthServiceClient creates mock of auth service. -func NewAuthServiceClient(users map[string]string) mainflux.AuthServiceClient { +func NewAuthServiceClient(users map[string]string) policies.AuthServiceClient { return &authServiceClient{users} } -func (svc authServiceClient) Identify(ctx context.Context, in *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { +func (svc authServiceClient) Identify(ctx context.Context, in *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { if id, ok := svc.users[in.Value]; ok { - return &mainflux.UserIdentity{Id: id, Email: id}, nil + return &policies.UserIdentity{Id: id, Email: id}, nil } return nil, errors.ErrAuthentication } -func (svc *authServiceClient) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { - return new(mainflux.Token), nil +func (svc *authServiceClient) Issue(ctx context.Context, in *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { + return new(policies.Token), nil } -func (svc *authServiceClient) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { +func (svc *authServiceClient) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { panic("not implemented") } -func (svc authServiceClient) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { +func (svc authServiceClient) AddPolicy(ctx context.Context, in *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { panic("not implemented") } -func (svc authServiceClient) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { - panic("not implemented") -} - -func (svc *authServiceClient) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - panic("not implemented") -} - -func (svc *authServiceClient) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { +func (svc authServiceClient) DeletePolicy(ctx context.Context, in *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { panic("not implemented") } diff --git a/twins/mocks/service.go b/twins/mocks/service.go index b6dd40d6f60..90e61d88d81 100644 --- a/twins/mocks/service.go +++ b/twins/mocks/service.go @@ -52,7 +52,7 @@ func CreateTwin(channels []string, subtopics []string) twins.Twin { } // CreateSenML creates SenML record array -func CreateSenML(n int, recs []senml.Record) { +func CreateSenML(recs []senml.Record) { for i, rec := range recs { rec.BaseTime = float64(time.Now().Unix()) rec.Time = float64(i) diff --git a/twins/service.go b/twins/service.go index ce04a314687..9904a459a60 100644 --- a/twins/service.go +++ b/twins/service.go @@ -13,6 +13,7 @@ import ( "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/messaging" + "github.com/mainflux/mainflux/users/policies" "github.com/mainflux/mainflux" "github.com/mainflux/senml" @@ -74,7 +75,7 @@ var crudOp = map[string]string{ type twinsService struct { publisher messaging.Publisher - auth mainflux.AuthServiceClient + auth policies.AuthServiceClient twins TwinRepository states StateRepository idProvider mainflux.IDProvider @@ -86,7 +87,7 @@ type twinsService struct { var _ Service = (*twinsService)(nil) // New instantiates the twins service implementation. -func New(publisher messaging.Publisher, auth mainflux.AuthServiceClient, twins TwinRepository, tcache TwinCache, sr StateRepository, idp mainflux.IDProvider, chann string, logger logger.Logger) Service { +func New(publisher messaging.Publisher, auth policies.AuthServiceClient, twins TwinRepository, tcache TwinCache, sr StateRepository, idp mainflux.IDProvider, chann string, logger logger.Logger) Service { return &twinsService{ publisher: publisher, auth: auth, @@ -104,7 +105,7 @@ func (ts *twinsService) AddTwin(ctx context.Context, token string, twin Twin, de var b []byte defer ts.publish(&id, &err, crudOp["createSucc"], crudOp["createFail"], &b) - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Twin{}, err } @@ -147,7 +148,7 @@ func (ts *twinsService) UpdateTwin(ctx context.Context, token string, twin Twin, var id string defer ts.publish(&id, &err, crudOp["updateSucc"], crudOp["updateFail"], &b) - _, err = ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + _, err = ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.ErrAuthentication } @@ -197,7 +198,7 @@ func (ts *twinsService) ViewTwin(ctx context.Context, token, twinID string) (tw var b []byte defer ts.publish(&twinID, &err, crudOp["getSucc"], crudOp["getFail"], &b) - _, err = ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + _, err = ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Twin{}, err } @@ -216,7 +217,7 @@ func (ts *twinsService) RemoveTwin(ctx context.Context, token, twinID string) (e var b []byte defer ts.publish(&twinID, &err, crudOp["removeSucc"], crudOp["removeFail"], &b) - _, err = ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + _, err = ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return errors.ErrAuthentication } @@ -229,7 +230,7 @@ func (ts *twinsService) RemoveTwin(ctx context.Context, token, twinID string) (e } func (ts *twinsService) ListTwins(ctx context.Context, token string, offset uint64, limit uint64, name string, metadata Metadata) (Page, error) { - res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + res, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return Page{}, errors.ErrAuthentication } @@ -238,7 +239,7 @@ func (ts *twinsService) ListTwins(ctx context.Context, token string, offset uint } func (ts *twinsService) ListStates(ctx context.Context, token string, offset uint64, limit uint64, twinID string) (StatesPage, error) { - _, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) + _, err := ts.auth.Identify(ctx, &policies.Token{Value: token}) if err != nil { return StatesPage{}, errors.ErrAuthentication } diff --git a/twins/service_test.go b/twins/service_test.go index 38347368fb3..7e281730823 100644 --- a/twins/service_test.go +++ b/twins/service_test.go @@ -258,7 +258,7 @@ func TestSaveStates(t *testing.T) { require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) var recs = make([]senml.Record, numRecs) - mocks.CreateSenML(numRecs, recs) + mocks.CreateSenML(recs) var ttlAdded uint64 @@ -332,7 +332,7 @@ func TestListStates(t *testing.T) { require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) var recs = make([]senml.Record, numRecs) - mocks.CreateSenML(numRecs, recs) + mocks.CreateSenML(recs) message, err := mocks.CreateMessage(attr, recs) require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) err = svc.SaveStates(message) diff --git a/users/README.md b/users/README.md index 4a011e555f1..3458839cfb1 100644 --- a/users/README.md +++ b/users/README.md @@ -1,98 +1,3 @@ -# Users service +# Clients -Users service provides an HTTP API for managing users. Through this API clients -are able to do the following actions: - -- register new accounts -- obtain access tokens -- verify access tokens - -For in-depth explanation of the aforementioned scenarios, as well as thorough -understanding of Mainflux, please check out the [official documentation][doc]. - -## Configuration - -The service is configured using the environment variables presented in the -following table. Note that any unset variables will be replaced with their -default values. - -| Variable | Description | Default | -| ------------------------- | ----------------------------------------------------------------------- | -------------- | -| MF_USERS_LOG_LEVEL | Log level for Users (debug, info, warn, error) | info | -| MF_USERS_DB_HOST | Database host address | localhost | -| MF_USERS_DB_PORT | Database host port | 5432 | -| MF_USERS_DB_USER | Database user | mainflux | -| MF_USERS_DB_PASSWORD | Database password | mainflux | -| MF_USERS_DB | Name of the database used by the service | users | -| MF_USERS_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable | -| MF_USERS_DB_SSL_CERT | Path to the PEM encoded certificate file | | -| MF_USERS_DB_SSL_KEY | Path to the PEM encoded key file | | -| MF_USERS_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | | -| MF_USERS_HTTP_PORT | Users service HTTP port | 8180 | -| MF_USERS_SERVER_CERT | Path to server certificate in pem format | | -| MF_USERS_SERVER_KEY | Path to server key in pem format | | -| MF_USERS_ADMIN_EMAIL | Default user, created on startup | | -| MF_USERS_ADMIN_PASSWORD | Default user password, created on startup | | -| MF_JAEGER_URL | Jaeger server URL | localhost:6831 | -| MF_EMAIL_HOST | Mail server host | localhost | -| MF_EMAIL_PORT | Mail server port | 25 | -| MF_EMAIL_USERNAME | Mail server username | | -| MF_EMAIL_PASSWORD | Mail server password | | -| MF_EMAIL_FROM_ADDRESS | Email "from" address | | -| MF_EMAIL_FROM_NAME | Email "from" name | | -| MF_EMAIL_TEMPLATE | Email template for sending emails with password reset link | email.tmpl | -| MF_TOKEN_RESET_ENDPOINT | Password request reset endpoint, for constructing link | /reset-request | - -## Deployment - -The service itself is distributed as Docker container. Check the [`users`](https://github.com/mainflux/mainflux/blob/master/docker/docker-compose.yml#L109-L143) service section in -docker-compose to see how service is deployed. - -To start the service outside of the container, execute the following shell script: - -```bash -# download the latest version of the service -git clone https://github.com/mainflux/mainflux - -cd mainflux - -# compile the service -make users - -# copy binary to bin -make install - -# set the environment variables and run the service -MF_USERS_LOG_LEVEL=[Users log level] \ -MF_USERS_DB_HOST=[Database host address] \ -MF_USERS_DB_PORT=[Database host port] \ -MF_USERS_DB_USER=[Database user] \ -MF_USERS_DB_PASS=[Database password] \ -MF_USERS_DB=[Name of the database used by the service] \ -MF_USERS_DB_SSL_MODE=[SSL mode to connect to the database with] \ -MF_USERS_DB_SSL_CERT=[Path to the PEM encoded certificate file] \ -MF_USERS_DB_SSL_KEY=[Path to the PEM encoded key file] \ -MF_USERS_DB_SSL_ROOT_CERT=[Path to the PEM encoded root certificate file] \ -MF_USERS_HTTP_PORT=[Service HTTP port] \ -MF_USERS_SERVER_CERT=[Path to server certificate] \ -MF_USERS_SERVER_KEY=[Path to server key] \ -MF_JAEGER_URL=[Jaeger server URL] \ -MF_EMAIL_HOST=[Mail server host] \ -MF_EMAIL_PORT=[Mail server port] \ -MF_EMAIL_USERNAME=[Mail server username] \ -MF_EMAIL_PASSWORD=[Mail server password] \ -MF_EMAIL_FROM_ADDRESS=[Email from address] \ -MF_EMAIL_FROM_NAME=[Email from name] \ -MF_EMAIL_TEMPLATE=[Email template file] \ -MF_TOKEN_RESET_ENDPOINT=[Password reset token endpoint] \ -$GOBIN/mainflux-users -``` - -If `MF_EMAIL_TEMPLATE` doesn't point to any file service will function but password reset functionality will not work. - -## Usage - -For more information about service capabilities and its usage, please check out -the [API documentation](https://api.mainflux.io/?urls.primaryName=users-openapi.yml). - -[doc]: https://docs.mainflux.io +Repository for Clients service for handling generic clients diff --git a/users/api/doc.go b/users/api/doc.go deleted file mode 100644 index fb3127e46b3..00000000000 --- a/users/api/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package api contains API-related concerns: endpoint definitions, middlewares -// and all resource representations. -package api diff --git a/users/api/endpoint.go b/users/api/endpoint.go deleted file mode 100644 index 59ef11d6984..00000000000 --- a/users/api/endpoint.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - - "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" -) - -func registrationEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(createUserReq) - if err := req.validate(); err != nil { - return createUserRes{}, err - } - uid, err := svc.Register(ctx, req.token, req.user) - if err != nil { - return createUserRes{}, err - } - ucr := createUserRes{ - ID: uid, - created: true, - } - - return ucr, nil - } -} - -// Password reset request endpoint. -// When successful password reset link is generated. -// Link is generated using MF_TOKEN_RESET_ENDPOINT env. -// and value from Referer header for host. -// {Referer}+{MF_TOKEN_RESET_ENDPOINT}+{token=TOKEN} -// http://mainflux.com/reset-request?token=xxxxxxxxxxx. -// Email with a link is being sent to the user. -// When user clicks on a link it should get the ui with form to -// enter new password, when form is submitted token and new password -// must be sent as PUT request to 'password/reset' passwordResetEndpoint -func passwordResetRequestEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(passwResetReq) - if err := req.validate(); err != nil { - return nil, err - } - res := passwResetReqRes{} - email := req.Email - if err := svc.GenerateResetToken(ctx, email, req.Host); err != nil { - return nil, err - } - res.Msg = MailSent - - return res, nil - } -} - -// This is endpoint that actually sets new password in password reset flow. -// When user clicks on a link in email finally ends on this endpoint as explained in -// the comment above. -func passwordResetEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(resetTokenReq) - if err := req.validate(); err != nil { - return nil, err - } - res := passwChangeRes{} - if err := svc.ResetPassword(ctx, req.Token, req.Password); err != nil { - return nil, err - } - return res, nil - } -} - -func viewUserEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(viewUserReq) - if err := req.validate(); err != nil { - return nil, err - } - - u, err := svc.ViewUser(ctx, req.token, req.id) - if err != nil { - return nil, err - } - return viewUserRes{ - ID: u.ID, - Email: u.Email, - Metadata: u.Metadata, - }, nil - } -} - -func viewProfileEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(viewUserReq) - if err := req.validate(); err != nil { - return nil, err - } - - u, err := svc.ViewProfile(ctx, req.token) - if err != nil { - return nil, err - } - return viewUserRes{ - ID: u.ID, - Email: u.Email, - Metadata: u.Metadata, - }, nil - } -} - -func listUsersEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listUsersReq) - if err := req.validate(); err != nil { - return users.UserPage{}, err - } - pm := users.PageMetadata{ - Offset: req.offset, - Limit: req.limit, - Email: req.email, - Status: req.status, - Metadata: req.metadata, - } - up, err := svc.ListUsers(ctx, req.token, pm) - if err != nil { - return users.UserPage{}, err - } - return buildUsersResponse(up), nil - } -} - -func updateUserEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(updateUserReq) - if err := req.validate(); err != nil { - return nil, err - } - user := users.User{ - Metadata: req.Metadata, - } - err := svc.UpdateUser(ctx, req.token, user) - if err != nil { - return nil, err - } - return updateUserRes{}, nil - } -} - -func passwordChangeEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(passwChangeReq) - if err := req.validate(); err != nil { - return nil, err - } - res := passwChangeRes{} - if err := svc.ChangePassword(ctx, req.token, req.Password, req.OldPassword); err != nil { - return nil, err - } - return res, nil - } -} - -func loginEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(userReq) - if err := req.validate(); err != nil { - return nil, err - } - token, err := svc.Login(ctx, req.user) - if err != nil { - return nil, err - } - - return tokenRes{token}, nil - } -} - -func listMembersEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listMemberGroupReq) - if err := req.validate(); err != nil { - return userPageRes{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - - pm := users.PageMetadata{ - Offset: req.offset, - Limit: req.limit, - Status: req.status, - Metadata: req.metadata, - } - page, err := svc.ListMembers(ctx, req.token, req.id, pm) - if err != nil { - return userPageRes{}, err - } - - return buildUsersResponse(page), nil - } -} - -func enableUserEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(changeUserStatusReq) - if err := req.validate(); err != nil { - return nil, err - } - if err := svc.EnableUser(ctx, req.token, req.id); err != nil { - return nil, err - } - return deleteRes{}, nil - } -} - -func disableUserEndpoint(svc users.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(changeUserStatusReq) - if err := req.validate(); err != nil { - return nil, err - } - if err := svc.DisableUser(ctx, req.token, req.id); err != nil { - return nil, err - } - return deleteRes{}, nil - } -} - -func buildUsersResponse(up users.UserPage) userPageRes { - res := userPageRes{ - pageRes: pageRes{ - Total: up.Total, - Offset: up.Offset, - Limit: up.Limit, - }, - Users: []viewUserRes{}, - } - for _, user := range up.Users { - view := viewUserRes{ - ID: user.ID, - Email: user.Email, - Metadata: user.Metadata, - } - res.Users = append(res.Users, view) - } - return res -} diff --git a/users/api/endpoint_test.go b/users/api/endpoint_test.go deleted file mode 100644 index 8a18a4786ab..00000000000 --- a/users/api/endpoint_test.go +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package api_test - -import ( - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "regexp" - "strings" - "testing" - - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - "github.com/mainflux/mainflux/users/api" - "github.com/mainflux/mainflux/users/bcrypt" - "github.com/mainflux/mainflux/users/mocks" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - contentType = "application/json" - validEmail = "user@example.com" - invalidEmail = "userexample.com" - validPass = "password" - invalidPass = "wrong" - memberRelationKey = "member" - authoritiesObjKey = "authorities" -) - -var ( - user = users.User{Email: validEmail, Password: validPass} - notFoundRes = toJSON(apiutil.ErrorRes{Err: errors.ErrNotFound.Error()}) - unauthRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthentication.Error()}) - malformedRes = toJSON(apiutil.ErrorRes{Err: errors.ErrMalformedEntity.Error()}) - weakPassword = toJSON(apiutil.ErrorRes{Err: users.ErrPasswordFormat.Error()}) - unsupportedRes = toJSON(apiutil.ErrorRes{Err: errors.ErrUnsupportedContentType.Error()}) - missingTokRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerToken.Error()}) - missingEmailRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingEmail.Error()}) - missingPassRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingPass.Error()}) - invalidRestPassRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrInvalidResetPass.Error()}) - passRegex = regexp.MustCompile("^.{8,}$") -) - -type testRequest struct { - client *http.Client - method string - url string - contentType string - token string - body io.Reader -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - - req.Header.Set("Referer", "http://localhost") - return tr.client.Do(req) -} - -func newService() users.Service { - usersRepo := mocks.NewUserRepository() - hasher := bcrypt.New() - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - email := mocks.NewEmailer() - idProvider := uuid.New() - - return users.New(usersRepo, hasher, auth, email, idProvider, passRegex) -} - -func newServer(svc users.Service) *httptest.Server { - logger := logger.NewMock() - mux := api.MakeHandler(svc, mocktracer.New(), logger) - return httptest.NewServer(mux) -} - -func toJSON(data interface{}) string { - jsonData, _ := json.Marshal(data) - return string(jsonData) -} - -func TestRegister(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - data := toJSON(user) - userNew := toJSON(users.User{Email: "user2@example.com", Password: "password"}) - invalidData := toJSON(users.User{Email: invalidEmail, Password: validPass}) - invalidPasswordData := toJSON(users.User{Email: validEmail, Password: invalidPass}) - invalidFieldData := fmt.Sprintf(`{"email": "%s", "pass": "%s"}`, user.Email, user.Password) - emptyEmailData := `{"email": ""}` - emptyHostData := fmt.Sprintf(`{"email": "%s"}`, user.Email) - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - token := tkn.GetValue() - - cases := []struct { - desc string - req string - contentType string - status int - token string - }{ - {"register new user", data, contentType, http.StatusCreated, token}, - {"register user with empty token", data, contentType, http.StatusUnauthorized, ""}, - {"register existing user", data, contentType, http.StatusConflict, token}, - {"register user with invalid email address", invalidData, contentType, http.StatusBadRequest, token}, - {"register user with weak password", invalidPasswordData, contentType, http.StatusBadRequest, token}, - {"register new user with unauthenticated access", userNew, contentType, http.StatusUnauthorized, "wrong"}, - {"register existing user with unauthenticated access", data, contentType, http.StatusUnauthorized, "wrong"}, - {"register user with invalid request format", "{", contentType, http.StatusBadRequest, token}, - {"register user with empty email request", emptyEmailData, contentType, http.StatusBadRequest, token}, - {"register user with empty host request", emptyHostData, contentType, http.StatusBadRequest, token}, - {"register user with empty request", "", contentType, http.StatusBadRequest, token}, - {"register user with invalid field name", invalidFieldData, contentType, http.StatusBadRequest, token}, - {"register user with missing content type", data, "", http.StatusUnsupportedMediaType, token}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPost, - url: fmt.Sprintf("%s/users", ts.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - } -} - -func TestLogin(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - token := tkn.GetValue() - tokenData := toJSON(map[string]string{"token": token}) - data := toJSON(user) - invalidEmailData := toJSON(users.User{ - Email: invalidEmail, - Password: validPass, - }) - invalidData := toJSON(users.User{ - Email: validEmail, - Password: "invalid_password", - }) - nonexistentData := toJSON(users.User{ - Email: "non-existentuser@example.com", - Password: validPass, - }) - _, err := svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("register user got unexpected error: %s", err)) - - cases := []struct { - desc string - req string - contentType string - status int - res string - }{ - {"login with valid credentials", data, contentType, http.StatusCreated, tokenData}, - {"login with invalid credentials", invalidData, contentType, http.StatusUnauthorized, unauthRes}, - {"login with invalid email address", invalidEmailData, contentType, http.StatusBadRequest, malformedRes}, - {"login non-existent user", nonexistentData, contentType, http.StatusUnauthorized, unauthRes}, - {"login with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes}, - {"login with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes}, - {"login with empty request", "", contentType, http.StatusBadRequest, malformedRes}, - {"login with missing content type", data, "", http.StatusUnsupportedMediaType, unsupportedRes}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPost, - url: fmt.Sprintf("%s/tokens", ts.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - body, err := ioutil.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - token := strings.Trim(string(body), "\n") - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res, token, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token)) - } -} - -func TestUser(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - token := tkn.GetValue() - - userID, err := svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("register user got unexpected error: %s", err)) - - cases := []struct { - desc string - token string - status int - res string - }{ - {"user info with valid token", token, http.StatusOK, ""}, - {"user info with invalid token", "", http.StatusUnauthorized, ""}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodGet, - url: fmt.Sprintf("%s/users/%s", ts.URL, userID), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - body, err := ioutil.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - token := strings.Trim(string(body), "\n") - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res, "", fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token)) - } -} - -func TestPasswordResetRequest(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - data := toJSON(user) - - nonexistentData := toJSON(users.User{ - Email: "non-existentuser@example.com", - Password: validPass, - }) - - expectedExisting := toJSON(struct { - Msg string `json:"msg"` - }{ - api.MailSent, - }) - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - token := tkn.GetValue() - - _, err := svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("register user got unexpected error: %s", err)) - - cases := []struct { - desc string - req string - contentType string - status int - res string - }{ - {"password reset request with valid email", data, contentType, http.StatusCreated, expectedExisting}, - {"password reset request with invalid email", nonexistentData, contentType, http.StatusNotFound, notFoundRes}, - {"password reset request with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes}, - {"password reset request with empty email request", "{}", contentType, http.StatusBadRequest, missingEmailRes}, - {"password reset request with empty request", "", contentType, http.StatusBadRequest, malformedRes}, - {"password reset request with missing content type", data, "", http.StatusUnsupportedMediaType, unsupportedRes}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPost, - url: fmt.Sprintf("%s/password/reset-request", ts.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - body, err := ioutil.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - token := strings.Trim(string(body), "\n") - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res, token, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token)) - } -} - -func TestPasswordReset(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - reqData := struct { - Token string `json:"token,omitempty"` - Password string `json:"password,omitempty"` - ConfPass string `json:"confirm_password,omitempty"` - }{} - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, err := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - require.Nil(t, err, fmt.Sprintf("issue user token error: %s", err)) - - token := tkn.GetValue() - - _, err = svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("register user got unexpected error: %s", err)) - - reqData.Password = user.Password - reqData.ConfPass = user.Password - reqData.Token = token - reqExisting := toJSON(reqData) - - reqData.Token = "wrong" - - reqNoExist := toJSON(reqData) - - reqData.Token = token - - reqData.ConfPass = invalidPass - reqPassNoMatch := toJSON(reqData) - - reqData.Password = invalidPass - reqPassWeak := toJSON(reqData) - - cases := []struct { - desc string - req string - contentType string - status int - res string - tok string - }{ - {"password reset with valid token", reqExisting, contentType, http.StatusCreated, "{}", token}, - {"password reset with invalid token", reqNoExist, contentType, http.StatusUnauthorized, unauthRes, token}, - {"password reset with confirm password not matching", reqPassNoMatch, contentType, http.StatusBadRequest, invalidRestPassRes, token}, - {"password reset request with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes, token}, - {"password reset request with empty JSON request", "{}", contentType, http.StatusBadRequest, missingPassRes, token}, - {"password reset request with empty request", "", contentType, http.StatusBadRequest, malformedRes, token}, - {"password reset request with missing content type", reqExisting, "", http.StatusUnsupportedMediaType, unsupportedRes, token}, - {"password reset with weak password", reqPassWeak, contentType, http.StatusBadRequest, weakPassword, token}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPut, - url: fmt.Sprintf("%s/password/reset", ts.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.req), - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - body, err := ioutil.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - token := strings.Trim(string(body), "\n") - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res, token, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token)) - } -} - -func TestPasswordChange(t *testing.T) { - svc := newService() - ts := newServer(svc) - defer ts.Close() - client := ts.Client() - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) - - auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) - token := tkn.GetValue() - - reqData := struct { - Token string `json:"token,omitempty"` - Password string `json:"password,omitempty"` - OldPassw string `json:"old_password,omitempty"` - }{} - - _, err := svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("register user got unexpected error: %s", err)) - - reqData.Password = user.Password - reqData.OldPassw = user.Password - reqData.Token = token - dataResExisting := toJSON(reqData) - - reqNoExist := toJSON(reqData) - - reqData.OldPassw = invalidPass - reqWrongPass := toJSON(reqData) - - reqData.OldPassw = user.Password - reqData.Password = invalidPass - reqWeakPass := toJSON(reqData) - - cases := []struct { - desc string - req string - contentType string - status int - res string - tok string - }{ - {"password change with valid token", dataResExisting, contentType, http.StatusCreated, "{}", token}, - {"password change with empty token", reqNoExist, contentType, http.StatusUnauthorized, missingTokRes, ""}, - {"password change with invalid old password", reqWrongPass, contentType, http.StatusUnauthorized, unauthRes, token}, - {"password change with invalid new password", reqWeakPass, contentType, http.StatusBadRequest, weakPassword, token}, - {"password change with empty JSON request", "{}", contentType, http.StatusBadRequest, missingPassRes, token}, - {"password change empty request", "", contentType, http.StatusBadRequest, malformedRes, token}, - {"password change missing content type", dataResExisting, "", http.StatusUnsupportedMediaType, unsupportedRes, token}, - } - - for _, tc := range cases { - req := testRequest{ - client: client, - method: http.MethodPatch, - url: fmt.Sprintf("%s/password", ts.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.req), - token: tc.tok, - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - body, err := ioutil.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - token := strings.Trim(string(body), "\n") - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res, token, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token)) - } -} diff --git a/users/api/logging.go b/users/api/logging.go deleted file mode 100644 index 718f108f85a..00000000000 --- a/users/api/logging.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package api - -import ( - "context" - "fmt" - "time" - - log "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/users" -) - -var _ users.Service = (*loggingMiddleware)(nil) - -type loggingMiddleware struct { - logger log.Logger - svc users.Service -} - -// LoggingMiddleware adds logging facilities to the core service. -func LoggingMiddleware(svc users.Service, logger log.Logger) users.Service { - return &loggingMiddleware{logger, svc} -} - -func (lm *loggingMiddleware) Register(ctx context.Context, token string, user users.User) (uid string, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method register for user %s took %s to complete", user.Email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - - }(time.Now()) - - return lm.svc.Register(ctx, token, user) -} - -func (lm *loggingMiddleware) Login(ctx context.Context, user users.User) (token string, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method login for user %s took %s to complete", user.Email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.Login(ctx, user) -} - -func (lm *loggingMiddleware) ViewUser(ctx context.Context, token, id string) (u users.User, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method view_user for user %s took %s to complete", u.Email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ViewUser(ctx, token, id) -} - -func (lm *loggingMiddleware) ViewProfile(ctx context.Context, token string) (u users.User, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method view_profile for user %s took %s to complete", u.Email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ViewProfile(ctx, token) -} - -func (lm *loggingMiddleware) ListUsers(ctx context.Context, token string, pm users.PageMetadata) (e users.UserPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_users for token %s took %s to complete", token, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListUsers(ctx, token, pm) -} - -func (lm *loggingMiddleware) UpdateUser(ctx context.Context, token string, u users.User) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method update_user for user %s took %s to complete", u.Email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.UpdateUser(ctx, token, u) -} - -func (lm *loggingMiddleware) GenerateResetToken(ctx context.Context, email, host string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method generate_reset_token for user %s took %s to complete", email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.GenerateResetToken(ctx, email, host) -} - -func (lm *loggingMiddleware) ChangePassword(ctx context.Context, email, password, oldPassword string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method change_password for user %s took %s to complete", email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ChangePassword(ctx, email, password, oldPassword) -} - -func (lm *loggingMiddleware) ResetPassword(ctx context.Context, email, password string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method reset_password for user %s took %s to complete", email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ResetPassword(ctx, email, password) -} - -func (lm *loggingMiddleware) SendPasswordReset(ctx context.Context, host, email, token string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method send_password_reset for user %s took %s to complete", email, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.SendPasswordReset(ctx, host, email, token) -} - -func (lm *loggingMiddleware) ListMembers(ctx context.Context, token, groupID string, pm users.PageMetadata) (mp users.UserPage, err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method list_members for group %s took %s to complete", groupID, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.ListMembers(ctx, token, groupID, pm) -} - -func (lm *loggingMiddleware) EnableUser(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method enable_user for user %s took %s to complete", id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.EnableUser(ctx, token, id) -} - -func (lm *loggingMiddleware) DisableUser(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - message := fmt.Sprintf("Method disable_user for user %s took %s to complete", id, time.Since(begin)) - if err != nil { - lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) - return - } - lm.logger.Info(fmt.Sprintf("%s without errors.", message)) - }(time.Now()) - - return lm.svc.DisableUser(ctx, token, id) -} diff --git a/users/api/metrics.go b/users/api/metrics.go deleted file mode 100644 index 02d8558bef5..00000000000 --- a/users/api/metrics.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package api - -import ( - "context" - "time" - - "github.com/go-kit/kit/metrics" - "github.com/mainflux/mainflux/users" -) - -var _ users.Service = (*metricsMiddleware)(nil) - -type metricsMiddleware struct { - counter metrics.Counter - latency metrics.Histogram - svc users.Service -} - -// MetricsMiddleware instruments core service by tracking request count and latency. -func MetricsMiddleware(svc users.Service, counter metrics.Counter, latency metrics.Histogram) users.Service { - return &metricsMiddleware{ - counter: counter, - latency: latency, - svc: svc, - } -} - -func (ms *metricsMiddleware) Register(ctx context.Context, token string, user users.User) (string, error) { - defer func(begin time.Time) { - ms.counter.With("method", "register").Add(1) - ms.latency.With("method", "register").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Register(ctx, token, user) -} - -func (ms *metricsMiddleware) Login(ctx context.Context, user users.User) (string, error) { - defer func(begin time.Time) { - ms.counter.With("method", "login").Add(1) - ms.latency.With("method", "login").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.Login(ctx, user) -} - -func (ms *metricsMiddleware) ViewUser(ctx context.Context, token, id string) (users.User, error) { - defer func(begin time.Time) { - ms.counter.With("method", "view_user").Add(1) - ms.latency.With("method", "view_user").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ViewUser(ctx, token, id) -} - -func (ms *metricsMiddleware) ViewProfile(ctx context.Context, token string) (users.User, error) { - defer func(begin time.Time) { - ms.counter.With("method", "view_profile").Add(1) - ms.latency.With("method", "view_profile").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ViewProfile(ctx, token) -} - -func (ms *metricsMiddleware) ListUsers(ctx context.Context, token string, pm users.PageMetadata) (users.UserPage, error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_users").Add(1) - ms.latency.With("method", "list_users").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListUsers(ctx, token, pm) -} - -func (ms *metricsMiddleware) UpdateUser(ctx context.Context, token string, u users.User) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "update_user").Add(1) - ms.latency.With("method", "update_user").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.UpdateUser(ctx, token, u) -} - -func (ms *metricsMiddleware) GenerateResetToken(ctx context.Context, email, host string) error { - defer func(begin time.Time) { - ms.counter.With("method", "generate_reset_token").Add(1) - ms.latency.With("method", "generate_reset_token").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.GenerateResetToken(ctx, email, host) -} - -func (ms *metricsMiddleware) ChangePassword(ctx context.Context, email, password, oldPassword string) error { - defer func(begin time.Time) { - ms.counter.With("method", "change_password").Add(1) - ms.latency.With("method", "change_password").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ChangePassword(ctx, email, password, oldPassword) -} - -func (ms *metricsMiddleware) ResetPassword(ctx context.Context, email, password string) error { - defer func(begin time.Time) { - ms.counter.With("method", "reset_password").Add(1) - ms.latency.With("method", "reset_password").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ResetPassword(ctx, email, password) -} - -func (ms *metricsMiddleware) SendPasswordReset(ctx context.Context, host, email, token string) error { - defer func(begin time.Time) { - ms.counter.With("method", "send_password_reset").Add(1) - ms.latency.With("method", "send_password_reset").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.SendPasswordReset(ctx, host, email, token) -} - -func (ms *metricsMiddleware) ListMembers(ctx context.Context, token, groupID string, pm users.PageMetadata) (users.UserPage, error) { - defer func(begin time.Time) { - ms.counter.With("method", "list_members").Add(1) - ms.latency.With("method", "list_members").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.ListMembers(ctx, token, groupID, pm) -} - -func (ms *metricsMiddleware) EnableUser(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "enable_user").Add(1) - ms.latency.With("method", "enable_user").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.EnableUser(ctx, token, id) -} - -func (ms *metricsMiddleware) DisableUser(ctx context.Context, token string, id string) (err error) { - defer func(begin time.Time) { - ms.counter.With("method", "disable_user").Add(1) - ms.latency.With("method", "disable_user").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return ms.svc.DisableUser(ctx, token, id) -} diff --git a/users/api/requests.go b/users/api/requests.go deleted file mode 100644 index e3e2fcba22e..00000000000 --- a/users/api/requests.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/users" -) - -const ( - maxLimitSize = 100 - maxEmailSize = 1024 -) - -type userReq struct { - user users.User -} - -func (req userReq) validate() error { - return req.user.Validate() -} - -type createUserReq struct { - user users.User - token string -} - -func (req createUserReq) validate() error { - return req.user.Validate() -} - -type viewUserReq struct { - token string - id string -} - -func (req viewUserReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - return nil -} - -type listUsersReq struct { - token string - status string - offset uint64 - limit uint64 - email string - metadata users.Metadata -} - -func (req listUsersReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.limit > maxLimitSize || req.limit < 1 { - return apiutil.ErrLimitSize - } - - if len(req.email) > maxEmailSize { - return apiutil.ErrEmailSize - } - if req.status != users.AllStatusKey && - req.status != users.EnabledStatusKey && - req.status != users.DisabledStatusKey { - return apiutil.ErrInvalidStatus - } - - return nil -} - -type updateUserReq struct { - token string - Metadata map[string]interface{} `json:"metadata,omitempty"` -} - -func (req updateUserReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - return nil -} - -type passwResetReq struct { - Email string `json:"email"` - Host string `json:"host"` -} - -func (req passwResetReq) validate() error { - if req.Email == "" { - return apiutil.ErrMissingEmail - } - - if req.Host == "" { - return apiutil.ErrMissingHost - } - - return nil -} - -type resetTokenReq struct { - Token string `json:"token"` - Password string `json:"password"` - ConfPass string `json:"confirm_password"` -} - -func (req resetTokenReq) validate() error { - if req.Password == "" { - return apiutil.ErrMissingPass - } - - if req.ConfPass == "" { - return apiutil.ErrMissingConfPass - } - - if req.Token == "" { - return apiutil.ErrBearerToken - } - - if req.Password != req.ConfPass { - return apiutil.ErrInvalidResetPass - } - - return nil -} - -type passwChangeReq struct { - token string - Password string `json:"password"` - OldPassword string `json:"old_password"` -} - -func (req passwChangeReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - if req.OldPassword == "" { - return apiutil.ErrMissingPass - } - return nil -} - -type listMemberGroupReq struct { - token string - status string - offset uint64 - limit uint64 - metadata users.Metadata - id string -} - -func (req listMemberGroupReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - if req.status != users.AllStatusKey && - req.status != users.EnabledStatusKey && - req.status != users.DisabledStatusKey { - return apiutil.ErrInvalidStatus - } - return nil -} - -type changeUserStatusReq struct { - token string - id string -} - -func (req changeUserStatusReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - if req.id == "" { - return apiutil.ErrMissingID - } - return nil -} diff --git a/users/api/responses.go b/users/api/responses.go deleted file mode 100644 index 969e4d32b3c..00000000000 --- a/users/api/responses.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "fmt" - "net/http" - - "github.com/mainflux/mainflux" -) - -var ( - _ mainflux.Response = (*tokenRes)(nil) - _ mainflux.Response = (*viewUserRes)(nil) - _ mainflux.Response = (*passwChangeRes)(nil) - _ mainflux.Response = (*createUserRes)(nil) - _ mainflux.Response = (*deleteRes)(nil) -) - -// MailSent message response when link is sent -const MailSent = "Email with reset link is sent" - -type pageRes struct { - Total uint64 `json:"total"` - Offset uint64 `json:"offset"` - Limit uint64 `json:"limit"` -} - -type createUserRes struct { - ID string - created bool -} - -func (res createUserRes) Code() int { - if res.created { - return http.StatusCreated - } - - return http.StatusOK -} - -func (res createUserRes) Headers() map[string]string { - if res.created { - return map[string]string{ - "Location": fmt.Sprintf("/users/%s", res.ID), - } - } - - return map[string]string{} -} - -func (res createUserRes) Empty() bool { - return true -} - -type tokenRes struct { - Token string `json:"token,omitempty"` -} - -func (res tokenRes) Code() int { - return http.StatusCreated -} - -func (res tokenRes) Headers() map[string]string { - return map[string]string{} -} - -func (res tokenRes) Empty() bool { - return res.Token == "" -} - -type updateUserRes struct{} - -func (res updateUserRes) Code() int { - return http.StatusOK -} - -func (res updateUserRes) Headers() map[string]string { - return map[string]string{} -} - -func (res updateUserRes) Empty() bool { - return true -} - -type viewUserRes struct { - ID string `json:"id"` - Email string `json:"email"` - Metadata map[string]interface{} `json:"metadata,omitempty"` -} - -func (res viewUserRes) Code() int { - return http.StatusOK -} - -func (res viewUserRes) Headers() map[string]string { - return map[string]string{} -} - -func (res viewUserRes) Empty() bool { - return false -} - -type userPageRes struct { - pageRes - Users []viewUserRes `json:"users"` -} - -func (res userPageRes) Code() int { - return http.StatusOK -} - -func (res userPageRes) Headers() map[string]string { - return map[string]string{} -} - -func (res userPageRes) Empty() bool { - return false -} - -type passwResetReqRes struct { - Msg string `json:"msg"` -} - -func (res passwResetReqRes) Code() int { - return http.StatusCreated -} - -func (res passwResetReqRes) Headers() map[string]string { - return map[string]string{} -} - -func (res passwResetReqRes) Empty() bool { - return false -} - -type passwChangeRes struct { -} - -func (res passwChangeRes) Code() int { - return http.StatusCreated -} - -func (res passwChangeRes) Headers() map[string]string { - return map[string]string{} -} - -func (res passwChangeRes) Empty() bool { - return false -} - -type deleteRes struct{} - -func (res deleteRes) Code() int { - return http.StatusNoContent -} - -func (res deleteRes) Headers() map[string]string { - return map[string]string{} -} - -func (res deleteRes) Empty() bool { - return true -} diff --git a/users/api/transport.go b/users/api/transport.go deleted file mode 100644 index dcdb8d27d42..00000000000 --- a/users/api/transport.go +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - "encoding/json" - "net/http" - "strings" - - kitot "github.com/go-kit/kit/tracing/opentracing" - kithttp "github.com/go-kit/kit/transport/http" - "github.com/go-zoo/bone" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/logger" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - opentracing "github.com/opentracing/opentracing-go" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -const ( - contentType = "application/json" - offsetKey = "offset" - limitKey = "limit" - emailKey = "email" - metadataKey = "metadata" - statusKey = "status" - defOffset = 0 - defLimit = 10 -) - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc users.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)), - } - - mux := bone.New() - - mux.Post("/users", kithttp.NewServer( - kitot.TraceServer(tracer, "register")(registrationEndpoint(svc)), - decodeCreateUserReq, - encodeResponse, - opts..., - )) - - mux.Get("/users/profile", kithttp.NewServer( - kitot.TraceServer(tracer, "view_profile")(viewProfileEndpoint(svc)), - decodeViewProfile, - encodeResponse, - opts..., - )) - - mux.Get("/users/:id", kithttp.NewServer( - kitot.TraceServer(tracer, "view_user")(viewUserEndpoint(svc)), - decodeViewUser, - encodeResponse, - opts..., - )) - - mux.Get("/users", kithttp.NewServer( - kitot.TraceServer(tracer, "list_users")(listUsersEndpoint(svc)), - decodeListUsers, - encodeResponse, - opts..., - )) - - mux.Put("/users", kithttp.NewServer( - kitot.TraceServer(tracer, "update_user")(updateUserEndpoint(svc)), - decodeUpdateUser, - encodeResponse, - opts..., - )) - - mux.Post("/password/reset-request", kithttp.NewServer( - kitot.TraceServer(tracer, "res-req")(passwordResetRequestEndpoint(svc)), - decodePasswordResetRequest, - encodeResponse, - opts..., - )) - - mux.Put("/password/reset", kithttp.NewServer( - kitot.TraceServer(tracer, "reset")(passwordResetEndpoint(svc)), - decodePasswordReset, - encodeResponse, - opts..., - )) - - mux.Patch("/password", kithttp.NewServer( - kitot.TraceServer(tracer, "reset")(passwordChangeEndpoint(svc)), - decodePasswordChange, - encodeResponse, - opts..., - )) - - mux.Get("/groups/:id", kithttp.NewServer( - kitot.TraceServer(tracer, "list_members")(listMembersEndpoint(svc)), - decodeListMembersRequest, - encodeResponse, - opts..., - )) - - mux.Post("/tokens", kithttp.NewServer( - kitot.TraceServer(tracer, "login")(loginEndpoint(svc)), - decodeCredentials, - encodeResponse, - opts..., - )) - - mux.Post("/users/:id/enable", kithttp.NewServer( - kitot.TraceServer(tracer, "enable_user")(enableUserEndpoint(svc)), - decodeChangeUserStatus, - encodeResponse, - opts..., - )) - - mux.Post("/users/:id/disable", kithttp.NewServer( - kitot.TraceServer(tracer, "disable_user")(disableUserEndpoint(svc)), - decodeChangeUserStatus, - encodeResponse, - opts..., - )) - - mux.GetFunc("/health", mainflux.Health("users")) - mux.Handle("/metrics", promhttp.Handler()) - - return mux -} - -func decodeViewUser(_ context.Context, r *http.Request) (interface{}, error) { - req := viewUserReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "id"), - } - - return req, nil -} - -func decodeViewProfile(_ context.Context, r *http.Request) (interface{}, error) { - req := viewUserReq{token: apiutil.ExtractBearerToken(r)} - - return req, nil -} - -func decodeListUsers(_ context.Context, r *http.Request) (interface{}, error) { - o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset) - if err != nil { - return nil, err - } - - l, err := apiutil.ReadUintQuery(r, limitKey, defLimit) - if err != nil { - return nil, err - } - - e, err := apiutil.ReadStringQuery(r, emailKey, "") - if err != nil { - return nil, err - } - - m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil) - if err != nil { - return nil, err - } - - s, err := apiutil.ReadStringQuery(r, statusKey, users.EnabledStatusKey) - if err != nil { - return nil, err - } - req := listUsersReq{ - token: apiutil.ExtractBearerToken(r), - status: s, - offset: o, - limit: l, - email: e, - metadata: m, - } - return req, nil -} - -func decodeUpdateUser(_ context.Context, r *http.Request) (interface{}, error) { - req := updateUserReq{token: apiutil.ExtractBearerToken(r)} - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeCredentials(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - var user users.User - if err := json.NewDecoder(r.Body).Decode(&user); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - user.Email = strings.TrimSpace(user.Email) - return userReq{user}, nil -} - -func decodeCreateUserReq(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - var user users.User - if err := json.NewDecoder(r.Body).Decode(&user); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - user.Email = strings.TrimSpace(user.Email) - req := createUserReq{ - user: user, - token: apiutil.ExtractBearerToken(r), - } - - return req, nil -} - -func decodePasswordResetRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - var req passwResetReq - - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - req.Host = r.Header.Get("Referer") - return req, nil -} - -func decodePasswordReset(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - var req resetTokenReq - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodePasswordChange(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.ErrUnsupportedContentType - } - - req := passwChangeReq{token: apiutil.ExtractBearerToken(r)} - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return req, nil -} - -func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, error) { - o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset) - if err != nil { - return nil, err - } - - l, err := apiutil.ReadUintQuery(r, limitKey, defLimit) - if err != nil { - return nil, err - } - - m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil) - if err != nil { - return nil, err - } - s, err := apiutil.ReadStringQuery(r, statusKey, users.EnabledStatusKey) - if err != nil { - return nil, err - } - - req := listMemberGroupReq{ - token: apiutil.ExtractBearerToken(r), - status: s, - id: bone.GetValue(r, "id"), - offset: o, - limit: l, - metadata: m, - } - return req, nil -} - -func decodeChangeUserStatus(_ context.Context, r *http.Request) (interface{}, error) { - req := changeUserStatusReq{ - token: apiutil.ExtractBearerToken(r), - id: bone.GetValue(r, "id"), - } - - return req, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - if ar, ok := response.(mainflux.Response); ok { - for k, v := range ar.Headers() { - w.Header().Set(k, v) - } - w.Header().Set("Content-Type", contentType) - w.WriteHeader(ar.Code()) - - if ar.Empty() { - return nil - } - } - - return json.NewEncoder(w).Encode(response) -} - -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - switch { - case errors.Contains(err, errors.ErrInvalidQueryParams), - errors.Contains(err, errors.ErrMalformedEntity), - errors.Contains(err, users.ErrPasswordFormat), - err == apiutil.ErrMissingEmail, - err == apiutil.ErrMissingHost, - err == apiutil.ErrMissingPass, - err == apiutil.ErrMissingConfPass, - err == apiutil.ErrLimitSize, - err == apiutil.ErrOffsetSize, - err == apiutil.ErrInvalidResetPass: - w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrAuthentication), - err == apiutil.ErrBearerToken: - w.WriteHeader(http.StatusUnauthorized) - case errors.Contains(err, errors.ErrAuthorization): - w.WriteHeader(http.StatusForbidden) - case errors.Contains(err, errors.ErrConflict), - errors.Contains(err, errors.ErrConflict): - w.WriteHeader(http.StatusConflict) - case errors.Contains(err, errors.ErrUnsupportedContentType): - w.WriteHeader(http.StatusUnsupportedMediaType) - case errors.Contains(err, errors.ErrNotFound): - w.WriteHeader(http.StatusNotFound) - - case errors.Contains(err, uuid.ErrGeneratingID), - errors.Contains(err, users.ErrRecoveryToken): - w.WriteHeader(http.StatusInternalServerError) - - case errors.Contains(err, errors.ErrCreateEntity), - errors.Contains(err, errors.ErrUpdateEntity), - errors.Contains(err, errors.ErrViewEntity), - errors.Contains(err, errors.ErrRemoveEntity): - w.WriteHeader(http.StatusInternalServerError) - - default: - w.WriteHeader(http.StatusInternalServerError) - } - - if errorVal, ok := err.(errors.Error); ok { - w.Header().Set("Content-Type", contentType) - if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil { - w.WriteHeader(http.StatusInternalServerError) - } - } -} diff --git a/users/bcrypt/hasher.go b/users/bcrypt/hasher.go deleted file mode 100644 index 590a3831ae8..00000000000 --- a/users/bcrypt/hasher.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package bcrypt provides a hasher implementation utilizing bcrypt. -package bcrypt - -import ( - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" - "golang.org/x/crypto/bcrypt" -) - -const cost int = 10 - -var ( - errHashPassword = errors.New("Generate hash from password failed") - errComparePassword = errors.New("Compare hash and password failed") -) - -var _ users.Hasher = (*bcryptHasher)(nil) - -type bcryptHasher struct{} - -// New instantiates a bcrypt-based hasher implementation. -func New() users.Hasher { - return &bcryptHasher{} -} - -func (bh *bcryptHasher) Hash(pwd string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(pwd), cost) - if err != nil { - return "", errors.Wrap(errHashPassword, err) - } - - return string(hash), nil -} - -func (bh *bcryptHasher) Compare(plain, hashed string) error { - err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(plain)) - if err != nil { - return errors.Wrap(errComparePassword, err) - } - return nil -} diff --git a/clients/clients/api/endpoints.go b/users/clients/api/endpoints.go similarity index 76% rename from clients/clients/api/endpoints.go rename to users/clients/api/endpoints.go index c0ac11e3110..ab95f7834a5 100644 --- a/clients/clients/api/endpoints.go +++ b/users/clients/api/endpoints.go @@ -4,7 +4,7 @@ import ( "context" "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/clients/clients" + "github.com/mainflux/mainflux/users/clients" ) func registrationEndpoint(svc clients.Service) endpoint.Endpoint { @@ -41,6 +41,23 @@ func viewClientEndpoint(svc clients.Service) endpoint.Endpoint { } } +func viewProfileEndpoint(svc clients.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(viewClientReq) + if err := req.validate(); err != nil { + return nil, err + } + + c, err := svc.ViewProfile(ctx, req.token) + if err != nil { + return nil, err + } + return viewClientRes{ + Client: c, + }, nil + } +} + func listClientsEndpoint(svc clients.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(listClientsReq) @@ -146,6 +163,50 @@ func updateClientIdentityEndpoint(svc clients.Service) endpoint.Endpoint { } } +// Password reset request endpoint. +// When successful password reset link is generated. +// Link is generated using MF_TOKEN_RESET_ENDPOINT env. +// and value from Referer header for host. +// {Referer}+{MF_TOKEN_RESET_ENDPOINT}+{token=TOKEN} +// http://mainflux.com/reset-request?token=xxxxxxxxxxx. +// Email with a link is being sent to the user. +// When user clicks on a link it should get the ui with form to +// enter new password, when form is submitted token and new password +// must be sent as PUT request to 'password/reset' passwordResetEndpoint +func passwordResetRequestEndpoint(svc clients.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(passwResetReq) + if err := req.validate(); err != nil { + return nil, err + } + res := passwResetReqRes{} + email := req.Email + if err := svc.GenerateResetToken(ctx, email, req.Host); err != nil { + return nil, err + } + res.Msg = MailSent + + return res, nil + } +} + +// This is endpoint that actually sets new password in password reset flow. +// When user clicks on a link in email finally ends on this endpoint as explained in +// the comment above. +func passwordResetEndpoint(svc clients.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(resetTokenReq) + if err := req.validate(); err != nil { + return nil, err + } + res := passwChangeRes{} + if err := svc.ResetSecret(ctx, req.Token, req.Password); err != nil { + return nil, err + } + return res, nil + } +} + func updateClientSecretEndpoint(svc clients.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(updateClientCredentialsReq) diff --git a/clients/clients/api/logging.go b/users/clients/api/logging.go similarity index 73% rename from clients/clients/api/logging.go rename to users/clients/api/logging.go index 14d33669502..6b4388beab7 100644 --- a/clients/clients/api/logging.go +++ b/users/clients/api/logging.go @@ -5,9 +5,9 @@ import ( "fmt" "time" - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/jwt" log "github.com/mainflux/mainflux/logger" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/jwt" ) var _ clients.Service = (*loggingMiddleware)(nil) @@ -69,6 +69,18 @@ func (lm *loggingMiddleware) ViewClient(ctx context.Context, token, id string) ( return lm.svc.ViewClient(ctx, token, id) } +func (lm *loggingMiddleware) ViewProfile(ctx context.Context, token string) (c clients.Client, err error) { + defer func(begin time.Time) { + message := fmt.Sprintf("Method view_profile for token %s took %s to complete", token, time.Since(begin)) + if err != nil { + lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) + return + } + lm.logger.Info(fmt.Sprintf("%s without errors.", message)) + }(time.Now()) + return lm.svc.ViewProfile(ctx, token) +} + func (lm *loggingMiddleware) ListClients(ctx context.Context, token string, pm clients.Page) (cp clients.ClientsPage, err error) { defer func(begin time.Time) { message := fmt.Sprintf("Method list_clients for token %s took %s to complete", token, time.Since(begin)) @@ -128,6 +140,42 @@ func (lm *loggingMiddleware) UpdateClientSecret(ctx context.Context, token, oldS return lm.svc.UpdateClientSecret(ctx, token, oldSecret, newSecret) } +func (lm *loggingMiddleware) GenerateResetToken(ctx context.Context, email, host string) (err error) { + defer func(begin time.Time) { + message := fmt.Sprintf("Method generate_reset_token for email %s took %s to complete", email, time.Since(begin)) + if err != nil { + lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) + return + } + lm.logger.Info(fmt.Sprintf("%s without errors.", message)) + }(time.Now()) + return lm.svc.GenerateResetToken(ctx, email, host) +} + +func (lm *loggingMiddleware) ResetSecret(ctx context.Context, token, secret string) (err error) { + defer func(begin time.Time) { + message := fmt.Sprintf("Method reset_secret for token %s took %s to complete", token, time.Since(begin)) + if err != nil { + lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) + return + } + lm.logger.Info(fmt.Sprintf("%s without errors.", message)) + }(time.Now()) + return lm.svc.ResetSecret(ctx, token, secret) +} + +func (lm *loggingMiddleware) SendPasswordReset(ctx context.Context, host, email, token string) (err error) { + defer func(begin time.Time) { + message := fmt.Sprintf("Method send_password_reset for token %s took %s to complete", token, time.Since(begin)) + if err != nil { + lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) + return + } + lm.logger.Info(fmt.Sprintf("%s without errors.", message)) + }(time.Now()) + return lm.svc.SendPasswordReset(ctx, host, email, token) +} + func (lm *loggingMiddleware) UpdateClientOwner(ctx context.Context, token string, client clients.Client) (c clients.Client, err error) { defer func(begin time.Time) { message := fmt.Sprintf("Method update_client_owner for token %s took %s to complete", token, time.Since(begin)) @@ -175,3 +223,15 @@ func (lm *loggingMiddleware) ListMembers(ctx context.Context, token, groupID str }(time.Now()) return lm.svc.ListMembers(ctx, token, groupID, cp) } + +func (lm *loggingMiddleware) Identify(ctx context.Context, token string) (c clients.UserIdentity, err error) { + defer func(begin time.Time) { + message := fmt.Sprintf("Method identify for token %s took %s to complete", token, time.Since(begin)) + if err != nil { + lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err)) + return + } + lm.logger.Info(fmt.Sprintf("%s without errors.", message)) + }(time.Now()) + return lm.svc.Identify(ctx, token) +} diff --git a/clients/clients/api/metrics.go b/users/clients/api/metrics.go similarity index 74% rename from clients/clients/api/metrics.go rename to users/clients/api/metrics.go index c694a7f070e..5ee2bb1cc64 100644 --- a/clients/clients/api/metrics.go +++ b/users/clients/api/metrics.go @@ -5,8 +5,8 @@ import ( "time" "github.com/go-kit/kit/metrics" - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/jwt" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/jwt" ) var _ clients.Service = (*metricsMiddleware)(nil) @@ -58,6 +58,14 @@ func (ms *metricsMiddleware) ViewClient(ctx context.Context, token, id string) ( return ms.svc.ViewClient(ctx, token, id) } +func (ms *metricsMiddleware) ViewProfile(ctx context.Context, token string) (clients.Client, error) { + defer func(begin time.Time) { + ms.counter.With("method", "view_profile").Add(1) + ms.latency.With("method", "view_profile").Observe(time.Since(begin).Seconds()) + }(time.Now()) + return ms.svc.ViewProfile(ctx, token) +} + func (ms *metricsMiddleware) ListClients(ctx context.Context, token string, pm clients.Page) (clients.ClientsPage, error) { defer func(begin time.Time) { ms.counter.With("method", "list_clients").Add(1) @@ -98,6 +106,30 @@ func (ms *metricsMiddleware) UpdateClientSecret(ctx context.Context, token, oldS return ms.svc.UpdateClientSecret(ctx, token, oldSecret, newSecret) } +func (ms *metricsMiddleware) GenerateResetToken(ctx context.Context, email, host string) error { + defer func(begin time.Time) { + ms.counter.With("method", "generate_reset_token").Add(1) + ms.latency.With("method", "generate_reset_token").Observe(time.Since(begin).Seconds()) + }(time.Now()) + return ms.svc.GenerateResetToken(ctx, email, host) +} + +func (ms *metricsMiddleware) ResetSecret(ctx context.Context, token, secret string) error { + defer func(begin time.Time) { + ms.counter.With("method", "reset_secret").Add(1) + ms.latency.With("method", "reset_secret").Observe(time.Since(begin).Seconds()) + }(time.Now()) + return ms.svc.ResetSecret(ctx, token, secret) +} + +func (ms *metricsMiddleware) SendPasswordReset(ctx context.Context, host, email, token string) error { + defer func(begin time.Time) { + ms.counter.With("method", "send_password_reset").Add(1) + ms.latency.With("method", "send_password_reset").Observe(time.Since(begin).Seconds()) + }(time.Now()) + return ms.svc.SendPasswordReset(ctx, email, host, token) +} + func (ms *metricsMiddleware) UpdateClientOwner(ctx context.Context, token string, client clients.Client) (clients.Client, error) { defer func(begin time.Time) { ms.counter.With("method", "update_client_owner").Add(1) @@ -129,3 +161,11 @@ func (ms *metricsMiddleware) ListMembers(ctx context.Context, token, groupID str }(time.Now()) return ms.svc.ListMembers(ctx, token, groupID, pm) } + +func (ms *metricsMiddleware) Identify(ctx context.Context, token string) (clients.UserIdentity, error) { + defer func(begin time.Time) { + ms.counter.With("method", "identify").Add(1) + ms.latency.With("method", "identify").Observe(time.Since(begin).Seconds()) + }(time.Now()) + return ms.svc.Identify(ctx, token) +} diff --git a/clients/clients/api/requests.go b/users/clients/api/requests.go similarity index 78% rename from clients/clients/api/requests.go rename to users/clients/api/requests.go index 8d8927c4ab8..e1ff028bff5 100644 --- a/clients/clients/api/requests.go +++ b/users/clients/api/requests.go @@ -1,9 +1,9 @@ package api import ( - "github.com/mainflux/mainflux/clients/clients" "github.com/mainflux/mainflux/internal/api" "github.com/mainflux/mainflux/internal/apiutil" + "github.com/mainflux/mainflux/users/clients" ) const maxLimitSize = 100 @@ -17,7 +17,7 @@ func (req createClientReq) validate() error { if len(req.client.Name) > api.MaxNameSize { return apiutil.ErrNameSize } - return nil + return req.client.Validate() } type viewClientReq struct { @@ -26,6 +26,9 @@ type viewClientReq struct { } func (req viewClientReq) validate() error { + if req.token == "" { + return apiutil.ErrBearerToken + } return nil } @@ -43,6 +46,9 @@ type listClientsReq struct { } func (req listClientsReq) validate() error { + if req.token == "" { + return apiutil.ErrBearerToken + } if req.limit > maxLimitSize || req.limit < 1 { return apiutil.ErrLimitSize } @@ -181,3 +187,46 @@ func (req tokenReq) validate() error { } return nil } + +type passwResetReq struct { + Email string `json:"email"` + Host string `json:"host"` +} + +func (req passwResetReq) validate() error { + if req.Email == "" { + return apiutil.ErrMissingEmail + } + + if req.Host == "" { + return apiutil.ErrMissingHost + } + + return nil +} + +type resetTokenReq struct { + Token string `json:"token"` + Password string `json:"password"` + ConfPass string `json:"confirm_password"` +} + +func (req resetTokenReq) validate() error { + if req.Password == "" { + return apiutil.ErrMissingPass + } + + if req.ConfPass == "" { + return apiutil.ErrMissingConfPass + } + + if req.Token == "" { + return apiutil.ErrBearerToken + } + + if req.Password != req.ConfPass { + return apiutil.ErrInvalidResetPass + } + + return nil +} diff --git a/clients/clients/api/responses.go b/users/clients/api/responses.go similarity index 79% rename from clients/clients/api/responses.go rename to users/clients/api/responses.go index 1343fec3479..3542d69254d 100644 --- a/clients/clients/api/responses.go +++ b/users/clients/api/responses.go @@ -5,9 +5,12 @@ import ( "net/http" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/clients" + "github.com/mainflux/mainflux/users/clients" ) +// MailSent message response when link is sent +const MailSent = "Email with reset link is sent" + var ( _ mainflux.Response = (*tokenRes)(nil) _ mainflux.Response = (*viewClientRes)(nil) @@ -22,8 +25,6 @@ type pageRes struct { Limit uint64 `json:"limit,omitempty"` Offset uint64 `json:"offset,omitempty"` Total uint64 `json:"total"` - Level uint64 `json:"level"` - Name string `json:"name"` } type createClientRes struct { @@ -42,7 +43,7 @@ func (res createClientRes) Code() int { func (res createClientRes) Headers() map[string]string { if res.created { return map[string]string{ - "Location": fmt.Sprintf("/clients/%s", res.ID), + "Location": fmt.Sprintf("/users/%s", res.ID), } } @@ -105,7 +106,7 @@ func (res viewClientRes) Empty() bool { type clientsPageRes struct { pageRes - Clients []viewClientRes `json:"clients"` + Clients []viewClientRes `json:"users"` } func (res clientsPageRes) Code() int { @@ -168,3 +169,34 @@ func (res deleteClientRes) Headers() map[string]string { func (res deleteClientRes) Empty() bool { return false } + +type passwResetReqRes struct { + Msg string `json:"msg"` +} + +func (res passwResetReqRes) Code() int { + return http.StatusCreated +} + +func (res passwResetReqRes) Headers() map[string]string { + return map[string]string{} +} + +func (res passwResetReqRes) Empty() bool { + return false +} + +type passwChangeRes struct { +} + +func (res passwChangeRes) Code() int { + return http.StatusCreated +} + +func (res passwChangeRes) Headers() map[string]string { + return map[string]string{} +} + +func (res passwChangeRes) Empty() bool { + return false +} diff --git a/clients/clients/api/transport.go b/users/clients/api/transport.go similarity index 76% rename from clients/clients/api/transport.go rename to users/clients/api/transport.go index ecd5270f08c..90a7b5d751a 100644 --- a/clients/clients/api/transport.go +++ b/users/clients/api/transport.go @@ -9,114 +9,137 @@ import ( kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/clients" "github.com/mainflux/mainflux/internal/api" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" "github.com/prometheus/client_golang/prometheus/promhttp" "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" ) // MakeClientsHandler returns a HTTP handler for API endpoints. -func MakeClientsHandler(svc clients.Service, mux *bone.Mux, logger logger.Logger) { +func MakeClientsHandler(svc clients.Service, mux *bone.Mux, logger logger.Logger) http.Handler { opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), } - mux.Post("/clients", kithttp.NewServer( + mux.Post("/users", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("register_client"))(registrationEndpoint(svc)), decodeCreateClientReq, api.EncodeResponse, opts..., )) - mux.Get("/clients/:id", kithttp.NewServer( + mux.Get("/users/profile", kithttp.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("view_profile"))(viewProfileEndpoint(svc)), + decodeViewProfile, + api.EncodeResponse, + opts..., + )) + + mux.Get("/users/:id", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("view_client"))(viewClientEndpoint(svc)), decodeViewClient, api.EncodeResponse, opts..., )) - mux.Get("/clients", kithttp.NewServer( + mux.Get("/users", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("list_clients"))(listClientsEndpoint(svc)), decodeListClients, api.EncodeResponse, opts..., )) - mux.Get("/clients/groups/:groupID/members", kithttp.NewServer( + mux.Get("/groups/:id/members", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("list_members"))(listMembersEndpoint(svc)), decodeListMembersRequest, api.EncodeResponse, opts..., )) - mux.Patch("/clients/:id", kithttp.NewServer( + mux.Patch("/users/:id", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("update_client_name_and_metadata"))(updateClientEndpoint(svc)), decodeUpdateClient, api.EncodeResponse, opts..., )) - mux.Patch("/clients/:id/tags", kithttp.NewServer( + mux.Patch("/users/:id/tags", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("update_client_tags"))(updateClientTagsEndpoint(svc)), decodeUpdateClientTags, api.EncodeResponse, opts..., )) - mux.Patch("/clients/:id/identity", kithttp.NewServer( + mux.Patch("/users/:id/identity", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("update_client_identity"))(updateClientIdentityEndpoint(svc)), decodeUpdateClientCredentials, api.EncodeResponse, opts..., )) - mux.Patch("/clients/:id/secret", kithttp.NewServer( + mux.Post("/password/reset-request", kithttp.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("password_reset_req"))(passwordResetRequestEndpoint(svc)), + decodePasswordResetRequest, + api.EncodeResponse, + opts..., + )) + + mux.Put("/password/reset", kithttp.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("password_reset"))(passwordResetEndpoint(svc)), + decodePasswordReset, + api.EncodeResponse, + opts..., + )) + + mux.Patch("/users/:id/secret", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("update_client_secret"))(updateClientSecretEndpoint(svc)), decodeUpdateClientCredentials, api.EncodeResponse, opts..., )) - mux.Patch("/clients/:id/owner", kithttp.NewServer( + mux.Patch("/users/:id/owner", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("update_client_owner"))(updateClientOwnerEndpoint(svc)), decodeUpdateClientOwner, api.EncodeResponse, opts..., )) - mux.Post("/clients/tokens/issue", kithttp.NewServer( + mux.Post("/users/tokens/issue", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("issue_token"))(issueTokenEndpoint(svc)), decodeCredentials, api.EncodeResponse, opts..., )) - mux.Post("/clients/tokens/refresh", kithttp.NewServer( + mux.Post("/users/tokens/refresh", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("refresh_token"))(refreshTokenEndpoint(svc)), decodeRefreshToken, api.EncodeResponse, opts..., )) - mux.Post("/clients/:id/enable", kithttp.NewServer( + mux.Post("/users/:id/enable", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("enable_client"))(enableClientEndpoint(svc)), decodeChangeClientStatus, api.EncodeResponse, opts..., )) - mux.Post("/clients/:id/disable", kithttp.NewServer( + mux.Post("/users/:id/disable", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("disable_client"))(disableClientEndpoint(svc)), decodeChangeClientStatus, api.EncodeResponse, opts..., )) - mux.GetFunc("/health", mainflux.Health("clients")) + mux.GetFunc("/health", mainflux.Health("users")) mux.Handle("/metrics", promhttp.Handler()) + + return mux } func decodeViewClient(_ context.Context, r *http.Request) (interface{}, error) { @@ -128,6 +151,12 @@ func decodeViewClient(_ context.Context, r *http.Request) (interface{}, error) { return req, nil } +func decodeViewProfile(_ context.Context, r *http.Request) (interface{}, error) { + req := viewClientReq{token: apiutil.ExtractBearerToken(r)} + + return req, nil +} + func decodeListClients(_ context.Context, r *http.Request) (interface{}, error) { var sid string s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus) @@ -226,6 +255,34 @@ func decodeUpdateClientCredentials(_ context.Context, r *http.Request) (interfac return req, nil } +func decodePasswordResetRequest(_ context.Context, r *http.Request) (interface{}, error) { + if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) { + return nil, errors.ErrUnsupportedContentType + } + + var req passwResetReq + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return nil, errors.Wrap(errors.ErrMalformedEntity, err) + } + + req.Host = r.Header.Get("Referer") + return req, nil +} + +func decodePasswordReset(_ context.Context, r *http.Request) (interface{}, error) { + if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) { + return nil, errors.ErrUnsupportedContentType + } + + var req resetTokenReq + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return nil, errors.Wrap(errors.ErrMalformedEntity, err) + } + + return req, nil +} + func decodeUpdateClientOwner(_ context.Context, r *http.Request) (interface{}, error) { req := updateClientOwnerReq{ token: apiutil.ExtractBearerToken(r), @@ -310,7 +367,7 @@ func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, Limit: l, Metadata: m, }, - groupID: bone.GetValue(r, "groupID"), + groupID: bone.GetValue(r, "id"), } return req, nil } diff --git a/clients/clients/clients.go b/users/clients/clients.go similarity index 65% rename from clients/clients/clients.go rename to users/clients/clients.go index d9de1c50c28..dffdf1d606e 100644 --- a/clients/clients/clients.go +++ b/users/clients/clients.go @@ -3,8 +3,28 @@ package clients import ( "context" "encoding/json" + "fmt" + "regexp" "strings" "time" + + "github.com/mainflux/mainflux/pkg/errors" + "golang.org/x/net/idna" +) + +const ( + maxLocalLen = 64 + maxDomainLen = 255 + maxTLDLen = 24 // longest TLD currently in existence + + atSeparator = "@" + dotSeparator = "." +) + +var ( + userRegexp = regexp.MustCompile("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$") + hostRegexp = regexp.MustCompile(`^[^\s]+\.[^\s]+$`) + userDotRegexp = regexp.MustCompile("(^[.]{1})|([.]{1}$)|([.]{2,})") ) // Credentials represent client credentials: its @@ -25,7 +45,13 @@ type Client struct { Metadata Metadata `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` - Status Status `json:"status"` // 1 for enabled, 0 for disabled + Status Status `json:"status"` // 1 for enabled, 0 for disabled + Role Role `json:"role,omitempty"` // 1 for admin, 0 for normal user +} + +type UserIdentity struct { + ID string + Email string } // ClientsPage contains page related metadata as well as list @@ -93,6 +119,9 @@ type ClientService interface { // ViewClient retrieves client info for a given client ID and an authorized token. ViewClient(ctx context.Context, token, id string) (Client, error) + // ViewProfile retrieves client info for a given token. + ViewProfile(ctx context.Context, token string) (Client, error) + // ListClients retrieves clients list for a valid auth token. ListClients(ctx context.Context, token string, pm Page) (ClientsPage, error) @@ -108,9 +137,20 @@ type ClientService interface { // UpdateClientIdentity updates the client's identity UpdateClientIdentity(ctx context.Context, token, id, identity string) (Client, error) + // GenerateResetToken email where mail will be sent. + // host is used for generating reset link. + GenerateResetToken(ctx context.Context, email, host string) error + // UpdateClientSecret updates the client's secret UpdateClientSecret(ctx context.Context, token, oldSecret, newSecret string) (Client, error) + // ResetSecret change users secret in reset flow. + // token can be authentication token or secret reset token. + ResetSecret(ctx context.Context, resetToken, secret string) error + + // SendPasswordReset sends reset password link to email. + SendPasswordReset(ctx context.Context, host, email, token string) error + // UpdateClientOwner updates the client's owner. UpdateClientOwner(ctx context.Context, token string, client Client) (Client, error) @@ -119,6 +159,9 @@ type ClientService interface { // DisableClient logically disables the client identified with the provided ID DisableClient(ctx context.Context, token, id string) (Client, error) + + // Identify returns the client email and id from the given token + Identify(ctx context.Context, tkn string) (UserIdentity, error) } // Custom Marshaller for Client @@ -133,3 +176,72 @@ func (s *Status) UnmarshalJSON(data []byte) error { *s = val return err } + +// Validate returns an error if client representation is invalid. +func (u Client) Validate() error { + if !isEmail(u.Credentials.Identity) { + return errors.ErrMalformedEntity + } + return nil +} + +func isEmail(email string) bool { + if email == "" { + return false + } + + es := strings.Split(email, atSeparator) + if len(es) != 2 { + return false + } + local, host := es[0], es[1] + + if local == "" || len(local) > maxLocalLen { + return false + } + + hs := strings.Split(host, dotSeparator) + if len(hs) < 2 { + return false + } + domain, ext := hs[0], hs[1] + + // Check subdomain and validate + if len(hs) > 2 { + if domain == "" { + return false + } + + for i := 1; i < len(hs)-1; i++ { + sub := hs[i] + if sub == "" { + return false + } + domain = fmt.Sprintf("%s.%s", domain, sub) + } + + ext = hs[len(hs)-1] + } + + if domain == "" || len(domain) > maxDomainLen { + return false + } + if ext == "" || len(ext) > maxTLDLen { + return false + } + + punyLocal, err := idna.ToASCII(local) + if err != nil { + return false + } + punyHost, err := idna.ToASCII(host) + if err != nil { + return false + } + + if userDotRegexp.MatchString(punyLocal) || !userRegexp.MatchString(punyLocal) || !hostRegexp.MatchString(punyHost) { + return false + } + + return true +} diff --git a/users/emailer.go b/users/clients/emailer.go similarity index 92% rename from users/emailer.go rename to users/clients/emailer.go index 5476afaf916..8ce7b62fdf4 100644 --- a/users/emailer.go +++ b/users/clients/emailer.go @@ -1,7 +1,7 @@ // Copyright (c) Mainflux // SPDX-License-Identifier: Apache-2.0 -package users +package clients // Emailer wrapper around the email type Emailer interface { diff --git a/users/emailer/emailer.go b/users/clients/emailer/emailer.go similarity index 77% rename from users/emailer/emailer.go rename to users/clients/emailer/emailer.go index 9a4cf3526df..3a72cf6e177 100644 --- a/users/emailer/emailer.go +++ b/users/clients/emailer/emailer.go @@ -6,10 +6,10 @@ import ( "fmt" "github.com/mainflux/mainflux/internal/email" - "github.com/mainflux/mainflux/users" + "github.com/mainflux/mainflux/users/clients" ) -var _ users.Emailer = (*emailer)(nil) +var _ clients.Emailer = (*emailer)(nil) type emailer struct { resetURL string @@ -17,7 +17,7 @@ type emailer struct { } // New creates new emailer utility -func New(url string, c *email.Config) (users.Emailer, error) { +func New(url string, c *email.Config) (clients.Emailer, error) { e, err := email.New(c) return &emailer{resetURL: url, agent: e}, err } diff --git a/clients/clients/hasher.go b/users/clients/hasher.go similarity index 100% rename from clients/clients/hasher.go rename to users/clients/hasher.go diff --git a/users/clients/mocks/authn.go b/users/clients/mocks/authn.go new file mode 100644 index 00000000000..516f5e650a7 --- /dev/null +++ b/users/clients/mocks/authn.go @@ -0,0 +1,79 @@ +// Copyright (c) Mainflux +// SPDX-License-Identifier: Apache-2.0 + +package mocks + +import ( + "context" + + "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" + "google.golang.org/grpc" +) + +var _ policies.AuthServiceClient = (*authServiceMock)(nil) + +type SubjectSet struct { + Subject string + Relation []string +} + +type authServiceMock struct { + users map[string]string + authz map[string][]SubjectSet +} + +func (svc authServiceMock) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { + res := policies.ListPoliciesRes{} + for key := range svc.authz { + res.Objects = append(res.Objects, key) + } + return &res, nil +} + +// NewAuthService creates mock of users service. +func NewAuthService(users map[string]string, authzDB map[string][]SubjectSet) policies.AuthServiceClient { + return &authServiceMock{users, authzDB} +} + +func (svc authServiceMock) Identify(ctx context.Context, in *policies.Token, opts ...grpc.CallOption) (*policies.UserIdentity, error) { + if id, ok := svc.users[in.Value]; ok { + return &policies.UserIdentity{Id: id, Email: id}, nil + } + return nil, errors.ErrAuthentication +} + +func (svc authServiceMock) Issue(ctx context.Context, in *policies.IssueReq, opts ...grpc.CallOption) (*policies.Token, error) { + if id, ok := svc.users[in.GetEmail()]; ok { + switch in.Type { + default: + return &policies.Token{Value: id}, nil + } + } + return nil, errors.ErrAuthentication +} + +func (svc authServiceMock) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { + for _, policy := range svc.authz[req.GetSub()] { + for _, r := range policy.Relation { + if r == req.GetAct() && policy.Subject == req.GetSub() { + return &policies.AuthorizeRes{Authorized: true}, nil + } + } + } + return &policies.AuthorizeRes{Authorized: false}, nil +} + +func (svc authServiceMock) AddPolicy(ctx context.Context, in *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { + if len(in.GetAct()) == 0 || in.GetObj() == "" || in.GetSub() == "" { + return &policies.AddPolicyRes{}, errors.ErrMalformedEntity + } + + svc.authz[in.GetSub()] = append(svc.authz[in.GetSub()], SubjectSet{Subject: in.GetSub(), Relation: in.GetAct()}) + return &policies.AddPolicyRes{Authorized: true}, nil +} + +func (svc authServiceMock) DeletePolicy(ctx context.Context, in *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { + // Not implemented + return &policies.DeletePolicyRes{Deleted: true}, nil +} diff --git a/clients/clients/mocks/clients.go b/users/clients/mocks/clients.go similarity index 98% rename from clients/clients/mocks/clients.go rename to users/clients/mocks/clients.go index 9333272327c..c0593db6616 100644 --- a/clients/clients/mocks/clients.go +++ b/users/clients/mocks/clients.go @@ -3,8 +3,8 @@ package mocks import ( "context" - "github.com/mainflux/mainflux/clients/clients" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" "github.com/stretchr/testify/mock" ) diff --git a/users/mocks/email.go b/users/clients/mocks/email.go similarity index 77% rename from users/mocks/email.go rename to users/clients/mocks/email.go index bc8657fb5ca..74629bc609b 100644 --- a/users/mocks/email.go +++ b/users/clients/mocks/email.go @@ -4,14 +4,14 @@ package mocks import ( - "github.com/mainflux/mainflux/users" + "github.com/mainflux/mainflux/users/clients" ) type emailerMock struct { } // NewEmailer provides emailer instance for the test -func NewEmailer() users.Emailer { +func NewEmailer() clients.Emailer { return &emailerMock{} } diff --git a/users/mocks/hasher.go b/users/clients/mocks/hasher.go similarity index 82% rename from users/mocks/hasher.go rename to users/clients/mocks/hasher.go index 9edfa5e9bb6..105733df81f 100644 --- a/users/mocks/hasher.go +++ b/users/clients/mocks/hasher.go @@ -5,16 +5,16 @@ package mocks import ( "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" + "github.com/mainflux/mainflux/users/clients" ) -var _ users.Hasher = (*hasherMock)(nil) +var _ clients.Hasher = (*hasherMock)(nil) type hasherMock struct{} // NewHasher creates "no-op" hasher for test purposes. This implementation will // return secrets without changing them. -func NewHasher() users.Hasher { +func NewHasher() clients.Hasher { return &hasherMock{} } diff --git a/clients/clients/page.go b/users/clients/page.go similarity index 100% rename from clients/clients/page.go rename to users/clients/page.go diff --git a/clients/clients/postgres/clients.go b/users/clients/postgres/clients.go similarity index 97% rename from clients/clients/postgres/clients.go rename to users/clients/postgres/clients.go index b9032790425..199c94f3212 100644 --- a/clients/clients/postgres/clients.go +++ b/users/clients/postgres/clients.go @@ -9,10 +9,10 @@ import ( "time" "github.com/jackc/pgtype" // required for SQL access - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/groups" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/groups" + "github.com/mainflux/mainflux/users/postgres" ) var _ clients.ClientRepository = (*clientRepo)(nil) @@ -30,12 +30,12 @@ func NewClientRepo(db postgres.Database) clients.ClientRepository { } func (repo clientRepo) Save(ctx context.Context, c clients.Client) (clients.Client, error) { - q := `INSERT INTO clients (id, name, tags, owner, identity, secret, metadata, created_at, updated_at, status) - VALUES (:id, :name, :tags, :owner, :identity, :secret, :metadata, :created_at, :updated_at, :status) + q := `INSERT INTO clients (id, name, tags, owner, identity, secret, metadata, created_at, updated_at, status, role) + VALUES (:id, :name, :tags, :owner, :identity, :secret, :metadata, :created_at, :updated_at, :status, :role) RETURNING id, name, tags, identity, metadata, COALESCE(owner, '') AS owner, status, created_at, updated_at` if c.Owner == "" { - q = `INSERT INTO clients (id, name, tags, identity, secret, metadata, created_at, updated_at, status) - VALUES (:id, :name, :tags, :identity, :secret, :metadata, :created_at, :updated_at, :status) + q = `INSERT INTO clients (id, name, tags, identity, secret, metadata, created_at, updated_at, status, role) + VALUES (:id, :name, :tags, :identity, :secret, :metadata, :created_at, :updated_at, :status, :role) RETURNING id, name, tags, identity, metadata, COALESCE(owner, '') AS owner, status, created_at, updated_at` } dbc, err := toDBClient(c) @@ -386,6 +386,7 @@ type dbClient struct { UpdatedAt time.Time `db:"updated_at"` Groups []groups.Group `db:"groups"` Status clients.Status `db:"status"` + Role clients.Role `db:"role"` } func toDBClient(c clients.Client) (dbClient, error) { @@ -413,6 +414,7 @@ func toDBClient(c clients.Client) (dbClient, error) { CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, Status: c.Status, + Role: c.Role, }, nil } diff --git a/clients/clients/postgres/clients_test.go b/users/clients/postgres/clients_test.go similarity index 98% rename from clients/clients/postgres/clients_test.go rename to users/clients/postgres/clients_test.go index 24f2a9024f3..7b042deffbe 100644 --- a/clients/clients/postgres/clients_test.go +++ b/users/clients/postgres/clients_test.go @@ -6,16 +6,16 @@ import ( "strings" "testing" - "github.com/mainflux/mainflux/clients/clients" - cpostgres "github.com/mainflux/mainflux/clients/clients/postgres" - "github.com/mainflux/mainflux/clients/groups" - gpostgres "github.com/mainflux/mainflux/clients/groups/postgres" - "github.com/mainflux/mainflux/clients/policies" - ppostgres "github.com/mainflux/mainflux/clients/policies/postgres" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + cpostgres "github.com/mainflux/mainflux/users/clients/postgres" + "github.com/mainflux/mainflux/users/groups" + gpostgres "github.com/mainflux/mainflux/users/groups/postgres" + "github.com/mainflux/mainflux/users/policies" + ppostgres "github.com/mainflux/mainflux/users/policies/postgres" + "github.com/mainflux/mainflux/users/postgres" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/clients/clients/postgres/doc.go b/users/clients/postgres/doc.go similarity index 100% rename from clients/clients/postgres/doc.go rename to users/clients/postgres/doc.go diff --git a/clients/policies/postgres/setup_test.go b/users/clients/postgres/setup_test.go similarity index 89% rename from clients/policies/postgres/setup_test.go rename to users/clients/postgres/setup_test.go index 9cb273dbc56..e3a4f089711 100644 --- a/clients/policies/postgres/setup_test.go +++ b/users/clients/postgres/setup_test.go @@ -11,7 +11,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux/clients/postgres" + pgClient "github.com/mainflux/mainflux/internal/clients/postgres" + "github.com/mainflux/mainflux/users/postgres" dockertest "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "go.opentelemetry.io/otel" @@ -61,7 +62,7 @@ func TestMain(m *testing.M) { log.Fatalf("Could not connect to docker: %s", err) } - dbConfig := postgres.Config{ + dbConfig := pgClient.Config{ Host: "localhost", Port: port, User: "test", @@ -73,9 +74,10 @@ func TestMain(m *testing.M) { SSLRootCert: "", } - if db, err = postgres.Connect(dbConfig); err != nil { + if db, err = pgClient.SetupDB(dbConfig, *postgres.Migration()); err != nil { log.Fatalf("Could not setup test DB connection: %s", err) } + database = postgres.NewDatabase(db, tracer) code := m.Run() diff --git a/users/clients/roles.go b/users/clients/roles.go new file mode 100644 index 00000000000..f50e8137454 --- /dev/null +++ b/users/clients/roles.go @@ -0,0 +1,28 @@ +package clients + +// Role represents Client role. +type Role uint8 + +// Possible Client role values +const ( + UserRole Role = iota + AdminRole +) + +// String representation of the possible role values. +const ( + Admin = "admin" + User = "user" +) + +// String converts client role to string literal. +func (cs Role) String() string { + switch cs { + case AdminRole: + return Admin + case UserRole: + return User + default: + return Unknown + } +} diff --git a/clients/clients/service.go b/users/clients/service.go similarity index 69% rename from clients/clients/service.go rename to users/clients/service.go index b7643bbb32f..e02ddbab310 100644 --- a/clients/clients/service.go +++ b/users/clients/service.go @@ -2,13 +2,14 @@ package clients import ( "context" + "regexp" "time" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/jwt" - "github.com/mainflux/mainflux/clients/policies" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/jwt" + "github.com/mainflux/mainflux/users/policies" ) const MyKey = "mine" @@ -25,6 +26,19 @@ var ( // ErrStatusAlreadyAssigned indicated that the client or group has already been assigned the status. ErrStatusAlreadyAssigned = errors.New("status already assigned") + + // ErrMissingResetToken indicates malformed or missing reset token + // for reseting password. + ErrMissingResetToken = errors.New("missing reset token") + + // ErrRecoveryToken indicates error in generating password recovery token. + ErrRecoveryToken = errors.New("failed to generate password recovery token") + + // ErrGetToken indicates error in getting signed token. + ErrGetToken = errors.New("failed to fetch signed token") + + // ErrPasswordFormat indicates weak password. + ErrPasswordFormat = errors.New("password does not meet the requirements") ) // Service unites Clients and Group services. @@ -39,16 +53,20 @@ type service struct { idProvider mainflux.IDProvider hasher Hasher tokens jwt.TokenRepository + email Emailer + passRegex *regexp.Regexp } // NewService returns a new Clients service implementation. -func NewService(c ClientRepository, p policies.PolicyRepository, t jwt.TokenRepository, h Hasher, idp mainflux.IDProvider) Service { +func NewService(c ClientRepository, p policies.PolicyRepository, t jwt.TokenRepository, e Emailer, h Hasher, idp mainflux.IDProvider, pr *regexp.Regexp) Service { return service{ clients: c, policies: p, hasher: h, tokens: t, + email: e, idProvider: idp, + passRegex: pr, } } @@ -59,9 +77,9 @@ func (svc service) RegisterClient(ctx context.Context, token string, cli Client) } // We don't check the error currently since we can register client with empty token - ownerID, _ := svc.identify(ctx, token) - if ownerID != "" && cli.Owner == "" { - cli.Owner = ownerID + owner, _ := svc.Identify(ctx, token) + if owner.ID != "" && cli.Owner == "" { + cli.Owner = owner.ID } if cli.Credentials.Secret == "" { return Client{}, apiutil.ErrMissingSecret @@ -74,7 +92,9 @@ func (svc service) RegisterClient(ctx context.Context, token string, cli Client) if cli.Status != DisabledStatus && cli.Status != EnabledStatus { return Client{}, apiutil.ErrInvalidStatus } - + if cli.Role != UserRole && cli.Role != AdminRole { + return Client{}, apiutil.ErrInvalidRole + } cli.ID = clientID cli.CreatedAt = time.Now() cli.UpdatedAt = cli.CreatedAt @@ -114,31 +134,39 @@ func (svc service) RefreshToken(ctx context.Context, accessToken string) (jwt.To } func (svc service) ViewClient(ctx context.Context, token string, id string) (Client, error) { - subject, err := svc.identify(ctx, token) + ir, err := svc.Identify(ctx, token) if err != nil { return Client{}, err } - if subject == id { + if ir.ID == id { return svc.clients.RetrieveByID(ctx, id) } - if err := svc.policies.Evaluate(ctx, "client", policies.Policy{Subject: subject, Object: id, Actions: []string{"c_list"}}); err != nil { + if err := svc.policies.Evaluate(ctx, "client", policies.Policy{Subject: ir.ID, Object: id, Actions: []string{"c_list"}}); err != nil { return Client{}, err } return svc.clients.RetrieveByID(ctx, id) } +func (svc service) ViewProfile(ctx context.Context, token string) (Client, error) { + ir, err := svc.Identify(ctx, token) + if err != nil { + return Client{}, err + } + return svc.clients.RetrieveByID(ctx, ir.ID) +} + func (svc service) ListClients(ctx context.Context, token string, pm Page) (ClientsPage, error) { - id, err := svc.identify(ctx, token) + ir, err := svc.Identify(ctx, token) if err != nil { return ClientsPage{}, err } if pm.SharedBy == MyKey { - pm.SharedBy = id + pm.SharedBy = ir.ID } if pm.OwnerID == MyKey { - pm.OwnerID = id + pm.OwnerID = ir.ID } pm.Action = "c_list" clients, err := svc.clients.RetrieveAll(ctx, pm) @@ -146,7 +174,7 @@ func (svc service) ListClients(ctx context.Context, token string, pm Page) (Clie return ClientsPage{}, err } for i, client := range clients.Clients { - if client.ID == id { + if client.ID == ir.ID { clients.Clients = append(clients.Clients[:i], clients.Clients[i+1:]...) if clients.Total != 0 { clients.Total = clients.Total - 1 @@ -200,26 +228,62 @@ func (svc service) UpdateClientIdentity(ctx context.Context, token, id, identity return svc.clients.UpdateIdentity(ctx, cli) } -func (svc service) UpdateClientSecret(ctx context.Context, token, oldSecret, newSecret string) (Client, error) { - id, err := svc.identify(ctx, token) +func (svc service) GenerateResetToken(ctx context.Context, email, host string) error { + client, err := svc.clients.RetrieveByIdentity(ctx, email) + if err != nil || client.Credentials.Identity == "" { + return errors.ErrNotFound + } + t, err := svc.IssueToken(ctx, client.Credentials.Identity, client.Credentials.Secret) if err != nil { - return Client{}, err + return errors.Wrap(ErrRecoveryToken, err) } - dbClient, err := svc.clients.RetrieveByID(ctx, id) + return svc.SendPasswordReset(ctx, host, email, t.AccessToken) +} + +func (svc service) ResetSecret(ctx context.Context, resetToken, secret string) error { + ir, err := svc.Identify(ctx, resetToken) if err != nil { - return Client{}, err + return errors.Wrap(errors.ErrAuthentication, err) + } + c, err := svc.clients.RetrieveByID(ctx, ir.ID) + if err != nil { + return err } - if err := svc.hasher.Compare(oldSecret, dbClient.Credentials.Secret); err != nil { - return Client{}, errors.Wrap(errors.ErrAuthentication, err) + if c.Credentials.Identity == "" { + return errors.ErrNotFound } - - c := Client{ + if !svc.passRegex.MatchString(secret) { + return ErrPasswordFormat + } + secret, err = svc.hasher.Hash(secret) + if err != nil { + return err + } + c = Client{ Credentials: Credentials{ - Identity: dbClient.Credentials.Identity, - Secret: oldSecret, + Identity: c.Credentials.Identity, + Secret: secret, }, } - if _, err := svc.IssueToken(ctx, c.Credentials.Identity, c.Credentials.Secret); err != nil { + if _, err := svc.clients.UpdateSecret(ctx, c); err != nil { + return err + } + return nil +} + +func (svc service) UpdateClientSecret(ctx context.Context, token, oldSecret, newSecret string) (Client, error) { + ir, err := svc.Identify(ctx, token) + if err != nil { + return Client{}, err + } + if !svc.passRegex.MatchString(newSecret) { + return Client{}, ErrPasswordFormat + } + dbClient, err := svc.clients.RetrieveByID(ctx, ir.ID) + if err != nil { + return Client{}, err + } + if _, err := svc.IssueToken(ctx, dbClient.Credentials.Identity, oldSecret); err != nil { return Client{}, errors.ErrAuthentication } newSecret, err = svc.hasher.Hash(newSecret) @@ -230,6 +294,11 @@ func (svc service) UpdateClientSecret(ctx context.Context, token, oldSecret, new return svc.clients.UpdateSecret(ctx, dbClient) } +func (svc service) SendPasswordReset(_ context.Context, host, email, token string) error { + to := []string{email} + return svc.email.SendPasswordReset(to, host, token) +} + func (svc service) UpdateClientOwner(ctx context.Context, token string, cli Client) (Client, error) { if err := svc.authorize(ctx, "client", policies.Policy{Subject: token, Object: cli.ID, Actions: []string{"c_update"}}); err != nil { return Client{}, err @@ -269,11 +338,11 @@ func (svc service) DisableClient(ctx context.Context, token, id string) (Client, } func (svc service) ListMembers(ctx context.Context, token, groupID string, pm Page) (MembersPage, error) { - id, err := svc.identify(ctx, token) + ir, err := svc.Identify(ctx, token) if err != nil { return MembersPage{}, err } - pm.Subject = id + pm.Subject = ir.ID pm.Action = "g_list" return svc.clients.Members(ctx, groupID, pm) @@ -295,22 +364,22 @@ func (svc service) authorize(ctx context.Context, entityType string, p policies. if err := p.Validate(); err != nil { return err } - id, err := svc.identify(ctx, p.Subject) + ir, err := svc.Identify(ctx, p.Subject) if err != nil { return err } - p.Subject = id + p.Subject = ir.ID return svc.policies.Evaluate(ctx, entityType, p) } -func (svc service) identify(ctx context.Context, tkn string) (string, error) { +func (svc service) Identify(ctx context.Context, tkn string) (UserIdentity, error) { claims, err := svc.tokens.Parse(ctx, tkn) if err != nil { - return "", errors.Wrap(errors.ErrAuthentication, err) + return UserIdentity{}, errors.Wrap(errors.ErrAuthentication, err) } if claims.Type != jwt.AccessToken { - return "", errors.ErrAuthentication + return UserIdentity{}, errors.ErrAuthentication } - return claims.ClientID, nil + return UserIdentity{ID: claims.ClientID, Email: claims.Email}, nil } diff --git a/clients/clients/service_test.go b/users/clients/service_test.go similarity index 95% rename from clients/clients/service_test.go rename to users/clients/service_test.go index 0c42f043569..fb83abcdea1 100644 --- a/clients/clients/service_test.go +++ b/users/clients/service_test.go @@ -3,19 +3,20 @@ package clients_test import ( context "context" fmt "fmt" + "regexp" "testing" "time" - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/clients/mocks" - cmocks "github.com/mainflux/mainflux/clients/clients/mocks" - "github.com/mainflux/mainflux/clients/hasher" - "github.com/mainflux/mainflux/clients/jwt" - pmocks "github.com/mainflux/mainflux/clients/policies/mocks" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/clients/mocks" + cmocks "github.com/mainflux/mainflux/users/clients/mocks" + "github.com/mainflux/mainflux/users/hasher" + "github.com/mainflux/mainflux/users/jwt" + pmocks "github.com/mainflux/mainflux/users/policies/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -36,6 +37,7 @@ var ( } inValidToken = "invalidToken" withinDuration = 5 * time.Second + passRegex = regexp.MustCompile("^.{8,}$") ) func generateValidToken(t *testing.T, clientID string, svc clients.Service, cRepo *mocks.ClientRepository) string { @@ -62,7 +64,8 @@ func TestRegisterClient(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) cases := []struct { desc string @@ -269,7 +272,8 @@ func TestViewClient(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) cases := []struct { desc string @@ -323,7 +327,8 @@ func TestListClients(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) var nClients = uint64(200) var aClients = []clients.Client{} @@ -604,7 +609,8 @@ func TestUpdateClient(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) client1 := client client2 := client @@ -673,7 +679,8 @@ func TestUpdateClientTags(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) client.Tags = []string{"updated"} @@ -725,7 +732,8 @@ func TestUpdateClientIdentity(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) client2 := client client2.Credentials.Identity = "updated@example.com" @@ -781,7 +789,8 @@ func TestUpdateClientOwner(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) client.Owner = "newowner@mail.com" @@ -833,7 +842,8 @@ func TestUpdateClientSecret(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) rClient := client rClient.Credentials.Secret, _ = phasher.Hash(client.Credentials.Secret) @@ -894,7 +904,8 @@ func TestEnableClient(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) enabledClient1 := clients.Client{ID: testsutil.GenerateUUID(t, idProvider), Credentials: clients.Credentials{Identity: "client1@example.com", Secret: "password"}, Status: clients.EnabledStatus} disabledClient1 := clients.Client{ID: testsutil.GenerateUUID(t, idProvider), Credentials: clients.Credentials{Identity: "client3@example.com", Secret: "password"}, Status: clients.DisabledStatus} @@ -1014,7 +1025,8 @@ func TestDisableClient(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) enabledClient1 := clients.Client{ID: testsutil.GenerateUUID(t, idProvider), Credentials: clients.Credentials{Identity: "client1@example.com", Secret: "password"}, Status: clients.EnabledStatus} disabledClient1 := clients.Client{ID: testsutil.GenerateUUID(t, idProvider), Credentials: clients.Credentials{Identity: "client3@example.com", Secret: "password"}, Status: clients.DisabledStatus} @@ -1133,7 +1145,8 @@ func TestListMembers(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) var nClients = uint64(10) var aClients = []clients.Client{} @@ -1247,7 +1260,8 @@ func TestIssueToken(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) rClient := client rClient2 := client @@ -1298,7 +1312,8 @@ func TestRefreshToken(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - svc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + svc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) rClient := client rClient.Credentials.Secret, _ = phasher.Hash(client.Credentials.Secret) diff --git a/clients/clients/status.go b/users/clients/status.go similarity index 100% rename from clients/clients/status.go rename to users/clients/status.go diff --git a/clients/clients/tracing/tracing.go b/users/clients/tracing/tracing.go similarity index 76% rename from clients/clients/tracing/tracing.go rename to users/clients/tracing/tracing.go index 3afbcc7fb42..dd3f399b7bb 100644 --- a/clients/clients/tracing/tracing.go +++ b/users/clients/tracing/tracing.go @@ -3,8 +3,8 @@ package tracing import ( "context" - "github.com/mainflux/mainflux/clients/clients" - "github.com/mainflux/mainflux/clients/jwt" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/jwt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -81,6 +81,38 @@ func (tm *tracingMiddleware) UpdateClientSecret(ctx context.Context, token, oldS } +func (tm *tracingMiddleware) GenerateResetToken(ctx context.Context, email, host string) error { + ctx, span := tm.tracer.Start(ctx, "svc_generate_reset_token") + defer span.End() + + return tm.svc.GenerateResetToken(ctx, email, host) + +} + +func (tm *tracingMiddleware) ResetSecret(ctx context.Context, token, secret string) error { + ctx, span := tm.tracer.Start(ctx, "svc_reset_secret") + defer span.End() + + return tm.svc.ResetSecret(ctx, token, secret) + +} + +func (tm *tracingMiddleware) SendPasswordReset(ctx context.Context, host, email, token string) error { + ctx, span := tm.tracer.Start(ctx, "svc_send_password_reset") + defer span.End() + + return tm.svc.SendPasswordReset(ctx, host, email, token) + +} + +func (tm *tracingMiddleware) ViewProfile(ctx context.Context, token string) (clients.Client, error) { + ctx, span := tm.tracer.Start(ctx, "svc_view_profile") + defer span.End() + + return tm.svc.ViewProfile(ctx, token) + +} + func (tm *tracingMiddleware) UpdateClientOwner(ctx context.Context, token string, cli clients.Client) (clients.Client, error) { ctx, span := tm.tracer.Start(ctx, "svc_update_client_owner", trace.WithAttributes(attribute.StringSlice("Tags", cli.Tags))) defer span.End() @@ -109,3 +141,10 @@ func (tm *tracingMiddleware) ListMembers(ctx context.Context, token, groupID str return tm.svc.ListMembers(ctx, token, groupID, pm) } + +func (tm *tracingMiddleware) Identify(ctx context.Context, token string) (clients.UserIdentity, error) { + ctx, span := tm.tracer.Start(ctx, "svc_identify", trace.WithAttributes(attribute.String("token", token))) + defer span.End() + + return tm.svc.Identify(ctx, token) +} diff --git a/clients/groups/api/endpoints.go b/users/groups/api/endpoints.go similarity index 99% rename from clients/groups/api/endpoints.go rename to users/groups/api/endpoints.go index 3998e0819c8..01c3c4d80c7 100644 --- a/clients/groups/api/endpoints.go +++ b/users/groups/api/endpoints.go @@ -4,7 +4,7 @@ import ( "context" "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/clients/groups" + "github.com/mainflux/mainflux/users/groups" ) func createGroupEndpoint(svc groups.Service) endpoint.Endpoint { diff --git a/clients/groups/api/logging.go b/users/groups/api/logging.go similarity index 98% rename from clients/groups/api/logging.go rename to users/groups/api/logging.go index 91e659d80e3..ef8d667fe8d 100644 --- a/clients/groups/api/logging.go +++ b/users/groups/api/logging.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/mainflux/mainflux/clients/groups" log "github.com/mainflux/mainflux/logger" + "github.com/mainflux/mainflux/users/groups" ) var _ groups.Service = (*loggingMiddleware)(nil) diff --git a/clients/groups/api/metrics.go b/users/groups/api/metrics.go similarity index 98% rename from clients/groups/api/metrics.go rename to users/groups/api/metrics.go index 06fbccdd400..074e5dc6fa1 100644 --- a/clients/groups/api/metrics.go +++ b/users/groups/api/metrics.go @@ -5,7 +5,7 @@ import ( "time" "github.com/go-kit/kit/metrics" - "github.com/mainflux/mainflux/clients/groups" + "github.com/mainflux/mainflux/users/groups" ) var _ groups.Service = (*metricsMiddleware)(nil) diff --git a/clients/groups/api/requests.go b/users/groups/api/requests.go similarity index 97% rename from clients/groups/api/requests.go rename to users/groups/api/requests.go index 4cd4fa698c7..8f5c2ee68b3 100644 --- a/clients/groups/api/requests.go +++ b/users/groups/api/requests.go @@ -1,9 +1,9 @@ package api import ( - "github.com/mainflux/mainflux/clients/groups" "github.com/mainflux/mainflux/internal/api" "github.com/mainflux/mainflux/internal/apiutil" + "github.com/mainflux/mainflux/users/groups" ) type createGroupReq struct { diff --git a/clients/groups/api/responses.go b/users/groups/api/responses.go similarity index 98% rename from clients/groups/api/responses.go rename to users/groups/api/responses.go index 860b340a611..d76b17c54f5 100644 --- a/clients/groups/api/responses.go +++ b/users/groups/api/responses.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/groups" + "github.com/mainflux/mainflux/users/groups" ) var ( diff --git a/clients/groups/api/transport.go b/users/groups/api/transport.go similarity index 65% rename from clients/groups/api/transport.go rename to users/groups/api/transport.go index 9269a7f809b..4f29dcea017 100644 --- a/clients/groups/api/transport.go +++ b/users/groups/api/transport.go @@ -8,16 +8,16 @@ import ( kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" - "github.com/mainflux/mainflux/clients/groups" "github.com/mainflux/mainflux/internal/api" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/groups" "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" ) // MakeGroupsHandler returns a HTTP handler for API endpoints. -func MakeGroupsHandler(svc groups.Service, mux *bone.Mux, logger logger.Logger) { +func MakeGroupsHandler(svc groups.Service, mux *bone.Mux, logger logger.Logger) http.Handler { opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), } @@ -42,7 +42,7 @@ func MakeGroupsHandler(svc groups.Service, mux *bone.Mux, logger logger.Logger) opts..., )) - mux.Get("/:clientID/memberships", kithttp.NewServer( + mux.Get("/users/:id/memberships", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("list_memberships"))(listMembershipsEndpoint(svc)), decodeListMembershipRequest, api.EncodeResponse, @@ -55,6 +55,21 @@ func MakeGroupsHandler(svc groups.Service, mux *bone.Mux, logger logger.Logger) api.EncodeResponse, opts..., )) + + mux.Get("/groups/:id/children", kithttp.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("list_children"))(listGroupsEndpoint(svc)), + decodeListChildrenRequest, + api.EncodeResponse, + opts..., + )) + + mux.Get("/groups/:id/parents", kithttp.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("list_parents"))(listGroupsEndpoint(svc)), + decodeListParentsRequest, + api.EncodeResponse, + opts..., + )) + mux.Post("/groups/:id/enable", kithttp.NewServer( otelkit.EndpointMiddleware(otelkit.WithOperation("enable_group"))(enableGroupEndpoint(svc)), decodeChangeGroupStatus, @@ -68,6 +83,8 @@ func MakeGroupsHandler(svc groups.Service, mux *bone.Mux, logger logger.Logger) api.EncodeResponse, opts..., )) + + return mux } func decodeListMembershipRequest(_ context.Context, r *http.Request) (interface{}, error) { @@ -113,7 +130,7 @@ func decodeListMembershipRequest(_ context.Context, r *http.Request) (interface{ } req := listMembershipReq{ token: apiutil.ExtractBearerToken(r), - clientID: bone.GetValue(r, "clientID"), + clientID: bone.GetValue(r, "id"), GroupsPage: groups.GroupsPage{ Level: level, ID: parentID, @@ -197,6 +214,120 @@ func decodeListGroupsRequest(_ context.Context, r *http.Request) (interface{}, e return req, nil } +func decodeListParentsRequest(_ context.Context, r *http.Request) (interface{}, error) { + s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefGroupStatus) + if err != nil { + return nil, err + } + level, err := apiutil.ReadNumQuery[uint64](r, api.LevelKey, api.DefLevel) + if err != nil { + return nil, err + } + offset, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset) + if err != nil { + return nil, err + } + limit, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit) + if err != nil { + return nil, err + } + ownerID, err := apiutil.ReadStringQuery(r, api.OwnerKey, "") + if err != nil { + return nil, err + } + name, err := apiutil.ReadStringQuery(r, api.NameKey, "") + if err != nil { + return nil, err + } + meta, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil) + if err != nil { + return nil, err + } + tree, err := apiutil.ReadBoolQuery(r, api.TreeKey, false) + if err != nil { + return nil, err + } + st, err := groups.ToStatus(s) + if err != nil { + return nil, err + } + req := listGroupsReq{ + token: apiutil.ExtractBearerToken(r), + tree: tree, + GroupsPage: groups.GroupsPage{ + Level: level, + ID: bone.GetValue(r, "id"), + Page: groups.Page{ + Offset: offset, + Limit: limit, + OwnerID: ownerID, + Name: name, + Metadata: meta, + Status: st, + }, + Direction: 1, + }, + } + return req, nil +} + +func decodeListChildrenRequest(_ context.Context, r *http.Request) (interface{}, error) { + s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefGroupStatus) + if err != nil { + return nil, err + } + level, err := apiutil.ReadNumQuery[uint64](r, api.LevelKey, api.DefLevel) + if err != nil { + return nil, err + } + offset, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset) + if err != nil { + return nil, err + } + limit, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit) + if err != nil { + return nil, err + } + ownerID, err := apiutil.ReadStringQuery(r, api.OwnerKey, "") + if err != nil { + return nil, err + } + name, err := apiutil.ReadStringQuery(r, api.NameKey, "") + if err != nil { + return nil, err + } + meta, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil) + if err != nil { + return nil, err + } + tree, err := apiutil.ReadBoolQuery(r, api.TreeKey, false) + if err != nil { + return nil, err + } + st, err := groups.ToStatus(s) + if err != nil { + return nil, err + } + req := listGroupsReq{ + token: apiutil.ExtractBearerToken(r), + tree: tree, + GroupsPage: groups.GroupsPage{ + Level: level, + ID: bone.GetValue(r, "id"), + Page: groups.Page{ + Offset: offset, + Limit: limit, + OwnerID: ownerID, + Name: name, + Metadata: meta, + Status: st, + }, + Direction: -1, + }, + } + return req, nil +} + func decodeGroupCreate(_ context.Context, r *http.Request) (interface{}, error) { if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) { return nil, errors.ErrUnsupportedContentType diff --git a/clients/groups/groups.go b/users/groups/groups.go similarity index 98% rename from clients/groups/groups.go rename to users/groups/groups.go index d33a6c01320..dc0e9a9710a 100644 --- a/clients/groups/groups.go +++ b/users/groups/groups.go @@ -28,7 +28,7 @@ type GroupsPage struct { Path string Level uint64 ID string - Direction int64 // ancestors (-1) or descendants (+1) + Direction int64 // ancestors (+1) or descendants (-1) Groups []Group } diff --git a/clients/groups/mocks/groups.go b/users/groups/mocks/groups.go similarity index 97% rename from clients/groups/mocks/groups.go rename to users/groups/mocks/groups.go index 41e327cf654..77b5faf45f9 100644 --- a/clients/groups/mocks/groups.go +++ b/users/groups/mocks/groups.go @@ -3,8 +3,8 @@ package mocks import ( "context" - "github.com/mainflux/mainflux/clients/groups" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/groups" "github.com/stretchr/testify/mock" ) diff --git a/clients/groups/page.go b/users/groups/page.go similarity index 100% rename from clients/groups/page.go rename to users/groups/page.go diff --git a/clients/groups/postgres/doc.go b/users/groups/postgres/doc.go similarity index 100% rename from clients/groups/postgres/doc.go rename to users/groups/postgres/doc.go diff --git a/clients/groups/postgres/groups.go b/users/groups/postgres/groups.go similarity index 99% rename from clients/groups/postgres/groups.go rename to users/groups/postgres/groups.go index 24d4203da49..cb6226089f6 100644 --- a/clients/groups/postgres/groups.go +++ b/users/groups/postgres/groups.go @@ -9,9 +9,9 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux/clients/groups" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/groups" + "github.com/mainflux/mainflux/users/postgres" ) var _ groups.GroupRepository = (*groupRepository)(nil) diff --git a/clients/groups/postgres/groups_test.go b/users/groups/postgres/groups_test.go similarity index 97% rename from clients/groups/postgres/groups_test.go rename to users/groups/postgres/groups_test.go index 6186fbdfc55..3e9c45f9738 100644 --- a/clients/groups/postgres/groups_test.go +++ b/users/groups/postgres/groups_test.go @@ -7,16 +7,16 @@ import ( "testing" "time" - "github.com/mainflux/mainflux/clients/clients" - cpostgres "github.com/mainflux/mainflux/clients/clients/postgres" - "github.com/mainflux/mainflux/clients/groups" - gpostgres "github.com/mainflux/mainflux/clients/groups/postgres" - "github.com/mainflux/mainflux/clients/policies" - ppostgres "github.com/mainflux/mainflux/clients/policies/postgres" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + cpostgres "github.com/mainflux/mainflux/users/clients/postgres" + "github.com/mainflux/mainflux/users/groups" + gpostgres "github.com/mainflux/mainflux/users/groups/postgres" + "github.com/mainflux/mainflux/users/policies" + ppostgres "github.com/mainflux/mainflux/users/policies/postgres" + "github.com/mainflux/mainflux/users/postgres" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/clients/clients/postgres/setup_test.go b/users/groups/postgres/setup_test.go similarity index 89% rename from clients/clients/postgres/setup_test.go rename to users/groups/postgres/setup_test.go index 9cb273dbc56..e3a4f089711 100644 --- a/clients/clients/postgres/setup_test.go +++ b/users/groups/postgres/setup_test.go @@ -11,7 +11,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux/clients/postgres" + pgClient "github.com/mainflux/mainflux/internal/clients/postgres" + "github.com/mainflux/mainflux/users/postgres" dockertest "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "go.opentelemetry.io/otel" @@ -61,7 +62,7 @@ func TestMain(m *testing.M) { log.Fatalf("Could not connect to docker: %s", err) } - dbConfig := postgres.Config{ + dbConfig := pgClient.Config{ Host: "localhost", Port: port, User: "test", @@ -73,9 +74,10 @@ func TestMain(m *testing.M) { SSLRootCert: "", } - if db, err = postgres.Connect(dbConfig); err != nil { + if db, err = pgClient.SetupDB(dbConfig, *postgres.Migration()); err != nil { log.Fatalf("Could not setup test DB connection: %s", err) } + database = postgres.NewDatabase(db, tracer) code := m.Run() diff --git a/clients/groups/service.go b/users/groups/service.go similarity index 97% rename from clients/groups/service.go rename to users/groups/service.go index 518a41fb8dd..726bc0c3915 100644 --- a/clients/groups/service.go +++ b/users/groups/service.go @@ -5,10 +5,10 @@ import ( "time" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/jwt" - "github.com/mainflux/mainflux/clients/policies" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/jwt" + "github.com/mainflux/mainflux/users/policies" ) // Possible token types are access and refresh tokens. diff --git a/clients/groups/service_test.go b/users/groups/service_test.go similarity index 94% rename from clients/groups/service_test.go rename to users/groups/service_test.go index 73dbb96a97c..62cca7fb6c1 100644 --- a/clients/groups/service_test.go +++ b/users/groups/service_test.go @@ -3,20 +3,21 @@ package groups_test import ( context "context" fmt "fmt" + "regexp" "testing" "time" - "github.com/mainflux/mainflux/clients/clients" - cmocks "github.com/mainflux/mainflux/clients/clients/mocks" - "github.com/mainflux/mainflux/clients/groups" - "github.com/mainflux/mainflux/clients/groups/mocks" - gmocks "github.com/mainflux/mainflux/clients/groups/mocks" - "github.com/mainflux/mainflux/clients/hasher" - "github.com/mainflux/mainflux/clients/jwt" - pmocks "github.com/mainflux/mainflux/clients/policies/mocks" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + cmocks "github.com/mainflux/mainflux/users/clients/mocks" + "github.com/mainflux/mainflux/users/groups" + "github.com/mainflux/mainflux/users/groups/mocks" + gmocks "github.com/mainflux/mainflux/users/groups/mocks" + "github.com/mainflux/mainflux/users/hasher" + "github.com/mainflux/mainflux/users/jwt" + pmocks "github.com/mainflux/mainflux/users/policies/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -37,6 +38,7 @@ var ( Status: groups.EnabledStatus, } withinDuration = 5 * time.Second + passRegex = regexp.MustCompile("^.{8,}$") ) func generateValidToken(t *testing.T, clientID string, svc clients.Service, cRepo *cmocks.ClientRepository) string { @@ -64,8 +66,8 @@ func TestCreateGroup(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) cases := []struct { @@ -140,8 +142,8 @@ func TestUpdateGroup(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) group.ID = testsutil.GenerateUUID(t, idProvider) @@ -279,8 +281,8 @@ func TestViewGroup(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) group.ID = testsutil.GenerateUUID(t, idProvider) @@ -332,8 +334,8 @@ func TestListGroups(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) nGroups := uint64(200) @@ -422,8 +424,8 @@ func TestEnableGroup(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) enabledGroup1 := groups.Group{ID: testsutil.GenerateUUID(t, idProvider), Name: "group1", Status: groups.EnabledStatus} @@ -547,8 +549,8 @@ func TestDisableGroup(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) enabledGroup1 := groups.Group{ID: testsutil.GenerateUUID(t, idProvider), Name: "group1", Status: groups.EnabledStatus} @@ -672,7 +674,8 @@ func TestListMemberships(t *testing.T) { gRepo := new(gmocks.GroupRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := cmocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := groups.NewService(gRepo, pRepo, tokenizer, idProvider) var nGroups = uint64(100) diff --git a/clients/groups/status.go b/users/groups/status.go similarity index 100% rename from clients/groups/status.go rename to users/groups/status.go diff --git a/clients/groups/tracing/tracing.go b/users/groups/tracing/tracing.go similarity index 98% rename from clients/groups/tracing/tracing.go rename to users/groups/tracing/tracing.go index b653b8a1e5f..28522a10118 100644 --- a/clients/groups/tracing/tracing.go +++ b/users/groups/tracing/tracing.go @@ -3,7 +3,7 @@ package tracing import ( "context" - "github.com/mainflux/mainflux/clients/groups" + "github.com/mainflux/mainflux/users/groups" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/users/hasher.go b/users/hasher.go deleted file mode 100644 index cafb6b0d1a3..00000000000 --- a/users/hasher.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package users - -// Hasher specifies an API for generating hashes of an arbitrary textual -// content. -type Hasher interface { - // Hash generates the hashed string from plain-text. - Hash(string) (string, error) - - // Compare compares plain-text version to the hashed one. An error should - // indicate failed comparison. - Compare(string, string) error -} diff --git a/clients/hasher/hasher.go b/users/hasher/hasher.go similarity index 95% rename from clients/hasher/hasher.go rename to users/hasher/hasher.go index ce46e8407eb..20e17fa62b7 100644 --- a/clients/hasher/hasher.go +++ b/users/hasher/hasher.go @@ -2,8 +2,8 @@ package hasher import ( - "github.com/mainflux/mainflux/clients/clients" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" "golang.org/x/crypto/bcrypt" ) diff --git a/clients/jwt/jwt.go b/users/jwt/jwt.go similarity index 97% rename from clients/jwt/jwt.go rename to users/jwt/jwt.go index fe2125c3d87..ae6b9e12e9d 100644 --- a/clients/jwt/jwt.go +++ b/users/jwt/jwt.go @@ -21,6 +21,7 @@ type Token struct { // Claims are the Client's internal JWT Claims. type Claims struct { ClientID string // ClientID is the client unique identifier. + Email string // Email is the client identity Role string // Role is the role of the specific client. Tag string // Tag related to the client. Type string // Type denotes the type of claim. Either AccessToken or RefreshToken. diff --git a/clients/jwt/tokens.go b/users/jwt/tokens.go similarity index 100% rename from clients/jwt/tokens.go rename to users/jwt/tokens.go diff --git a/clients/jwt/tracing.go b/users/jwt/tracing.go similarity index 100% rename from clients/jwt/tracing.go rename to users/jwt/tracing.go diff --git a/users/mocks/authn.go b/users/mocks/authn.go deleted file mode 100644 index 2da336ac981..00000000000 --- a/users/mocks/authn.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package mocks - -import ( - "context" - - "github.com/golang/protobuf/ptypes/empty" - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/pkg/errors" - "google.golang.org/grpc" -) - -var _ mainflux.AuthServiceClient = (*authServiceMock)(nil) - -type SubjectSet struct { - Object string - Relation string -} - -type authServiceMock struct { - users map[string]string - authz map[string][]SubjectSet -} - -func (svc authServiceMock) ListPolicies(ctx context.Context, in *mainflux.ListPoliciesReq, opts ...grpc.CallOption) (*mainflux.ListPoliciesRes, error) { - panic("not implemented") -} - -// NewAuthService creates mock of users service. -func NewAuthService(users map[string]string, authzDB map[string][]SubjectSet) mainflux.AuthServiceClient { - return &authServiceMock{users, authzDB} -} - -func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { - if id, ok := svc.users[in.Value]; ok { - return &mainflux.UserIdentity{Id: id, Email: id}, nil - } - return nil, errors.ErrAuthentication -} - -func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { - if id, ok := svc.users[in.GetEmail()]; ok { - switch in.Type { - default: - return &mainflux.Token{Value: id}, nil - } - } - return nil, errors.ErrAuthentication -} - -func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { - if sub, ok := svc.authz[req.GetSub()]; ok { - for _, v := range sub { - if v.Relation == req.GetAct() && v.Object == req.GetObj() { - return &mainflux.AuthorizeRes{Authorized: true}, nil - } - } - } - return &mainflux.AuthorizeRes{Authorized: false}, nil -} - -func (svc authServiceMock) AddPolicy(ctx context.Context, in *mainflux.AddPolicyReq, opts ...grpc.CallOption) (*mainflux.AddPolicyRes, error) { - svc.authz[in.GetSub()] = append(svc.authz[in.GetSub()], SubjectSet{Object: in.GetObj(), Relation: in.GetAct()}) - return &mainflux.AddPolicyRes{Authorized: true}, nil -} - -func (svc authServiceMock) DeletePolicy(ctx context.Context, in *mainflux.DeletePolicyReq, opts ...grpc.CallOption) (*mainflux.DeletePolicyRes, error) { - // Not implemented - return &mainflux.DeletePolicyRes{Deleted: true}, nil -} - -func (svc authServiceMock) Members(ctx context.Context, req *mainflux.MembersReq, _ ...grpc.CallOption) (r *mainflux.MembersRes, err error) { - panic("not implemented") -} - -func (svc authServiceMock) Assign(ctx context.Context, req *mainflux.Assignment, _ ...grpc.CallOption) (r *empty.Empty, err error) { - panic("not implemented") -} diff --git a/users/mocks/users.go b/users/mocks/users.go deleted file mode 100644 index 3e34b27c703..00000000000 --- a/users/mocks/users.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package mocks - -import ( - "context" - "sort" - "sync" - - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" -) - -var _ users.UserRepository = (*userRepositoryMock)(nil) - -type userRepositoryMock struct { - mu sync.Mutex - users map[string]users.User - usersByID map[string]users.User - usersByGroupID map[string]users.User -} - -// NewUserRepository creates in-memory user repository -func NewUserRepository() users.UserRepository { - return &userRepositoryMock{ - users: make(map[string]users.User), - usersByID: make(map[string]users.User), - usersByGroupID: make(map[string]users.User), - } -} - -func (urm *userRepositoryMock) Save(ctx context.Context, user users.User) (string, error) { - urm.mu.Lock() - defer urm.mu.Unlock() - - if _, ok := urm.users[user.Email]; ok { - return "", errors.ErrConflict - } - - urm.users[user.Email] = user - urm.usersByID[user.ID] = user - return user.ID, nil -} - -func (urm *userRepositoryMock) Update(ctx context.Context, user users.User) error { - urm.mu.Lock() - defer urm.mu.Unlock() - - if _, ok := urm.users[user.Email]; !ok { - return errors.ErrNotFound - } - - urm.users[user.Email] = user - return nil -} - -func (urm *userRepositoryMock) UpdateUser(ctx context.Context, user users.User) error { - urm.mu.Lock() - defer urm.mu.Unlock() - - if _, ok := urm.users[user.Email]; !ok { - return errors.ErrNotFound - } - - urm.users[user.Email] = user - return nil -} - -func (urm *userRepositoryMock) RetrieveByEmail(ctx context.Context, email string) (users.User, error) { - urm.mu.Lock() - defer urm.mu.Unlock() - - val, ok := urm.users[email] - if !ok { - return users.User{}, errors.ErrNotFound - } - - return val, nil -} - -func (urm *userRepositoryMock) RetrieveByID(ctx context.Context, id string) (users.User, error) { - urm.mu.Lock() - defer urm.mu.Unlock() - - val, ok := urm.usersByID[id] - if !ok { - return users.User{}, errors.ErrNotFound - } - - return val, nil -} - -func (urm *userRepositoryMock) RetrieveAll(ctx context.Context, ids []string, pm users.PageMetadata) (users.UserPage, error) { - urm.mu.Lock() - defer urm.mu.Unlock() - - up := users.UserPage{} - i := uint64(0) - - if pm.Email != "" { - val, ok := urm.users[pm.Email] - if !ok { - return users.UserPage{}, errors.ErrNotFound - } - up.Offset = pm.Offset - up.Limit = pm.Limit - up.Total = uint64(i) - up.Users = []users.User{val} - return up, nil - } - - if pm.Status == users.EnabledStatusKey || pm.Status == users.DisabledStatusKey { - for _, u := range sortUsers(urm.users) { - if i >= pm.Offset && i < (pm.Limit+pm.Offset) { - if pm.Status == u.Status { - up.Users = append(up.Users, u) - } - } - i++ - } - up.Offset = pm.Offset - up.Limit = pm.Limit - up.Total = uint64(i) - return up, nil - } - for _, u := range sortUsers(urm.users) { - if i >= pm.Offset && i < (pm.Limit+pm.Offset) { - up.Users = append(up.Users, u) - } - i++ - } - - up.Offset = pm.Offset - up.Limit = pm.Limit - up.Total = uint64(i) - - return up, nil -} - -func (urm *userRepositoryMock) UpdatePassword(_ context.Context, token, password string) error { - urm.mu.Lock() - defer urm.mu.Unlock() - - if _, ok := urm.users[token]; !ok { - return errors.ErrNotFound - } - return nil -} - -func (urm *userRepositoryMock) ChangeStatus(ctx context.Context, id, status string) error { - urm.mu.Lock() - defer urm.mu.Unlock() - - user, ok := urm.usersByID[id] - if !ok { - return errors.ErrNotFound - } - user.Status = status - urm.usersByID[id] = user - urm.users[user.Email] = user - return nil -} -func sortUsers(us map[string]users.User) []users.User { - users := []users.User{} - ids := make([]string, 0, len(us)) - for k := range us { - ids = append(ids, k) - } - - sort.Strings(ids) - for _, id := range ids { - users = append(users, us[id]) - } - - return users -} diff --git a/users/policies/api/grpc/client.go b/users/policies/api/grpc/client.go new file mode 100644 index 00000000000..3cc1f8dac18 --- /dev/null +++ b/users/policies/api/grpc/client.go @@ -0,0 +1,238 @@ +package grpc + +import ( + "context" + "time" + + "github.com/go-kit/kit/endpoint" + kitgrpc "github.com/go-kit/kit/transport/grpc" + "github.com/mainflux/mainflux/users/policies" + "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" + "google.golang.org/grpc" +) + +const svcName = "policies.AuthService" + +var _ policies.AuthServiceClient = (*grpcClient)(nil) + +type grpcClient struct { + authorize endpoint.Endpoint + issue endpoint.Endpoint + identify endpoint.Endpoint + addPolicy endpoint.Endpoint + deletePolicy endpoint.Endpoint + listPolicies endpoint.Endpoint + timeout time.Duration +} + +// NewClient returns new gRPC client instance. +func NewClient(conn *grpc.ClientConn, timeout time.Duration) policies.AuthServiceClient { + return &grpcClient{ + authorize: otelkit.EndpointMiddleware(otelkit.WithOperation("authorize"))(kitgrpc.NewClient( + conn, + svcName, + "Authorize", + encodeAuthorizeRequest, + decodeAuthorizeResponse, + policies.AuthorizeRes{}, + ).Endpoint()), + issue: otelkit.EndpointMiddleware(otelkit.WithOperation("issue"))(kitgrpc.NewClient( + conn, + svcName, + "Issue", + encodeIssueRequest, + decodeIssueResponse, + policies.UserIdentity{}, + ).Endpoint()), + identify: otelkit.EndpointMiddleware(otelkit.WithOperation("identify"))(kitgrpc.NewClient( + conn, + svcName, + "Identify", + encodeIdentifyRequest, + decodeIdentifyResponse, + policies.UserIdentity{}, + ).Endpoint()), + addPolicy: otelkit.EndpointMiddleware(otelkit.WithOperation("add_policy"))(kitgrpc.NewClient( + conn, + svcName, + "AddPolicy", + encodeAddPolicyRequest, + decodeAddPolicyResponse, + policies.AddPolicyRes{}, + ).Endpoint()), + deletePolicy: otelkit.EndpointMiddleware(otelkit.WithOperation("delete_policy"))(kitgrpc.NewClient( + conn, + svcName, + "DeletePolicy", + encodeDeletePolicyRequest, + decodeDeletePolicyResponse, + policies.DeletePolicyRes{}, + ).Endpoint()), + listPolicies: otelkit.EndpointMiddleware(otelkit.WithOperation("list_policies"))(kitgrpc.NewClient( + conn, + svcName, + "ListPolicies", + encodeListPoliciesRequest, + decodeListPoliciesResponse, + policies.ListPoliciesRes{}, + ).Endpoint()), + + timeout: timeout, + } +} + +func (client grpcClient) Authorize(ctx context.Context, req *policies.AuthorizeReq, _ ...grpc.CallOption) (r *policies.AuthorizeRes, err error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.authorize(ctx, authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub(), EntityType: req.GetEntityType()}) + if err != nil { + return &policies.AuthorizeRes{}, err + } + + ar := res.(authorizeRes) + return &policies.AuthorizeRes{Authorized: ar.authorized}, err +} + +func decodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.AuthorizeRes) + return authorizeRes{authorized: res.Authorized}, nil +} + +func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(authReq) + return &policies.AuthorizeReq{ + Sub: req.Sub, + Obj: req.Obj, + Act: req.Act, + EntityType: req.EntityType, + }, nil +} + +func (client grpcClient) Issue(ctx context.Context, req *policies.IssueReq, _ ...grpc.CallOption) (*policies.Token, error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.issue(ctx, issueReq{id: req.GetId(), email: req.GetEmail()}) + if err != nil { + return nil, err + } + + ir := res.(identityRes) + return &policies.Token{Value: ir.id}, nil +} + +func encodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(issueReq) + return &policies.IssueReq{Id: req.id, Email: req.email}, nil +} + +func decodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.UserIdentity) + return identityRes{id: res.GetId(), email: res.GetEmail()}, nil +} + +func (client grpcClient) Identify(ctx context.Context, token *policies.Token, _ ...grpc.CallOption) (*policies.UserIdentity, error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.identify(ctx, identityReq{token: token.GetValue()}) + if err != nil { + return nil, err + } + + ir := res.(identityRes) + return &policies.UserIdentity{Id: ir.id, Email: ir.email}, nil +} + +func encodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(identityReq) + return &policies.Token{Value: req.token}, nil +} + +func decodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.UserIdentity) + return identityRes{id: res.GetId(), email: res.GetEmail()}, nil +} + +func (client grpcClient) AddPolicy(ctx context.Context, in *policies.AddPolicyReq, opts ...grpc.CallOption) (*policies.AddPolicyRes, error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.addPolicy(ctx, addPolicyReq{Token: in.GetToken(), Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()}) + if err != nil { + return &policies.AddPolicyRes{}, err + } + + apr := res.(addPolicyRes) + return &policies.AddPolicyRes{Authorized: apr.authorized}, err +} + +func decodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.AddPolicyRes) + return addPolicyRes{authorized: res.Authorized}, nil +} + +func encodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(addPolicyReq) + return &policies.AddPolicyReq{ + Token: req.Token, + Sub: req.Sub, + Obj: req.Obj, + Act: req.Act, + }, nil +} + +func (client grpcClient) DeletePolicy(ctx context.Context, in *policies.DeletePolicyReq, opts ...grpc.CallOption) (*policies.DeletePolicyRes, error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.deletePolicy(ctx, policyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()}) + if err != nil { + return &policies.DeletePolicyRes{}, err + } + + dpr := res.(deletePolicyRes) + return &policies.DeletePolicyRes{Deleted: dpr.deleted}, err +} + +func decodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.DeletePolicyRes) + return deletePolicyRes{deleted: res.GetDeleted()}, nil +} + +func encodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(policyReq) + return &policies.DeletePolicyReq{ + Sub: req.Sub, + Obj: req.Obj, + Act: req.Act, + }, nil +} + +func (client grpcClient) ListPolicies(ctx context.Context, in *policies.ListPoliciesReq, opts ...grpc.CallOption) (*policies.ListPoliciesRes, error) { + ctx, close := context.WithTimeout(ctx, client.timeout) + defer close() + + res, err := client.listPolicies(ctx, listPoliciesReq{Obj: in.GetObj(), Act: in.GetAct(), Sub: in.GetSub()}) + if err != nil { + return &policies.ListPoliciesRes{}, err + } + + lpr := res.(listPoliciesRes) + return &policies.ListPoliciesRes{Objects: lpr.objects}, err +} + +func decodeListPoliciesResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(*policies.ListPoliciesRes) + return listPoliciesRes{objects: res.GetObjects()}, nil +} + +func encodeListPoliciesRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(listPoliciesReq) + return &policies.ListPoliciesReq{ + Sub: req.Sub, + Obj: req.Obj, + Act: req.Act, + }, nil +} diff --git a/users/policies/api/grpc/endpoint.go b/users/policies/api/grpc/endpoint.go new file mode 100644 index 00000000000..c4c890e0f64 --- /dev/null +++ b/users/policies/api/grpc/endpoint.go @@ -0,0 +1,107 @@ +package grpc + +import ( + "context" + + "github.com/go-kit/kit/endpoint" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/policies" +) + +func authorizeEndpoint(svc policies.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(authReq) + + if err := req.validate(); err != nil { + return authorizeRes{}, err + } + + err := svc.Authorize(ctx, req.EntityType, policies.Policy{Subject: req.Sub, Object: req.Obj, Actions: []string{req.Act}}) + if err != nil { + return authorizeRes{}, err + } + return authorizeRes{authorized: true}, err + } +} + +func issueEndpoint(svc clients.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(issueReq) + if err := req.validate(); err != nil { + return issueRes{}, err + } + + tkn, err := svc.IssueToken(ctx, req.email, "") + if err != nil { + return issueRes{}, err + } + + return issueRes{value: tkn.AccessToken}, nil + } +} + +func identifyEndpoint(svc clients.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(identityReq) + if err := req.validate(); err != nil { + return identityRes{}, err + } + + ir, err := svc.Identify(ctx, req.token) + if err != nil { + return identityRes{}, err + } + + ret := identityRes{ + id: ir.ID, + email: ir.Email, + } + return ret, nil + } +} + +func addPolicyEndpoint(svc policies.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(addPolicyReq) + if err := req.validate(); err != nil { + return addPolicyRes{}, err + } + + err := svc.AddPolicy(ctx, req.Token, policies.Policy{Subject: req.Sub, Object: req.Obj, Actions: req.Act}) + if err != nil { + return addPolicyRes{}, err + } + return addPolicyRes{authorized: true}, err + } +} + +func deletePolicyEndpoint(svc policies.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(policyReq) + if err := req.validate(); err != nil { + return deletePolicyRes{}, err + } + + err := svc.DeletePolicy(ctx, "", policies.Policy{Subject: req.Sub, Object: req.Obj, Actions: []string{req.Act}}) + if err != nil { + return deletePolicyRes{}, err + } + return deletePolicyRes{deleted: true}, nil + } +} + +func listPoliciesEndpoint(svc policies.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(listPoliciesReq) + + page, err := svc.ListPolicy(ctx, "", policies.Page{Subject: req.Sub, Object: req.Obj, Action: req.Act}) + if err != nil { + return deletePolicyRes{}, err + } + var objects []string + for _, p := range page.Policies { + objects = append(objects, p.Object) + } + return listPoliciesRes{objects: objects}, nil + } +} diff --git a/auth/api/grpc/requests.go b/users/policies/api/grpc/requests.go similarity index 50% rename from auth/api/grpc/requests.go rename to users/policies/api/grpc/requests.go index 269c950d8dc..a21e4d6ad30 100644 --- a/auth/api/grpc/requests.go +++ b/users/policies/api/grpc/requests.go @@ -1,99 +1,73 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - package grpc import ( - "github.com/mainflux/mainflux/auth" "github.com/mainflux/mainflux/internal/apiutil" ) +// authReq represents authorization request. It contains: +// 1. subject - an action invoker (client) +// 2. object - an entity over which action will be executed (client, group, computation, dataset) +// 3. action - type of action that will be executed (read/write) +type authReq struct { + Sub string + Obj string + Act string + EntityType string +} + +func (req authReq) validate() error { + if req.Sub == "" { + return apiutil.ErrMissingPolicySub + } + if req.Obj == "" { + return apiutil.ErrMissingPolicyObj + } + if req.Act == "" { + return apiutil.ErrMissingPolicyAct + } + if req.EntityType == "" { + return apiutil.ErrMissingPolicyEntityType + } + + return nil +} + type identityReq struct { token string - kind uint32 } func (req identityReq) validate() error { if req.token == "" { return apiutil.ErrBearerToken } - if req.kind != auth.LoginKey && - req.kind != auth.APIKey && - req.kind != auth.RecoveryKey { - return apiutil.ErrInvalidAuthKey - } return nil } type issueReq struct { - id string - email string - keyType uint32 + id string + email string } func (req issueReq) validate() error { if req.email == "" { return apiutil.ErrMissingEmail } - if req.keyType != auth.LoginKey && - req.keyType != auth.APIKey && - req.keyType != auth.RecoveryKey { - return apiutil.ErrInvalidAuthKey - } - - return nil -} - -type assignReq struct { - token string - groupID string - memberID string - groupType string -} -func (req assignReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - if req.groupID == "" || req.memberID == "" { - return apiutil.ErrMissingID - } return nil } -type membersReq struct { - token string - groupID string - offset uint64 - limit uint64 - memberType string +type addPolicyReq struct { + Token string + Sub string + Obj string + Act []string } -func (req membersReq) validate() error { - if req.token == "" { +func (req addPolicyReq) validate() error { + if req.Token == "" { return apiutil.ErrBearerToken } - if req.groupID == "" { - return apiutil.ErrMissingID - } - if req.memberType == "" { - return apiutil.ErrMissingMemberType - } - return nil -} - -// authReq represents authorization request. It contains: -// 1. subject - an action invoker -// 2. object - an entity over which action will be executed -// 3. action - type of action that will be executed (read/write) -type authReq struct { - Sub string - Obj string - Act string -} - -func (req authReq) validate() error { if req.Sub == "" { return apiutil.ErrMissingPolicySub } @@ -102,7 +76,7 @@ func (req authReq) validate() error { return apiutil.ErrMissingPolicyObj } - if req.Act == "" { + if len(req.Act) == 0 { return apiutil.ErrMissingPolicyAct } diff --git a/auth/api/grpc/responses.go b/users/policies/api/grpc/responses.go similarity index 54% rename from auth/api/grpc/responses.go rename to users/policies/api/grpc/responses.go index fd21f4df9ae..adc64176728 100644 --- a/auth/api/grpc/responses.go +++ b/users/policies/api/grpc/responses.go @@ -1,8 +1,9 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - package grpc +type authorizeRes struct { + authorized bool +} + type identityRes struct { id string email string @@ -12,10 +13,6 @@ type issueRes struct { value string } -type authorizeRes struct { - authorized bool -} - type addPolicyRes struct { authorized bool } @@ -25,16 +22,5 @@ type deletePolicyRes struct { } type listPoliciesRes struct { - policies []string -} - -type membersRes struct { - total uint64 - offset uint64 - limit uint64 - groupType string - members []string -} -type emptyRes struct { - err error + objects []string } diff --git a/users/policies/api/grpc/transport.go b/users/policies/api/grpc/transport.go new file mode 100644 index 00000000000..a7646797e1a --- /dev/null +++ b/users/policies/api/grpc/transport.go @@ -0,0 +1,195 @@ +package grpc + +import ( + "context" + + kitgrpc "github.com/go-kit/kit/transport/grpc" + "github.com/mainflux/mainflux/internal/apiutil" + "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/policies" + "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var _ policies.AuthServiceServer = (*grpcServer)(nil) + +type grpcServer struct { + authorize kitgrpc.Handler + issue kitgrpc.Handler + identify kitgrpc.Handler + addPolicy kitgrpc.Handler + deletePolicy kitgrpc.Handler + listPolicies kitgrpc.Handler + policies.UnimplementedAuthServiceServer +} + +// NewServer returns new AuthServiceServer instance. +func NewServer(csvc clients.Service, psvc policies.Service) policies.AuthServiceServer { + return &grpcServer{ + authorize: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("authorize"))(authorizeEndpoint(psvc)), + decodeAuthorizeRequest, + encodeAuthorizeResponse, + ), + issue: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("issue"))(issueEndpoint(csvc)), + decodeIssueRequest, + encodeIssueResponse, + ), + identify: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("identify"))(identifyEndpoint(csvc)), + decodeIdentifyRequest, + encodeIdentifyResponse, + ), + addPolicy: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("add_policy"))(addPolicyEndpoint(psvc)), + decodeAddPolicyRequest, + encodeAddPolicyResponse, + ), + deletePolicy: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("delete_policy"))(deletePolicyEndpoint(psvc)), + decodeDeletePolicyRequest, + encodeDeletePolicyResponse, + ), + listPolicies: kitgrpc.NewServer( + otelkit.EndpointMiddleware(otelkit.WithOperation("list_policies"))(listPoliciesEndpoint(psvc)), + decodeListPoliciesRequest, + encodeListPoliciesResponse, + ), + } +} + +func (s *grpcServer) Authorize(ctx context.Context, req *policies.AuthorizeReq) (*policies.AuthorizeRes, error) { + _, res, err := s.authorize.ServeGRPC(ctx, req) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.AuthorizeRes), nil +} + +func (s *grpcServer) Issue(ctx context.Context, req *policies.IssueReq) (*policies.Token, error) { + _, res, err := s.issue.ServeGRPC(ctx, req) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.Token), nil +} + +func (s *grpcServer) Identify(ctx context.Context, token *policies.Token) (*policies.UserIdentity, error) { + _, res, err := s.identify.ServeGRPC(ctx, token) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.UserIdentity), nil +} + +func (s *grpcServer) AddPolicy(ctx context.Context, req *policies.AddPolicyReq) (*policies.AddPolicyRes, error) { + _, res, err := s.addPolicy.ServeGRPC(ctx, req) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.AddPolicyRes), nil +} + +func (s *grpcServer) DeletePolicy(ctx context.Context, req *policies.DeletePolicyReq) (*policies.DeletePolicyRes, error) { + _, res, err := s.deletePolicy.ServeGRPC(ctx, req) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.DeletePolicyRes), nil +} + +func (s *grpcServer) ListPolicies(ctx context.Context, req *policies.ListPoliciesReq) (*policies.ListPoliciesRes, error) { + _, res, err := s.listPolicies.ServeGRPC(ctx, req) + if err != nil { + return nil, encodeError(err) + } + return res.(*policies.ListPoliciesRes), nil +} + +func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.AuthorizeReq) + return authReq{Act: req.GetAct(), Obj: req.GetObj(), Sub: req.GetSub(), EntityType: req.GetEntityType()}, nil +} + +func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(authorizeRes) + return &policies.AuthorizeRes{Authorized: res.authorized}, nil +} + +func decodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.IssueReq) + return issueReq{id: req.GetId(), email: req.GetEmail()}, nil +} + +func encodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(issueRes) + return &policies.Token{Value: res.value}, nil +} + +func decodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.Token) + return identityReq{token: req.GetValue()}, nil +} + +func encodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(identityRes) + return &policies.UserIdentity{Id: res.id, Email: res.email}, nil +} + +func decodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.AddPolicyReq) + return addPolicyReq{Token: req.GetToken(), Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil +} + +func encodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(addPolicyRes) + return &policies.AddPolicyRes{Authorized: res.authorized}, nil +} + +func decodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.DeletePolicyReq) + return policyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil +} + +func encodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(deletePolicyRes) + return &policies.DeletePolicyRes{Deleted: res.deleted}, nil +} + +func decodeListPoliciesRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { + req := grpcReq.(*policies.ListPoliciesReq) + return listPoliciesReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil +} + +func encodeListPoliciesResponse(_ context.Context, grpcRes interface{}) (interface{}, error) { + res := grpcRes.(listPoliciesRes) + return &policies.ListPoliciesRes{Objects: res.objects}, nil +} + +func encodeError(err error) error { + switch { + case errors.Contains(err, nil): + return nil + case errors.Contains(err, errors.ErrMalformedEntity), + err == apiutil.ErrInvalidAuthKey, + err == apiutil.ErrMissingID, + err == apiutil.ErrBearerToken, + err == apiutil.ErrMissingPolicySub, + err == apiutil.ErrMissingPolicyObj, + err == apiutil.ErrMissingPolicyAct, + err == apiutil.ErrMalformedPolicy, + err == apiutil.ErrMissingPolicyOwner, + err == apiutil.ErrHigherPolicyRank: + return status.Error(codes.InvalidArgument, err.Error()) + case errors.Contains(err, errors.ErrAuthentication), + err == apiutil.ErrBearerToken: + return status.Error(codes.Unauthenticated, err.Error()) + case errors.Contains(err, errors.ErrAuthorization): + return status.Error(codes.PermissionDenied, err.Error()) + default: + return status.Error(codes.Internal, "internal server error") + } +} diff --git a/clients/policies/api/http/endpoints.go b/users/policies/api/http/endpoints.go similarity index 98% rename from clients/policies/api/http/endpoints.go rename to users/policies/api/http/endpoints.go index fbe120143f7..b6963ba9be1 100644 --- a/clients/policies/api/http/endpoints.go +++ b/users/policies/api/http/endpoints.go @@ -4,7 +4,7 @@ import ( "context" "github.com/go-kit/kit/endpoint" - "github.com/mainflux/mainflux/clients/policies" + "github.com/mainflux/mainflux/users/policies" ) func authorizeEndpoint(svc policies.Service) endpoint.Endpoint { diff --git a/clients/policies/api/http/logging.go b/users/policies/api/http/logging.go similarity index 98% rename from clients/policies/api/http/logging.go rename to users/policies/api/http/logging.go index 83bdc7ba568..3bd2e6b2d7c 100644 --- a/clients/policies/api/http/logging.go +++ b/users/policies/api/http/logging.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/mainflux/mainflux/clients/policies" log "github.com/mainflux/mainflux/logger" + "github.com/mainflux/mainflux/users/policies" ) var _ policies.Service = (*loggingMiddleware)(nil) diff --git a/clients/policies/api/http/metrics.go b/users/policies/api/http/metrics.go similarity index 97% rename from clients/policies/api/http/metrics.go rename to users/policies/api/http/metrics.go index 1773479c03d..6f39d6333a1 100644 --- a/clients/policies/api/http/metrics.go +++ b/users/policies/api/http/metrics.go @@ -5,7 +5,7 @@ import ( "time" "github.com/go-kit/kit/metrics" - "github.com/mainflux/mainflux/clients/policies" + "github.com/mainflux/mainflux/users/policies" ) var _ policies.Service = (*metricsMiddleware)(nil) diff --git a/clients/policies/api/http/requests.go b/users/policies/api/http/requests.go similarity index 97% rename from clients/policies/api/http/requests.go rename to users/policies/api/http/requests.go index d767d23f2d8..eb293e90857 100644 --- a/clients/policies/api/http/requests.go +++ b/users/policies/api/http/requests.go @@ -1,8 +1,8 @@ package api import ( - "github.com/mainflux/mainflux/clients/policies" "github.com/mainflux/mainflux/internal/apiutil" + "github.com/mainflux/mainflux/users/policies" ) type authorizeReq struct { diff --git a/clients/policies/api/http/responses.go b/users/policies/api/http/responses.go similarity index 100% rename from clients/policies/api/http/responses.go rename to users/policies/api/http/responses.go diff --git a/clients/policies/api/http/transport.go b/users/policies/api/http/transport.go similarity index 97% rename from clients/policies/api/http/transport.go rename to users/policies/api/http/transport.go index 7f199443608..4551c291c76 100644 --- a/clients/policies/api/http/transport.go +++ b/users/policies/api/http/transport.go @@ -8,16 +8,16 @@ import ( kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" - "github.com/mainflux/mainflux/clients/policies" "github.com/mainflux/mainflux/internal/api" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/logger" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/policies" "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" ) // MakeHandler returns a HTTP handler for API endpoints. -func MakePolicyHandler(svc policies.Service, mux *bone.Mux, logger logger.Logger) { +func MakePolicyHandler(svc policies.Service, mux *bone.Mux, logger logger.Logger) http.Handler { opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), } @@ -55,6 +55,8 @@ func MakePolicyHandler(svc policies.Service, mux *bone.Mux, logger logger.Logger api.EncodeResponse, opts..., )) + + return mux } func decodeAuthorize(_ context.Context, r *http.Request) (interface{}, error) { diff --git a/users/policies/clientauth.pb.go b/users/policies/clientauth.pb.go new file mode 100644 index 00000000000..f482b2753a0 --- /dev/null +++ b/users/policies/clientauth.pb.go @@ -0,0 +1,923 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: users/policies/clientauth.proto + +package policies + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type AuthorizeReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sub string `protobuf:"bytes,1,opt,name=sub,proto3" json:"sub,omitempty"` + Obj string `protobuf:"bytes,2,opt,name=obj,proto3" json:"obj,omitempty"` + Act string `protobuf:"bytes,3,opt,name=act,proto3" json:"act,omitempty"` + EntityType string `protobuf:"bytes,4,opt,name=entityType,proto3" json:"entityType,omitempty"` +} + +func (x *AuthorizeReq) Reset() { + *x = AuthorizeReq{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthorizeReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthorizeReq) ProtoMessage() {} + +func (x *AuthorizeReq) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthorizeReq.ProtoReflect.Descriptor instead. +func (*AuthorizeReq) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{0} +} + +func (x *AuthorizeReq) GetSub() string { + if x != nil { + return x.Sub + } + return "" +} + +func (x *AuthorizeReq) GetObj() string { + if x != nil { + return x.Obj + } + return "" +} + +func (x *AuthorizeReq) GetAct() string { + if x != nil { + return x.Act + } + return "" +} + +func (x *AuthorizeReq) GetEntityType() string { + if x != nil { + return x.EntityType + } + return "" +} + +type AuthorizeRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"` +} + +func (x *AuthorizeRes) Reset() { + *x = AuthorizeRes{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthorizeRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthorizeRes) ProtoMessage() {} + +func (x *AuthorizeRes) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthorizeRes.ProtoReflect.Descriptor instead. +func (*AuthorizeRes) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{1} +} + +func (x *AuthorizeRes) GetAuthorized() bool { + if x != nil { + return x.Authorized + } + return false +} + +type IssueReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *IssueReq) Reset() { + *x = IssueReq{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IssueReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IssueReq) ProtoMessage() {} + +func (x *IssueReq) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IssueReq.ProtoReflect.Descriptor instead. +func (*IssueReq) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{2} +} + +func (x *IssueReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *IssueReq) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *IssueReq) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +type Token struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Token) Reset() { + *x = Token{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Token) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Token) ProtoMessage() {} + +func (x *Token) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Token.ProtoReflect.Descriptor instead. +func (*Token) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{3} +} + +func (x *Token) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type UserIdentity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` +} + +func (x *UserIdentity) Reset() { + *x = UserIdentity{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserIdentity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserIdentity) ProtoMessage() {} + +func (x *UserIdentity) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserIdentity.ProtoReflect.Descriptor instead. +func (*UserIdentity) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{4} +} + +func (x *UserIdentity) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UserIdentity) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +type AddPolicyReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + Sub string `protobuf:"bytes,2,opt,name=sub,proto3" json:"sub,omitempty"` + Obj string `protobuf:"bytes,3,opt,name=obj,proto3" json:"obj,omitempty"` + Act []string `protobuf:"bytes,4,rep,name=act,proto3" json:"act,omitempty"` +} + +func (x *AddPolicyReq) Reset() { + *x = AddPolicyReq{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPolicyReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPolicyReq) ProtoMessage() {} + +func (x *AddPolicyReq) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddPolicyReq.ProtoReflect.Descriptor instead. +func (*AddPolicyReq) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{5} +} + +func (x *AddPolicyReq) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +func (x *AddPolicyReq) GetSub() string { + if x != nil { + return x.Sub + } + return "" +} + +func (x *AddPolicyReq) GetObj() string { + if x != nil { + return x.Obj + } + return "" +} + +func (x *AddPolicyReq) GetAct() []string { + if x != nil { + return x.Act + } + return nil +} + +type AddPolicyRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"` +} + +func (x *AddPolicyRes) Reset() { + *x = AddPolicyRes{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPolicyRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPolicyRes) ProtoMessage() {} + +func (x *AddPolicyRes) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddPolicyRes.ProtoReflect.Descriptor instead. +func (*AddPolicyRes) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{6} +} + +func (x *AddPolicyRes) GetAuthorized() bool { + if x != nil { + return x.Authorized + } + return false +} + +type DeletePolicyReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sub string `protobuf:"bytes,1,opt,name=sub,proto3" json:"sub,omitempty"` + Obj string `protobuf:"bytes,2,opt,name=obj,proto3" json:"obj,omitempty"` + Act string `protobuf:"bytes,3,opt,name=act,proto3" json:"act,omitempty"` +} + +func (x *DeletePolicyReq) Reset() { + *x = DeletePolicyReq{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePolicyReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePolicyReq) ProtoMessage() {} + +func (x *DeletePolicyReq) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeletePolicyReq.ProtoReflect.Descriptor instead. +func (*DeletePolicyReq) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{7} +} + +func (x *DeletePolicyReq) GetSub() string { + if x != nil { + return x.Sub + } + return "" +} + +func (x *DeletePolicyReq) GetObj() string { + if x != nil { + return x.Obj + } + return "" +} + +func (x *DeletePolicyReq) GetAct() string { + if x != nil { + return x.Act + } + return "" +} + +type DeletePolicyRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` +} + +func (x *DeletePolicyRes) Reset() { + *x = DeletePolicyRes{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePolicyRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePolicyRes) ProtoMessage() {} + +func (x *DeletePolicyRes) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeletePolicyRes.ProtoReflect.Descriptor instead. +func (*DeletePolicyRes) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{8} +} + +func (x *DeletePolicyRes) GetDeleted() bool { + if x != nil { + return x.Deleted + } + return false +} + +type ListPoliciesReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sub string `protobuf:"bytes,1,opt,name=sub,proto3" json:"sub,omitempty"` + Obj string `protobuf:"bytes,2,opt,name=obj,proto3" json:"obj,omitempty"` + Act string `protobuf:"bytes,3,opt,name=act,proto3" json:"act,omitempty"` +} + +func (x *ListPoliciesReq) Reset() { + *x = ListPoliciesReq{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPoliciesReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPoliciesReq) ProtoMessage() {} + +func (x *ListPoliciesReq) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPoliciesReq.ProtoReflect.Descriptor instead. +func (*ListPoliciesReq) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{9} +} + +func (x *ListPoliciesReq) GetSub() string { + if x != nil { + return x.Sub + } + return "" +} + +func (x *ListPoliciesReq) GetObj() string { + if x != nil { + return x.Obj + } + return "" +} + +func (x *ListPoliciesReq) GetAct() string { + if x != nil { + return x.Act + } + return "" +} + +type ListPoliciesRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Objects []string `protobuf:"bytes,1,rep,name=objects,proto3" json:"objects,omitempty"` +} + +func (x *ListPoliciesRes) Reset() { + *x = ListPoliciesRes{} + if protoimpl.UnsafeEnabled { + mi := &file_users_policies_clientauth_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPoliciesRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPoliciesRes) ProtoMessage() {} + +func (x *ListPoliciesRes) ProtoReflect() protoreflect.Message { + mi := &file_users_policies_clientauth_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPoliciesRes.ProtoReflect.Descriptor instead. +func (*ListPoliciesRes) Descriptor() ([]byte, []int) { + return file_users_policies_clientauth_proto_rawDescGZIP(), []int{10} +} + +func (x *ListPoliciesRes) GetObjects() []string { + if x != nil { + return x.Objects + } + return nil +} + +var File_users_policies_clientauth_proto protoreflect.FileDescriptor + +var file_users_policies_clientauth_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0c, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x75, 0x62, 0x12, 0x10, 0x0a, + 0x03, 0x6f, 0x62, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x62, 0x6a, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x63, + 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x2e, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, + 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, + 0x64, 0x22, 0x44, 0x0a, 0x08, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, + 0x61, 0x69, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x5a, 0x0a, 0x0c, + 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x73, 0x75, 0x62, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x62, 0x6a, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6f, 0x62, 0x6a, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x03, 0x61, 0x63, 0x74, 0x22, 0x2e, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x47, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x75, 0x62, 0x12, 0x10, 0x0a, + 0x03, 0x6f, 0x62, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x62, 0x6a, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x63, + 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x52, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x47, + 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x73, 0x75, 0x62, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x62, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6f, 0x62, 0x6a, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x61, 0x63, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x32, 0x82, 0x03, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x65, 0x12, 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, + 0x73, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x05, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x12, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x71, + 0x1a, 0x0f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x12, + 0x0f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x1a, 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x09, 0x41, 0x64, + 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x1a, + 0x16, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0c, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x19, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x22, + 0x00, 0x12, 0x46, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x12, 0x19, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_users_policies_clientauth_proto_rawDescOnce sync.Once + file_users_policies_clientauth_proto_rawDescData = file_users_policies_clientauth_proto_rawDesc +) + +func file_users_policies_clientauth_proto_rawDescGZIP() []byte { + file_users_policies_clientauth_proto_rawDescOnce.Do(func() { + file_users_policies_clientauth_proto_rawDescData = protoimpl.X.CompressGZIP(file_users_policies_clientauth_proto_rawDescData) + }) + return file_users_policies_clientauth_proto_rawDescData +} + +var file_users_policies_clientauth_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_users_policies_clientauth_proto_goTypes = []interface{}{ + (*AuthorizeReq)(nil), // 0: policies.AuthorizeReq + (*AuthorizeRes)(nil), // 1: policies.AuthorizeRes + (*IssueReq)(nil), // 2: policies.IssueReq + (*Token)(nil), // 3: policies.Token + (*UserIdentity)(nil), // 4: policies.UserIdentity + (*AddPolicyReq)(nil), // 5: policies.AddPolicyReq + (*AddPolicyRes)(nil), // 6: policies.AddPolicyRes + (*DeletePolicyReq)(nil), // 7: policies.DeletePolicyReq + (*DeletePolicyRes)(nil), // 8: policies.DeletePolicyRes + (*ListPoliciesReq)(nil), // 9: policies.ListPoliciesReq + (*ListPoliciesRes)(nil), // 10: policies.ListPoliciesRes +} +var file_users_policies_clientauth_proto_depIdxs = []int32{ + 0, // 0: policies.AuthService.Authorize:input_type -> policies.AuthorizeReq + 2, // 1: policies.AuthService.Issue:input_type -> policies.IssueReq + 3, // 2: policies.AuthService.Identify:input_type -> policies.Token + 5, // 3: policies.AuthService.AddPolicy:input_type -> policies.AddPolicyReq + 7, // 4: policies.AuthService.DeletePolicy:input_type -> policies.DeletePolicyReq + 9, // 5: policies.AuthService.ListPolicies:input_type -> policies.ListPoliciesReq + 1, // 6: policies.AuthService.Authorize:output_type -> policies.AuthorizeRes + 3, // 7: policies.AuthService.Issue:output_type -> policies.Token + 4, // 8: policies.AuthService.Identify:output_type -> policies.UserIdentity + 6, // 9: policies.AuthService.AddPolicy:output_type -> policies.AddPolicyRes + 8, // 10: policies.AuthService.DeletePolicy:output_type -> policies.DeletePolicyRes + 10, // 11: policies.AuthService.ListPolicies:output_type -> policies.ListPoliciesRes + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_users_policies_clientauth_proto_init() } +func file_users_policies_clientauth_proto_init() { + if File_users_policies_clientauth_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_users_policies_clientauth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthorizeReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthorizeRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IssueReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Token); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserIdentity); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPolicyReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPolicyRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePolicyReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePolicyRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPoliciesReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_users_policies_clientauth_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPoliciesRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_users_policies_clientauth_proto_rawDesc, + NumEnums: 0, + NumMessages: 11, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_users_policies_clientauth_proto_goTypes, + DependencyIndexes: file_users_policies_clientauth_proto_depIdxs, + MessageInfos: file_users_policies_clientauth_proto_msgTypes, + }.Build() + File_users_policies_clientauth_proto = out.File + file_users_policies_clientauth_proto_rawDesc = nil + file_users_policies_clientauth_proto_goTypes = nil + file_users_policies_clientauth_proto_depIdxs = nil +} diff --git a/users/policies/clientauth.proto b/users/policies/clientauth.proto new file mode 100644 index 00000000000..5a30bceaff6 --- /dev/null +++ b/users/policies/clientauth.proto @@ -0,0 +1,71 @@ +syntax = "proto3"; + +package policies; + +option go_package = "./policies"; + +service AuthService { + rpc Authorize(AuthorizeReq) returns (AuthorizeRes) {} + rpc Issue(IssueReq) returns (Token) {} + rpc Identify(Token) returns (UserIdentity) {} + rpc AddPolicy(AddPolicyReq) returns (AddPolicyRes) {} + rpc DeletePolicy(DeletePolicyReq) returns (DeletePolicyRes) {} + rpc ListPolicies(ListPoliciesReq) returns (ListPoliciesRes) {} +} + +message AuthorizeReq { + string sub = 1; + string obj = 2; + string act = 3; + string entityType = 4; +} + +message AuthorizeRes { + bool authorized = 1; +} + +message IssueReq { + string id = 1; + string email = 2; + uint32 type = 3; +} + +message Token { + string value = 1; +} + +message UserIdentity { + string id = 1; + string email = 2; +} + +message AddPolicyReq { + string token = 1; + string sub = 2; + string obj = 3; + repeated string act = 4; +} + +message AddPolicyRes { + bool authorized = 1; +} + +message DeletePolicyReq { + string sub = 1; + string obj = 2; + string act = 3; +} + +message DeletePolicyRes { + bool deleted = 1; +} + +message ListPoliciesReq { + string sub = 1; + string obj = 2; + string act = 3; +} + +message ListPoliciesRes { + repeated string objects = 1; +} diff --git a/users/policies/clientauth_grpc.pb.go b/users/policies/clientauth_grpc.pb.go new file mode 100644 index 00000000000..9ec5298b675 --- /dev/null +++ b/users/policies/clientauth_grpc.pb.go @@ -0,0 +1,285 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: users/policies/clientauth.proto + +package policies + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// AuthServiceClient is the client API for AuthService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AuthServiceClient interface { + Authorize(ctx context.Context, in *AuthorizeReq, opts ...grpc.CallOption) (*AuthorizeRes, error) + Issue(ctx context.Context, in *IssueReq, opts ...grpc.CallOption) (*Token, error) + Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*UserIdentity, error) + AddPolicy(ctx context.Context, in *AddPolicyReq, opts ...grpc.CallOption) (*AddPolicyRes, error) + DeletePolicy(ctx context.Context, in *DeletePolicyReq, opts ...grpc.CallOption) (*DeletePolicyRes, error) + ListPolicies(ctx context.Context, in *ListPoliciesReq, opts ...grpc.CallOption) (*ListPoliciesRes, error) +} + +type authServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient { + return &authServiceClient{cc} +} + +func (c *authServiceClient) Authorize(ctx context.Context, in *AuthorizeReq, opts ...grpc.CallOption) (*AuthorizeRes, error) { + out := new(AuthorizeRes) + err := c.cc.Invoke(ctx, "/policies.AuthService/Authorize", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) Issue(ctx context.Context, in *IssueReq, opts ...grpc.CallOption) (*Token, error) { + out := new(Token) + err := c.cc.Invoke(ctx, "/policies.AuthService/Issue", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*UserIdentity, error) { + out := new(UserIdentity) + err := c.cc.Invoke(ctx, "/policies.AuthService/Identify", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) AddPolicy(ctx context.Context, in *AddPolicyReq, opts ...grpc.CallOption) (*AddPolicyRes, error) { + out := new(AddPolicyRes) + err := c.cc.Invoke(ctx, "/policies.AuthService/AddPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) DeletePolicy(ctx context.Context, in *DeletePolicyReq, opts ...grpc.CallOption) (*DeletePolicyRes, error) { + out := new(DeletePolicyRes) + err := c.cc.Invoke(ctx, "/policies.AuthService/DeletePolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) ListPolicies(ctx context.Context, in *ListPoliciesReq, opts ...grpc.CallOption) (*ListPoliciesRes, error) { + out := new(ListPoliciesRes) + err := c.cc.Invoke(ctx, "/policies.AuthService/ListPolicies", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AuthServiceServer is the server API for AuthService service. +// All implementations must embed UnimplementedAuthServiceServer +// for forward compatibility +type AuthServiceServer interface { + Authorize(context.Context, *AuthorizeReq) (*AuthorizeRes, error) + Issue(context.Context, *IssueReq) (*Token, error) + Identify(context.Context, *Token) (*UserIdentity, error) + AddPolicy(context.Context, *AddPolicyReq) (*AddPolicyRes, error) + DeletePolicy(context.Context, *DeletePolicyReq) (*DeletePolicyRes, error) + ListPolicies(context.Context, *ListPoliciesReq) (*ListPoliciesRes, error) + mustEmbedUnimplementedAuthServiceServer() +} + +// UnimplementedAuthServiceServer must be embedded to have forward compatible implementations. +type UnimplementedAuthServiceServer struct { +} + +func (UnimplementedAuthServiceServer) Authorize(context.Context, *AuthorizeReq) (*AuthorizeRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method Authorize not implemented") +} +func (UnimplementedAuthServiceServer) Issue(context.Context, *IssueReq) (*Token, error) { + return nil, status.Errorf(codes.Unimplemented, "method Issue not implemented") +} +func (UnimplementedAuthServiceServer) Identify(context.Context, *Token) (*UserIdentity, error) { + return nil, status.Errorf(codes.Unimplemented, "method Identify not implemented") +} +func (UnimplementedAuthServiceServer) AddPolicy(context.Context, *AddPolicyReq) (*AddPolicyRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPolicy not implemented") +} +func (UnimplementedAuthServiceServer) DeletePolicy(context.Context, *DeletePolicyReq) (*DeletePolicyRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePolicy not implemented") +} +func (UnimplementedAuthServiceServer) ListPolicies(context.Context, *ListPoliciesReq) (*ListPoliciesRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPolicies not implemented") +} +func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {} + +// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AuthServiceServer will +// result in compilation errors. +type UnsafeAuthServiceServer interface { + mustEmbedUnimplementedAuthServiceServer() +} + +func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) { + s.RegisterService(&AuthService_ServiceDesc, srv) +} + +func _AuthService_Authorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AuthorizeReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).Authorize(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/Authorize", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).Authorize(ctx, req.(*AuthorizeReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_Issue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IssueReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).Issue(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/Issue", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).Issue(ctx, req.(*IssueReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_Identify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Token) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).Identify(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/Identify", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).Identify(ctx, req.(*Token)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_AddPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPolicyReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).AddPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/AddPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).AddPolicy(ctx, req.(*AddPolicyReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_DeletePolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePolicyReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).DeletePolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/DeletePolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).DeletePolicy(ctx, req.(*DeletePolicyReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_ListPolicies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListPoliciesReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).ListPolicies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/policies.AuthService/ListPolicies", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).ListPolicies(ctx, req.(*ListPoliciesReq)) + } + return interceptor(ctx, in, info, handler) +} + +// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AuthService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "policies.AuthService", + HandlerType: (*AuthServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Authorize", + Handler: _AuthService_Authorize_Handler, + }, + { + MethodName: "Issue", + Handler: _AuthService_Issue_Handler, + }, + { + MethodName: "Identify", + Handler: _AuthService_Identify_Handler, + }, + { + MethodName: "AddPolicy", + Handler: _AuthService_AddPolicy_Handler, + }, + { + MethodName: "DeletePolicy", + Handler: _AuthService_DeletePolicy_Handler, + }, + { + MethodName: "ListPolicies", + Handler: _AuthService_ListPolicies_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "users/policies/clientauth.proto", +} diff --git a/clients/policies/mocks/policies.go b/users/policies/mocks/policies.go similarity index 83% rename from clients/policies/mocks/policies.go rename to users/policies/mocks/policies.go index da001f4c4a9..52d59ab8d03 100644 --- a/clients/policies/mocks/policies.go +++ b/users/policies/mocks/policies.go @@ -3,7 +3,7 @@ package mocks import ( "context" - "github.com/mainflux/mainflux/clients/policies" + "github.com/mainflux/mainflux/users/policies" "github.com/stretchr/testify/mock" ) @@ -40,3 +40,9 @@ func (m *PolicyRepository) Evaluate(ctx context.Context, entityType string, p po return ret.Error(0) } + +func (m *PolicyRepository) CheckAdmin(ctx context.Context, id string) error { + ret := m.Called(ctx, id) + + return ret.Error(0) +} diff --git a/clients/policies/page.go b/users/policies/page.go similarity index 100% rename from clients/policies/page.go rename to users/policies/page.go diff --git a/clients/policies/policies.go b/users/policies/policies.go similarity index 97% rename from clients/policies/policies.go rename to users/policies/policies.go index cb6945fa82b..977f7c471cf 100644 --- a/clients/policies/policies.go +++ b/users/policies/policies.go @@ -33,6 +33,9 @@ type PolicyRepository interface { // error in case of failures. Save(ctx context.Context, p Policy) error + // CheckAdmin checks if the user is an admin user + CheckAdmin(ctx context.Context, id string) error + // Evaluate is used to evaluate if you have the correct permissions. // We evaluate if we are in the same group first then evaluate if the // object has that action over the subject diff --git a/clients/policies/postgres/doc.go b/users/policies/postgres/doc.go similarity index 100% rename from clients/policies/postgres/doc.go rename to users/policies/postgres/doc.go diff --git a/clients/policies/postgres/policies.go b/users/policies/postgres/policies.go similarity index 91% rename from clients/policies/postgres/policies.go rename to users/policies/postgres/policies.go index fe37c1ff1ba..cab72512845 100644 --- a/clients/policies/postgres/policies.go +++ b/users/policies/postgres/policies.go @@ -7,9 +7,10 @@ import ( "time" "github.com/jackc/pgtype" - "github.com/mainflux/mainflux/clients/policies" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/policies" + "github.com/mainflux/mainflux/users/postgres" ) var _ policies.PolicyRepository = (*policyRepository)(nil) @@ -49,6 +50,20 @@ func (pr policyRepository) Save(ctx context.Context, policy policies.Policy) err return nil } +func (pr policyRepository) CheckAdmin(ctx context.Context, id string) error { + q := fmt.Sprintf(`SELECT id FROM clients WHERE id = '%s' AND role = '%d';`, id, clients.AdminRole) + + var clientID string + if err := pr.db.QueryRowxContext(ctx, q).Scan(&clientID); err != nil { + return errors.Wrap(errors.ErrAuthorization, err) + } + if clientID == "" { + return errors.ErrAuthorization + } + + return nil +} + func (pr policyRepository) Evaluate(ctx context.Context, entityType string, policy policies.Policy) error { q := "" switch entityType { diff --git a/clients/policies/postgres/policies_test.go b/users/policies/postgres/policies_test.go similarity index 97% rename from clients/policies/postgres/policies_test.go rename to users/policies/postgres/policies_test.go index de3f25930bd..93a7430125e 100644 --- a/clients/policies/postgres/policies_test.go +++ b/users/policies/postgres/policies_test.go @@ -5,17 +5,17 @@ import ( "fmt" "testing" - "github.com/mainflux/mainflux/clients/clients" - cpostgres "github.com/mainflux/mainflux/clients/clients/postgres" - "github.com/mainflux/mainflux/clients/groups" - gpostgres "github.com/mainflux/mainflux/clients/groups/postgres" - "github.com/mainflux/mainflux/clients/policies" - ppostgres "github.com/mainflux/mainflux/clients/policies/postgres" - "github.com/mainflux/mainflux/clients/postgres" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + cpostgres "github.com/mainflux/mainflux/users/clients/postgres" + "github.com/mainflux/mainflux/users/groups" + gpostgres "github.com/mainflux/mainflux/users/groups/postgres" + "github.com/mainflux/mainflux/users/policies" + ppostgres "github.com/mainflux/mainflux/users/policies/postgres" + "github.com/mainflux/mainflux/users/postgres" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/clients/groups/postgres/setup_test.go b/users/policies/postgres/setup_test.go similarity index 89% rename from clients/groups/postgres/setup_test.go rename to users/policies/postgres/setup_test.go index 9cb273dbc56..e3a4f089711 100644 --- a/clients/groups/postgres/setup_test.go +++ b/users/policies/postgres/setup_test.go @@ -11,7 +11,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/mainflux/mainflux/clients/postgres" + pgClient "github.com/mainflux/mainflux/internal/clients/postgres" + "github.com/mainflux/mainflux/users/postgres" dockertest "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "go.opentelemetry.io/otel" @@ -61,7 +62,7 @@ func TestMain(m *testing.M) { log.Fatalf("Could not connect to docker: %s", err) } - dbConfig := postgres.Config{ + dbConfig := pgClient.Config{ Host: "localhost", Port: port, User: "test", @@ -73,9 +74,10 @@ func TestMain(m *testing.M) { SSLRootCert: "", } - if db, err = postgres.Connect(dbConfig); err != nil { + if db, err = pgClient.SetupDB(dbConfig, *postgres.Migration()); err != nil { log.Fatalf("Could not setup test DB connection: %s", err) } + database = postgres.NewDatabase(db, tracer) code := m.Run() diff --git a/clients/policies/service.go b/users/policies/service.go similarity index 96% rename from clients/policies/service.go rename to users/policies/service.go index 2380b07edf7..bba39bcdf76 100644 --- a/clients/policies/service.go +++ b/users/policies/service.go @@ -5,9 +5,9 @@ import ( "time" "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/clients/jwt" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/pkg/errors" + "github.com/mainflux/mainflux/users/jwt" ) // Possible token types are access and refresh tokens. @@ -43,7 +43,11 @@ func (svc service) Authorize(ctx context.Context, entityType string, p Policy) e if err != nil { return err } + if err = svc.policies.CheckAdmin(ctx, id); err == nil { + return nil + } p.Subject = id + return svc.policies.Evaluate(ctx, entityType, p) } func (svc service) UpdatePolicy(ctx context.Context, token string, p Policy) error { diff --git a/clients/policies/service_test.go b/users/policies/service_test.go similarity index 87% rename from clients/policies/service_test.go rename to users/policies/service_test.go index 098c1c8bdcc..70659570a82 100644 --- a/clients/policies/service_test.go +++ b/users/policies/service_test.go @@ -3,18 +3,20 @@ package policies_test import ( context "context" fmt "fmt" + "regexp" "testing" - "github.com/mainflux/mainflux/clients/clients" - cmocks "github.com/mainflux/mainflux/clients/clients/mocks" - "github.com/mainflux/mainflux/clients/hasher" - "github.com/mainflux/mainflux/clients/jwt" - "github.com/mainflux/mainflux/clients/policies" - pmocks "github.com/mainflux/mainflux/clients/policies/mocks" "github.com/mainflux/mainflux/internal/apiutil" "github.com/mainflux/mainflux/internal/testsutil" "github.com/mainflux/mainflux/pkg/errors" "github.com/mainflux/mainflux/pkg/uuid" + "github.com/mainflux/mainflux/users/clients" + "github.com/mainflux/mainflux/users/clients/mocks" + cmocks "github.com/mainflux/mainflux/users/clients/mocks" + "github.com/mainflux/mainflux/users/hasher" + "github.com/mainflux/mainflux/users/jwt" + "github.com/mainflux/mainflux/users/policies" + pmocks "github.com/mainflux/mainflux/users/policies/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -27,6 +29,7 @@ var ( inValidToken = "invalidToken" memberActions = []string{"g_list"} authoritiesObj = "authorities" + passRegex = regexp.MustCompile("^.{8,}$") ) func generateValidToken(t *testing.T, clientID string, svc clients.Service, cRepo *cmocks.ClientRepository) string { @@ -53,7 +56,8 @@ func TestAddPolicy(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := policies.NewService(pRepo, tokenizer, idProvider) policy := policies.Policy{Object: "obj1", Actions: []string{"m_read"}, Subject: "sub1"} @@ -146,10 +150,11 @@ func TestAddPolicy(t *testing.T) { } for _, tc := range cases { - repo1Call := pRepo.On("Evaluate", context.Background(), "client", mock.Anything).Return(nil) - repoCall := pRepo.On("Update", context.Background(), tc.policy).Return(tc.err) - repoCall1 := pRepo.On("Save", context.Background(), mock.Anything).Return(tc.err) - repoCall2 := pRepo.On("Retrieve", context.Background(), mock.Anything).Return(tc.page, nil) + repoCall := pRepo.On("CheckAdmin", context.Background(), mock.Anything).Return(nil) + repoCall1 := pRepo.On("Evaluate", context.Background(), "client", mock.Anything).Return(nil) + repoCall2 := pRepo.On("Update", context.Background(), tc.policy).Return(tc.err) + repoCall3 := pRepo.On("Save", context.Background(), mock.Anything).Return(tc.err) + repoCall4 := pRepo.On("Retrieve", context.Background(), mock.Anything).Return(tc.page, nil) err := svc.AddPolicy(context.Background(), tc.token, tc.policy) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) if err == nil { @@ -161,7 +166,8 @@ func TestAddPolicy(t *testing.T) { repoCall.Unset() repoCall1.Unset() repoCall2.Unset() - repo1Call.Unset() + repoCall3.Unset() + repoCall4.Unset() } } @@ -170,7 +176,8 @@ func TestAuthorize(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := policies.NewService(pRepo, tokenizer, idProvider) cases := []struct { @@ -206,10 +213,12 @@ func TestAuthorize(t *testing.T) { } for _, tc := range cases { - repoCall := pRepo.On("Evaluate", context.Background(), tc.domain, mock.Anything).Return(tc.err) + repoCall := pRepo.On("CheckAdmin", context.Background(), mock.Anything).Return(tc.err) + repoCall1 := pRepo.On("Evaluate", context.Background(), tc.domain, mock.Anything).Return(tc.err) err := svc.Authorize(context.Background(), tc.domain, tc.policy) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) repoCall.Unset() + repoCall1.Unset() } } @@ -218,7 +227,8 @@ func TestDeletePolicy(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := policies.NewService(pRepo, tokenizer, idProvider) pr := policies.Policy{Object: authoritiesObj, Actions: memberActions, Subject: testsutil.GenerateUUID(t, idProvider)} @@ -235,7 +245,8 @@ func TestListPolicies(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := policies.NewService(pRepo, tokenizer, idProvider) id := testsutil.GenerateUUID(t, idProvider) @@ -327,7 +338,8 @@ func TestUpdatePolicies(t *testing.T) { cRepo := new(cmocks.ClientRepository) pRepo := new(pmocks.PolicyRepository) tokenizer := jwt.NewTokenRepo([]byte(secret)) - csvc := clients.NewService(cRepo, pRepo, tokenizer, phasher, idProvider) + e := mocks.NewEmailer() + csvc := clients.NewService(cRepo, pRepo, tokenizer, e, phasher, idProvider, passRegex) svc := policies.NewService(pRepo, tokenizer, idProvider) policy := policies.Policy{Object: "obj1", Actions: []string{"m_read"}, Subject: "sub1"} diff --git a/clients/policies/status.go b/users/policies/status.go similarity index 100% rename from clients/policies/status.go rename to users/policies/status.go diff --git a/clients/policies/tracing/tracing.go b/users/policies/tracing/tracing.go similarity index 97% rename from clients/policies/tracing/tracing.go rename to users/policies/tracing/tracing.go index 78f4614602e..82b65304204 100644 --- a/clients/policies/tracing/tracing.go +++ b/users/policies/tracing/tracing.go @@ -3,7 +3,7 @@ package tracing import ( "context" - "github.com/mainflux/mainflux/clients/policies" + "github.com/mainflux/mainflux/users/policies" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/clients/postgres/common.go b/users/postgres/common.go similarity index 100% rename from clients/postgres/common.go rename to users/postgres/common.go diff --git a/users/postgres/database.go b/users/postgres/database.go deleted file mode 100644 index 946cb8d9ba4..00000000000 --- a/users/postgres/database.go +++ /dev/null @@ -1,60 +0,0 @@ -package postgres - -import ( - "context" - "database/sql" - - "github.com/jmoiron/sqlx" - "github.com/opentracing/opentracing-go" -) - -var _ Database = (*database)(nil) - -type database struct { - db *sqlx.DB -} - -// Database provides a database interface -type Database interface { - NamedExecContext(context.Context, string, interface{}) (sql.Result, error) - QueryRowxContext(context.Context, string, ...interface{}) *sqlx.Row - NamedQueryContext(context.Context, string, interface{}) (*sqlx.Rows, error) - GetContext(context.Context, interface{}, string, ...interface{}) error -} - -// NewDatabase creates a ThingDatabase instance -func NewDatabase(db *sqlx.DB) Database { - return &database{ - db: db, - } -} - -func (dm database) NamedExecContext(ctx context.Context, query string, args interface{}) (sql.Result, error) { - addSpanTags(ctx, query) - return dm.db.NamedExecContext(ctx, query, args) -} - -func (dm database) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row { - addSpanTags(ctx, query) - return dm.db.QueryRowxContext(ctx, query, args...) -} - -func (dm database) NamedQueryContext(ctx context.Context, query string, args interface{}) (*sqlx.Rows, error) { - addSpanTags(ctx, query) - return dm.db.NamedQueryContext(ctx, query, args) -} - -func (dm database) GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error { - addSpanTags(ctx, query) - return dm.db.GetContext(ctx, dest, query, args...) -} - -func addSpanTags(ctx context.Context, query string) { - span := opentracing.SpanFromContext(ctx) - if span != nil { - span.SetTag("sql.statement", query) - span.SetTag("span.kind", "client") - span.SetTag("peer.service", "postgres") - span.SetTag("db.type", "sql") - } -} diff --git a/users/postgres/doc.go b/users/postgres/doc.go deleted file mode 100644 index 522b9a7acf7..00000000000 --- a/users/postgres/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package postgres contains repository implementations using PostgreSQL as -// the underlying database. -package postgres diff --git a/clients/postgres/errors.go b/users/postgres/errors.go similarity index 100% rename from clients/postgres/errors.go rename to users/postgres/errors.go diff --git a/users/postgres/init.go b/users/postgres/init.go index 5bb917e4218..6e119f72f50 100644 --- a/users/postgres/init.go +++ b/users/postgres/init.go @@ -1,57 +1,58 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - package postgres -import migrate "github.com/rubenv/sql-migrate" +import ( + _ "github.com/jackc/pgx/v5/stdlib" // required for SQL access + migrate "github.com/rubenv/sql-migrate" +) // Migration of Users service func Migration() *migrate.MemoryMigrationSource { return &migrate.MemoryMigrationSource{ Migrations: []*migrate.Migration{ { - Id: "users_1", + Id: "clients_01", Up: []string{ - `CREATE TABLE IF NOT EXISTS users ( - email VARCHAR(254) PRIMARY KEY, - password CHAR(60) NOT NULL + `CREATE TABLE IF NOT EXISTS clients ( + id VARCHAR(254) PRIMARY KEY, + name VARCHAR(254), + owner VARCHAR(254), + identity VARCHAR(254) UNIQUE NOT NULL, + secret TEXT NOT NULL, + tags TEXT[], + metadata JSONB, + created_at TIMESTAMP, + updated_at TIMESTAMP, + status SMALLINT NOT NULL CHECK (status >= 0) DEFAULT 1, + role SMALLINT CHECK (status >= 0) DEFAULT 0 + )`, + `CREATE TABLE IF NOT EXISTS groups ( + id VARCHAR(254) PRIMARY KEY, + parent_id VARCHAR(254), + owner_id VARCHAR(254) NOT NULL, + name VARCHAR(254) NOT NULL, + description VARCHAR(1024), + metadata JSONB, + created_at TIMESTAMP, + updated_at TIMESTAMP, + status SMALLINT NOT NULL CHECK (status >= 0) DEFAULT 1, + UNIQUE (owner_id, name), + FOREIGN KEY (parent_id) REFERENCES groups (id) ON DELETE CASCADE + )`, + `CREATE TABLE IF NOT EXISTS policies ( + owner_id VARCHAR(254) NOT NULL, + subject VARCHAR(254) NOT NULL, + object VARCHAR(254) NOT NULL, + actions TEXT[] NOT NULL, + created_at TIMESTAMP, + updated_at TIMESTAMP, + FOREIGN KEY (subject) REFERENCES clients (id), + PRIMARY KEY (subject, object, actions) )`, }, - Down: []string{"DROP TABLE users"}, - }, - { - Id: "users_2", - Up: []string{ - `ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS metadata JSONB`, - }, - }, - { - Id: "users_3", - Up: []string{ - `CREATE EXTENSION IF NOT EXISTS "pgcrypto"; - ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS - id UUID NOT NULL DEFAULT gen_random_uuid()`, - }, - }, - { - Id: "users_4", - Up: []string{ - `ALTER TABLE IF EXISTS users DROP CONSTRAINT users_pkey`, - `ALTER TABLE IF EXISTS users ADD CONSTRAINT users_email_key UNIQUE (email)`, - `ALTER TABLE IF EXISTS users ADD PRIMARY KEY (id)`, - }, - }, - { - Id: "users_5", - Up: []string{ - `DO $$ - BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_status') THEN - CREATE TYPE user_status AS ENUM ('enabled', 'disabled'); - END IF; - END$$;`, - `ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS - status USER_STATUS NOT NULL DEFAULT 'enabled'`, + Down: []string{ + `DROP TABLE IF EXISTS clients`, + `DROP TABLE IF EXISTS groups`, + `DROP TABLE IF EXISTS memberships`, }, }, }, diff --git a/users/postgres/setup_test.go b/users/postgres/setup_test.go deleted file mode 100644 index 1b366a8e742..00000000000 --- a/users/postgres/setup_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package postgres_test contains tests for PostgreSQL repository -// implementations. -package postgres_test - -import ( - "database/sql" - "fmt" - "log" - "os" - "testing" - - "github.com/jmoiron/sqlx" - - pgClient "github.com/mainflux/mainflux/internal/clients/postgres" - "github.com/mainflux/mainflux/users/postgres" - dockertest "github.com/ory/dockertest/v3" -) - -var db *sqlx.DB - -func TestMain(m *testing.M) { - pool, err := dockertest.NewPool("") - if err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - cfg := []string{ - "POSTGRES_USER=test", - "POSTGRES_PASSWORD=test", - "POSTGRES_DB=test", - } - container, err := pool.Run("postgres", "13.3-alpine", cfg) - if err != nil { - log.Fatalf("Could not start container: %s", err) - } - - port := container.GetPort("5432/tcp") - - if err := pool.Retry(func() error { - url := fmt.Sprintf("host=localhost port=%s user=test dbname=test password=test sslmode=disable", port) - db, err := sql.Open("pgx", url) - if err != nil { - return err - } - return db.Ping() - }); err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - dbConfig := pgClient.Config{ - Host: "localhost", - Port: port, - User: "test", - Pass: "test", - Name: "test", - SSLMode: "disable", - SSLCert: "", - SSLKey: "", - SSLRootCert: "", - } - - if db, err = pgClient.SetupDB(dbConfig, *postgres.Migration()); err != nil { - log.Fatalf("Could not setup test DB connection: %s", err) - } - - code := m.Run() - - // Defers will not be run when using os.Exit - db.Close() - if err := pool.Purge(container); err != nil { - log.Fatalf("Could not purge container: %s", err) - } - - os.Exit(code) -} diff --git a/clients/postgres/tracing.go b/users/postgres/tracing.go similarity index 100% rename from clients/postgres/tracing.go rename to users/postgres/tracing.go diff --git a/users/postgres/users.go b/users/postgres/users.go deleted file mode 100644 index 094405444ce..00000000000 --- a/users/postgres/users.go +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import ( - "context" - "database/sql" - "encoding/json" - "fmt" - "strings" - - "github.com/jackc/pgerrcode" - "github.com/jackc/pgx/v5/pgconn" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" -) - -var _ users.UserRepository = (*userRepository)(nil) - -type userRepository struct { - db Database -} - -// NewUserRepo instantiates a PostgreSQL implementation of user -// repository. -func NewUserRepo(db Database) users.UserRepository { - return &userRepository{ - db: db, - } -} - -func (ur userRepository) Save(ctx context.Context, user users.User) (string, error) { - q := `INSERT INTO users (email, password, id, metadata, status) VALUES (:email, :password, :id, :metadata, :status) RETURNING id` - if user.ID == "" || user.Email == "" { - return "", errors.ErrMalformedEntity - } - - dbu, err := toDBUser(user) - if err != nil { - return "", errors.Wrap(errors.ErrCreateEntity, err) - } - - row, err := ur.db.NamedQueryContext(ctx, q, dbu) - - if err != nil { - pgErr, ok := err.(*pgconn.PgError) - if ok { - switch pgErr.Code { - case pgerrcode.InvalidTextRepresentation: - return "", errors.Wrap(errors.ErrMalformedEntity, err) - case pgerrcode.UniqueViolation: - return "", errors.Wrap(errors.ErrConflict, err) - } - } - return "", errors.Wrap(errors.ErrCreateEntity, err) - } - - defer row.Close() - row.Next() - var id string - if err := row.Scan(&id); err != nil { - return "", err - } - return id, nil -} - -func (ur userRepository) Update(ctx context.Context, user users.User) error { - q := `UPDATE users SET(email, password, metadata, status) VALUES (:email, :password, :metadata, :status) WHERE email = :email;` - - dbu, err := toDBUser(user) - if err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - if _, err := ur.db.NamedExecContext(ctx, q, dbu); err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - return nil -} - -func (ur userRepository) UpdateUser(ctx context.Context, user users.User) error { - q := `UPDATE users SET metadata = :metadata WHERE email = :email AND status = 'enabled'` - - dbu, err := toDBUser(user) - if err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - if _, err := ur.db.NamedExecContext(ctx, q, dbu); err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - return nil -} - -func (ur userRepository) RetrieveByEmail(ctx context.Context, email string) (users.User, error) { - q := `SELECT id, password, metadata FROM users WHERE email = $1 AND status = 'enabled'` - - dbu := dbUser{ - Email: email, - } - - if err := ur.db.QueryRowxContext(ctx, q, email).StructScan(&dbu); err != nil { - if err == sql.ErrNoRows { - return users.User{}, errors.Wrap(errors.ErrNotFound, err) - - } - return users.User{}, errors.Wrap(errors.ErrViewEntity, err) - } - - return toUser(dbu) -} - -func (ur userRepository) RetrieveByID(ctx context.Context, id string) (users.User, error) { - q := `SELECT email, password, metadata FROM users WHERE id = $1` - - dbu := dbUser{ - ID: id, - } - - if err := ur.db.QueryRowxContext(ctx, q, id).StructScan(&dbu); err != nil { - if err == sql.ErrNoRows { - return users.User{}, errors.Wrap(errors.ErrNotFound, err) - - } - return users.User{}, errors.Wrap(errors.ErrViewEntity, err) - } - - return toUser(dbu) -} - -func (ur userRepository) RetrieveAll(ctx context.Context, userIDs []string, pm users.PageMetadata) (users.UserPage, error) { - eq, ep, err := createEmailQuery("", pm.Email) - if err != nil { - return users.UserPage{}, errors.Wrap(errors.ErrViewEntity, err) - } - - mq, mp, err := createMetadataQuery("", pm.Metadata) - if err != nil { - return users.UserPage{}, errors.Wrap(errors.ErrViewEntity, err) - } - aq := fmt.Sprintf("status = '%s'", pm.Status) - if pm.Status == users.AllStatusKey { - aq = "" - } - - var query []string - var emq string - if eq != "" { - query = append(query, eq) - } - if mq != "" { - query = append(query, mq) - } - if aq != "" { - query = append(query, aq) - } - - if len(userIDs) > 0 { - query = append(query, fmt.Sprintf("id IN ('%s')", strings.Join(userIDs, "','"))) - } - if len(query) > 0 { - emq = fmt.Sprintf(" WHERE %s", strings.Join(query, " AND ")) - } - - q := fmt.Sprintf(`SELECT id, email, metadata FROM users %s ORDER BY email LIMIT :limit OFFSET :offset;`, emq) - params := map[string]interface{}{ - "limit": pm.Limit, - "offset": pm.Offset, - "email": ep, - "metadata": mp, - } - - rows, err := ur.db.NamedQueryContext(ctx, q, params) - if err != nil { - return users.UserPage{}, errors.Wrap(errors.ErrViewEntity, err) - } - defer rows.Close() - - var items []users.User - for rows.Next() { - dbusr := dbUser{} - if err := rows.StructScan(&dbusr); err != nil { - return users.UserPage{}, errors.Wrap(errors.ErrViewEntity, err) - } - - user, err := toUser(dbusr) - if err != nil { - return users.UserPage{}, err - } - - items = append(items, user) - } - - cq := fmt.Sprintf(`SELECT COUNT(*) FROM users %s;`, emq) - - total, err := total(ctx, ur.db, cq, params) - if err != nil { - return users.UserPage{}, errors.Wrap(errors.ErrViewEntity, err) - } - - page := users.UserPage{ - Users: items, - PageMetadata: users.PageMetadata{ - Total: total, - Offset: pm.Offset, - Limit: pm.Limit, - }, - } - - return page, nil -} - -func (ur userRepository) UpdatePassword(ctx context.Context, email, password string) error { - q := `UPDATE users SET password = :password WHERE status = 'enabled' AND email = :email` - - db := dbUser{ - Email: email, - Password: password, - } - - if _, err := ur.db.NamedExecContext(ctx, q, db); err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - return nil -} - -func (ur userRepository) ChangeStatus(ctx context.Context, id, status string) error { - q := fmt.Sprintf(`UPDATE users SET status = '%s' WHERE id = :id`, status) - - dbu := dbUser{ - ID: id, - } - - if _, err := ur.db.NamedExecContext(ctx, q, dbu); err != nil { - return errors.Wrap(errors.ErrUpdateEntity, err) - } - - return nil -} - -type dbUser struct { - ID string `db:"id"` - Email string `db:"email"` - Password string `db:"password"` - Metadata []byte `db:"metadata"` - Groups []auth.Group `db:"groups"` - Status string `db:"status"` -} - -func toDBUser(u users.User) (dbUser, error) { - data := []byte("{}") - if len(u.Metadata) > 0 { - b, err := json.Marshal(u.Metadata) - if err != nil { - return dbUser{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - data = b - } - - return dbUser{ - ID: u.ID, - Email: u.Email, - Password: u.Password, - Metadata: data, - Status: u.Status, - }, nil -} - -func total(ctx context.Context, db Database, query string, params interface{}) (uint64, error) { - rows, err := db.NamedQueryContext(ctx, query, params) - if err != nil { - return 0, err - } - defer rows.Close() - total := uint64(0) - if rows.Next() { - if err := rows.Scan(&total); err != nil { - return 0, err - } - } - return total, nil -} - -func toUser(dbu dbUser) (users.User, error) { - var metadata map[string]interface{} - if dbu.Metadata != nil { - if err := json.Unmarshal([]byte(dbu.Metadata), &metadata); err != nil { - return users.User{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - } - - return users.User{ - ID: dbu.ID, - Email: dbu.Email, - Password: dbu.Password, - Metadata: metadata, - Status: dbu.Status, - }, nil -} - -func createEmailQuery(entity string, email string) (string, string, error) { - if email == "" { - return "", "", nil - } - - // Create LIKE operator to search Users with email containing a given string - param := fmt.Sprintf(`%%%s%%`, email) - query := fmt.Sprintf("%semail LIKE :email", entity) - - return query, param, nil -} - -func createMetadataQuery(entity string, um users.Metadata) (string, []byte, error) { - if len(um) == 0 { - return "", nil, nil - } - - param, err := json.Marshal(um) - if err != nil { - return "", nil, err - } - query := fmt.Sprintf("%smetadata @> :metadata", entity) - - return query, param, nil -} diff --git a/users/postgres/users_test.go b/users/postgres/users_test.go deleted file mode 100644 index 65e6e1179f9..00000000000 --- a/users/postgres/users_test.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package postgres_test - -import ( - "context" - "fmt" - "testing" - - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - "github.com/mainflux/mainflux/users/postgres" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var idProvider = uuid.New() - -func TestUserSave(t *testing.T) { - email := "user-save@example.com" - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := []struct { - desc string - user users.User - err error - }{ - { - desc: "new user", - user: users.User{ - ID: uid, - Email: email, - Password: "pass", - Status: users.EnabledStatusKey, - }, - err: nil, - }, - { - desc: "duplicate user", - user: users.User{ - ID: uid, - Email: email, - Password: "pass", - Status: users.EnabledStatusKey, - }, - err: errors.ErrConflict, - }, - { - desc: "invalid user status", - user: users.User{ - ID: uid, - Email: email, - Password: "pass", - Status: "invalid", - }, - err: errors.ErrMalformedEntity, - }, - } - - dbMiddleware := postgres.NewDatabase(db) - repo := postgres.NewUserRepo(dbMiddleware) - - for _, tc := range cases { - _, err := repo.Save(context.Background(), tc.user) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestSingleUserRetrieval(t *testing.T) { - dbMiddleware := postgres.NewDatabase(db) - repo := postgres.NewUserRepo(dbMiddleware) - - email := "user-retrieval@example.com" - - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - user := users.User{ - ID: uid, - Email: email, - Password: "pass", - Status: users.EnabledStatusKey, - } - - _, err = repo.Save(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := map[string]struct { - email string - err error - }{ - "existing user": {email, nil}, - "non-existing user": {"unknown@example.com", errors.ErrNotFound}, - } - - for desc, tc := range cases { - _, err := repo.RetrieveByEmail(context.Background(), tc.email) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestRetrieveAll(t *testing.T) { - dbMiddleware := postgres.NewDatabase(db) - userRepo := postgres.NewUserRepo(dbMiddleware) - metaNum := uint64(2) - var nUsers = uint64(10) - - meta := users.Metadata{ - "admin": "true", - } - - wrongMeta := users.Metadata{ - "wrong": "true", - } - - var ids []string - for i := uint64(0); i < nUsers; i++ { - uid, err := idProvider.ID() - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - email := fmt.Sprintf("TestRetrieveAll%d@example.com", i) - user := users.User{ - ID: uid, - Email: email, - Password: "pass", - Status: users.EnabledStatusKey, - } - if i < metaNum { - user.Metadata = meta - } - ids = append(ids, uid) - _, err = userRepo.Save(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - } - - cases := map[string]struct { - email string - offset uint64 - limit uint64 - size uint64 - total uint64 - ids []string - metadata users.Metadata - }{ - "retrieve all users filtered by email": { - email: "All", - offset: 0, - limit: nUsers, - size: nUsers, - total: nUsers, - ids: ids, - }, - "retrieve all users by email with limit and offset": { - email: "All", - offset: 2, - limit: 5, - size: 5, - total: nUsers, - ids: ids, - }, - "retrieve all users by metadata": { - email: "All", - offset: 0, - limit: nUsers, - size: metaNum, - total: nUsers, - metadata: meta, - ids: ids, - }, - "retrieve users by metadata and ids": { - email: "All", - offset: 0, - limit: nUsers, - size: 1, - total: nUsers, - metadata: meta, - ids: []string{ids[0]}, - }, - "retrieve users by wrong metadata": { - email: "All", - offset: 0, - limit: nUsers, - size: 0, - total: nUsers, - metadata: wrongMeta, - ids: ids, - }, - "retrieve users by wrong metadata and ids": { - email: "All", - offset: 0, - limit: nUsers, - size: 0, - total: nUsers, - metadata: wrongMeta, - ids: []string{ids[0]}, - }, - "retrieve all users by list of ids with limit and offset": { - email: "All", - offset: 2, - limit: 5, - size: 5, - total: nUsers, - ids: ids, - }, - "retrieve all users by list of ids with limit and offset and metadata": { - email: "All", - offset: 1, - limit: 5, - size: 1, - total: nUsers, - ids: ids[0:5], - metadata: meta, - }, - "retrieve all users from empty ids": { - email: "All", - offset: 0, - limit: nUsers, - size: nUsers, - total: nUsers, - ids: []string{}, - }, - "retrieve all users from empty ids with offset": { - email: "All", - offset: 1, - limit: 5, - size: 5, - total: nUsers, - ids: []string{}, - }, - } - for desc, tc := range cases { - pm := users.PageMetadata{ - Offset: tc.offset, - Limit: tc.limit, - Email: tc.email, - Metadata: tc.metadata, - Status: users.EnabledStatusKey, - } - page, err := userRepo.RetrieveAll(context.Background(), tc.ids, pm) - size := uint64(len(page.Users)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.size, size)) - assert.Nil(t, err, fmt.Sprintf("%s: expected no error got %d\n", desc, err)) - } -} diff --git a/users/service.go b/users/service.go deleted file mode 100644 index 29a51eff0d3..00000000000 --- a/users/service.go +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package users - -import ( - "context" - "regexp" - - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/auth" - "github.com/mainflux/mainflux/internal/apiutil" - "github.com/mainflux/mainflux/pkg/errors" -) - -const ( - memberRelationKey = "member" - authoritiesObjKey = "authorities" - usersObjKey = "users" - EnabledStatusKey = "enabled" - DisabledStatusKey = "disabled" - AllStatusKey = "all" -) - -var ( - // ErrMissingResetToken indicates malformed or missing reset token - // for reseting password. - ErrMissingResetToken = errors.New("missing reset token") - - // ErrRecoveryToken indicates error in generating password recovery token. - ErrRecoveryToken = errors.New("failed to generate password recovery token") - - // ErrGetToken indicates error in getting signed token. - ErrGetToken = errors.New("failed to fetch signed token") - - // ErrPasswordFormat indicates weak password. - ErrPasswordFormat = errors.New("password does not meet the requirements") - - // ErrAlreadyEnabledUser indicates the user is already enabled. - ErrAlreadyEnabledUser = errors.New("the user is already enabled") - - // ErrAlreadyDisabledUser indicates the user is already disabled. - ErrAlreadyDisabledUser = errors.New("the user is already disabled") -) - -// Service specifies an API that must be fullfiled by the domain service -// implementation, and all of its decorators (e.g. logging & metrics). -type Service interface { - // Register creates new user account. In case of the failed registration, a - // non-nil error value is returned. The user registration is only allowed - // for admin. - Register(ctx context.Context, token string, user User) (string, error) - - // Login authenticates the user given its credentials. Successful - // authentication generates new access token. Failed invocations are - // identified by the non-nil error values in the response. - Login(ctx context.Context, user User) (string, error) - - // ViewUser retrieves user info for a given user ID and an authorized token. - ViewUser(ctx context.Context, token, id string) (User, error) - - // ViewProfile retrieves user info for a given token. - ViewProfile(ctx context.Context, token string) (User, error) - - // ListUsers retrieves users list for a valid admin token. - ListUsers(ctx context.Context, token string, pm PageMetadata) (UserPage, error) - - // UpdateUser updates the user metadata. - UpdateUser(ctx context.Context, token string, user User) error - - // GenerateResetToken email where mail will be sent. - // host is used for generating reset link. - GenerateResetToken(ctx context.Context, email, host string) error - - // ChangePassword change users password for authenticated user. - ChangePassword(ctx context.Context, authToken, password, oldPassword string) error - - // ResetPassword change users password in reset flow. - // token can be authentication token or password reset token. - ResetPassword(ctx context.Context, resetToken, password string) error - - // SendPasswordReset sends reset password link to email. - SendPasswordReset(ctx context.Context, host, email, token string) error - - // ListMembers retrieves everything that is assigned to a group identified by groupID. - ListMembers(ctx context.Context, token, groupID string, pm PageMetadata) (UserPage, error) - - // EnableUser logically enableds the user identified with the provided ID - EnableUser(ctx context.Context, token, id string) error - - // DisableUser logically disables the user identified with the provided ID - DisableUser(ctx context.Context, token, id string) error -} - -// PageMetadata contains page metadata that helps navigation. -type PageMetadata struct { - Total uint64 - Offset uint64 - Limit uint64 - Email string - Status string - Metadata Metadata -} - -// GroupPage contains a page of groups. -type GroupPage struct { - PageMetadata - Groups []auth.Group -} - -// UserPage contains a page of users. -type UserPage struct { - PageMetadata - Users []User -} - -var _ Service = (*usersService)(nil) - -type usersService struct { - users UserRepository - hasher Hasher - email Emailer - auth mainflux.AuthServiceClient - idProvider mainflux.IDProvider - passRegex *regexp.Regexp -} - -// New instantiates the users service implementation -func New(users UserRepository, hasher Hasher, auth mainflux.AuthServiceClient, e Emailer, idp mainflux.IDProvider, passRegex *regexp.Regexp) Service { - return &usersService{ - users: users, - hasher: hasher, - auth: auth, - email: e, - idProvider: idp, - passRegex: passRegex, - } -} - -func (svc usersService) Register(ctx context.Context, token string, user User) (string, error) { - if err := svc.checkAuthz(ctx, token); err != nil { - return "", err - } - - if err := user.Validate(); err != nil { - return "", err - } - if !svc.passRegex.MatchString(user.Password) { - return "", ErrPasswordFormat - } - - uid, err := svc.idProvider.ID() - if err != nil { - return "", err - } - user.ID = uid - - if err := svc.claimOwnership(ctx, user.ID, usersObjKey, memberRelationKey); err != nil { - return "", err - } - - hash, err := svc.hasher.Hash(user.Password) - if err != nil { - return "", errors.Wrap(errors.ErrMalformedEntity, err) - } - user.Password = hash - if user.Status == "" { - user.Status = EnabledStatusKey - } - - if user.Status != AllStatusKey && - user.Status != EnabledStatusKey && - user.Status != DisabledStatusKey { - return "", apiutil.ErrInvalidStatus - } - - uid, err = svc.users.Save(ctx, user) - if err != nil { - return "", err - } - return uid, nil -} - -func (svc usersService) checkAuthz(ctx context.Context, token string) error { - if err := svc.authorize(ctx, "*", "user", "create"); err == nil { - return nil - } - if token == "" { - return errors.ErrAuthentication - } - - ir, err := svc.identify(ctx, token) - if err != nil { - return err - } - - return svc.authorize(ctx, ir.id, authoritiesObjKey, memberRelationKey) -} - -func (svc usersService) Login(ctx context.Context, user User) (string, error) { - dbUser, err := svc.users.RetrieveByEmail(ctx, user.Email) - if err != nil { - return "", errors.Wrap(errors.ErrAuthentication, err) - } - if err := svc.hasher.Compare(user.Password, dbUser.Password); err != nil { - return "", errors.Wrap(errors.ErrAuthentication, err) - } - return svc.issue(ctx, dbUser.ID, dbUser.Email, auth.LoginKey) -} - -func (svc usersService) ViewUser(ctx context.Context, token, id string) (User, error) { - if _, err := svc.identify(ctx, token); err != nil { - return User{}, err - } - - dbUser, err := svc.users.RetrieveByID(ctx, id) - if err != nil { - return User{}, errors.Wrap(errors.ErrNotFound, err) - } - - return User{ - ID: id, - Email: dbUser.Email, - Password: "", - Metadata: dbUser.Metadata, - Status: dbUser.Status, - }, nil -} - -func (svc usersService) ViewProfile(ctx context.Context, token string) (User, error) { - ir, err := svc.identify(ctx, token) - if err != nil { - return User{}, err - } - - dbUser, err := svc.users.RetrieveByEmail(ctx, ir.email) - if err != nil { - return User{}, errors.Wrap(errors.ErrAuthentication, err) - } - - return User{ - ID: dbUser.ID, - Email: ir.email, - Metadata: dbUser.Metadata, - }, nil -} - -func (svc usersService) ListUsers(ctx context.Context, token string, pm PageMetadata) (UserPage, error) { - id, err := svc.identify(ctx, token) - if err != nil { - return UserPage{}, err - } - - if err := svc.authorize(ctx, id.id, "authorities", "member"); err != nil { - return UserPage{}, err - } - return svc.users.RetrieveAll(ctx, nil, pm) -} - -func (svc usersService) UpdateUser(ctx context.Context, token string, u User) error { - ir, err := svc.identify(ctx, token) - if err != nil { - return err - } - user := User{ - Email: ir.email, - Metadata: u.Metadata, - } - return svc.users.UpdateUser(ctx, user) -} - -func (svc usersService) GenerateResetToken(ctx context.Context, email, host string) error { - user, err := svc.users.RetrieveByEmail(ctx, email) - if err != nil || user.Email == "" { - return errors.ErrNotFound - } - t, err := svc.issue(ctx, user.ID, user.Email, auth.RecoveryKey) - if err != nil { - return errors.Wrap(ErrRecoveryToken, err) - } - return svc.SendPasswordReset(ctx, host, email, t) -} - -func (svc usersService) ResetPassword(ctx context.Context, resetToken, password string) error { - ir, err := svc.identify(ctx, resetToken) - if err != nil { - return errors.Wrap(errors.ErrAuthentication, err) - } - u, err := svc.users.RetrieveByEmail(ctx, ir.email) - if err != nil { - return err - } - if u.Email == "" { - return errors.ErrNotFound - } - if !svc.passRegex.MatchString(password) { - return ErrPasswordFormat - } - password, err = svc.hasher.Hash(password) - if err != nil { - return err - } - return svc.users.UpdatePassword(ctx, ir.email, password) -} - -func (svc usersService) ChangePassword(ctx context.Context, authToken, password, oldPassword string) error { - ir, err := svc.identify(ctx, authToken) - if err != nil { - return errors.Wrap(errors.ErrAuthentication, err) - } - if !svc.passRegex.MatchString(password) { - return ErrPasswordFormat - } - u := User{ - Email: ir.email, - Password: oldPassword, - } - if _, err := svc.Login(ctx, u); err != nil { - return errors.ErrAuthentication - } - u, err = svc.users.RetrieveByEmail(ctx, ir.email) - if err != nil || u.Email == "" { - return errors.ErrNotFound - } - - password, err = svc.hasher.Hash(password) - if err != nil { - return err - } - return svc.users.UpdatePassword(ctx, ir.email, password) -} - -func (svc usersService) SendPasswordReset(_ context.Context, host, email, token string) error { - to := []string{email} - return svc.email.SendPasswordReset(to, host, token) -} - -func (svc usersService) ListMembers(ctx context.Context, token, groupID string, pm PageMetadata) (UserPage, error) { - if _, err := svc.identify(ctx, token); err != nil { - return UserPage{}, err - } - - userIDs, err := svc.members(ctx, token, groupID, pm.Offset, pm.Limit) - if err != nil { - return UserPage{}, err - } - - if len(userIDs) == 0 { - return UserPage{ - Users: []User{}, - PageMetadata: PageMetadata{ - Total: 0, - Offset: pm.Offset, - Limit: pm.Limit, - }, - }, nil - } - - return svc.users.RetrieveAll(ctx, userIDs, pm) -} - -func (svc usersService) EnableUser(ctx context.Context, token, id string) error { - if err := svc.changeStatus(ctx, token, id, EnabledStatusKey); err != nil { - return err - } - return nil -} - -func (svc usersService) DisableUser(ctx context.Context, token, id string) error { - if err := svc.changeStatus(ctx, token, id, DisabledStatusKey); err != nil { - return err - } - return nil -} - -func (svc usersService) changeStatus(ctx context.Context, token, id, status string) error { - if _, err := svc.identify(ctx, token); err != nil { - return err - } - - dbUser, err := svc.users.RetrieveByID(ctx, id) - if err != nil { - return errors.Wrap(errors.ErrNotFound, err) - } - if dbUser.Status == status { - if status == DisabledStatusKey { - return ErrAlreadyDisabledUser - } - return ErrAlreadyEnabledUser - } - - return svc.users.ChangeStatus(ctx, id, status) -} - -// Auth helpers -func (svc usersService) issue(ctx context.Context, id, email string, keyType uint32) (string, error) { - key, err := svc.auth.Issue(ctx, &mainflux.IssueReq{Id: id, Email: email, Type: keyType}) - if err != nil { - return "", errors.Wrap(errors.ErrNotFound, err) - } - return key.GetValue(), nil -} - -type userIdentity struct { - id string - email string -} - -func (svc usersService) identify(ctx context.Context, token string) (userIdentity, error) { - identity, err := svc.auth.Identify(ctx, &mainflux.Token{Value: token}) - if err != nil { - return userIdentity{}, errors.Wrap(errors.ErrAuthentication, err) - } - - return userIdentity{identity.Id, identity.Email}, nil -} - -func (svc usersService) authorize(ctx context.Context, subject, object, relation string) error { - req := &mainflux.AuthorizeReq{ - Sub: subject, - Obj: object, - Act: relation, - } - res, err := svc.auth.Authorize(ctx, req) - if err != nil { - return errors.Wrap(errors.ErrAuthorization, err) - } - if !res.GetAuthorized() { - return errors.ErrAuthorization - } - return nil -} - -func (svc usersService) claimOwnership(ctx context.Context, subject, object, relation string) error { - req := &mainflux.AddPolicyReq{ - Sub: subject, - Obj: object, - Act: relation, - } - res, err := svc.auth.AddPolicy(ctx, req) - if err != nil { - return errors.Wrap(errors.ErrAuthorization, err) - } - if !res.GetAuthorized() { - return errors.ErrAuthorization - } - return nil -} - -func (svc usersService) members(ctx context.Context, token, groupID string, limit, offset uint64) ([]string, error) { - req := mainflux.MembersReq{ - Token: token, - GroupID: groupID, - Offset: offset, - Limit: limit, - Type: "users", - } - - res, err := svc.auth.Members(ctx, &req) - if err != nil { - return nil, err - } - return res.Members, nil -} diff --git a/users/service_test.go b/users/service_test.go deleted file mode 100644 index 0e3670254b2..00000000000 --- a/users/service_test.go +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package users_test - -import ( - "context" - "fmt" - "regexp" - "testing" - - "github.com/mainflux/mainflux" - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/mainflux/mainflux/users" - - "github.com/mainflux/mainflux/users/mocks" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const wrong string = "wrong-value" - -var ( - user = users.User{Email: "user@example.com", Password: "password", Metadata: map[string]interface{}{"role": "user"}} - nonExistingUser = users.User{Email: "non-ex-user@example.com", Password: "password", Metadata: map[string]interface{}{"role": "user"}} - host = "example.com" - - idProvider = uuid.New() - passRegex = regexp.MustCompile("^.{8,}$") - - unauthzToken = "unauthorizedtoken" -) - -func newService() users.Service { - userRepo := mocks.NewUserRepository() - hasher := mocks.NewHasher() - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - mockAuthzDB[unauthzToken] = append(mockAuthzDB[unauthzToken], mocks.SubjectSet{Object: "nothing", Relation: "do"}) - mockUsers := map[string]string{user.Email: user.Email, unauthzToken: unauthzToken} - - authSvc := mocks.NewAuthService(mockUsers, mockAuthzDB) - e := mocks.NewEmailer() - - return users.New(userRepo, hasher, authSvc, e, idProvider, passRegex) -} - -func TestRegister(t *testing.T) { - svc := newService() - - cases := []struct { - desc string - user users.User - token string - err error - }{ - { - desc: "register new user", - user: user, - token: user.Email, - err: nil, - }, - { - desc: "register existing user", - user: user, - token: user.Email, - err: errors.ErrConflict, - }, - { - desc: "register new user with weak password", - user: users.User{ - Email: user.Email, - Password: "weak", - }, - token: user.Email, - err: users.ErrPasswordFormat, - }, - { - desc: "register a new user with unauthorized access", - user: users.User{Email: "newuser@example.com", Password: "12345678"}, - err: errors.ErrAuthorization, - token: unauthzToken, - }, - } - - for _, tc := range cases { - _, err := svc.Register(context.Background(), tc.token, tc.user) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestLogin(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - noAuthUser := users.User{ - Email: "email@test.com", - Password: "12345678", - } - - cases := map[string]struct { - user users.User - err error - }{ - "login with good credentials": { - user: user, - err: nil, - }, - "login with wrong e-mail": { - user: users.User{ - Email: wrong, - Password: user.Password, - }, - err: errors.ErrAuthentication, - }, - "login with wrong password": { - user: users.User{ - Email: user.Email, - Password: wrong, - }, - err: errors.ErrAuthentication, - }, - "login failed auth": { - user: noAuthUser, - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - _, err := svc.Login(context.Background(), tc.user) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestViewUser(t *testing.T) { - svc := newService() - id, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - token, err := svc.Login(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - u := user - u.Password = "" - - cases := map[string]struct { - user users.User - token string - userID string - err error - }{ - "view user with authorized token": { - user: u, - token: token, - userID: id, - err: nil, - }, - "view user with empty token": { - user: users.User{}, - token: "", - userID: id, - err: errors.ErrAuthentication, - }, - "view user with valid token and invalid user id": { - user: users.User{}, - token: token, - userID: "", - err: errors.ErrNotFound, - }, - } - - for desc, tc := range cases { - _, err := svc.ViewUser(context.Background(), tc.token, tc.userID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestViewProfile(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - token, err := svc.Login(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - u := user - u.Password = "" - - cases := map[string]struct { - user users.User - token string - err error - }{ - "valid token's user info": { - user: u, - token: token, - err: nil, - }, - "invalid token's user info": { - user: users.User{}, - token: "", - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - _, err := svc.ViewProfile(context.Background(), tc.token) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestListUsers(t *testing.T) { - svc := newService() - - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - token, err := svc.Login(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - var nUsers = uint64(10) - - for i := uint64(1); i < nUsers; i++ { - email := fmt.Sprintf("TestListUsers%d@example.com", i) - user := users.User{ - Email: email, - Password: "passpass", - } - _, err := svc.Register(context.Background(), token, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - } - - cases := map[string]struct { - token string - offset uint64 - limit uint64 - email string - size uint64 - err error - }{ - "list users with authorized token": { - token: token, - size: 0, - err: nil, - }, - "list users with unauthorized token": { - token: unauthzToken, - size: 0, - err: errors.ErrAuthorization, - }, - "list user with emtpy token": { - token: "", - size: 0, - err: errors.ErrAuthentication, - }, - "list users with offset and limit": { - token: token, - offset: 6, - limit: nUsers, - size: nUsers - 6, - }, - "list using non-existent user": { - token: token, - email: nonExistingUser.Email, - err: errors.ErrNotFound, - }, - } - - for desc, tc := range cases { - pm := users.PageMetadata{ - Offset: tc.offset, - Limit: tc.limit, - Email: tc.email, - Metadata: nil, - Status: "all", - } - page, err := svc.ListUsers(context.Background(), tc.token, pm) - size := uint64(len(page.Users)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.size, size)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestUpdateUser(t *testing.T) { - svc := newService() - - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - token, err := svc.Login(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - user.Metadata = map[string]interface{}{"role": "test"} - - cases := map[string]struct { - user users.User - token string - err error - }{ - "update user with valid token": { - user: user, - token: token, - err: nil, - }, - "update user with invalid token": { - user: user, - token: "non-existent", - err: errors.ErrAuthentication, - }, - } - - for desc, tc := range cases { - err := svc.UpdateUser(context.Background(), tc.token, tc.user) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestGenerateResetToken(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - cases := map[string]struct { - email string - err error - }{ - "valid user reset token": {user.Email, nil}, - "invalid user rest token": {nonExistingUser.Email, errors.ErrNotFound}, - } - - for desc, tc := range cases { - err := svc.GenerateResetToken(context.Background(), tc.email, host) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestChangePassword(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("register user error: %s", err)) - token, _ := svc.Login(context.Background(), user) - - cases := map[string]struct { - token string - password string - oldPassword string - err error - }{ - "valid user change password ": {token, "newpassword", user.Password, nil}, - "valid user change password with wrong password": {token, "newpassword", "wrongpassword", errors.ErrAuthentication}, - "valid user change password invalid token": {"", "newpassword", user.Password, errors.ErrAuthentication}, - } - - for desc, tc := range cases { - err := svc.ChangePassword(context.Background(), tc.token, tc.password, tc.oldPassword) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - - } -} - -func TestResetPassword(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - mockAuthzDB := map[string][]mocks.SubjectSet{} - mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: "authorities", Relation: "member"}) - authSvc := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) - - resetToken, err := authSvc.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 2}) - assert.Nil(t, err, fmt.Sprintf("Generating reset token expected to succeed: %s", err)) - cases := map[string]struct { - token string - password string - err error - }{ - "valid user reset password ": {resetToken.GetValue(), user.Email, nil}, - "invalid user reset password ": {"", "newpassword", errors.ErrAuthentication}, - } - - for desc, tc := range cases { - err := svc.ResetPassword(context.Background(), tc.token, tc.password) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} - -func TestSendPasswordReset(t *testing.T) { - svc := newService() - _, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("register user error: %s", err)) - token, _ := svc.Login(context.Background(), user) - - cases := map[string]struct { - token string - email string - err error - }{ - "valid user reset password ": {token, user.Email, nil}, - } - - for desc, tc := range cases { - err := svc.SendPasswordReset(context.Background(), host, tc.email, tc.token) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - - } -} - -func TestDisableUser(t *testing.T) { - enabledUser1 := users.User{Email: "user1@example.com", Password: "password"} - enabledUser2 := users.User{Email: "user2@example.com", Password: "password", Status: "enabled"} - disabledUser1 := users.User{Email: "user3@example.com", Password: "password", Status: "disabled"} - - svc := newService() - - id, err := svc.Register(context.Background(), user.Email, user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - user.ID = id - user.Status = "enabled" - token, err := svc.Login(context.Background(), user) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - - id, err = svc.Register(context.Background(), token, enabledUser1) - require.Nil(t, err, fmt.Sprintf("register enabledUser1 error: %s", err)) - enabledUser1.ID = id - enabledUser1.Status = "enabled" - - id, err = svc.Register(context.Background(), token, enabledUser2) - require.Nil(t, err, fmt.Sprintf("register enabledUser2 error: %s", err)) - enabledUser2.ID = id - enabledUser2.Status = "disabled" - - id, err = svc.Register(context.Background(), token, disabledUser1) - require.Nil(t, err, fmt.Sprintf("register disabledUser1 error: %s", err)) - disabledUser1.ID = id - disabledUser1.Status = "disabled" - - cases := []struct { - desc string - id string - token string - err error - }{ - { - desc: "disable user with wrong credentials", - id: enabledUser2.ID, - token: "", - err: errors.ErrAuthentication, - }, - { - desc: "disable existing user", - id: enabledUser2.ID, - token: token, - err: nil, - }, - { - desc: "disable disabled user", - id: enabledUser2.ID, - token: token, - err: users.ErrAlreadyDisabledUser, - }, - { - desc: "disable non-existing user", - id: "", - token: token, - err: errors.ErrNotFound, - }, - } - - for _, tc := range cases { - err := svc.DisableUser(context.Background(), tc.token, tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } - - _, err = svc.Login(context.Background(), enabledUser2) - assert.True(t, errors.Contains(err, errors.ErrNotFound), fmt.Sprintf("Login disabled user: expected %s got %s\n", errors.ErrNotFound, err)) - - cases2 := map[string]struct { - status string - size uint64 - response []users.User - }{ - "list enabled users": { - status: "enabled", - size: 2, - response: []users.User{enabledUser1, user}, - }, - "list disabled users": { - status: "disabled", - size: 2, - response: []users.User{enabledUser2, disabledUser1}, - }, - "list enabled and disabled users": { - status: "all", - size: 4, - response: []users.User{enabledUser1, enabledUser2, disabledUser1, user}, - }, - } - - for desc, tc := range cases2 { - pm := users.PageMetadata{ - Offset: 0, - Limit: 100, - Status: tc.status, - } - page, err := svc.ListUsers(context.Background(), token, pm) - require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) - size := uint64(len(page.Users)) - assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.size, size)) - assert.ElementsMatch(t, tc.response, page.Users, fmt.Sprintf("%s: expected %s got %s\n", desc, tc.response, page.Users)) - } -} diff --git a/users/tracing/users.go b/users/tracing/users.go deleted file mode 100644 index a33e9977791..00000000000 --- a/users/tracing/users.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -// Package tracing contains middlewares that will add spans -// to existing traces. -package tracing - -import ( - "context" - - "github.com/mainflux/mainflux/users" - opentracing "github.com/opentracing/opentracing-go" -) - -const ( - saveOp = "save_op" - retrieveByEmailOp = "retrieve_by_email" - updatePassword = "update_password" - members = "members" -) - -var _ users.UserRepository = (*userRepositoryMiddleware)(nil) - -type userRepositoryMiddleware struct { - tracer opentracing.Tracer - repo users.UserRepository -} - -// UserRepositoryMiddleware tracks request and their latency, and adds spans -// to context. -func UserRepositoryMiddleware(repo users.UserRepository, tracer opentracing.Tracer) users.UserRepository { - return userRepositoryMiddleware{ - tracer: tracer, - repo: repo, - } -} - -func (urm userRepositoryMiddleware) Save(ctx context.Context, user users.User) (string, error) { - span := createSpan(ctx, urm.tracer, saveOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.Save(ctx, user) -} - -func (urm userRepositoryMiddleware) UpdateUser(ctx context.Context, user users.User) error { - span := createSpan(ctx, urm.tracer, saveOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.UpdateUser(ctx, user) -} - -func (urm userRepositoryMiddleware) RetrieveByEmail(ctx context.Context, email string) (users.User, error) { - span := createSpan(ctx, urm.tracer, retrieveByEmailOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.RetrieveByEmail(ctx, email) -} - -func (urm userRepositoryMiddleware) RetrieveByID(ctx context.Context, id string) (users.User, error) { - span := createSpan(ctx, urm.tracer, retrieveByEmailOp) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.RetrieveByID(ctx, id) -} - -func (urm userRepositoryMiddleware) UpdatePassword(ctx context.Context, email, password string) error { - span := createSpan(ctx, urm.tracer, updatePassword) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.UpdatePassword(ctx, email, password) -} - -func (urm userRepositoryMiddleware) RetrieveAll(ctx context.Context, ids []string, pm users.PageMetadata) (users.UserPage, error) { - span := createSpan(ctx, urm.tracer, members) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.RetrieveAll(ctx, ids, pm) -} - -func (urm userRepositoryMiddleware) ChangeStatus(ctx context.Context, id, status string) error { - span := createSpan(ctx, urm.tracer, members) - defer span.Finish() - ctx = opentracing.ContextWithSpan(ctx, span) - - return urm.repo.ChangeStatus(ctx, id, status) -} - -func createSpan(ctx context.Context, tracer opentracing.Tracer, opName string) opentracing.Span { - if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil { - return tracer.StartSpan( - opName, - opentracing.ChildOf(parentSpan.Context()), - ) - } - return tracer.StartSpan(opName) -} diff --git a/users/users.go b/users/users.go deleted file mode 100644 index 63002ce761a..00000000000 --- a/users/users.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package users - -import ( - "context" - "fmt" - "regexp" - "strings" - - "github.com/mainflux/mainflux/pkg/errors" - "golang.org/x/net/idna" -) - -const ( - maxLocalLen = 64 - maxDomainLen = 255 - maxTLDLen = 24 // longest TLD currently in existence - - atSeparator = "@" - dotSeparator = "." -) - -var ( - userRegexp = regexp.MustCompile("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$") - hostRegexp = regexp.MustCompile(`^[^\s]+\.[^\s]+$`) - userDotRegexp = regexp.MustCompile("(^[.]{1})|([.]{1}$)|([.]{2,})") -) - -// Metadata to be used for Mainflux thing or channel for customized -// describing of particular thing or channel. -type Metadata map[string]interface{} - -// User represents a Mainflux user account. Each user is identified given its -// email and password. -type User struct { - ID string - Email string - Password string - Metadata Metadata - Status string -} - -// Validate returns an error if user representation is invalid. -func (u User) Validate() error { - if !isEmail(u.Email) { - return errors.ErrMalformedEntity - } - return nil -} - -// UserRepository specifies an account persistence API. -type UserRepository interface { - // Save persists the user account. A non-nil error is returned to indicate - // operation failure. - Save(ctx context.Context, u User) (string, error) - - // Update updates the user metadata. - UpdateUser(ctx context.Context, u User) error - - // RetrieveByEmail retrieves user by its unique identifier (i.e. email). - RetrieveByEmail(ctx context.Context, email string) (User, error) - - // RetrieveByID retrieves user by its unique identifier ID. - RetrieveByID(ctx context.Context, id string) (User, error) - - // RetrieveAll retrieves all users for given array of userIDs. - RetrieveAll(ctx context.Context, userIDs []string, pm PageMetadata) (UserPage, error) - - // UpdatePassword updates password for user with given email - UpdatePassword(ctx context.Context, email, password string) error - - // ChangeStatus changes users status to enabled or disabled - ChangeStatus(ctx context.Context, id, status string) error -} - -func isEmail(email string) bool { - if email == "" { - return false - } - - es := strings.Split(email, atSeparator) - if len(es) != 2 { - return false - } - local, host := es[0], es[1] - - if local == "" || len(local) > maxLocalLen { - return false - } - - hs := strings.Split(host, dotSeparator) - if len(hs) < 2 { - return false - } - domain, ext := hs[0], hs[1] - - // Check subdomain and validate - if len(hs) > 2 { - if domain == "" { - return false - } - - for i := 1; i < len(hs)-1; i++ { - sub := hs[i] - if sub == "" { - return false - } - domain = fmt.Sprintf("%s.%s", domain, sub) - } - - ext = hs[len(hs)-1] - } - - if domain == "" || len(domain) > maxDomainLen { - return false - } - if ext == "" || len(ext) > maxTLDLen { - return false - } - - punyLocal, err := idna.ToASCII(local) - if err != nil { - return false - } - punyHost, err := idna.ToASCII(host) - if err != nil { - return false - } - - if userDotRegexp.MatchString(punyLocal) || !userRegexp.MatchString(punyLocal) || !hostRegexp.MatchString(punyHost) { - return false - } - - return true -} diff --git a/users/users_test.go b/users/users_test.go deleted file mode 100644 index 4c3a37dda5b..00000000000 --- a/users/users_test.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) Mainflux -// SPDX-License-Identifier: Apache-2.0 - -package users_test - -import ( - "fmt" - "math/rand" - "testing" - - "github.com/mainflux/mainflux/pkg/errors" - "github.com/mainflux/mainflux/users" - "github.com/stretchr/testify/assert" -) - -const ( - email = "user@example.com" - password = "password" - - maxLocalLen = 64 - maxDomainLen = 255 - maxTLDLen = 24 -) - -var letters = "abcdefghijklmnopqrstuvwxyz" - -func randomString(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letters[rand.Intn(len(letters))] - } - return string(b) -} - -func TestValidate(t *testing.T) { - cases := map[string]struct { - user users.User - err error - }{ - "validate user with valid data": { - user: users.User{ - Email: email, - Password: password, - }, - err: nil, - }, - "validate user with valid domain and subdomain": { - user: users.User{ - Email: "user@example.sub.domain.com", - Password: password, - }, - err: nil, - }, - "validate user with invalid subdomain": { - user: users.User{ - Email: "user@example..domain.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with invalid domain": { - user: users.User{ - Email: "user@.sub.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with empty email": { - user: users.User{ - Email: "", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with invalid email": { - user: users.User{ - Email: "userexample.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with utf8 email (cyrillic)": { - user: users.User{ - Email: "почта@кино-россия.рф", - Password: password, - }, - err: nil, - }, - "validate user with utf8 email (hieroglyph)": { - user: users.User{ - Email: "艾付忧西开@艾付忧西开.再得", - Password: password, - }, - err: nil, - }, - "validate user with no email tld": { - user: users.User{ - Email: "user@example.", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with too long email tld": { - user: users.User{ - Email: "user@example." + randomString(maxTLDLen+1), - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with no email domain": { - user: users.User{ - Email: "user@.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with too long email domain": { - user: users.User{ - Email: "user@" + randomString(maxDomainLen+1) + ".com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with no email local": { - user: users.User{ - Email: "@example.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - "validate user with too long email local": { - user: users.User{ - Email: randomString(maxLocalLen+1) + "@example.com", - Password: password, - }, - err: errors.ErrMalformedEntity, - }, - } - - for desc, tc := range cases { - err := tc.user.Validate() - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err)) - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/.gitignore b/vendor/github.com/golang-jwt/jwt/v4/.gitignore deleted file mode 100644 index 09573e0169c..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -bin -.idea/ - diff --git a/vendor/github.com/golang-jwt/jwt/v4/LICENSE b/vendor/github.com/golang-jwt/jwt/v4/LICENSE deleted file mode 100644 index 35dbc252041..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2012 Dave Grijalva -Copyright (c) 2021 golang-jwt maintainers - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md b/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md deleted file mode 100644 index 32966f59818..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md +++ /dev/null @@ -1,22 +0,0 @@ -## Migration Guide (v4.0.0) - -Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be: - - "github.com/golang-jwt/jwt/v4" - -The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as -`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having -troubles migrating, please open an issue. - -You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`. - -And then you'd typically run: - -``` -go get github.com/golang-jwt/jwt/v4 -go mod tidy -``` - -## Older releases (before v3.2.0) - -The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. diff --git a/vendor/github.com/golang-jwt/jwt/v4/README.md b/vendor/github.com/golang-jwt/jwt/v4/README.md deleted file mode 100644 index f5d551ca8fd..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# jwt-go - -[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) -[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v4.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) - -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519). - -Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. -See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. - -> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic. - - -**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail. - -**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - -### Supported Go versions - -Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy). -So we will support a major version of Go until there are two newer major releases. -We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities -which will not be fixed. - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Installation Guidelines - -1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program. - -```sh -go get -u github.com/golang-jwt/jwt/v4 -``` - -2. Import it in your code: - -```go -import "github.com/golang-jwt/jwt/v4" -``` - -## Examples - -See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage: - -* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac) -* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac) -* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods or key functions. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod` or provide a `jwt.Keyfunc`. - -A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs) or to implement additional standards. - -| Extension | Purpose | Repo | -| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go | -| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms | -| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc | - -*Disclaimer*: Unless otherwise specified, these integrations are maintained by third parties and should not be considered as a primary offer by any of the mentioned cloud providers - -## Compliance - -This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases). - -**BREAKING CHANGES:*** -A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### Signing Methods and Key Types - -Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones: - -* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation -* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation -* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation -* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -### Troubleshooting - -This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types. - -## More - -Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. - -[golang-jwt](https://github.com/orgs/golang-jwt) incorporates a modified version of the JWT logo, which is distributed under the terms of the [MIT License](https://github.com/jsonwebtoken/jsonwebtoken.github.io/blob/master/LICENSE.txt). diff --git a/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md b/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md deleted file mode 100644 index b08402c3427..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md +++ /dev/null @@ -1,19 +0,0 @@ -# Security Policy - -## Supported Versions - -As of February 2022 (and until this document is updated), the latest version `v4` is supported. - -## Reporting a Vulnerability - -If you think you found a vulnerability, and even if you are not sure, please report it to jwt-go-security@googlegroups.com or one of the other [golang-jwt maintainers](https://github.com/orgs/golang-jwt/people). Please try be explicit, describe steps to reproduce the security issue with code example(s). - -You will receive a response within a timely manner. If the issue is confirmed, we will do our best to release a patch as soon as possible given the complexity of the problem. - -## Public Discussions - -Please avoid publicly discussing a potential security vulnerability. - -Let's take this offline and find a solution first, this limits the potential impact as much as possible. - -We appreciate your help! diff --git a/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md b/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md deleted file mode 100644 index afbfc4e408d..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md +++ /dev/null @@ -1,135 +0,0 @@ -## `jwt-go` Version History - -#### 4.0.0 - -* Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`. - -#### 3.2.2 - -* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)). -* Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)). -* Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)). -* Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)). - -#### 3.2.1 - -* **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code - * Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt` -* Fixed type confusing issue between `string` and `[]string` in `VerifyAudience` ([#12](https://github.com/golang-jwt/jwt/pull/12)). This fixes CVE-2020-26160 - -#### 3.2.0 - -* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation -* HMAC signing method returns `ErrInvalidKeyType` instead of `ErrInvalidKey` where appropriate -* Added options to `request.ParseFromRequest`, which allows for an arbitrary list of modifiers to parsing behavior. Initial set include `WithClaims` and `WithParser`. Existing usage of this function will continue to work as before. -* Deprecated `ParseFromRequestWithClaims` to simplify API in the future. - -#### 3.1.0 - -* Improvements to `jwt` command line tool -* Added `SkipClaimsValidation` option to `Parser` -* Documentation updates - -#### 3.0.0 - -* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code - * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. - * `ParseFromRequest` has been moved to `request` subpackage and usage has changed - * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. -* Other Additions and Changes - * Added `Claims` interface type to allow users to decode the claims into a custom type - * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. - * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage - * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` - * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. - * Added several new, more specific, validation errors to error type bitmask - * Moved examples from README to executable example files - * Signing method registry is now thread safe - * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) - -#### 2.7.0 - -This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. - -* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying -* Error text for expired tokens includes how long it's been expired -* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` -* Documentation updates - -#### 2.6.0 - -* Exposed inner error within ValidationError -* Fixed validation errors when using UseJSONNumber flag -* Added several unit tests - -#### 2.5.0 - -* Added support for signing method none. You shouldn't use this. The API tries to make this clear. -* Updated/fixed some documentation -* Added more helpful error message when trying to parse tokens that begin with `BEARER ` - -#### 2.4.0 - -* Added new type, Parser, to allow for configuration of various parsing parameters - * You can now specify a list of valid signing methods. Anything outside this set will be rejected. - * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON -* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) -* Fixed some bugs with ECDSA parsing - -#### 2.3.0 - -* Added support for ECDSA signing methods -* Added support for RSA PSS signing methods (requires go v1.4) - -#### 2.2.0 - -* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. - -#### 2.1.0 - -Backwards compatible API change that was missed in 2.0.0. - -* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` - -#### 2.0.0 - -There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. - -The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. - -It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. - -* **Compatibility Breaking Changes** - * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` - * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` - * `KeyFunc` now returns `interface{}` instead of `[]byte` - * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key - * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key -* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodHS256` - * Added public package global `SigningMethodHS384` - * Added public package global `SigningMethodHS512` -* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodRS256` - * Added public package global `SigningMethodRS384` - * Added public package global `SigningMethodRS512` -* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. -* Refactored the RSA implementation to be easier to read -* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` - -#### 1.0.2 - -* Fixed bug in parsing public keys from certificates -* Added more tests around the parsing of keys for RS256 -* Code refactoring in RS256 implementation. No functional changes - -#### 1.0.1 - -* Fixed panic if RS256 signing method was passed an invalid key - -#### 1.0.0 - -* First versioned release -* API stabilized -* Supports creating, signing, parsing, and validating JWT tokens -* Supports RS256 and HS256 signing methods diff --git a/vendor/github.com/golang-jwt/jwt/v4/claims.go b/vendor/github.com/golang-jwt/jwt/v4/claims.go deleted file mode 100644 index 9d95cad2bf2..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/claims.go +++ /dev/null @@ -1,273 +0,0 @@ -package jwt - -import ( - "crypto/subtle" - "fmt" - "time" -) - -// Claims must just have a Valid method that determines -// if the token is invalid for any supported reason -type Claims interface { - Valid() error -} - -// RegisteredClaims are a structured version of the JWT Claims Set, -// restricted to Registered Claim Names, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 -// -// This type can be used on its own, but then additional private and -// public claims embedded in the JWT will not be parsed. The typical usecase -// therefore is to embedded this in a user-defined claim type. -// -// See examples for how to use this with your own claim types. -type RegisteredClaims struct { - // the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 - Issuer string `json:"iss,omitempty"` - - // the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2 - Subject string `json:"sub,omitempty"` - - // the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 - Audience ClaimStrings `json:"aud,omitempty"` - - // the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 - ExpiresAt *NumericDate `json:"exp,omitempty"` - - // the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 - NotBefore *NumericDate `json:"nbf,omitempty"` - - // the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 - IssuedAt *NumericDate `json:"iat,omitempty"` - - // the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 - ID string `json:"jti,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c RegisteredClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := now.Sub(c.ExpiresAt.Time) - vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = ErrTokenUsedBeforeIssued - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = ErrTokenNotValidYet - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud(c.Audience, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool { - if c.ExpiresAt == nil { - return verifyExp(nil, cmp, req) - } - - return verifyExp(&c.ExpiresAt.Time, cmp, req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool { - if c.IssuedAt == nil { - return verifyIat(nil, cmp, req) - } - - return verifyIat(&c.IssuedAt.Time, cmp, req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool { - if c.NotBefore == nil { - return verifyNbf(nil, cmp, req) - } - - return verifyNbf(&c.NotBefore.Time, cmp, req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// StandardClaims are a structured version of the JWT Claims Set, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the -// specification exactly, since they were based on an earlier draft of the -// specification and not updated. The main difference is that they only -// support integer-based date fields and singular audiences. This might lead to -// incompatibilities with other JWT implementations. The use of this is discouraged, instead -// the newer RegisteredClaims struct should be used. -// -// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct. -type StandardClaims struct { - Audience string `json:"aud,omitempty"` - ExpiresAt int64 `json:"exp,omitempty"` - Id string `json:"jti,omitempty"` - IssuedAt int64 `json:"iat,omitempty"` - Issuer string `json:"iss,omitempty"` - NotBefore int64 `json:"nbf,omitempty"` - Subject string `json:"sub,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c StandardClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) - vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = ErrTokenUsedBeforeIssued - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = ErrTokenNotValidYet - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud([]string{c.Audience}, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { - if c.ExpiresAt == 0 { - return verifyExp(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.ExpiresAt, 0) - return verifyExp(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { - if c.IssuedAt == 0 { - return verifyIat(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.IssuedAt, 0) - return verifyIat(&t, time.Unix(cmp, 0), req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { - if c.NotBefore == 0 { - return verifyNbf(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.NotBefore, 0) - return verifyNbf(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// ----- helpers - -func verifyAud(aud []string, cmp string, required bool) bool { - if len(aud) == 0 { - return !required - } - // use a var here to keep constant time compare when looping over a number of claims - result := false - - var stringClaims string - for _, a := range aud { - if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 { - result = true - } - stringClaims = stringClaims + a - } - - // case where "" is sent in one or many aud claims - if len(stringClaims) == 0 { - return !required - } - - return result -} - -func verifyExp(exp *time.Time, now time.Time, required bool) bool { - if exp == nil { - return !required - } - return now.Before(*exp) -} - -func verifyIat(iat *time.Time, now time.Time, required bool) bool { - if iat == nil { - return !required - } - return now.After(*iat) || now.Equal(*iat) -} - -func verifyNbf(nbf *time.Time, now time.Time, required bool) bool { - if nbf == nil { - return !required - } - return now.After(*nbf) || now.Equal(*nbf) -} - -func verifyIss(iss string, cmp string, required bool) bool { - if iss == "" { - return !required - } - if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 { - return true - } else { - return false - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/doc.go b/vendor/github.com/golang-jwt/jwt/v4/doc.go deleted file mode 100644 index a86dc1a3b34..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html -// -// See README.md for more info. -package jwt diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go deleted file mode 100644 index eac023fc6c8..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go +++ /dev/null @@ -1,142 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rand" - "errors" - "math/big" -) - -var ( - // Sadly this is missing from crypto/ecdsa compared to crypto/rsa - ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") -) - -// SigningMethodECDSA implements the ECDSA family of signing methods. -// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification -type SigningMethodECDSA struct { - Name string - Hash crypto.Hash - KeySize int - CurveBits int -} - -// Specific instances for EC256 and company -var ( - SigningMethodES256 *SigningMethodECDSA - SigningMethodES384 *SigningMethodECDSA - SigningMethodES512 *SigningMethodECDSA -) - -func init() { - // ES256 - SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} - RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { - return SigningMethodES256 - }) - - // ES384 - SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} - RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { - return SigningMethodES384 - }) - - // ES512 - SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} - RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { - return SigningMethodES512 - }) -} - -func (m *SigningMethodECDSA) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an ecdsa.PublicKey struct -func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - // Get the key - var ecdsaKey *ecdsa.PublicKey - switch k := key.(type) { - case *ecdsa.PublicKey: - ecdsaKey = k - default: - return ErrInvalidKeyType - } - - if len(sig) != 2*m.KeySize { - return ErrECDSAVerification - } - - r := big.NewInt(0).SetBytes(sig[:m.KeySize]) - s := big.NewInt(0).SetBytes(sig[m.KeySize:]) - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus { - return nil - } - - return ErrECDSAVerification -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an ecdsa.PrivateKey struct -func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { - // Get the key - var ecdsaKey *ecdsa.PrivateKey - switch k := key.(type) { - case *ecdsa.PrivateKey: - ecdsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return r, s - if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { - curveBits := ecdsaKey.Curve.Params().BitSize - - if m.CurveBits != curveBits { - return "", ErrInvalidKey - } - - keyBytes := curveBits / 8 - if curveBits%8 > 0 { - keyBytes += 1 - } - - // We serialize the outputs (r and s) into big-endian byte arrays - // padded with zeros on the left to make sure the sizes work out. - // Output must be 2*keyBytes long. - out := make([]byte, 2*keyBytes) - r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output. - s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output. - - return EncodeSegment(out), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go deleted file mode 100644 index 5700636d35b..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go +++ /dev/null @@ -1,69 +0,0 @@ -package jwt - -import ( - "crypto/ecdsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrNotECPublicKey = errors.New("key is not a valid ECDSA public key") - ErrNotECPrivateKey = errors.New("key is not a valid ECDSA private key") -) - -// ParseECPrivateKeyFromPEM parses a PEM encoded Elliptic Curve Private Key Structure -func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *ecdsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { - return nil, ErrNotECPrivateKey - } - - return pkey, nil -} - -// ParseECPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key -func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *ecdsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { - return nil, ErrNotECPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519.go deleted file mode 100644 index 07d3aacd631..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ed25519.go +++ /dev/null @@ -1,85 +0,0 @@ -package jwt - -import ( - "errors" - - "crypto" - "crypto/ed25519" - "crypto/rand" -) - -var ( - ErrEd25519Verification = errors.New("ed25519: verification error") -) - -// SigningMethodEd25519 implements the EdDSA family. -// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification -type SigningMethodEd25519 struct{} - -// Specific instance for EdDSA -var ( - SigningMethodEdDSA *SigningMethodEd25519 -) - -func init() { - SigningMethodEdDSA = &SigningMethodEd25519{} - RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod { - return SigningMethodEdDSA - }) -} - -func (m *SigningMethodEd25519) Alg() string { - return "EdDSA" -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an ed25519.PublicKey -func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error { - var err error - var ed25519Key ed25519.PublicKey - var ok bool - - if ed25519Key, ok = key.(ed25519.PublicKey); !ok { - return ErrInvalidKeyType - } - - if len(ed25519Key) != ed25519.PublicKeySize { - return ErrInvalidKey - } - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - // Verify the signature - if !ed25519.Verify(ed25519Key, []byte(signingString), sig) { - return ErrEd25519Verification - } - - return nil -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an ed25519.PrivateKey -func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { - var ed25519Key crypto.Signer - var ok bool - - if ed25519Key, ok = key.(crypto.Signer); !ok { - return "", ErrInvalidKeyType - } - - if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok { - return "", ErrInvalidKey - } - - // Sign the string and return the encoded result - // ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0) - sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0)) - if err != nil { - return "", err - } - return EncodeSegment(sig), nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go deleted file mode 100644 index cdb5e68e876..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go +++ /dev/null @@ -1,64 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/ed25519" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrNotEdPrivateKey = errors.New("key is not a valid Ed25519 private key") - ErrNotEdPublicKey = errors.New("key is not a valid Ed25519 public key") -) - -// ParseEdPrivateKeyFromPEM parses a PEM-encoded Edwards curve private key -func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - - var pkey ed25519.PrivateKey - var ok bool - if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok { - return nil, ErrNotEdPrivateKey - } - - return pkey, nil -} - -// ParseEdPublicKeyFromPEM parses a PEM-encoded Edwards curve public key -func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - return nil, err - } - - var pkey ed25519.PublicKey - var ok bool - if pkey, ok = parsedKey.(ed25519.PublicKey); !ok { - return nil, ErrNotEdPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/errors.go b/vendor/github.com/golang-jwt/jwt/v4/errors.go deleted file mode 100644 index 10ac8835cc8..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/errors.go +++ /dev/null @@ -1,112 +0,0 @@ -package jwt - -import ( - "errors" -) - -// Error constants -var ( - ErrInvalidKey = errors.New("key is invalid") - ErrInvalidKeyType = errors.New("key is of invalid type") - ErrHashUnavailable = errors.New("the requested hash function is unavailable") - - ErrTokenMalformed = errors.New("token is malformed") - ErrTokenUnverifiable = errors.New("token is unverifiable") - ErrTokenSignatureInvalid = errors.New("token signature is invalid") - - ErrTokenInvalidAudience = errors.New("token has invalid audience") - ErrTokenExpired = errors.New("token is expired") - ErrTokenUsedBeforeIssued = errors.New("token used before issued") - ErrTokenInvalidIssuer = errors.New("token has invalid issuer") - ErrTokenNotValidYet = errors.New("token is not valid yet") - ErrTokenInvalidId = errors.New("token has invalid id") - ErrTokenInvalidClaims = errors.New("token has invalid claims") -) - -// The errors that might occur when parsing and validating a token -const ( - ValidationErrorMalformed uint32 = 1 << iota // Token is malformed - ValidationErrorUnverifiable // Token could not be verified because of signing problems - ValidationErrorSignatureInvalid // Signature validation failed - - // Standard Claim validation errors - ValidationErrorAudience // AUD validation failed - ValidationErrorExpired // EXP validation failed - ValidationErrorIssuedAt // IAT validation failed - ValidationErrorIssuer // ISS validation failed - ValidationErrorNotValidYet // NBF validation failed - ValidationErrorId // JTI validation failed - ValidationErrorClaimsInvalid // Generic claims validation error -) - -// NewValidationError is a helper for constructing a ValidationError with a string error message -func NewValidationError(errorText string, errorFlags uint32) *ValidationError { - return &ValidationError{ - text: errorText, - Errors: errorFlags, - } -} - -// ValidationError represents an error from Parse if token is not valid -type ValidationError struct { - Inner error // stores the error returned by external dependencies, i.e.: KeyFunc - Errors uint32 // bitfield. see ValidationError... constants - text string // errors that do not have a valid error just have text -} - -// Error is the implementation of the err interface. -func (e ValidationError) Error() string { - if e.Inner != nil { - return e.Inner.Error() - } else if e.text != "" { - return e.text - } else { - return "token is invalid" - } -} - -// Unwrap gives errors.Is and errors.As access to the inner error. -func (e *ValidationError) Unwrap() error { - return e.Inner -} - -// No errors -func (e *ValidationError) valid() bool { - return e.Errors == 0 -} - -// Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message -// by comparing the inner error message. If that fails, we compare using the error flags. This way we can use -// custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables. -func (e *ValidationError) Is(err error) bool { - // Check, if our inner error is a direct match - if errors.Is(errors.Unwrap(e), err) { - return true - } - - // Otherwise, we need to match using our error flags - switch err { - case ErrTokenMalformed: - return e.Errors&ValidationErrorMalformed != 0 - case ErrTokenUnverifiable: - return e.Errors&ValidationErrorUnverifiable != 0 - case ErrTokenSignatureInvalid: - return e.Errors&ValidationErrorSignatureInvalid != 0 - case ErrTokenInvalidAudience: - return e.Errors&ValidationErrorAudience != 0 - case ErrTokenExpired: - return e.Errors&ValidationErrorExpired != 0 - case ErrTokenUsedBeforeIssued: - return e.Errors&ValidationErrorIssuedAt != 0 - case ErrTokenInvalidIssuer: - return e.Errors&ValidationErrorIssuer != 0 - case ErrTokenNotValidYet: - return e.Errors&ValidationErrorNotValidYet != 0 - case ErrTokenInvalidId: - return e.Errors&ValidationErrorId != 0 - case ErrTokenInvalidClaims: - return e.Errors&ValidationErrorClaimsInvalid != 0 - } - - return false -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/hmac.go b/vendor/github.com/golang-jwt/jwt/v4/hmac.go deleted file mode 100644 index 011f68a2744..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/hmac.go +++ /dev/null @@ -1,95 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/hmac" - "errors" -) - -// SigningMethodHMAC implements the HMAC-SHA family of signing methods. -// Expects key type of []byte for both signing and validation -type SigningMethodHMAC struct { - Name string - Hash crypto.Hash -} - -// Specific instances for HS256 and company -var ( - SigningMethodHS256 *SigningMethodHMAC - SigningMethodHS384 *SigningMethodHMAC - SigningMethodHS512 *SigningMethodHMAC - ErrSignatureInvalid = errors.New("signature is invalid") -) - -func init() { - // HS256 - SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { - return SigningMethodHS256 - }) - - // HS384 - SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { - return SigningMethodHS384 - }) - - // HS512 - SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { - return SigningMethodHS512 - }) -} - -func (m *SigningMethodHMAC) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod. Returns nil if the signature is valid. -func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { - // Verify the key is the right type - keyBytes, ok := key.([]byte) - if !ok { - return ErrInvalidKeyType - } - - // Decode signature, for comparison - sig, err := DecodeSegment(signature) - if err != nil { - return err - } - - // Can we use the specified hashing method? - if !m.Hash.Available() { - return ErrHashUnavailable - } - - // This signing method is symmetric, so we validate the signature - // by reproducing the signature from the signing string and key, then - // comparing that against the provided signature. - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - if !hmac.Equal(sig, hasher.Sum(nil)) { - return ErrSignatureInvalid - } - - // No validation errors. Signature is good. - return nil -} - -// Sign implements token signing for the SigningMethod. -// Key must be []byte -func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { - if keyBytes, ok := key.([]byte); ok { - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - - return EncodeSegment(hasher.Sum(nil)), nil - } - - return "", ErrInvalidKeyType -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/map_claims.go b/vendor/github.com/golang-jwt/jwt/v4/map_claims.go deleted file mode 100644 index 2700d64a0d0..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/map_claims.go +++ /dev/null @@ -1,151 +0,0 @@ -package jwt - -import ( - "encoding/json" - "errors" - "time" - // "fmt" -) - -// MapClaims is a claims type that uses the map[string]interface{} for JSON decoding. -// This is the default claims type if you don't supply one -type MapClaims map[string]interface{} - -// VerifyAudience Compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyAudience(cmp string, req bool) bool { - var aud []string - switch v := m["aud"].(type) { - case string: - aud = append(aud, v) - case []string: - aud = v - case []interface{}: - for _, a := range v { - vs, ok := a.(string) - if !ok { - return false - } - aud = append(aud, vs) - } - } - return verifyAud(aud, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp). -// If req is false, it will return true, if exp is unset. -func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["exp"] - if !ok { - return !req - } - - switch exp := v.(type) { - case float64: - if exp == 0 { - return verifyExp(nil, cmpTime, req) - } - - return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req) - case json.Number: - v, _ := exp.Float64() - - return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["iat"] - if !ok { - return !req - } - - switch iat := v.(type) { - case float64: - if iat == 0 { - return verifyIat(nil, cmpTime, req) - } - - return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req) - case json.Number: - v, _ := iat.Float64() - - return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["nbf"] - if !ok { - return !req - } - - switch nbf := v.(type) { - case float64: - if nbf == 0 { - return verifyNbf(nil, cmpTime, req) - } - - return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req) - case json.Number: - v, _ := nbf.Float64() - - return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { - iss, _ := m["iss"].(string) - return verifyIss(iss, cmp, req) -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (m MapClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - if !m.VerifyExpiresAt(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenExpired - vErr.Inner = errors.New("Token is expired") - vErr.Errors |= ValidationErrorExpired - } - - if !m.VerifyIssuedAt(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenUsedBeforeIssued - vErr.Inner = errors.New("Token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if !m.VerifyNotBefore(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenNotValidYet - vErr.Inner = errors.New("Token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/none.go b/vendor/github.com/golang-jwt/jwt/v4/none.go deleted file mode 100644 index f19835d2078..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/none.go +++ /dev/null @@ -1,52 +0,0 @@ -package jwt - -// SigningMethodNone implements the none signing method. This is required by the spec -// but you probably should never use it. -var SigningMethodNone *signingMethodNone - -const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" - -var NoneSignatureTypeDisallowedError error - -type signingMethodNone struct{} -type unsafeNoneMagicConstant string - -func init() { - SigningMethodNone = &signingMethodNone{} - NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) - - RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { - return SigningMethodNone - }) -} - -func (m *signingMethodNone) Alg() string { - return "none" -} - -// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { - // Key must be UnsafeAllowNoneSignatureType to prevent accidentally - // accepting 'none' signing method - if _, ok := key.(unsafeNoneMagicConstant); !ok { - return NoneSignatureTypeDisallowedError - } - // If signing method is none, signature must be an empty string - if signature != "" { - return NewValidationError( - "'none' signing method with non-empty signature", - ValidationErrorSignatureInvalid, - ) - } - - // Accept 'none' signing method. - return nil -} - -// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { - if _, ok := key.(unsafeNoneMagicConstant); ok { - return "", nil - } - return "", NoneSignatureTypeDisallowedError -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser.go b/vendor/github.com/golang-jwt/jwt/v4/parser.go deleted file mode 100644 index 2f61a69d7fc..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/parser.go +++ /dev/null @@ -1,170 +0,0 @@ -package jwt - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" -) - -type Parser struct { - // If populated, only these methods will be considered valid. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - ValidMethods []string - - // Use JSON Number format in JSON decoder. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - UseJSONNumber bool - - // Skip claims validation during token parsing. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - SkipClaimsValidation bool -} - -// NewParser creates a new Parser with the specified options -func NewParser(options ...ParserOption) *Parser { - p := &Parser{} - - // loop through our parsing options and apply them - for _, option := range options { - option(p) - } - - return p -} - -// Parse parses, validates, verifies the signature and returns the parsed token. -// keyFunc will receive the parsed token and should return the key for validating. -func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { - return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) -} - -func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - token, parts, err := p.ParseUnverified(tokenString, claims) - if err != nil { - return token, err - } - - // Verify signing method is in the required set - if p.ValidMethods != nil { - var signingMethodValid = false - var alg = token.Method.Alg() - for _, m := range p.ValidMethods { - if m == alg { - signingMethodValid = true - break - } - } - if !signingMethodValid { - // signing method is not in the listed set - return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) - } - } - - // Lookup key - var key interface{} - if keyFunc == nil { - // keyFunc was not provided. short circuiting validation - return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) - } - if key, err = keyFunc(token); err != nil { - // keyFunc returned an error - if ve, ok := err.(*ValidationError); ok { - return token, ve - } - return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} - } - - vErr := &ValidationError{} - - // Validate Claims - if !p.SkipClaimsValidation { - if err := token.Claims.Valid(); err != nil { - - // If the Claims Valid returned an error, check if it is a validation error, - // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set - if e, ok := err.(*ValidationError); !ok { - vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} - } else { - vErr = e - } - } - } - - // Perform validation - token.Signature = parts[2] - if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { - vErr.Inner = err - vErr.Errors |= ValidationErrorSignatureInvalid - } - - if vErr.valid() { - token.Valid = true - return token, nil - } - - return token, vErr -} - -// ParseUnverified parses the token but doesn't validate the signature. -// -// WARNING: Don't use this method unless you know what you're doing. -// -// It's only ever useful in cases where you know the signature is valid (because it has -// been checked previously in the stack) and you want to extract values from it. -func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { - parts = strings.Split(tokenString, ".") - if len(parts) != 3 { - return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) - } - - token = &Token{Raw: tokenString} - - // parse Header - var headerBytes []byte - if headerBytes, err = DecodeSegment(parts[0]); err != nil { - if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { - return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) - } - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // parse Claims - var claimBytes []byte - token.Claims = claims - - if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) - if p.UseJSONNumber { - dec.UseNumber() - } - // JSON Decode. Special case for map type to avoid weird pointer behavior - if c, ok := token.Claims.(MapClaims); ok { - err = dec.Decode(&c) - } else { - err = dec.Decode(&claims) - } - // Handle decode error - if err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // Lookup signature method - if method, ok := token.Header["alg"].(string); ok { - if token.Method = GetSigningMethod(method); token.Method == nil { - return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) - } - } else { - return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) - } - - return token, parts, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser_option.go b/vendor/github.com/golang-jwt/jwt/v4/parser_option.go deleted file mode 100644 index 6ea6f9527de..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/parser_option.go +++ /dev/null @@ -1,29 +0,0 @@ -package jwt - -// ParserOption is used to implement functional-style options that modify the behavior of the parser. To add -// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that -// takes a *Parser type as input and manipulates its configuration accordingly. -type ParserOption func(*Parser) - -// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid. -// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/. -func WithValidMethods(methods []string) ParserOption { - return func(p *Parser) { - p.ValidMethods = methods - } -} - -// WithJSONNumber is an option to configure the underlying JSON parser with UseNumber -func WithJSONNumber() ParserOption { - return func(p *Parser) { - p.UseJSONNumber = true - } -} - -// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know -// what you are doing. -func WithoutClaimsValidation() ParserOption { - return func(p *Parser) { - p.SkipClaimsValidation = true - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa.go b/vendor/github.com/golang-jwt/jwt/v4/rsa.go deleted file mode 100644 index b910b19c0b5..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa.go +++ /dev/null @@ -1,101 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// SigningMethodRSA implements the RSA family of signing methods. -// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation -type SigningMethodRSA struct { - Name string - Hash crypto.Hash -} - -// Specific instances for RS256 and company -var ( - SigningMethodRS256 *SigningMethodRSA - SigningMethodRS384 *SigningMethodRSA - SigningMethodRS512 *SigningMethodRSA -) - -func init() { - // RS256 - SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { - return SigningMethodRS256 - }) - - // RS384 - SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { - return SigningMethodRS384 - }) - - // RS512 - SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { - return SigningMethodRS512 - }) -} - -func (m *SigningMethodRSA) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod -// For this signing method, must be an *rsa.PublicKey structure. -func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - var ok bool - - if rsaKey, ok = key.(*rsa.PublicKey); !ok { - return ErrInvalidKeyType - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) -} - -// Sign implements token signing for the SigningMethod -// For this signing method, must be an *rsa.PrivateKey structure. -func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - var ok bool - - // Validate type of key - if rsaKey, ok = key.(*rsa.PrivateKey); !ok { - return "", ErrInvalidKey - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go deleted file mode 100644 index 4fd6f9e610b..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go +++ /dev/null @@ -1,143 +0,0 @@ -//go:build go1.4 -// +build go1.4 - -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// SigningMethodRSAPSS implements the RSAPSS family of signing methods signing methods -type SigningMethodRSAPSS struct { - *SigningMethodRSA - Options *rsa.PSSOptions - // VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS. - // Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow - // https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously. - // See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details. - VerifyOptions *rsa.PSSOptions -} - -// Specific instances for RS/PS and company. -var ( - SigningMethodPS256 *SigningMethodRSAPSS - SigningMethodPS384 *SigningMethodRSAPSS - SigningMethodPS512 *SigningMethodRSAPSS -) - -func init() { - // PS256 - SigningMethodPS256 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS256", - Hash: crypto.SHA256, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { - return SigningMethodPS256 - }) - - // PS384 - SigningMethodPS384 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS384", - Hash: crypto.SHA384, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { - return SigningMethodPS384 - }) - - // PS512 - SigningMethodPS512 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS512", - Hash: crypto.SHA512, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { - return SigningMethodPS512 - }) -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an rsa.PublicKey struct -func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - switch k := key.(type) { - case *rsa.PublicKey: - rsaKey = k - default: - return ErrInvalidKey - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - opts := m.Options - if m.VerifyOptions != nil { - opts = m.VerifyOptions - } - - return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts) -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an rsa.PrivateKey struct -func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - - switch k := key.(type) { - case *rsa.PrivateKey: - rsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go deleted file mode 100644 index 1966c450bf8..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go +++ /dev/null @@ -1,105 +0,0 @@ -package jwt - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key") - ErrNotRSAPrivateKey = errors.New("key is not a valid RSA private key") - ErrNotRSAPublicKey = errors.New("key is not a valid RSA public key") -) - -// ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key -func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, ErrNotRSAPrivateKey - } - - return pkey, nil -} - -// ParseRSAPrivateKeyFromPEMWithPassword parses a PEM encoded PKCS1 or PKCS8 private key protected with password -// -// Deprecated: This function is deprecated and should not be used anymore. It uses the deprecated x509.DecryptPEMBlock -// function, which was deprecated since RFC 1423 is regarded insecure by design. Unfortunately, there is no alternative -// in the Go standard library for now. See https://github.com/golang/go/issues/8860. -func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - var parsedKey interface{} - - var blockDecrypted []byte - if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil { - return nil, err - } - - if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, ErrNotRSAPrivateKey - } - - return pkey, nil -} - -// ParseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key -func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *rsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, ErrNotRSAPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/signing_method.go b/vendor/github.com/golang-jwt/jwt/v4/signing_method.go deleted file mode 100644 index 241ae9c60d0..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/signing_method.go +++ /dev/null @@ -1,46 +0,0 @@ -package jwt - -import ( - "sync" -) - -var signingMethods = map[string]func() SigningMethod{} -var signingMethodLock = new(sync.RWMutex) - -// SigningMethod can be used add new methods for signing or verifying tokens. -type SigningMethod interface { - Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid - Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error - Alg() string // returns the alg identifier for this method (example: 'HS256') -} - -// RegisterSigningMethod registers the "alg" name and a factory function for signing method. -// This is typically done during init() in the method's implementation -func RegisterSigningMethod(alg string, f func() SigningMethod) { - signingMethodLock.Lock() - defer signingMethodLock.Unlock() - - signingMethods[alg] = f -} - -// GetSigningMethod retrieves a signing method from an "alg" string -func GetSigningMethod(alg string) (method SigningMethod) { - signingMethodLock.RLock() - defer signingMethodLock.RUnlock() - - if methodF, ok := signingMethods[alg]; ok { - method = methodF() - } - return -} - -// GetAlgorithms returns a list of registered "alg" names -func GetAlgorithms() (algs []string) { - signingMethodLock.RLock() - defer signingMethodLock.RUnlock() - - for alg := range signingMethods { - algs = append(algs, alg) - } - return -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf b/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf deleted file mode 100644 index 53745d51d7c..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf +++ /dev/null @@ -1 +0,0 @@ -checks = ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1023"] diff --git a/vendor/github.com/golang-jwt/jwt/v4/token.go b/vendor/github.com/golang-jwt/jwt/v4/token.go deleted file mode 100644 index 3cb0f3f0e4c..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/token.go +++ /dev/null @@ -1,127 +0,0 @@ -package jwt - -import ( - "encoding/base64" - "encoding/json" - "strings" - "time" -) - -// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515 -// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations -// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global -// variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. -// To use the non-recommended decoding, set this boolean to `true` prior to using this package. -var DecodePaddingAllowed bool - -// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). -// You can override it to use another time value. This is useful for testing or if your -// server uses a different time zone than your tokens. -var TimeFunc = time.Now - -// Keyfunc will be used by the Parse methods as a callback function to supply -// the key for verification. The function receives the parsed, -// but unverified Token. This allows you to use properties in the -// Header of the token (such as `kid`) to identify which key to use. -type Keyfunc func(*Token) (interface{}, error) - -// Token represents a JWT Token. Different fields will be used depending on whether you're -// creating or parsing/verifying a token. -type Token struct { - Raw string // The raw token. Populated when you Parse a token - Method SigningMethod // The signing method used or to be used - Header map[string]interface{} // The first segment of the token - Claims Claims // The second segment of the token - Signature string // The third segment of the token. Populated when you Parse a token - Valid bool // Is the token valid? Populated when you Parse/Verify a token -} - -// New creates a new Token with the specified signing method and an empty map of claims. -func New(method SigningMethod) *Token { - return NewWithClaims(method, MapClaims{}) -} - -// NewWithClaims creates a new Token with the specified signing method and claims. -func NewWithClaims(method SigningMethod, claims Claims) *Token { - return &Token{ - Header: map[string]interface{}{ - "typ": "JWT", - "alg": method.Alg(), - }, - Claims: claims, - Method: method, - } -} - -// SignedString creates and returns a complete, signed JWT. -// The token is signed using the SigningMethod specified in the token. -func (t *Token) SignedString(key interface{}) (string, error) { - var sig, sstr string - var err error - if sstr, err = t.SigningString(); err != nil { - return "", err - } - if sig, err = t.Method.Sign(sstr, key); err != nil { - return "", err - } - return strings.Join([]string{sstr, sig}, "."), nil -} - -// SigningString generates the signing string. This is the -// most expensive part of the whole deal. Unless you -// need this for something special, just go straight for -// the SignedString. -func (t *Token) SigningString() (string, error) { - var err error - var jsonValue []byte - - if jsonValue, err = json.Marshal(t.Header); err != nil { - return "", err - } - header := EncodeSegment(jsonValue) - - if jsonValue, err = json.Marshal(t.Claims); err != nil { - return "", err - } - claim := EncodeSegment(jsonValue) - - return strings.Join([]string{header, claim}, "."), nil -} - -// Parse parses, validates, verifies the signature and returns the parsed token. -// keyFunc will receive the parsed token and should return the cryptographic key -// for verifying the signature. -// The caller is strongly encouraged to set the WithValidMethods option to -// validate the 'alg' claim in the token matches the expected algorithm. -// For more details about the importance of validating the 'alg' claim, -// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ -func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).Parse(tokenString, keyFunc) -} - -func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) -} - -// EncodeSegment encodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func EncodeSegment(seg []byte) string { - return base64.RawURLEncoding.EncodeToString(seg) -} - -// DecodeSegment decodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func DecodeSegment(seg string) ([]byte, error) { - if DecodePaddingAllowed { - if l := len(seg) % 4; l > 0 { - seg += strings.Repeat("=", 4-l) - } - return base64.URLEncoding.DecodeString(seg) - } - - return base64.RawURLEncoding.DecodeString(seg) -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/types.go b/vendor/github.com/golang-jwt/jwt/v4/types.go deleted file mode 100644 index ac8e140eb11..00000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/types.go +++ /dev/null @@ -1,145 +0,0 @@ -package jwt - -import ( - "encoding/json" - "fmt" - "math" - "reflect" - "strconv" - "time" -) - -// TimePrecision sets the precision of times and dates within this library. -// This has an influence on the precision of times when comparing expiry or -// other related time fields. Furthermore, it is also the precision of times -// when serializing. -// -// For backwards compatibility the default precision is set to seconds, so that -// no fractional timestamps are generated. -var TimePrecision = time.Second - -// MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially -// its MarshalJSON function. -// -// If it is set to true (the default), it will always serialize the type as an -// array of strings, even if it just contains one element, defaulting to the behaviour -// of the underlying []string. If it is set to false, it will serialize to a single -// string, if it contains one element. Otherwise, it will serialize to an array of strings. -var MarshalSingleStringAsArray = true - -// NumericDate represents a JSON numeric date value, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-2. -type NumericDate struct { - time.Time -} - -// NewNumericDate constructs a new *NumericDate from a standard library time.Time struct. -// It will truncate the timestamp according to the precision specified in TimePrecision. -func NewNumericDate(t time.Time) *NumericDate { - return &NumericDate{t.Truncate(TimePrecision)} -} - -// newNumericDateFromSeconds creates a new *NumericDate out of a float64 representing a -// UNIX epoch with the float fraction representing non-integer seconds. -func newNumericDateFromSeconds(f float64) *NumericDate { - round, frac := math.Modf(f) - return NewNumericDate(time.Unix(int64(round), int64(frac*1e9))) -} - -// MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch -// represented in NumericDate to a byte array, using the precision specified in TimePrecision. -func (date NumericDate) MarshalJSON() (b []byte, err error) { - var prec int - if TimePrecision < time.Second { - prec = int(math.Log10(float64(time.Second) / float64(TimePrecision))) - } - truncatedDate := date.Truncate(TimePrecision) - - // For very large timestamps, UnixNano would overflow an int64, but this - // function requires nanosecond level precision, so we have to use the - // following technique to get round the issue: - // 1. Take the normal unix timestamp to form the whole number part of the - // output, - // 2. Take the result of the Nanosecond function, which retuns the offset - // within the second of the particular unix time instance, to form the - // decimal part of the output - // 3. Concatenate them to produce the final result - seconds := strconv.FormatInt(truncatedDate.Unix(), 10) - nanosecondsOffset := strconv.FormatFloat(float64(truncatedDate.Nanosecond())/float64(time.Second), 'f', prec, 64) - - output := append([]byte(seconds), []byte(nanosecondsOffset)[1:]...) - - return output, nil -} - -// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a -// NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch -// with either integer or non-integer seconds. -func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { - var ( - number json.Number - f float64 - ) - - if err = json.Unmarshal(b, &number); err != nil { - return fmt.Errorf("could not parse NumericData: %w", err) - } - - if f, err = number.Float64(); err != nil { - return fmt.Errorf("could not convert json number value to float: %w", err) - } - - n := newNumericDateFromSeconds(f) - *date = *n - - return nil -} - -// ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string. -// This type is necessary, since the "aud" claim can either be a single string or an array. -type ClaimStrings []string - -func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { - var value interface{} - - if err = json.Unmarshal(data, &value); err != nil { - return err - } - - var aud []string - - switch v := value.(type) { - case string: - aud = append(aud, v) - case []string: - aud = ClaimStrings(v) - case []interface{}: - for _, vv := range v { - vs, ok := vv.(string) - if !ok { - return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)} - } - aud = append(aud, vs) - } - case nil: - return nil - default: - return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)} - } - - *s = aud - - return -} - -func (s ClaimStrings) MarshalJSON() (b []byte, err error) { - // This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field, - // only contains one element, it MAY be serialized as a single string. This may or may not be - // desired based on the ecosystem of other JWT library used, so we make it configurable by the - // variable MarshalSingleStringAsArray. - if len(s) == 1 && !MarshalSingleStringAsArray { - return json.Marshal(s[0]) - } - - return json.Marshal([]string(s)) -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/.npmignore b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/.npmignore deleted file mode 100644 index e796b66a819..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/.npmignore +++ /dev/null @@ -1 +0,0 @@ -*.go diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/LICENSE b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/LICENSE deleted file mode 100644 index 261eeb9e9f8..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/README.md b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/README.md deleted file mode 100644 index 30dfcee9028..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Ory Keto gRPC Client - -This package provides the generated gRPC client for [Ory Keto](https://ory.sh/keto). -Go to [the documentation](https://ory.sh/keto/docs) to learn more diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.pb.go deleted file mode 100644 index 1cb0f641c55..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.pb.go +++ /dev/null @@ -1,391 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/acl.proto - -package acl - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// RelationTuple defines a relation between an Object and a Subject. -type RelationTuple struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The namespace this relation tuple lives in. - Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` - // The object related by this tuple. - // It is an object in the namespace of the tuple. - Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` - // The relation between an Object and a Subject. - Relation string `protobuf:"bytes,3,opt,name=relation,proto3" json:"relation,omitempty"` - // The subject related by this tuple. - // A Subject either represents a concrete subject id or - // a `SubjectSet` that expands to more Subjects. - Subject *Subject `protobuf:"bytes,4,opt,name=subject,proto3" json:"subject,omitempty"` -} - -func (x *RelationTuple) Reset() { - *x = RelationTuple{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RelationTuple) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RelationTuple) ProtoMessage() {} - -func (x *RelationTuple) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RelationTuple.ProtoReflect.Descriptor instead. -func (*RelationTuple) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_acl_proto_rawDescGZIP(), []int{0} -} - -func (x *RelationTuple) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *RelationTuple) GetObject() string { - if x != nil { - return x.Object - } - return "" -} - -func (x *RelationTuple) GetRelation() string { - if x != nil { - return x.Relation - } - return "" -} - -func (x *RelationTuple) GetSubject() *Subject { - if x != nil { - return x.Subject - } - return nil -} - -// Subject is either a concrete subject id or -// a `SubjectSet` expanding to more Subjects. -type Subject struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The reference of this abstract subject. - // - // Types that are assignable to Ref: - // *Subject_Id - // *Subject_Set - Ref isSubject_Ref `protobuf_oneof:"ref"` -} - -func (x *Subject) Reset() { - *x = Subject{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Subject) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Subject) ProtoMessage() {} - -func (x *Subject) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Subject.ProtoReflect.Descriptor instead. -func (*Subject) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_acl_proto_rawDescGZIP(), []int{1} -} - -func (m *Subject) GetRef() isSubject_Ref { - if m != nil { - return m.Ref - } - return nil -} - -func (x *Subject) GetId() string { - if x, ok := x.GetRef().(*Subject_Id); ok { - return x.Id - } - return "" -} - -func (x *Subject) GetSet() *SubjectSet { - if x, ok := x.GetRef().(*Subject_Set); ok { - return x.Set - } - return nil -} - -type isSubject_Ref interface { - isSubject_Ref() -} - -type Subject_Id struct { - // A concrete id of the subject. - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` -} - -type Subject_Set struct { - // A subject set that expands to more Subjects. - // More information are available under [concepts](../concepts/subjects.mdx). - Set *SubjectSet `protobuf:"bytes,2,opt,name=set,proto3,oneof"` -} - -func (*Subject_Id) isSubject_Ref() {} - -func (*Subject_Set) isSubject_Ref() {} - -// SubjectSet refers to all subjects who have -// the same `relation` on an `object`. -type SubjectSet struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The namespace of the object and relation - // referenced in this subject set. - Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` - // The object related by this subject set. - Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` - // The relation between the object and the subjects. - Relation string `protobuf:"bytes,3,opt,name=relation,proto3" json:"relation,omitempty"` -} - -func (x *SubjectSet) Reset() { - *x = SubjectSet{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SubjectSet) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubjectSet) ProtoMessage() {} - -func (x *SubjectSet) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubjectSet.ProtoReflect.Descriptor instead. -func (*SubjectSet) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_acl_proto_rawDescGZIP(), []int{2} -} - -func (x *SubjectSet) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *SubjectSet) GetObject() string { - if x != nil { - return x.Object - } - return "" -} - -func (x *SubjectSet) GetRelation() string { - if x != nil { - return x.Relation - } - return "" -} - -var File_ory_keto_acl_v1alpha1_acl_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_acl_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x15, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x9b, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x07, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x59, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x03, 0x73, 0x65, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x72, 0x65, - 0x66, 0x22, 0x5e, 0x0a, 0x0a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x74, 0x12, - 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x8b, 0x01, 0x0a, 0x18, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, - 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x08, - 0x41, 0x63, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, - 0x63, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x63, 0x6c, 0xaa, - 0x02, 0x15, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x41, 0x63, 0x6c, 0x2e, 0x56, - 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, - 0x74, 0x6f, 0x5c, 0x41, 0x63, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_acl_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_acl_proto_rawDescData = file_ory_keto_acl_v1alpha1_acl_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_acl_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_acl_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_acl_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_acl_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_acl_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_acl_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_ory_keto_acl_v1alpha1_acl_proto_goTypes = []interface{}{ - (*RelationTuple)(nil), // 0: ory.keto.acl.v1alpha1.RelationTuple - (*Subject)(nil), // 1: ory.keto.acl.v1alpha1.Subject - (*SubjectSet)(nil), // 2: ory.keto.acl.v1alpha1.SubjectSet -} -var file_ory_keto_acl_v1alpha1_acl_proto_depIdxs = []int32{ - 1, // 0: ory.keto.acl.v1alpha1.RelationTuple.subject:type_name -> ory.keto.acl.v1alpha1.Subject - 2, // 1: ory.keto.acl.v1alpha1.Subject.set:type_name -> ory.keto.acl.v1alpha1.SubjectSet - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_acl_proto_init() } -func file_ory_keto_acl_v1alpha1_acl_proto_init() { - if File_ory_keto_acl_v1alpha1_acl_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RelationTuple); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Subject); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubjectSet); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_ory_keto_acl_v1alpha1_acl_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Subject_Id)(nil), - (*Subject_Set)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_acl_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_ory_keto_acl_v1alpha1_acl_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_acl_proto_depIdxs, - MessageInfos: file_ory_keto_acl_v1alpha1_acl_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_acl_proto = out.File - file_ory_keto_acl_v1alpha1_acl_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_acl_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_acl_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.proto deleted file mode 100644 index 8f169125edc..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl.proto +++ /dev/null @@ -1,51 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "AclProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - - -// RelationTuple defines a relation between an Object and a Subject. -message RelationTuple { - // The namespace this relation tuple lives in. - string namespace = 1; - // The object related by this tuple. - // It is an object in the namespace of the tuple. - string object = 2; - // The relation between an Object and a Subject. - string relation = 3; - // The subject related by this tuple. - // A Subject either represents a concrete subject id or - // a `SubjectSet` that expands to more Subjects. - Subject subject = 4; -} - -// Subject is either a concrete subject id or -// a `SubjectSet` expanding to more Subjects. -message Subject { - // The reference of this abstract subject. - oneof ref { - // A concrete id of the subject. - string id = 1; - // A subject set that expands to more Subjects. - // More information are available under [concepts](../concepts/subjects.mdx). - SubjectSet set = 2; - } -} - -// SubjectSet refers to all subjects who have -// the same `relation` on an `object`. -message SubjectSet { - // The namespace of the object and relation - // referenced in this subject set. - string namespace = 1; - // The object related by this subject set. - string object = 2; - // The relation between the object and the subjects. - string relation = 3; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_grpc_pb.js deleted file mode 100644 index 97b3a2461db..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_grpc_pb.js +++ /dev/null @@ -1 +0,0 @@ -// GENERATED CODE -- NO SERVICES IN PROTO \ No newline at end of file diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.d.ts deleted file mode 100644 index b69b3b5978b..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.d.ts +++ /dev/null @@ -1,115 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/acl.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; - -export class RelationTuple extends jspb.Message { - getNamespace(): string; - setNamespace(value: string): RelationTuple; - - getObject(): string; - setObject(value: string): RelationTuple; - - getRelation(): string; - setRelation(value: string): RelationTuple; - - - hasSubject(): boolean; - clearSubject(): void; - getSubject(): Subject | undefined; - setSubject(value?: Subject): RelationTuple; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): RelationTuple.AsObject; - static toObject(includeInstance: boolean, msg: RelationTuple): RelationTuple.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: RelationTuple, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): RelationTuple; - static deserializeBinaryFromReader(message: RelationTuple, reader: jspb.BinaryReader): RelationTuple; -} - -export namespace RelationTuple { - export type AsObject = { - namespace: string, - object: string, - relation: string, - subject?: Subject.AsObject, - } -} - -export class Subject extends jspb.Message { - - hasId(): boolean; - clearId(): void; - getId(): string; - setId(value: string): Subject; - - - hasSet(): boolean; - clearSet(): void; - getSet(): SubjectSet | undefined; - setSet(value?: SubjectSet): Subject; - - - getRefCase(): Subject.RefCase; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): Subject.AsObject; - static toObject(includeInstance: boolean, msg: Subject): Subject.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: Subject, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): Subject; - static deserializeBinaryFromReader(message: Subject, reader: jspb.BinaryReader): Subject; -} - -export namespace Subject { - export type AsObject = { - id: string, - set?: SubjectSet.AsObject, - } - - export enum RefCase { - REF_NOT_SET = 0, - - ID = 1, - - SET = 2, - - } - -} - -export class SubjectSet extends jspb.Message { - getNamespace(): string; - setNamespace(value: string): SubjectSet; - - getObject(): string; - setObject(value: string): SubjectSet; - - getRelation(): string; - setRelation(value: string): SubjectSet; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): SubjectSet.AsObject; - static toObject(includeInstance: boolean, msg: SubjectSet): SubjectSet.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: SubjectSet, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): SubjectSet; - static deserializeBinaryFromReader(message: SubjectSet, reader: jspb.BinaryReader): SubjectSet; -} - -export namespace SubjectSet { - export type AsObject = { - namespace: string, - object: string, - relation: string, - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.js deleted file mode 100644 index ffed4ed94be..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/acl_pb.js +++ /dev/null @@ -1,738 +0,0 @@ -// source: ory/keto/acl/v1alpha1/acl.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.RelationTuple', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.Subject', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.Subject.RefCase', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.SubjectSet', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.RelationTuple = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.RelationTuple, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.RelationTuple.displayName = 'proto.ory.keto.acl.v1alpha1.RelationTuple'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.Subject = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.Subject, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.Subject.displayName = 'proto.ory.keto.acl.v1alpha1.Subject'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.SubjectSet = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.SubjectSet, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.SubjectSet.displayName = 'proto.ory.keto.acl.v1alpha1.SubjectSet'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.RelationTuple.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.RelationTuple} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.toObject = function(includeInstance, msg) { - var f, obj = { - namespace: jspb.Message.getFieldWithDefault(msg, 1, ""), - object: jspb.Message.getFieldWithDefault(msg, 2, ""), - relation: jspb.Message.getFieldWithDefault(msg, 3, ""), - subject: (f = msg.getSubject()) && proto.ory.keto.acl.v1alpha1.Subject.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.RelationTuple; - return proto.ory.keto.acl.v1alpha1.RelationTuple.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.RelationTuple} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setNamespace(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setObject(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setRelation(value); - break; - case 4: - var value = new proto.ory.keto.acl.v1alpha1.Subject; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.Subject.deserializeBinaryFromReader); - msg.setSubject(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.RelationTuple.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.RelationTuple} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getNamespace(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getObject(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getRelation(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getSubject(); - if (f != null) { - writer.writeMessage( - 4, - f, - proto.ory.keto.acl.v1alpha1.Subject.serializeBinaryToWriter - ); - } -}; - - -/** - * optional string namespace = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.getNamespace = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.setNamespace = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string object = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.getObject = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.setObject = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * optional string relation = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.getRelation = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.setRelation = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional Subject subject = 4; - * @return {?proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.getSubject = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.Subject} */ ( - jspb.Message.getWrapperField(this, proto.ory.keto.acl.v1alpha1.Subject, 4)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.Subject|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} returns this -*/ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.setSubject = function(value) { - return jspb.Message.setWrapperField(this, 4, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.clearSubject = function() { - return this.setSubject(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.RelationTuple.prototype.hasSubject = function() { - return jspb.Message.getField(this, 4) != null; -}; - - - -/** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const - */ -proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_ = [[1,2]]; - -/** - * @enum {number} - */ -proto.ory.keto.acl.v1alpha1.Subject.RefCase = { - REF_NOT_SET: 0, - ID: 1, - SET: 2 -}; - -/** - * @return {proto.ory.keto.acl.v1alpha1.Subject.RefCase} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.getRefCase = function() { - return /** @type {proto.ory.keto.acl.v1alpha1.Subject.RefCase} */(jspb.Message.computeOneofCase(this, proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_[0])); -}; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.Subject.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.Subject} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.Subject.toObject = function(includeInstance, msg) { - var f, obj = { - id: jspb.Message.getFieldWithDefault(msg, 1, ""), - set: (f = msg.getSet()) && proto.ory.keto.acl.v1alpha1.SubjectSet.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.Subject.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.Subject; - return proto.ory.keto.acl.v1alpha1.Subject.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.Subject} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.Subject.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setId(value); - break; - case 2: - var value = new proto.ory.keto.acl.v1alpha1.SubjectSet; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.SubjectSet.deserializeBinaryFromReader); - msg.setSet(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.Subject.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.Subject} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.Subject.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = /** @type {string} */ (jspb.Message.getField(message, 1)); - if (f != null) { - writer.writeString( - 1, - f - ); - } - f = message.getSet(); - if (f != null) { - writer.writeMessage( - 2, - f, - proto.ory.keto.acl.v1alpha1.SubjectSet.serializeBinaryToWriter - ); - } -}; - - -/** - * optional string id = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.getId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.Subject} returns this - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.setId = function(value) { - return jspb.Message.setOneofField(this, 1, proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_[0], value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.Subject} returns this - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.clearId = function() { - return jspb.Message.setOneofField(this, 1, proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_[0], undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.hasId = function() { - return jspb.Message.getField(this, 1) != null; -}; - - -/** - * optional SubjectSet set = 2; - * @return {?proto.ory.keto.acl.v1alpha1.SubjectSet} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.getSet = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.SubjectSet} */ ( - jspb.Message.getWrapperField(this, proto.ory.keto.acl.v1alpha1.SubjectSet, 2)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.SubjectSet|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.Subject} returns this -*/ -proto.ory.keto.acl.v1alpha1.Subject.prototype.setSet = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.ory.keto.acl.v1alpha1.Subject.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.Subject} returns this - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.clearSet = function() { - return this.setSet(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.Subject.prototype.hasSet = function() { - return jspb.Message.getField(this, 2) != null; -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.SubjectSet.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.SubjectSet} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.toObject = function(includeInstance, msg) { - var f, obj = { - namespace: jspb.Message.getFieldWithDefault(msg, 1, ""), - object: jspb.Message.getFieldWithDefault(msg, 2, ""), - relation: jspb.Message.getFieldWithDefault(msg, 3, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectSet} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.SubjectSet; - return proto.ory.keto.acl.v1alpha1.SubjectSet.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.SubjectSet} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectSet} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setNamespace(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setObject(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setRelation(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.SubjectSet.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.SubjectSet} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getNamespace(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getObject(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getRelation(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } -}; - - -/** - * optional string namespace = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.getNamespace = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectSet} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.setNamespace = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string object = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.getObject = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectSet} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.setObject = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * optional string relation = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.getRelation = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectSet} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectSet.prototype.setRelation = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.pb.go deleted file mode 100644 index e28b9da801d..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.pb.go +++ /dev/null @@ -1,354 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/check_service.proto - -package acl - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The request for a CheckService.Check RPC. -// Checks whether a specific subject is related to an object. -type CheckRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The namespace to evaluate the check. - // - // Note: If you use the expand-API and the check - // evaluates a RelationTuple specifying a SubjectSet as - // subject or due to a rewrite rule in a namespace config - // this check request may involve other namespaces automatically. - Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` - // The related object in this check. - Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` - // The relation between the Object and the Subject. - Relation string `protobuf:"bytes,3,opt,name=relation,proto3" json:"relation,omitempty"` - // The related subject in this check. - Subject *Subject `protobuf:"bytes,4,opt,name=subject,proto3" json:"subject,omitempty"` - // This field is not implemented yet and has no effect. - // - Latest bool `protobuf:"varint,5,opt,name=latest,proto3" json:"latest,omitempty"` - // This field is not implemented yet and has no effect. - // - Snaptoken string `protobuf:"bytes,6,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` -} - -func (x *CheckRequest) Reset() { - *x = CheckRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CheckRequest) ProtoMessage() {} - -func (x *CheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CheckRequest.ProtoReflect.Descriptor instead. -func (*CheckRequest) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_check_service_proto_rawDescGZIP(), []int{0} -} - -func (x *CheckRequest) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *CheckRequest) GetObject() string { - if x != nil { - return x.Object - } - return "" -} - -func (x *CheckRequest) GetRelation() string { - if x != nil { - return x.Relation - } - return "" -} - -func (x *CheckRequest) GetSubject() *Subject { - if x != nil { - return x.Subject - } - return nil -} - -func (x *CheckRequest) GetLatest() bool { - if x != nil { - return x.Latest - } - return false -} - -func (x *CheckRequest) GetSnaptoken() string { - if x != nil { - return x.Snaptoken - } - return "" -} - -// The response for a CheckService.Check rpc. -type CheckResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Whether the specified subject (id) - // is related to the requested object. - // - // It is false by default if no ACL matches. - Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` - // This field is not implemented yet and has no effect. - // - Snaptoken string `protobuf:"bytes,2,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` -} - -func (x *CheckResponse) Reset() { - *x = CheckResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CheckResponse) ProtoMessage() {} - -func (x *CheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CheckResponse.ProtoReflect.Descriptor instead. -func (*CheckResponse) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_check_service_proto_rawDescGZIP(), []int{1} -} - -func (x *CheckResponse) GetAllowed() bool { - if x != nil { - return x.Allowed - } - return false -} - -func (x *CheckResponse) GetSnaptoken() string { - if x != nil { - return x.Snaptoken - } - return "" -} - -var File_ory_keto_acl_v1alpha1_check_service_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_check_service_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x1f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xd0, 0x01, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, - 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6e, 0x61, - 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x47, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, - 0x62, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x52, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x23, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, - 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x94, 0x01, 0x0a, 0x18, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, - 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x42, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x63, 0x6c, 0xaa, 0x02, 0x15, 0x4f, 0x72, 0x79, - 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x41, 0x63, 0x6c, 0x2e, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, 0x74, 0x6f, 0x5c, 0x41, 0x63, - 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_check_service_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_check_service_proto_rawDescData = file_ory_keto_acl_v1alpha1_check_service_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_check_service_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_check_service_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_check_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_check_service_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_check_service_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_ory_keto_acl_v1alpha1_check_service_proto_goTypes = []interface{}{ - (*CheckRequest)(nil), // 0: ory.keto.acl.v1alpha1.CheckRequest - (*CheckResponse)(nil), // 1: ory.keto.acl.v1alpha1.CheckResponse - (*Subject)(nil), // 2: ory.keto.acl.v1alpha1.Subject -} -var file_ory_keto_acl_v1alpha1_check_service_proto_depIdxs = []int32{ - 2, // 0: ory.keto.acl.v1alpha1.CheckRequest.subject:type_name -> ory.keto.acl.v1alpha1.Subject - 0, // 1: ory.keto.acl.v1alpha1.CheckService.Check:input_type -> ory.keto.acl.v1alpha1.CheckRequest - 1, // 2: ory.keto.acl.v1alpha1.CheckService.Check:output_type -> ory.keto.acl.v1alpha1.CheckResponse - 2, // [2:3] is the sub-list for method output_type - 1, // [1:2] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_check_service_proto_init() } -func file_ory_keto_acl_v1alpha1_check_service_proto_init() { - if File_ory_keto_acl_v1alpha1_check_service_proto != nil { - return - } - file_ory_keto_acl_v1alpha1_acl_proto_init() - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_check_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_ory_keto_acl_v1alpha1_check_service_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_check_service_proto_depIdxs, - MessageInfos: file_ory_keto_acl_v1alpha1_check_service_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_check_service_proto = out.File - file_ory_keto_acl_v1alpha1_check_service_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_check_service_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_check_service_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.proto deleted file mode 100644 index 88135a96611..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service.proto +++ /dev/null @@ -1,99 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -import "ory/keto/acl/v1alpha1/acl.proto"; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "CheckServiceProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - -// The service that performs authorization checks -// based on the stored Access Control Lists. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -service CheckService { - // Performs an authorization check. - rpc Check(CheckRequest) returns (CheckResponse); -} - -// The request for a CheckService.Check RPC. -// Checks whether a specific subject is related to an object. -message CheckRequest { - // The namespace to evaluate the check. - // - // Note: If you use the expand-API and the check - // evaluates a RelationTuple specifying a SubjectSet as - // subject or due to a rewrite rule in a namespace config - // this check request may involve other namespaces automatically. - string namespace = 1; - // The related object in this check. - string object = 2; - // The relation between the Object and the Subject. - string relation = 3; - // The related subject in this check. - Subject subject = 4; - // This field is not implemented yet and has no effect. - // - bool latest = 5; - // This field is not implemented yet and has no effect. - // - string snaptoken = 6; -} - -// The response for a CheckService.Check rpc. -message CheckResponse { - // Whether the specified subject (id) - // is related to the requested object. - // - // It is false by default if no ACL matches. - bool allowed = 1; - // This field is not implemented yet and has no effect. - // - string snaptoken = 2; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc.pb.go deleted file mode 100644 index 629b65779f9..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc.pb.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package acl - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// CheckServiceClient is the client API for CheckService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type CheckServiceClient interface { - // Performs an authorization check. - Check(ctx context.Context, in *CheckRequest, opts ...grpc.CallOption) (*CheckResponse, error) -} - -type checkServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewCheckServiceClient(cc grpc.ClientConnInterface) CheckServiceClient { - return &checkServiceClient{cc} -} - -func (c *checkServiceClient) Check(ctx context.Context, in *CheckRequest, opts ...grpc.CallOption) (*CheckResponse, error) { - out := new(CheckResponse) - err := c.cc.Invoke(ctx, "/ory.keto.acl.v1alpha1.CheckService/Check", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// CheckServiceServer is the server API for CheckService service. -// All implementations should embed UnimplementedCheckServiceServer -// for forward compatibility -type CheckServiceServer interface { - // Performs an authorization check. - Check(context.Context, *CheckRequest) (*CheckResponse, error) -} - -// UnimplementedCheckServiceServer should be embedded to have forward compatible implementations. -type UnimplementedCheckServiceServer struct { -} - -func (UnimplementedCheckServiceServer) Check(context.Context, *CheckRequest) (*CheckResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Check not implemented") -} - -// UnsafeCheckServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to CheckServiceServer will -// result in compilation errors. -type UnsafeCheckServiceServer interface { - mustEmbedUnimplementedCheckServiceServer() -} - -func RegisterCheckServiceServer(s grpc.ServiceRegistrar, srv CheckServiceServer) { - s.RegisterService(&CheckService_ServiceDesc, srv) -} - -func _CheckService_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CheckRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CheckServiceServer).Check(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ory.keto.acl.v1alpha1.CheckService/Check", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CheckServiceServer).Check(ctx, req.(*CheckRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// CheckService_ServiceDesc is the grpc.ServiceDesc for CheckService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var CheckService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "ory.keto.acl.v1alpha1.CheckService", - HandlerType: (*CheckServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Check", - Handler: _CheckService_Check_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ory/keto/acl/v1alpha1/check_service.proto", -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.d.ts deleted file mode 100644 index 393a6edc9ce..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/check_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as grpc from "grpc"; -import * as ory_keto_acl_v1alpha1_check_service_pb from "../../../../ory/keto/acl/v1alpha1/check_service_pb"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -interface ICheckServiceService extends grpc.ServiceDefinition { - check: ICheckServiceService_ICheck; -} - -interface ICheckServiceService_ICheck extends grpc.MethodDefinition { - path: "/ory.keto.acl.v1alpha1.CheckService/Check"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} - -export const CheckServiceService: ICheckServiceService; - -export interface ICheckServiceServer { - check: grpc.handleUnaryCall; -} - -export interface ICheckServiceClient { - check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; - check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; - check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; -} - -export class CheckServiceClient extends grpc.Client implements ICheckServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; - public check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; - public check(request: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.js deleted file mode 100644 index 9d3e1386508..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_grpc_pb.js +++ /dev/null @@ -1,50 +0,0 @@ -// GENERATED CODE -- DO NOT EDIT! - -'use strict'; -var grpc = require('@grpc/grpc-js'); -var ory_keto_acl_v1alpha1_check_service_pb = require('../../../../ory/keto/acl/v1alpha1/check_service_pb.js'); -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); - -function serialize_ory_keto_acl_v1alpha1_CheckRequest(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_check_service_pb.CheckRequest)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.CheckRequest'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_CheckRequest(buffer_arg) { - return ory_keto_acl_v1alpha1_check_service_pb.CheckRequest.deserializeBinary(new Uint8Array(buffer_arg)); -} - -function serialize_ory_keto_acl_v1alpha1_CheckResponse(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_check_service_pb.CheckResponse)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.CheckResponse'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_CheckResponse(buffer_arg) { - return ory_keto_acl_v1alpha1_check_service_pb.CheckResponse.deserializeBinary(new Uint8Array(buffer_arg)); -} - - -// The service that performs authorization checks -// based on the stored Access Control Lists. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -var CheckServiceService = exports.CheckServiceService = { - // Performs an authorization check. -check: { - path: '/ory.keto.acl.v1alpha1.CheckService/Check', - requestStream: false, - responseStream: false, - requestType: ory_keto_acl_v1alpha1_check_service_pb.CheckRequest, - responseType: ory_keto_acl_v1alpha1_check_service_pb.CheckResponse, - requestSerialize: serialize_ory_keto_acl_v1alpha1_CheckRequest, - requestDeserialize: deserialize_ory_keto_acl_v1alpha1_CheckRequest, - responseSerialize: serialize_ory_keto_acl_v1alpha1_CheckResponse, - responseDeserialize: deserialize_ory_keto_acl_v1alpha1_CheckResponse, - }, -}; - -exports.CheckServiceClient = grpc.makeGenericClientConstructor(CheckServiceService); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.d.ts deleted file mode 100644 index 7c13b6ea897..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.d.ts +++ /dev/null @@ -1,77 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/check_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -export class CheckRequest extends jspb.Message { - getNamespace(): string; - setNamespace(value: string): CheckRequest; - - getObject(): string; - setObject(value: string): CheckRequest; - - getRelation(): string; - setRelation(value: string): CheckRequest; - - - hasSubject(): boolean; - clearSubject(): void; - getSubject(): ory_keto_acl_v1alpha1_acl_pb.Subject | undefined; - setSubject(value?: ory_keto_acl_v1alpha1_acl_pb.Subject): CheckRequest; - - getLatest(): boolean; - setLatest(value: boolean): CheckRequest; - - getSnaptoken(): string; - setSnaptoken(value: string): CheckRequest; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): CheckRequest.AsObject; - static toObject(includeInstance: boolean, msg: CheckRequest): CheckRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: CheckRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): CheckRequest; - static deserializeBinaryFromReader(message: CheckRequest, reader: jspb.BinaryReader): CheckRequest; -} - -export namespace CheckRequest { - export type AsObject = { - namespace: string, - object: string, - relation: string, - subject?: ory_keto_acl_v1alpha1_acl_pb.Subject.AsObject, - latest: boolean, - snaptoken: string, - } -} - -export class CheckResponse extends jspb.Message { - getAllowed(): boolean; - setAllowed(value: boolean): CheckResponse; - - getSnaptoken(): string; - setSnaptoken(value: string): CheckResponse; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): CheckResponse.AsObject; - static toObject(includeInstance: boolean, msg: CheckResponse): CheckResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: CheckResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): CheckResponse; - static deserializeBinaryFromReader(message: CheckResponse, reader: jspb.BinaryReader): CheckResponse; -} - -export namespace CheckResponse { - export type AsObject = { - allowed: boolean, - snaptoken: string, - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.js deleted file mode 100644 index c26177bd70c..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/check_service_pb.js +++ /dev/null @@ -1,522 +0,0 @@ -// source: ory/keto/acl/v1alpha1/check_service.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); -goog.object.extend(proto, ory_keto_acl_v1alpha1_acl_pb); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.CheckRequest', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.CheckResponse', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.CheckRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.CheckRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.CheckRequest.displayName = 'proto.ory.keto.acl.v1alpha1.CheckRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.CheckResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.CheckResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.CheckResponse.displayName = 'proto.ory.keto.acl.v1alpha1.CheckResponse'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.CheckRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.CheckRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.toObject = function(includeInstance, msg) { - var f, obj = { - namespace: jspb.Message.getFieldWithDefault(msg, 1, ""), - object: jspb.Message.getFieldWithDefault(msg, 2, ""), - relation: jspb.Message.getFieldWithDefault(msg, 3, ""), - subject: (f = msg.getSubject()) && ory_keto_acl_v1alpha1_acl_pb.Subject.toObject(includeInstance, f), - latest: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), - snaptoken: jspb.Message.getFieldWithDefault(msg, 6, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.CheckRequest; - return proto.ory.keto.acl.v1alpha1.CheckRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.CheckRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setNamespace(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setObject(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setRelation(value); - break; - case 4: - var value = new ory_keto_acl_v1alpha1_acl_pb.Subject; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.Subject.deserializeBinaryFromReader); - msg.setSubject(value); - break; - case 5: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setLatest(value); - break; - case 6: - var value = /** @type {string} */ (reader.readString()); - msg.setSnaptoken(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.CheckRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.CheckRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getNamespace(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getObject(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getRelation(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getSubject(); - if (f != null) { - writer.writeMessage( - 4, - f, - ory_keto_acl_v1alpha1_acl_pb.Subject.serializeBinaryToWriter - ); - } - f = message.getLatest(); - if (f) { - writer.writeBool( - 5, - f - ); - } - f = message.getSnaptoken(); - if (f.length > 0) { - writer.writeString( - 6, - f - ); - } -}; - - -/** - * optional string namespace = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getNamespace = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setNamespace = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string object = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getObject = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setObject = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * optional string relation = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getRelation = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setRelation = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional Subject subject = 4; - * @return {?proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getSubject = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.Subject} */ ( - jspb.Message.getWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.Subject, 4)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.Subject|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this -*/ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setSubject = function(value) { - return jspb.Message.setWrapperField(this, 4, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.clearSubject = function() { - return this.setSubject(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.hasSubject = function() { - return jspb.Message.getField(this, 4) != null; -}; - - -/** - * optional bool latest = 5; - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getLatest = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setLatest = function(value) { - return jspb.Message.setProto3BooleanField(this, 5, value); -}; - - -/** - * optional string snaptoken = 6; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.getSnaptoken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckRequest.prototype.setSnaptoken = function(value) { - return jspb.Message.setProto3StringField(this, 6, value); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.CheckResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.CheckResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.toObject = function(includeInstance, msg) { - var f, obj = { - allowed: jspb.Message.getBooleanFieldWithDefault(msg, 1, false), - snaptoken: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.CheckResponse} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.CheckResponse; - return proto.ory.keto.acl.v1alpha1.CheckResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.CheckResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.CheckResponse} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setAllowed(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setSnaptoken(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.CheckResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.CheckResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getAllowed(); - if (f) { - writer.writeBool( - 1, - f - ); - } - f = message.getSnaptoken(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } -}; - - -/** - * optional bool allowed = 1; - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.getAllowed = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.setAllowed = function(value) { - return jspb.Message.setProto3BooleanField(this, 1, value); -}; - - -/** - * optional string snaptoken = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.getSnaptoken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.CheckResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.CheckResponse.prototype.setSnaptoken = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.pb.go deleted file mode 100644 index 5adc07a8aca..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.pb.go +++ /dev/null @@ -1,449 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/expand_service.proto - -package acl - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type NodeType int32 - -const ( - NodeType_NODE_TYPE_UNSPECIFIED NodeType = 0 - // This node expands to a union of all children. - NodeType_NODE_TYPE_UNION NodeType = 1 - // Not implemented yet. - NodeType_NODE_TYPE_EXCLUSION NodeType = 2 - // Not implemented yet. - NodeType_NODE_TYPE_INTERSECTION NodeType = 3 - // This node is a leaf and contains no children. - // Its subject is a `SubjectID` unless `max_depth` was reached. - NodeType_NODE_TYPE_LEAF NodeType = 4 -) - -// Enum value maps for NodeType. -var ( - NodeType_name = map[int32]string{ - 0: "NODE_TYPE_UNSPECIFIED", - 1: "NODE_TYPE_UNION", - 2: "NODE_TYPE_EXCLUSION", - 3: "NODE_TYPE_INTERSECTION", - 4: "NODE_TYPE_LEAF", - } - NodeType_value = map[string]int32{ - "NODE_TYPE_UNSPECIFIED": 0, - "NODE_TYPE_UNION": 1, - "NODE_TYPE_EXCLUSION": 2, - "NODE_TYPE_INTERSECTION": 3, - "NODE_TYPE_LEAF": 4, - } -) - -func (x NodeType) Enum() *NodeType { - p := new(NodeType) - *p = x - return p -} - -func (x NodeType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (NodeType) Descriptor() protoreflect.EnumDescriptor { - return file_ory_keto_acl_v1alpha1_expand_service_proto_enumTypes[0].Descriptor() -} - -func (NodeType) Type() protoreflect.EnumType { - return &file_ory_keto_acl_v1alpha1_expand_service_proto_enumTypes[0] -} - -func (x NodeType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use NodeType.Descriptor instead. -func (NodeType) EnumDescriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescGZIP(), []int{0} -} - -// The request for an ExpandService.Expand RPC. -// Expands the given subject set. -type ExpandRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The subject to expand. - Subject *Subject `protobuf:"bytes,1,opt,name=subject,proto3" json:"subject,omitempty"` - // The maximum depth of tree to build. - // It is important to set this parameter to a meaningful - // value. Ponder how deep you really want to display this. - MaxDepth int32 `protobuf:"varint,2,opt,name=max_depth,json=maxDepth,proto3" json:"max_depth,omitempty"` - // This field is not implemented yet and has no effect. - // - Snaptoken string `protobuf:"bytes,3,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` -} - -func (x *ExpandRequest) Reset() { - *x = ExpandRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExpandRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExpandRequest) ProtoMessage() {} - -func (x *ExpandRequest) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExpandRequest.ProtoReflect.Descriptor instead. -func (*ExpandRequest) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescGZIP(), []int{0} -} - -func (x *ExpandRequest) GetSubject() *Subject { - if x != nil { - return x.Subject - } - return nil -} - -func (x *ExpandRequest) GetMaxDepth() int32 { - if x != nil { - return x.MaxDepth - } - return 0 -} - -func (x *ExpandRequest) GetSnaptoken() string { - if x != nil { - return x.Snaptoken - } - return "" -} - -// The response for a ExpandService.Expand RPC. -type ExpandResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The tree the requested subject set expands to. - // The requested subject set is the subject of the root. - // - // This field can be nil in some circumstances. - Tree *SubjectTree `protobuf:"bytes,1,opt,name=tree,proto3" json:"tree,omitempty"` -} - -func (x *ExpandResponse) Reset() { - *x = ExpandResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExpandResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExpandResponse) ProtoMessage() {} - -func (x *ExpandResponse) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExpandResponse.ProtoReflect.Descriptor instead. -func (*ExpandResponse) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescGZIP(), []int{1} -} - -func (x *ExpandResponse) GetTree() *SubjectTree { - if x != nil { - return x.Tree - } - return nil -} - -type SubjectTree struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The type of the node. - NodeType NodeType `protobuf:"varint,1,opt,name=node_type,json=nodeType,proto3,enum=ory.keto.acl.v1alpha1.NodeType" json:"node_type,omitempty"` - // The subject this node represents. - Subject *Subject `protobuf:"bytes,2,opt,name=subject,proto3" json:"subject,omitempty"` - // The children of this node. - // - // This is never set if `node_type` == `NODE_TYPE_LEAF`. - Children []*SubjectTree `protobuf:"bytes,3,rep,name=children,proto3" json:"children,omitempty"` -} - -func (x *SubjectTree) Reset() { - *x = SubjectTree{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SubjectTree) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubjectTree) ProtoMessage() {} - -func (x *SubjectTree) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubjectTree.ProtoReflect.Descriptor instead. -func (*SubjectTree) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescGZIP(), []int{2} -} - -func (x *SubjectTree) GetNodeType() NodeType { - if x != nil { - return x.NodeType - } - return NodeType_NODE_TYPE_UNSPECIFIED -} - -func (x *SubjectTree) GetSubject() *Subject { - if x != nil { - return x.Subject - } - return nil -} - -func (x *SubjectTree) GetChildren() []*SubjectTree { - if x != nil { - return x.Children - } - return nil -} - -var File_ory_keto_acl_v1alpha1_expand_service_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_expand_service_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x1a, 0x1f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, - 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, - 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x12, 0x1c, 0x0a, - 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x48, 0x0a, 0x0e, 0x45, - 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, - 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x72, 0x65, 0x65, 0x52, - 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0xc5, 0x01, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, - 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, - 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x3e, 0x0a, - 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x2a, 0x83, 0x01, - 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4e, 0x4f, - 0x44, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4e, 0x4f, - 0x44, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x53, 0x49, 0x4f, - 0x4e, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x53, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, - 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x45, 0x41, - 0x46, 0x10, 0x04, 0x32, 0x66, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0x24, - 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, - 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, - 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x95, 0x01, 0x0a, 0x18, - 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x12, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, - 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, - 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x61, 0x63, 0x6c, 0xaa, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x41, - 0x63, 0x6c, 0x2e, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, 0x72, - 0x79, 0x5c, 0x4b, 0x65, 0x74, 0x6f, 0x5c, 0x41, 0x63, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescData = file_ory_keto_acl_v1alpha1_expand_service_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_expand_service_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_expand_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_ory_keto_acl_v1alpha1_expand_service_proto_goTypes = []interface{}{ - (NodeType)(0), // 0: ory.keto.acl.v1alpha1.NodeType - (*ExpandRequest)(nil), // 1: ory.keto.acl.v1alpha1.ExpandRequest - (*ExpandResponse)(nil), // 2: ory.keto.acl.v1alpha1.ExpandResponse - (*SubjectTree)(nil), // 3: ory.keto.acl.v1alpha1.SubjectTree - (*Subject)(nil), // 4: ory.keto.acl.v1alpha1.Subject -} -var file_ory_keto_acl_v1alpha1_expand_service_proto_depIdxs = []int32{ - 4, // 0: ory.keto.acl.v1alpha1.ExpandRequest.subject:type_name -> ory.keto.acl.v1alpha1.Subject - 3, // 1: ory.keto.acl.v1alpha1.ExpandResponse.tree:type_name -> ory.keto.acl.v1alpha1.SubjectTree - 0, // 2: ory.keto.acl.v1alpha1.SubjectTree.node_type:type_name -> ory.keto.acl.v1alpha1.NodeType - 4, // 3: ory.keto.acl.v1alpha1.SubjectTree.subject:type_name -> ory.keto.acl.v1alpha1.Subject - 3, // 4: ory.keto.acl.v1alpha1.SubjectTree.children:type_name -> ory.keto.acl.v1alpha1.SubjectTree - 1, // 5: ory.keto.acl.v1alpha1.ExpandService.Expand:input_type -> ory.keto.acl.v1alpha1.ExpandRequest - 2, // 6: ory.keto.acl.v1alpha1.ExpandService.Expand:output_type -> ory.keto.acl.v1alpha1.ExpandResponse - 6, // [6:7] is the sub-list for method output_type - 5, // [5:6] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_expand_service_proto_init() } -func file_ory_keto_acl_v1alpha1_expand_service_proto_init() { - if File_ory_keto_acl_v1alpha1_expand_service_proto != nil { - return - } - file_ory_keto_acl_v1alpha1_acl_proto_init() - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExpandRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExpandResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubjectTree); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_expand_service_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_ory_keto_acl_v1alpha1_expand_service_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_expand_service_proto_depIdxs, - EnumInfos: file_ory_keto_acl_v1alpha1_expand_service_proto_enumTypes, - MessageInfos: file_ory_keto_acl_v1alpha1_expand_service_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_expand_service_proto = out.File - file_ory_keto_acl_v1alpha1_expand_service_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_expand_service_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_expand_service_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.proto deleted file mode 100644 index 08fc7c5a941..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service.proto +++ /dev/null @@ -1,82 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -import "ory/keto/acl/v1alpha1/acl.proto"; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "ExpandServiceProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - -// The service that performs subject set expansion -// based on the stored Access Control Lists. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -service ExpandService { - // Expands the subject set into a tree of subjects. - rpc Expand(ExpandRequest) returns (ExpandResponse); -} - -// The request for an ExpandService.Expand RPC. -// Expands the given subject set. -message ExpandRequest { - // The subject to expand. - Subject subject = 1; - // The maximum depth of tree to build. - // It is important to set this parameter to a meaningful - // value. Ponder how deep you really want to display this. - int32 max_depth = 2; - // This field is not implemented yet and has no effect. - // - string snaptoken = 3; -} - -// The response for a ExpandService.Expand RPC. -message ExpandResponse { - // The tree the requested subject set expands to. - // The requested subject set is the subject of the root. - // - // This field can be nil in some circumstances. - SubjectTree tree = 1; -} - -enum NodeType { - NODE_TYPE_UNSPECIFIED = 0; - // This node expands to a union of all children. - NODE_TYPE_UNION = 1; - // Not implemented yet. - NODE_TYPE_EXCLUSION = 2; - // Not implemented yet. - NODE_TYPE_INTERSECTION = 3; - // This node is a leaf and contains no children. - // Its subject is a `SubjectID` unless `max_depth` was reached. - NODE_TYPE_LEAF = 4; -} - -message SubjectTree { - // The type of the node. - NodeType node_type = 1; - // The subject this node represents. - Subject subject = 2; - // The children of this node. - // - // This is never set if `node_type` == `NODE_TYPE_LEAF`. - repeated SubjectTree children = 3; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc.pb.go deleted file mode 100644 index 7b55fb971ab..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc.pb.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package acl - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// ExpandServiceClient is the client API for ExpandService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ExpandServiceClient interface { - // Expands the subject set into a tree of subjects. - Expand(ctx context.Context, in *ExpandRequest, opts ...grpc.CallOption) (*ExpandResponse, error) -} - -type expandServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewExpandServiceClient(cc grpc.ClientConnInterface) ExpandServiceClient { - return &expandServiceClient{cc} -} - -func (c *expandServiceClient) Expand(ctx context.Context, in *ExpandRequest, opts ...grpc.CallOption) (*ExpandResponse, error) { - out := new(ExpandResponse) - err := c.cc.Invoke(ctx, "/ory.keto.acl.v1alpha1.ExpandService/Expand", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ExpandServiceServer is the server API for ExpandService service. -// All implementations should embed UnimplementedExpandServiceServer -// for forward compatibility -type ExpandServiceServer interface { - // Expands the subject set into a tree of subjects. - Expand(context.Context, *ExpandRequest) (*ExpandResponse, error) -} - -// UnimplementedExpandServiceServer should be embedded to have forward compatible implementations. -type UnimplementedExpandServiceServer struct { -} - -func (UnimplementedExpandServiceServer) Expand(context.Context, *ExpandRequest) (*ExpandResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Expand not implemented") -} - -// UnsafeExpandServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ExpandServiceServer will -// result in compilation errors. -type UnsafeExpandServiceServer interface { - mustEmbedUnimplementedExpandServiceServer() -} - -func RegisterExpandServiceServer(s grpc.ServiceRegistrar, srv ExpandServiceServer) { - s.RegisterService(&ExpandService_ServiceDesc, srv) -} - -func _ExpandService_Expand_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ExpandRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ExpandServiceServer).Expand(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ory.keto.acl.v1alpha1.ExpandService/Expand", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ExpandServiceServer).Expand(ctx, req.(*ExpandRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// ExpandService_ServiceDesc is the grpc.ServiceDesc for ExpandService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var ExpandService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "ory.keto.acl.v1alpha1.ExpandService", - HandlerType: (*ExpandServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Expand", - Handler: _ExpandService_Expand_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ory/keto/acl/v1alpha1/expand_service.proto", -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.d.ts deleted file mode 100644 index 36305fc058b..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/expand_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as grpc from "grpc"; -import * as ory_keto_acl_v1alpha1_expand_service_pb from "../../../../ory/keto/acl/v1alpha1/expand_service_pb"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -interface IExpandServiceService extends grpc.ServiceDefinition { - expand: IExpandServiceService_IExpand; -} - -interface IExpandServiceService_IExpand extends grpc.MethodDefinition { - path: "/ory.keto.acl.v1alpha1.ExpandService/Expand"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} - -export const ExpandServiceService: IExpandServiceService; - -export interface IExpandServiceServer { - expand: grpc.handleUnaryCall; -} - -export interface IExpandServiceClient { - expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; - expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; - expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; -} - -export class ExpandServiceClient extends grpc.Client implements IExpandServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; - public expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; - public expand(request: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.js deleted file mode 100644 index 6dc9e238b50..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_grpc_pb.js +++ /dev/null @@ -1,50 +0,0 @@ -// GENERATED CODE -- DO NOT EDIT! - -'use strict'; -var grpc = require('@grpc/grpc-js'); -var ory_keto_acl_v1alpha1_expand_service_pb = require('../../../../ory/keto/acl/v1alpha1/expand_service_pb.js'); -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); - -function serialize_ory_keto_acl_v1alpha1_ExpandRequest(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.ExpandRequest'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_ExpandRequest(buffer_arg) { - return ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest.deserializeBinary(new Uint8Array(buffer_arg)); -} - -function serialize_ory_keto_acl_v1alpha1_ExpandResponse(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.ExpandResponse'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_ExpandResponse(buffer_arg) { - return ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse.deserializeBinary(new Uint8Array(buffer_arg)); -} - - -// The service that performs subject set expansion -// based on the stored Access Control Lists. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -var ExpandServiceService = exports.ExpandServiceService = { - // Expands the subject set into a tree of subjects. -expand: { - path: '/ory.keto.acl.v1alpha1.ExpandService/Expand', - requestStream: false, - responseStream: false, - requestType: ory_keto_acl_v1alpha1_expand_service_pb.ExpandRequest, - responseType: ory_keto_acl_v1alpha1_expand_service_pb.ExpandResponse, - requestSerialize: serialize_ory_keto_acl_v1alpha1_ExpandRequest, - requestDeserialize: deserialize_ory_keto_acl_v1alpha1_ExpandRequest, - responseSerialize: serialize_ory_keto_acl_v1alpha1_ExpandResponse, - responseDeserialize: deserialize_ory_keto_acl_v1alpha1_ExpandResponse, - }, -}; - -exports.ExpandServiceClient = grpc.makeGenericClientConstructor(ExpandServiceService); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.d.ts deleted file mode 100644 index 803dbeff77c..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/expand_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -export class ExpandRequest extends jspb.Message { - - hasSubject(): boolean; - clearSubject(): void; - getSubject(): ory_keto_acl_v1alpha1_acl_pb.Subject | undefined; - setSubject(value?: ory_keto_acl_v1alpha1_acl_pb.Subject): ExpandRequest; - - getMaxDepth(): number; - setMaxDepth(value: number): ExpandRequest; - - getSnaptoken(): string; - setSnaptoken(value: string): ExpandRequest; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): ExpandRequest.AsObject; - static toObject(includeInstance: boolean, msg: ExpandRequest): ExpandRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: ExpandRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): ExpandRequest; - static deserializeBinaryFromReader(message: ExpandRequest, reader: jspb.BinaryReader): ExpandRequest; -} - -export namespace ExpandRequest { - export type AsObject = { - subject?: ory_keto_acl_v1alpha1_acl_pb.Subject.AsObject, - maxDepth: number, - snaptoken: string, - } -} - -export class ExpandResponse extends jspb.Message { - - hasTree(): boolean; - clearTree(): void; - getTree(): SubjectTree | undefined; - setTree(value?: SubjectTree): ExpandResponse; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): ExpandResponse.AsObject; - static toObject(includeInstance: boolean, msg: ExpandResponse): ExpandResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: ExpandResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): ExpandResponse; - static deserializeBinaryFromReader(message: ExpandResponse, reader: jspb.BinaryReader): ExpandResponse; -} - -export namespace ExpandResponse { - export type AsObject = { - tree?: SubjectTree.AsObject, - } -} - -export class SubjectTree extends jspb.Message { - getNodeType(): NodeType; - setNodeType(value: NodeType): SubjectTree; - - - hasSubject(): boolean; - clearSubject(): void; - getSubject(): ory_keto_acl_v1alpha1_acl_pb.Subject | undefined; - setSubject(value?: ory_keto_acl_v1alpha1_acl_pb.Subject): SubjectTree; - - clearChildrenList(): void; - getChildrenList(): Array; - setChildrenList(value: Array): SubjectTree; - addChildren(value?: SubjectTree, index?: number): SubjectTree; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): SubjectTree.AsObject; - static toObject(includeInstance: boolean, msg: SubjectTree): SubjectTree.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: SubjectTree, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): SubjectTree; - static deserializeBinaryFromReader(message: SubjectTree, reader: jspb.BinaryReader): SubjectTree; -} - -export namespace SubjectTree { - export type AsObject = { - nodeType: NodeType, - subject?: ory_keto_acl_v1alpha1_acl_pb.Subject.AsObject, - childrenList: Array, - } -} - -export enum NodeType { - NODE_TYPE_UNSPECIFIED = 0, - NODE_TYPE_UNION = 1, - NODE_TYPE_EXCLUSION = 2, - NODE_TYPE_INTERSECTION = 3, - NODE_TYPE_LEAF = 4, -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.js deleted file mode 100644 index 80c0fb9f65b..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/expand_service_pb.js +++ /dev/null @@ -1,698 +0,0 @@ -// source: ory/keto/acl/v1alpha1/expand_service.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); -goog.object.extend(proto, ory_keto_acl_v1alpha1_acl_pb); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.ExpandRequest', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.ExpandResponse', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.NodeType', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.SubjectTree', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.ExpandRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.ExpandRequest.displayName = 'proto.ory.keto.acl.v1alpha1.ExpandRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.ExpandResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.ExpandResponse.displayName = 'proto.ory.keto.acl.v1alpha1.ExpandResponse'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.SubjectTree = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.acl.v1alpha1.SubjectTree.repeatedFields_, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.SubjectTree, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.SubjectTree.displayName = 'proto.ory.keto.acl.v1alpha1.SubjectTree'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.ExpandRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.ExpandRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.toObject = function(includeInstance, msg) { - var f, obj = { - subject: (f = msg.getSubject()) && ory_keto_acl_v1alpha1_acl_pb.Subject.toObject(includeInstance, f), - maxDepth: jspb.Message.getFieldWithDefault(msg, 2, 0), - snaptoken: jspb.Message.getFieldWithDefault(msg, 3, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.ExpandRequest; - return proto.ory.keto.acl.v1alpha1.ExpandRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.ExpandRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new ory_keto_acl_v1alpha1_acl_pb.Subject; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.Subject.deserializeBinaryFromReader); - msg.setSubject(value); - break; - case 2: - var value = /** @type {number} */ (reader.readInt32()); - msg.setMaxDepth(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setSnaptoken(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.ExpandRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.ExpandRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getSubject(); - if (f != null) { - writer.writeMessage( - 1, - f, - ory_keto_acl_v1alpha1_acl_pb.Subject.serializeBinaryToWriter - ); - } - f = message.getMaxDepth(); - if (f !== 0) { - writer.writeInt32( - 2, - f - ); - } - f = message.getSnaptoken(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } -}; - - -/** - * optional Subject subject = 1; - * @return {?proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.getSubject = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.Subject} */ ( - jspb.Message.getWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.Subject, 1)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.Subject|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} returns this -*/ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.setSubject = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.clearSubject = function() { - return this.setSubject(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.hasSubject = function() { - return jspb.Message.getField(this, 1) != null; -}; - - -/** - * optional int32 max_depth = 2; - * @return {number} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.getMaxDepth = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.setMaxDepth = function(value) { - return jspb.Message.setProto3IntField(this, 2, value); -}; - - -/** - * optional string snaptoken = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.getSnaptoken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ExpandRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ExpandRequest.prototype.setSnaptoken = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.ExpandResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.ExpandResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.toObject = function(includeInstance, msg) { - var f, obj = { - tree: (f = msg.getTree()) && proto.ory.keto.acl.v1alpha1.SubjectTree.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandResponse} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.ExpandResponse; - return proto.ory.keto.acl.v1alpha1.ExpandResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.ExpandResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandResponse} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new proto.ory.keto.acl.v1alpha1.SubjectTree; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.SubjectTree.deserializeBinaryFromReader); - msg.setTree(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.ExpandResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.ExpandResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getTree(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.ory.keto.acl.v1alpha1.SubjectTree.serializeBinaryToWriter - ); - } -}; - - -/** - * optional SubjectTree tree = 1; - * @return {?proto.ory.keto.acl.v1alpha1.SubjectTree} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.getTree = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.SubjectTree} */ ( - jspb.Message.getWrapperField(this, proto.ory.keto.acl.v1alpha1.SubjectTree, 1)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.SubjectTree|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.ExpandResponse} returns this -*/ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.setTree = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.ExpandResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.clearTree = function() { - return this.setTree(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.ExpandResponse.prototype.hasTree = function() { - return jspb.Message.getField(this, 1) != null; -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.repeatedFields_ = [3]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.SubjectTree.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.SubjectTree} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.toObject = function(includeInstance, msg) { - var f, obj = { - nodeType: jspb.Message.getFieldWithDefault(msg, 1, 0), - subject: (f = msg.getSubject()) && ory_keto_acl_v1alpha1_acl_pb.Subject.toObject(includeInstance, f), - childrenList: jspb.Message.toObjectList(msg.getChildrenList(), - proto.ory.keto.acl.v1alpha1.SubjectTree.toObject, includeInstance) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.SubjectTree; - return proto.ory.keto.acl.v1alpha1.SubjectTree.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.SubjectTree} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!proto.ory.keto.acl.v1alpha1.NodeType} */ (reader.readEnum()); - msg.setNodeType(value); - break; - case 2: - var value = new ory_keto_acl_v1alpha1_acl_pb.Subject; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.Subject.deserializeBinaryFromReader); - msg.setSubject(value); - break; - case 3: - var value = new proto.ory.keto.acl.v1alpha1.SubjectTree; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.SubjectTree.deserializeBinaryFromReader); - msg.addChildren(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.SubjectTree.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.SubjectTree} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getNodeType(); - if (f !== 0.0) { - writer.writeEnum( - 1, - f - ); - } - f = message.getSubject(); - if (f != null) { - writer.writeMessage( - 2, - f, - ory_keto_acl_v1alpha1_acl_pb.Subject.serializeBinaryToWriter - ); - } - f = message.getChildrenList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 3, - f, - proto.ory.keto.acl.v1alpha1.SubjectTree.serializeBinaryToWriter - ); - } -}; - - -/** - * optional NodeType node_type = 1; - * @return {!proto.ory.keto.acl.v1alpha1.NodeType} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.getNodeType = function() { - return /** @type {!proto.ory.keto.acl.v1alpha1.NodeType} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); -}; - - -/** - * @param {!proto.ory.keto.acl.v1alpha1.NodeType} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.setNodeType = function(value) { - return jspb.Message.setProto3EnumField(this, 1, value); -}; - - -/** - * optional Subject subject = 2; - * @return {?proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.getSubject = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.Subject} */ ( - jspb.Message.getWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.Subject, 2)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.Subject|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} returns this -*/ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.setSubject = function(value) { - return jspb.Message.setWrapperField(this, 2, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.clearSubject = function() { - return this.setSubject(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.hasSubject = function() { - return jspb.Message.getField(this, 2) != null; -}; - - -/** - * repeated SubjectTree children = 3; - * @return {!Array} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.getChildrenList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.ory.keto.acl.v1alpha1.SubjectTree, 3)); -}; - - -/** - * @param {!Array} value - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} returns this -*/ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.setChildrenList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 3, value); -}; - - -/** - * @param {!proto.ory.keto.acl.v1alpha1.SubjectTree=} opt_value - * @param {number=} opt_index - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.addChildren = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.ory.keto.acl.v1alpha1.SubjectTree, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.ory.keto.acl.v1alpha1.SubjectTree} returns this - */ -proto.ory.keto.acl.v1alpha1.SubjectTree.prototype.clearChildrenList = function() { - return this.setChildrenList([]); -}; - - -/** - * @enum {number} - */ -proto.ory.keto.acl.v1alpha1.NodeType = { - NODE_TYPE_UNSPECIFIED: 0, - NODE_TYPE_UNION: 1, - NODE_TYPE_EXCLUSION: 2, - NODE_TYPE_INTERSECTION: 3, - NODE_TYPE_LEAF: 4 -}; - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package-lock.json b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package-lock.json deleted file mode 100644 index 9be3d183cb5..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package-lock.json +++ /dev/null @@ -1,517 +0,0 @@ -{ - "name": "@ory/keto-grpc-client", - "version": "0.6.0-alpha.1-pre", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@ory/keto-grpc-client", - "version": "0.6.0-alpha.1-pre", - "dependencies": { - "@grpc/grpc-js": "^1.2.6", - "google-protobuf": "^3.15.0-rc.1" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.6.tgz", - "integrity": "sha512-wfYwFy7CvVEmBKzeDX1kQQYrv5NBpe8Z+VwXipFvqof3lCXKch7k+4T3grKtptaH5GQ5KP9iKwPr9hMDSynIUw==", - "dependencies": { - "@types/node": ">=12.12.47", - "google-auth-library": "^6.1.1", - "semver": "^6.2.0" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@types/node": { - "version": "14.14.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.27.tgz", - "integrity": "sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "engines": { - "node": ">=8" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "node_modules/bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" - }, - "node_modules/gaxios": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", - "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", - "dependencies": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gcp-metadata": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", - "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", - "dependencies": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-auth-library": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", - "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", - "dependencies": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-p12-pem": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", - "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", - "dependencies": { - "node-forge": "^0.10.0" - }, - "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-protobuf": { - "version": "3.15.0-rc.1", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.0-rc.1.tgz", - "integrity": "sha512-aDpp0vaiFaM9Thv5H0UC2FJ3x4XzBABM1v+Q5V5GGyTNd1VsZXjKTPdI0ObFgio2tpBWO7nFy2cQmJ9n+6n95A==" - }, - "node_modules/gtoken": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", - "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", - "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.0.3", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - }, - "dependencies": { - "@grpc/grpc-js": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.6.tgz", - "integrity": "sha512-wfYwFy7CvVEmBKzeDX1kQQYrv5NBpe8Z+VwXipFvqof3lCXKch7k+4T3grKtptaH5GQ5KP9iKwPr9hMDSynIUw==", - "requires": { - "@types/node": ">=12.12.47", - "google-auth-library": "^6.1.1", - "semver": "^6.2.0" - } - }, - "@types/node": { - "version": "14.14.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.27.tgz", - "integrity": "sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==" - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" - }, - "gaxios": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", - "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", - "requires": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.3.0" - } - }, - "gcp-metadata": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", - "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", - "requires": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - } - }, - "google-auth-library": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", - "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", - "requires": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - } - }, - "google-p12-pem": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", - "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", - "requires": { - "node-forge": "^0.10.0" - } - }, - "google-protobuf": { - "version": "3.15.0-rc.1", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.0-rc.1.tgz", - "integrity": "sha512-aDpp0vaiFaM9Thv5H0UC2FJ3x4XzBABM1v+Q5V5GGyTNd1VsZXjKTPdI0ObFgio2tpBWO7nFy2cQmJ9n+6n95A==" - }, - "gtoken": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", - "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", - "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.0.3", - "jws": "^4.0.0" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - }, - "json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "requires": { - "bignumber.js": "^9.0.0" - } - }, - "jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "requires": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" - }, - "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package.json b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package.json deleted file mode 100644 index fadbe738954..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@ory/keto-grpc-client", - "version": "0.6.0-alpha.1", - "description": "gRPC client for Ory Keto", - "homepage": "https://www.ory.sh/keto", - "bugs": "https://github.com/ory/keto/issues", - "dependencies": { - "@grpc/grpc-js": "^1.2.6", - "google-protobuf": "^3.15.0-rc.1" - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.pb.go deleted file mode 100644 index 5008e51266c..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.pb.go +++ /dev/null @@ -1,444 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/read_service.proto - -package acl - -import ( - field_mask "google.golang.org/genproto/protobuf/field_mask" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Request for ReadService.ListRelationTuples RPC. -// See `ListRelationTuplesRequest_Query` for how to filter the query. -type ListRelationTuplesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // All query constraints are concatenated - // with a logical AND operator. - // - // The RelationTuple list from ListRelationTuplesResponse - // is ordered from the newest RelationTuple to the oldest. - Query *ListRelationTuplesRequest_Query `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - // This field is not implemented yet and has no effect. - // - ExpandMask *field_mask.FieldMask `protobuf:"bytes,2,opt,name=expand_mask,json=expandMask,proto3" json:"expand_mask,omitempty"` - // This field is not implemented yet and has no effect. - // - Snaptoken string `protobuf:"bytes,3,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` - // Optional. The maximum number of - // RelationTuples to return in the response. - // - // Default: 100 - PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - // Optional. An opaque pagination token returned from - // a previous call to `ListRelationTuples` that - // indicates where the page should start at. - // - // An empty token denotes the first page. All successive - // pages require the token from the previous page. - PageToken string `protobuf:"bytes,5,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` -} - -func (x *ListRelationTuplesRequest) Reset() { - *x = ListRelationTuplesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListRelationTuplesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListRelationTuplesRequest) ProtoMessage() {} - -func (x *ListRelationTuplesRequest) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListRelationTuplesRequest.ProtoReflect.Descriptor instead. -func (*ListRelationTuplesRequest) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_read_service_proto_rawDescGZIP(), []int{0} -} - -func (x *ListRelationTuplesRequest) GetQuery() *ListRelationTuplesRequest_Query { - if x != nil { - return x.Query - } - return nil -} - -func (x *ListRelationTuplesRequest) GetExpandMask() *field_mask.FieldMask { - if x != nil { - return x.ExpandMask - } - return nil -} - -func (x *ListRelationTuplesRequest) GetSnaptoken() string { - if x != nil { - return x.Snaptoken - } - return "" -} - -func (x *ListRelationTuplesRequest) GetPageSize() int32 { - if x != nil { - return x.PageSize - } - return 0 -} - -func (x *ListRelationTuplesRequest) GetPageToken() string { - if x != nil { - return x.PageToken - } - return "" -} - -// The response of a ReadService.ListRelationTuples RPC. -type ListRelationTuplesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The relation tuples matching the list request. - RelationTuples []*RelationTuple `protobuf:"bytes,1,rep,name=relation_tuples,json=relationTuples,proto3" json:"relation_tuples,omitempty"` - // The token required to get the next page. - // If this is the last page, the token will be the empty string. - NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` -} - -func (x *ListRelationTuplesResponse) Reset() { - *x = ListRelationTuplesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListRelationTuplesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListRelationTuplesResponse) ProtoMessage() {} - -func (x *ListRelationTuplesResponse) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListRelationTuplesResponse.ProtoReflect.Descriptor instead. -func (*ListRelationTuplesResponse) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_read_service_proto_rawDescGZIP(), []int{1} -} - -func (x *ListRelationTuplesResponse) GetRelationTuples() []*RelationTuple { - if x != nil { - return x.RelationTuples - } - return nil -} - -func (x *ListRelationTuplesResponse) GetNextPageToken() string { - if x != nil { - return x.NextPageToken - } - return "" -} - -// The query for listing relation tuples. -// Clients can specify any optional field to -// partially filter for specific relation tuples. -// -// Example use cases (namespace is always required): -// - object only: display a list of all permissions referring to a specific object -// - relation only: get all groups that have members; get all directories that have content -// - object & relation: display all subjects that have a specific permission relation -// - subject & relation: display all groups a subject belongs to; display all objects a subject has access to -// - object & relation & subject: check whether the relation tuple already exists -// -type ListRelationTuplesRequest_Query struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. The namespace to query. - Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` - // Optional. The object to query for. - Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` - // Optional. The relation to query for. - Relation string `protobuf:"bytes,3,opt,name=relation,proto3" json:"relation,omitempty"` - // Optional. The subject to query for. - Subject *Subject `protobuf:"bytes,4,opt,name=subject,proto3" json:"subject,omitempty"` -} - -func (x *ListRelationTuplesRequest_Query) Reset() { - *x = ListRelationTuplesRequest_Query{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListRelationTuplesRequest_Query) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListRelationTuplesRequest_Query) ProtoMessage() {} - -func (x *ListRelationTuplesRequest_Query) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListRelationTuplesRequest_Query.ProtoReflect.Descriptor instead. -func (*ListRelationTuplesRequest_Query) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_read_service_proto_rawDescGZIP(), []int{0, 0} -} - -func (x *ListRelationTuplesRequest_Query) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *ListRelationTuplesRequest_Query) GetObject() string { - if x != nil { - return x.Object - } - return "" -} - -func (x *ListRelationTuplesRequest_Query) GetRelation() string { - if x != nil { - return x.Relation - } - return "" -} - -func (x *ListRelationTuplesRequest_Query) GetSubject() *Subject { - if x != nil { - return x.Subject - } - return nil -} - -var File_ory_keto_acl_v1alpha1_read_service_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_read_service_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x6f, 0x72, 0x79, 0x2e, - 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x1a, 0x1f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x03, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x36, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, - 0x6b, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x1c, 0x0a, - 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, - 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, - 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x93, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, - 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x93, 0x01, - 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, - 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0f, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, - 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x0e, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, - 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x32, 0x88, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x79, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, - 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, - 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x93, - 0x01, 0x0a, 0x18, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, - 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x52, 0x65, 0x61, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, - 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, - 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x3b, 0x61, 0x63, 0x6c, 0xaa, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, - 0x41, 0x63, 0x6c, 0x2e, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, - 0x72, 0x79, 0x5c, 0x4b, 0x65, 0x74, 0x6f, 0x5c, 0x41, 0x63, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_read_service_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_read_service_proto_rawDescData = file_ory_keto_acl_v1alpha1_read_service_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_read_service_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_read_service_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_read_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_read_service_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_read_service_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_ory_keto_acl_v1alpha1_read_service_proto_goTypes = []interface{}{ - (*ListRelationTuplesRequest)(nil), // 0: ory.keto.acl.v1alpha1.ListRelationTuplesRequest - (*ListRelationTuplesResponse)(nil), // 1: ory.keto.acl.v1alpha1.ListRelationTuplesResponse - (*ListRelationTuplesRequest_Query)(nil), // 2: ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query - (*field_mask.FieldMask)(nil), // 3: google.protobuf.FieldMask - (*RelationTuple)(nil), // 4: ory.keto.acl.v1alpha1.RelationTuple - (*Subject)(nil), // 5: ory.keto.acl.v1alpha1.Subject -} -var file_ory_keto_acl_v1alpha1_read_service_proto_depIdxs = []int32{ - 2, // 0: ory.keto.acl.v1alpha1.ListRelationTuplesRequest.query:type_name -> ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query - 3, // 1: ory.keto.acl.v1alpha1.ListRelationTuplesRequest.expand_mask:type_name -> google.protobuf.FieldMask - 4, // 2: ory.keto.acl.v1alpha1.ListRelationTuplesResponse.relation_tuples:type_name -> ory.keto.acl.v1alpha1.RelationTuple - 5, // 3: ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.subject:type_name -> ory.keto.acl.v1alpha1.Subject - 0, // 4: ory.keto.acl.v1alpha1.ReadService.ListRelationTuples:input_type -> ory.keto.acl.v1alpha1.ListRelationTuplesRequest - 1, // 5: ory.keto.acl.v1alpha1.ReadService.ListRelationTuples:output_type -> ory.keto.acl.v1alpha1.ListRelationTuplesResponse - 5, // [5:6] is the sub-list for method output_type - 4, // [4:5] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_read_service_proto_init() } -func file_ory_keto_acl_v1alpha1_read_service_proto_init() { - if File_ory_keto_acl_v1alpha1_read_service_proto != nil { - return - } - file_ory_keto_acl_v1alpha1_acl_proto_init() - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListRelationTuplesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListRelationTuplesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListRelationTuplesRequest_Query); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_read_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_ory_keto_acl_v1alpha1_read_service_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_read_service_proto_depIdxs, - MessageInfos: file_ory_keto_acl_v1alpha1_read_service_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_read_service_proto = out.File - file_ory_keto_acl_v1alpha1_read_service_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_read_service_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_read_service_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.proto deleted file mode 100644 index d4152ec5281..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service.proto +++ /dev/null @@ -1,91 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -import "ory/keto/acl/v1alpha1/acl.proto"; -import "google/protobuf/field_mask.proto"; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "ReadServiceProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - -// The service to query relation tuples. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -service ReadService { - // Lists ACL relation tuples. - rpc ListRelationTuples(ListRelationTuplesRequest) returns (ListRelationTuplesResponse); -} - -// Request for ReadService.ListRelationTuples RPC. -// See `ListRelationTuplesRequest_Query` for how to filter the query. -message ListRelationTuplesRequest { - // The query for listing relation tuples. - // Clients can specify any optional field to - // partially filter for specific relation tuples. - // - // Example use cases (namespace is always required): - // - object only: display a list of all permissions referring to a specific object - // - relation only: get all groups that have members; get all directories that have content - // - object & relation: display all subjects that have a specific permission relation - // - subject & relation: display all groups a subject belongs to; display all objects a subject has access to - // - object & relation & subject: check whether the relation tuple already exists - // - message Query { - // Required. The namespace to query. - string namespace = 1; - // Optional. The object to query for. - string object = 2; - // Optional. The relation to query for. - string relation = 3; - // Optional. The subject to query for. - Subject subject = 4; - } - // All query constraints are concatenated - // with a logical AND operator. - // - // The RelationTuple list from ListRelationTuplesResponse - // is ordered from the newest RelationTuple to the oldest. - Query query = 1; - // This field is not implemented yet and has no effect. - // - google.protobuf.FieldMask expand_mask = 2; - // This field is not implemented yet and has no effect. - // - string snaptoken = 3; - // Optional. The maximum number of - // RelationTuples to return in the response. - // - // Default: 100 - int32 page_size = 4; - // Optional. An opaque pagination token returned from - // a previous call to `ListRelationTuples` that - // indicates where the page should start at. - // - // An empty token denotes the first page. All successive - // pages require the token from the previous page. - string page_token = 5; -} - -// The response of a ReadService.ListRelationTuples RPC. -message ListRelationTuplesResponse { - // The relation tuples matching the list request. - repeated RelationTuple relation_tuples = 1; - // The token required to get the next page. - // If this is the last page, the token will be the empty string. - string next_page_token = 2; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc.pb.go deleted file mode 100644 index 2ddf34d72ea..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc.pb.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package acl - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// ReadServiceClient is the client API for ReadService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ReadServiceClient interface { - // Lists ACL relation tuples. - ListRelationTuples(ctx context.Context, in *ListRelationTuplesRequest, opts ...grpc.CallOption) (*ListRelationTuplesResponse, error) -} - -type readServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewReadServiceClient(cc grpc.ClientConnInterface) ReadServiceClient { - return &readServiceClient{cc} -} - -func (c *readServiceClient) ListRelationTuples(ctx context.Context, in *ListRelationTuplesRequest, opts ...grpc.CallOption) (*ListRelationTuplesResponse, error) { - out := new(ListRelationTuplesResponse) - err := c.cc.Invoke(ctx, "/ory.keto.acl.v1alpha1.ReadService/ListRelationTuples", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ReadServiceServer is the server API for ReadService service. -// All implementations should embed UnimplementedReadServiceServer -// for forward compatibility -type ReadServiceServer interface { - // Lists ACL relation tuples. - ListRelationTuples(context.Context, *ListRelationTuplesRequest) (*ListRelationTuplesResponse, error) -} - -// UnimplementedReadServiceServer should be embedded to have forward compatible implementations. -type UnimplementedReadServiceServer struct { -} - -func (UnimplementedReadServiceServer) ListRelationTuples(context.Context, *ListRelationTuplesRequest) (*ListRelationTuplesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListRelationTuples not implemented") -} - -// UnsafeReadServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ReadServiceServer will -// result in compilation errors. -type UnsafeReadServiceServer interface { - mustEmbedUnimplementedReadServiceServer() -} - -func RegisterReadServiceServer(s grpc.ServiceRegistrar, srv ReadServiceServer) { - s.RegisterService(&ReadService_ServiceDesc, srv) -} - -func _ReadService_ListRelationTuples_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListRelationTuplesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ReadServiceServer).ListRelationTuples(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ory.keto.acl.v1alpha1.ReadService/ListRelationTuples", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ReadServiceServer).ListRelationTuples(ctx, req.(*ListRelationTuplesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// ReadService_ServiceDesc is the grpc.ServiceDesc for ReadService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var ReadService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "ory.keto.acl.v1alpha1.ReadService", - HandlerType: (*ReadServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "ListRelationTuples", - Handler: _ReadService_ListRelationTuples_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ory/keto/acl/v1alpha1/read_service.proto", -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.d.ts deleted file mode 100644 index d86ee4aa398..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/read_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as grpc from "grpc"; -import * as ory_keto_acl_v1alpha1_read_service_pb from "../../../../ory/keto/acl/v1alpha1/read_service_pb"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; -import * as google_protobuf_field_mask_pb from "google-protobuf/google/protobuf/field_mask_pb"; - -interface IReadServiceService extends grpc.ServiceDefinition { - listRelationTuples: IReadServiceService_IListRelationTuples; -} - -interface IReadServiceService_IListRelationTuples extends grpc.MethodDefinition { - path: "/ory.keto.acl.v1alpha1.ReadService/ListRelationTuples"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} - -export const ReadServiceService: IReadServiceService; - -export interface IReadServiceServer { - listRelationTuples: grpc.handleUnaryCall; -} - -export interface IReadServiceClient { - listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; - listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; - listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; -} - -export class ReadServiceClient extends grpc.Client implements IReadServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; - public listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; - public listRelationTuples(request: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.js deleted file mode 100644 index 56f1f7d0151..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_grpc_pb.js +++ /dev/null @@ -1,50 +0,0 @@ -// GENERATED CODE -- DO NOT EDIT! - -'use strict'; -var grpc = require('@grpc/grpc-js'); -var ory_keto_acl_v1alpha1_read_service_pb = require('../../../../ory/keto/acl/v1alpha1/read_service_pb.js'); -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); -var google_protobuf_field_mask_pb = require('google-protobuf/google/protobuf/field_mask_pb.js'); - -function serialize_ory_keto_acl_v1alpha1_ListRelationTuplesRequest(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.ListRelationTuplesRequest'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_ListRelationTuplesRequest(buffer_arg) { - return ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest.deserializeBinary(new Uint8Array(buffer_arg)); -} - -function serialize_ory_keto_acl_v1alpha1_ListRelationTuplesResponse(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.ListRelationTuplesResponse'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_ListRelationTuplesResponse(buffer_arg) { - return ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse.deserializeBinary(new Uint8Array(buffer_arg)); -} - - -// The service to query relation tuples. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis). -var ReadServiceService = exports.ReadServiceService = { - // Lists ACL relation tuples. -listRelationTuples: { - path: '/ory.keto.acl.v1alpha1.ReadService/ListRelationTuples', - requestStream: false, - responseStream: false, - requestType: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesRequest, - responseType: ory_keto_acl_v1alpha1_read_service_pb.ListRelationTuplesResponse, - requestSerialize: serialize_ory_keto_acl_v1alpha1_ListRelationTuplesRequest, - requestDeserialize: deserialize_ory_keto_acl_v1alpha1_ListRelationTuplesRequest, - responseSerialize: serialize_ory_keto_acl_v1alpha1_ListRelationTuplesResponse, - responseDeserialize: deserialize_ory_keto_acl_v1alpha1_ListRelationTuplesResponse, - }, -}; - -exports.ReadServiceClient = grpc.makeGenericClientConstructor(ReadServiceService); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.d.ts deleted file mode 100644 index 9c4a40d6856..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.d.ts +++ /dev/null @@ -1,117 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/read_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; -import * as google_protobuf_field_mask_pb from "google-protobuf/google/protobuf/field_mask_pb"; - -export class ListRelationTuplesRequest extends jspb.Message { - - hasQuery(): boolean; - clearQuery(): void; - getQuery(): ListRelationTuplesRequest.Query | undefined; - setQuery(value?: ListRelationTuplesRequest.Query): ListRelationTuplesRequest; - - - hasExpandMask(): boolean; - clearExpandMask(): void; - getExpandMask(): google_protobuf_field_mask_pb.FieldMask | undefined; - setExpandMask(value?: google_protobuf_field_mask_pb.FieldMask): ListRelationTuplesRequest; - - getSnaptoken(): string; - setSnaptoken(value: string): ListRelationTuplesRequest; - - getPageSize(): number; - setPageSize(value: number): ListRelationTuplesRequest; - - getPageToken(): string; - setPageToken(value: string): ListRelationTuplesRequest; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): ListRelationTuplesRequest.AsObject; - static toObject(includeInstance: boolean, msg: ListRelationTuplesRequest): ListRelationTuplesRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: ListRelationTuplesRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): ListRelationTuplesRequest; - static deserializeBinaryFromReader(message: ListRelationTuplesRequest, reader: jspb.BinaryReader): ListRelationTuplesRequest; -} - -export namespace ListRelationTuplesRequest { - export type AsObject = { - query?: ListRelationTuplesRequest.Query.AsObject, - expandMask?: google_protobuf_field_mask_pb.FieldMask.AsObject, - snaptoken: string, - pageSize: number, - pageToken: string, - } - - - export class Query extends jspb.Message { - getNamespace(): string; - setNamespace(value: string): Query; - - getObject(): string; - setObject(value: string): Query; - - getRelation(): string; - setRelation(value: string): Query; - - - hasSubject(): boolean; - clearSubject(): void; - getSubject(): ory_keto_acl_v1alpha1_acl_pb.Subject | undefined; - setSubject(value?: ory_keto_acl_v1alpha1_acl_pb.Subject): Query; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): Query.AsObject; - static toObject(includeInstance: boolean, msg: Query): Query.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: Query, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): Query; - static deserializeBinaryFromReader(message: Query, reader: jspb.BinaryReader): Query; - } - - export namespace Query { - export type AsObject = { - namespace: string, - object: string, - relation: string, - subject?: ory_keto_acl_v1alpha1_acl_pb.Subject.AsObject, - } - } - -} - -export class ListRelationTuplesResponse extends jspb.Message { - clearRelationTuplesList(): void; - getRelationTuplesList(): Array; - setRelationTuplesList(value: Array): ListRelationTuplesResponse; - addRelationTuples(value?: ory_keto_acl_v1alpha1_acl_pb.RelationTuple, index?: number): ory_keto_acl_v1alpha1_acl_pb.RelationTuple; - - getNextPageToken(): string; - setNextPageToken(value: string): ListRelationTuplesResponse; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): ListRelationTuplesResponse.AsObject; - static toObject(includeInstance: boolean, msg: ListRelationTuplesResponse): ListRelationTuplesResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: ListRelationTuplesResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): ListRelationTuplesResponse; - static deserializeBinaryFromReader(message: ListRelationTuplesResponse, reader: jspb.BinaryReader): ListRelationTuplesResponse; -} - -export namespace ListRelationTuplesResponse { - export type AsObject = { - relationTuplesList: Array, - nextPageToken: string, - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.js deleted file mode 100644 index fde6f5da394..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/read_service_pb.js +++ /dev/null @@ -1,808 +0,0 @@ -// source: ory/keto/acl/v1alpha1/read_service.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); -goog.object.extend(proto, ory_keto_acl_v1alpha1_acl_pb); -var google_protobuf_field_mask_pb = require('google-protobuf/google/protobuf/field_mask_pb.js'); -goog.object.extend(proto, google_protobuf_field_mask_pb); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.displayName = 'proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.displayName = 'proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.repeatedFields_, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.displayName = 'proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.toObject = function(includeInstance, msg) { - var f, obj = { - query: (f = msg.getQuery()) && proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.toObject(includeInstance, f), - expandMask: (f = msg.getExpandMask()) && google_protobuf_field_mask_pb.FieldMask.toObject(includeInstance, f), - snaptoken: jspb.Message.getFieldWithDefault(msg, 3, ""), - pageSize: jspb.Message.getFieldWithDefault(msg, 4, 0), - pageToken: jspb.Message.getFieldWithDefault(msg, 5, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest; - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.deserializeBinaryFromReader); - msg.setQuery(value); - break; - case 2: - var value = new google_protobuf_field_mask_pb.FieldMask; - reader.readMessage(value,google_protobuf_field_mask_pb.FieldMask.deserializeBinaryFromReader); - msg.setExpandMask(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setSnaptoken(value); - break; - case 4: - var value = /** @type {number} */ (reader.readInt32()); - msg.setPageSize(value); - break; - case 5: - var value = /** @type {string} */ (reader.readString()); - msg.setPageToken(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getQuery(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.serializeBinaryToWriter - ); - } - f = message.getExpandMask(); - if (f != null) { - writer.writeMessage( - 2, - f, - google_protobuf_field_mask_pb.FieldMask.serializeBinaryToWriter - ); - } - f = message.getSnaptoken(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getPageSize(); - if (f !== 0) { - writer.writeInt32( - 4, - f - ); - } - f = message.getPageToken(); - if (f.length > 0) { - writer.writeString( - 5, - f - ); - } -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.toObject = function(includeInstance, msg) { - var f, obj = { - namespace: jspb.Message.getFieldWithDefault(msg, 1, ""), - object: jspb.Message.getFieldWithDefault(msg, 2, ""), - relation: jspb.Message.getFieldWithDefault(msg, 3, ""), - subject: (f = msg.getSubject()) && ory_keto_acl_v1alpha1_acl_pb.Subject.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query; - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setNamespace(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setObject(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setRelation(value); - break; - case 4: - var value = new ory_keto_acl_v1alpha1_acl_pb.Subject; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.Subject.deserializeBinaryFromReader); - msg.setSubject(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getNamespace(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getObject(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getRelation(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getSubject(); - if (f != null) { - writer.writeMessage( - 4, - f, - ory_keto_acl_v1alpha1_acl_pb.Subject.serializeBinaryToWriter - ); - } -}; - - -/** - * optional string namespace = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.getNamespace = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.setNamespace = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string object = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.getObject = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.setObject = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * optional string relation = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.getRelation = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.setRelation = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional Subject subject = 4; - * @return {?proto.ory.keto.acl.v1alpha1.Subject} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.getSubject = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.Subject} */ ( - jspb.Message.getWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.Subject, 4)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.Subject|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} returns this -*/ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.setSubject = function(value) { - return jspb.Message.setWrapperField(this, 4, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.clearSubject = function() { - return this.setSubject(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query.prototype.hasSubject = function() { - return jspb.Message.getField(this, 4) != null; -}; - - -/** - * optional Query query = 1; - * @return {?proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.getQuery = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query} */ ( - jspb.Message.getWrapperField(this, proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query, 1)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.Query|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this -*/ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.setQuery = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.clearQuery = function() { - return this.setQuery(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.hasQuery = function() { - return jspb.Message.getField(this, 1) != null; -}; - - -/** - * optional google.protobuf.FieldMask expand_mask = 2; - * @return {?proto.google.protobuf.FieldMask} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.getExpandMask = function() { - return /** @type{?proto.google.protobuf.FieldMask} */ ( - jspb.Message.getWrapperField(this, google_protobuf_field_mask_pb.FieldMask, 2)); -}; - - -/** - * @param {?proto.google.protobuf.FieldMask|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this -*/ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.setExpandMask = function(value) { - return jspb.Message.setWrapperField(this, 2, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.clearExpandMask = function() { - return this.setExpandMask(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.hasExpandMask = function() { - return jspb.Message.getField(this, 2) != null; -}; - - -/** - * optional string snaptoken = 3; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.getSnaptoken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.setSnaptoken = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional int32 page_size = 4; - * @return {number} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.getPageSize = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.setPageSize = function(value) { - return jspb.Message.setProto3IntField(this, 4, value); -}; - - -/** - * optional string page_token = 5; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.getPageToken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesRequest.prototype.setPageToken = function(value) { - return jspb.Message.setProto3StringField(this, 5, value); -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.toObject = function(includeInstance, msg) { - var f, obj = { - relationTuplesList: jspb.Message.toObjectList(msg.getRelationTuplesList(), - ory_keto_acl_v1alpha1_acl_pb.RelationTuple.toObject, includeInstance), - nextPageToken: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse; - return proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new ory_keto_acl_v1alpha1_acl_pb.RelationTuple; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.RelationTuple.deserializeBinaryFromReader); - msg.addRelationTuples(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setNextPageToken(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getRelationTuplesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 1, - f, - ory_keto_acl_v1alpha1_acl_pb.RelationTuple.serializeBinaryToWriter - ); - } - f = message.getNextPageToken(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } -}; - - -/** - * repeated RelationTuple relation_tuples = 1; - * @return {!Array} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.getRelationTuplesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.RelationTuple, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} returns this -*/ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.setRelationTuplesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); -}; - - -/** - * @param {!proto.ory.keto.acl.v1alpha1.RelationTuple=} opt_value - * @param {number=} opt_index - * @return {!proto.ory.keto.acl.v1alpha1.RelationTuple} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.addRelationTuples = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ory.keto.acl.v1alpha1.RelationTuple, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.clearRelationTuplesList = function() { - return this.setRelationTuplesList([]); -}; - - -/** - * optional string next_page_token = 2; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.getNextPageToken = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.ListRelationTuplesResponse.prototype.setNextPageToken = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.pb.go deleted file mode 100644 index 9485ccbf098..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.pb.go +++ /dev/null @@ -1,218 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/version.proto - -package acl - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Request for the VersionService.GetVersion RPC. -type GetVersionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetVersionRequest) Reset() { - *x = GetVersionRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_version_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetVersionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVersionRequest) ProtoMessage() {} - -func (x *GetVersionRequest) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_version_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVersionRequest.ProtoReflect.Descriptor instead. -func (*GetVersionRequest) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_version_proto_rawDescGZIP(), []int{0} -} - -// Response of the VersionService.GetVersion RPC. -type GetVersionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The version string of the Ory Keto instance. - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *GetVersionResponse) Reset() { - *x = GetVersionResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_version_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetVersionResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVersionResponse) ProtoMessage() {} - -func (x *GetVersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_version_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVersionResponse.ProtoReflect.Descriptor instead. -func (*GetVersionResponse) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_version_proto_rawDescGZIP(), []int{1} -} - -func (x *GetVersionResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -var File_ory_keto_acl_v1alpha1_version_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_version_proto_rawDesc = []byte{ - 0x0a, 0x23, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, - 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x13, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x2e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x32, 0x73, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x28, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x96, 0x01, 0x0a, 0x18, 0x73, 0x68, 0x2e, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x42, 0x13, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, - 0x63, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x63, 0x6c, 0xaa, - 0x02, 0x15, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x41, 0x63, 0x6c, 0x2e, 0x56, - 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, - 0x74, 0x6f, 0x5c, 0x41, 0x63, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_version_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_version_proto_rawDescData = file_ory_keto_acl_v1alpha1_version_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_version_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_version_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_version_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_version_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_version_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_ory_keto_acl_v1alpha1_version_proto_goTypes = []interface{}{ - (*GetVersionRequest)(nil), // 0: ory.keto.acl.v1alpha1.GetVersionRequest - (*GetVersionResponse)(nil), // 1: ory.keto.acl.v1alpha1.GetVersionResponse -} -var file_ory_keto_acl_v1alpha1_version_proto_depIdxs = []int32{ - 0, // 0: ory.keto.acl.v1alpha1.VersionService.GetVersion:input_type -> ory.keto.acl.v1alpha1.GetVersionRequest - 1, // 1: ory.keto.acl.v1alpha1.VersionService.GetVersion:output_type -> ory.keto.acl.v1alpha1.GetVersionResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_version_proto_init() } -func file_ory_keto_acl_v1alpha1_version_proto_init() { - if File_ory_keto_acl_v1alpha1_version_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVersionRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_version_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVersionResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_version_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_ory_keto_acl_v1alpha1_version_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_version_proto_depIdxs, - MessageInfos: file_ory_keto_acl_v1alpha1_version_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_version_proto = out.File - file_ory_keto_acl_v1alpha1_version_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_version_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_version_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.proto deleted file mode 100644 index 456df2161bc..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version.proto +++ /dev/null @@ -1,27 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "VersionServiceProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - -// The service returning the specific Ory Keto instance version. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis) and [write-APIs](../concepts/api-overview.mdx#write-apis). -service VersionService { - // Returns the version of the Ory Keto instance. - rpc GetVersion(GetVersionRequest) returns (GetVersionResponse); -} - -// Request for the VersionService.GetVersion RPC. -message GetVersionRequest {} - -// Response of the VersionService.GetVersion RPC. -message GetVersionResponse { - // The version string of the Ory Keto instance. - string version = 1; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc.pb.go deleted file mode 100644 index abb39c39a27..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc.pb.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package acl - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// VersionServiceClient is the client API for VersionService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type VersionServiceClient interface { - // Returns the version of the Ory Keto instance. - GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) -} - -type versionServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewVersionServiceClient(cc grpc.ClientConnInterface) VersionServiceClient { - return &versionServiceClient{cc} -} - -func (c *versionServiceClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) { - out := new(GetVersionResponse) - err := c.cc.Invoke(ctx, "/ory.keto.acl.v1alpha1.VersionService/GetVersion", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// VersionServiceServer is the server API for VersionService service. -// All implementations should embed UnimplementedVersionServiceServer -// for forward compatibility -type VersionServiceServer interface { - // Returns the version of the Ory Keto instance. - GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) -} - -// UnimplementedVersionServiceServer should be embedded to have forward compatible implementations. -type UnimplementedVersionServiceServer struct { -} - -func (UnimplementedVersionServiceServer) GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") -} - -// UnsafeVersionServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to VersionServiceServer will -// result in compilation errors. -type UnsafeVersionServiceServer interface { - mustEmbedUnimplementedVersionServiceServer() -} - -func RegisterVersionServiceServer(s grpc.ServiceRegistrar, srv VersionServiceServer) { - s.RegisterService(&VersionService_ServiceDesc, srv) -} - -func _VersionService_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetVersionRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(VersionServiceServer).GetVersion(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ory.keto.acl.v1alpha1.VersionService/GetVersion", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(VersionServiceServer).GetVersion(ctx, req.(*GetVersionRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// VersionService_ServiceDesc is the grpc.ServiceDesc for VersionService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var VersionService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "ory.keto.acl.v1alpha1.VersionService", - HandlerType: (*VersionServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetVersion", - Handler: _VersionService_GetVersion_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ory/keto/acl/v1alpha1/version.proto", -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.d.ts deleted file mode 100644 index a7449ecc5e2..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/version.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as grpc from "grpc"; -import * as ory_keto_acl_v1alpha1_version_pb from "../../../../ory/keto/acl/v1alpha1/version_pb"; - -interface IVersionServiceService extends grpc.ServiceDefinition { - getVersion: IVersionServiceService_IGetVersion; -} - -interface IVersionServiceService_IGetVersion extends grpc.MethodDefinition { - path: "/ory.keto.acl.v1alpha1.VersionService/GetVersion"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} - -export const VersionServiceService: IVersionServiceService; - -export interface IVersionServiceServer { - getVersion: grpc.handleUnaryCall; -} - -export interface IVersionServiceClient { - getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; - getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; - getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; -} - -export class VersionServiceClient extends grpc.Client implements IVersionServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; - public getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; - public getVersion(request: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.js deleted file mode 100644 index 4438eb196cb..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_grpc_pb.js +++ /dev/null @@ -1,48 +0,0 @@ -// GENERATED CODE -- DO NOT EDIT! - -'use strict'; -var grpc = require('@grpc/grpc-js'); -var ory_keto_acl_v1alpha1_version_pb = require('../../../../ory/keto/acl/v1alpha1/version_pb.js'); - -function serialize_ory_keto_acl_v1alpha1_GetVersionRequest(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_version_pb.GetVersionRequest)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.GetVersionRequest'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_GetVersionRequest(buffer_arg) { - return ory_keto_acl_v1alpha1_version_pb.GetVersionRequest.deserializeBinary(new Uint8Array(buffer_arg)); -} - -function serialize_ory_keto_acl_v1alpha1_GetVersionResponse(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_version_pb.GetVersionResponse)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.GetVersionResponse'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_GetVersionResponse(buffer_arg) { - return ory_keto_acl_v1alpha1_version_pb.GetVersionResponse.deserializeBinary(new Uint8Array(buffer_arg)); -} - - -// The service returning the specific Ory Keto instance version. -// -// This service is part of the [read-APIs](../concepts/api-overview.mdx#read-apis) and [write-APIs](../concepts/api-overview.mdx#write-apis). -var VersionServiceService = exports.VersionServiceService = { - // Returns the version of the Ory Keto instance. -getVersion: { - path: '/ory.keto.acl.v1alpha1.VersionService/GetVersion', - requestStream: false, - responseStream: false, - requestType: ory_keto_acl_v1alpha1_version_pb.GetVersionRequest, - responseType: ory_keto_acl_v1alpha1_version_pb.GetVersionResponse, - requestSerialize: serialize_ory_keto_acl_v1alpha1_GetVersionRequest, - requestDeserialize: deserialize_ory_keto_acl_v1alpha1_GetVersionRequest, - responseSerialize: serialize_ory_keto_acl_v1alpha1_GetVersionResponse, - responseDeserialize: deserialize_ory_keto_acl_v1alpha1_GetVersionResponse, - }, -}; - -exports.VersionServiceClient = grpc.makeGenericClientConstructor(VersionServiceService); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.d.ts deleted file mode 100644 index d37dcf17df9..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/version.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; - -export class GetVersionRequest extends jspb.Message { - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetVersionRequest.AsObject; - static toObject(includeInstance: boolean, msg: GetVersionRequest): GetVersionRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetVersionRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetVersionRequest; - static deserializeBinaryFromReader(message: GetVersionRequest, reader: jspb.BinaryReader): GetVersionRequest; -} - -export namespace GetVersionRequest { - export type AsObject = { - } -} - -export class GetVersionResponse extends jspb.Message { - getVersion(): string; - setVersion(value: string): GetVersionResponse; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetVersionResponse.AsObject; - static toObject(includeInstance: boolean, msg: GetVersionResponse): GetVersionResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetVersionResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetVersionResponse; - static deserializeBinaryFromReader(message: GetVersionResponse, reader: jspb.BinaryReader): GetVersionResponse; -} - -export namespace GetVersionResponse { - export type AsObject = { - version: string, - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.js deleted file mode 100644 index 000b78d8535..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/version_pb.js +++ /dev/null @@ -1,290 +0,0 @@ -// source: ory/keto/acl/v1alpha1/version.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.GetVersionRequest', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.GetVersionResponse', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.GetVersionRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.GetVersionRequest.displayName = 'proto.ory.keto.acl.v1alpha1.GetVersionRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.GetVersionResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.GetVersionResponse.displayName = 'proto.ory.keto.acl.v1alpha1.GetVersionResponse'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.GetVersionRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.toObject = function(includeInstance, msg) { - var f, obj = { - - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.GetVersionRequest} - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.GetVersionRequest; - return proto.ory.keto.acl.v1alpha1.GetVersionRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.GetVersionRequest} - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.GetVersionRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.GetVersionRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.GetVersionResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.toObject = function(includeInstance, msg) { - var f, obj = { - version: jspb.Message.getFieldWithDefault(msg, 1, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.GetVersionResponse; - return proto.ory.keto.acl.v1alpha1.GetVersionResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setVersion(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.GetVersionResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getVersion(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } -}; - - -/** - * optional string version = 1; - * @return {string} - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.prototype.getVersion = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.ory.keto.acl.v1alpha1.GetVersionResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.GetVersionResponse.prototype.setVersion = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.pb.go deleted file mode 100644 index 5f4e267e2d2..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.pb.go +++ /dev/null @@ -1,399 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.13.0 -// source: ory/keto/acl/v1alpha1/write_service.proto - -package acl - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type RelationTupleDelta_Action int32 - -const ( - // Unspecified. - // The `TransactRelationTuples` RPC ignores this - // RelationTupleDelta if an action was unspecified. - RelationTupleDelta_ACTION_UNSPECIFIED RelationTupleDelta_Action = 0 - // Insertion of a new RelationTuple. - // It is ignored if already existing. - RelationTupleDelta_INSERT RelationTupleDelta_Action = 1 - // Deletion of the RelationTuple. - // It is ignored if it does not exist. - RelationTupleDelta_DELETE RelationTupleDelta_Action = 2 -) - -// Enum value maps for RelationTupleDelta_Action. -var ( - RelationTupleDelta_Action_name = map[int32]string{ - 0: "ACTION_UNSPECIFIED", - 1: "INSERT", - 2: "DELETE", - } - RelationTupleDelta_Action_value = map[string]int32{ - "ACTION_UNSPECIFIED": 0, - "INSERT": 1, - "DELETE": 2, - } -) - -func (x RelationTupleDelta_Action) Enum() *RelationTupleDelta_Action { - p := new(RelationTupleDelta_Action) - *p = x - return p -} - -func (x RelationTupleDelta_Action) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (RelationTupleDelta_Action) Descriptor() protoreflect.EnumDescriptor { - return file_ory_keto_acl_v1alpha1_write_service_proto_enumTypes[0].Descriptor() -} - -func (RelationTupleDelta_Action) Type() protoreflect.EnumType { - return &file_ory_keto_acl_v1alpha1_write_service_proto_enumTypes[0] -} - -func (x RelationTupleDelta_Action) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use RelationTupleDelta_Action.Descriptor instead. -func (RelationTupleDelta_Action) EnumDescriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_write_service_proto_rawDescGZIP(), []int{1, 0} -} - -// The request of a WriteService.TransactRelationTuples RPC. -type TransactRelationTuplesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The write delta for the relation tuples operated in one single transaction. - // Either all actions succeed or no change takes effect on error. - RelationTupleDeltas []*RelationTupleDelta `protobuf:"bytes,1,rep,name=relation_tuple_deltas,json=relationTupleDeltas,proto3" json:"relation_tuple_deltas,omitempty"` -} - -func (x *TransactRelationTuplesRequest) Reset() { - *x = TransactRelationTuplesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransactRelationTuplesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactRelationTuplesRequest) ProtoMessage() {} - -func (x *TransactRelationTuplesRequest) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TransactRelationTuplesRequest.ProtoReflect.Descriptor instead. -func (*TransactRelationTuplesRequest) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_write_service_proto_rawDescGZIP(), []int{0} -} - -func (x *TransactRelationTuplesRequest) GetRelationTupleDeltas() []*RelationTupleDelta { - if x != nil { - return x.RelationTupleDeltas - } - return nil -} - -// Write-delta for a TransactRelationTuplesRequest. -type RelationTupleDelta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The action to do on the RelationTuple. - Action RelationTupleDelta_Action `protobuf:"varint,1,opt,name=action,proto3,enum=ory.keto.acl.v1alpha1.RelationTupleDelta_Action" json:"action,omitempty"` - // The target RelationTuple. - RelationTuple *RelationTuple `protobuf:"bytes,2,opt,name=relation_tuple,json=relationTuple,proto3" json:"relation_tuple,omitempty"` -} - -func (x *RelationTupleDelta) Reset() { - *x = RelationTupleDelta{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RelationTupleDelta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RelationTupleDelta) ProtoMessage() {} - -func (x *RelationTupleDelta) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RelationTupleDelta.ProtoReflect.Descriptor instead. -func (*RelationTupleDelta) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_write_service_proto_rawDescGZIP(), []int{1} -} - -func (x *RelationTupleDelta) GetAction() RelationTupleDelta_Action { - if x != nil { - return x.Action - } - return RelationTupleDelta_ACTION_UNSPECIFIED -} - -func (x *RelationTupleDelta) GetRelationTuple() *RelationTuple { - if x != nil { - return x.RelationTuple - } - return nil -} - -// The response of a WriteService.TransactRelationTuples rpc. -type TransactRelationTuplesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // This field is not implemented yet and has no effect. - // - Snaptokens []string `protobuf:"bytes,1,rep,name=snaptokens,proto3" json:"snaptokens,omitempty"` -} - -func (x *TransactRelationTuplesResponse) Reset() { - *x = TransactRelationTuplesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransactRelationTuplesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactRelationTuplesResponse) ProtoMessage() {} - -func (x *TransactRelationTuplesResponse) ProtoReflect() protoreflect.Message { - mi := &file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TransactRelationTuplesResponse.ProtoReflect.Descriptor instead. -func (*TransactRelationTuplesResponse) Descriptor() ([]byte, []int) { - return file_ory_keto_acl_v1alpha1_write_service_proto_rawDescGZIP(), []int{2} -} - -func (x *TransactRelationTuplesResponse) GetSnaptokens() []string { - if x != nil { - return x.Snaptokens - } - return nil -} - -var File_ory_keto_acl_v1alpha1_write_service_proto protoreflect.FileDescriptor - -var file_ory_keto_acl_v1alpha1_write_service_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x1f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x7e, 0x0a, 0x1d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x15, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, - 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x52, 0x13, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x6c, - 0x74, 0x61, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x48, 0x0a, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, - 0x44, 0x65, 0x6c, 0x74, 0x61, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, - 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, - 0x65, 0x22, 0x38, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x10, 0x01, 0x12, - 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x22, 0x40, 0x0a, 0x1e, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, - 0x0a, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x32, 0x96, 0x01, - 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x85, - 0x01, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x6f, 0x72, 0x79, 0x2e, - 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x35, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x94, 0x01, 0x0a, 0x18, 0x73, 0x68, 0x2e, 0x6f, 0x72, - 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x42, 0x11, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x6c, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x63, 0x6c, 0xaa, 0x02, 0x15, - 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x41, 0x63, 0x6c, 0x2e, 0x56, 0x31, 0x41, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, 0x74, 0x6f, - 0x5c, 0x41, 0x63, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_ory_keto_acl_v1alpha1_write_service_proto_rawDescOnce sync.Once - file_ory_keto_acl_v1alpha1_write_service_proto_rawDescData = file_ory_keto_acl_v1alpha1_write_service_proto_rawDesc -) - -func file_ory_keto_acl_v1alpha1_write_service_proto_rawDescGZIP() []byte { - file_ory_keto_acl_v1alpha1_write_service_proto_rawDescOnce.Do(func() { - file_ory_keto_acl_v1alpha1_write_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_ory_keto_acl_v1alpha1_write_service_proto_rawDescData) - }) - return file_ory_keto_acl_v1alpha1_write_service_proto_rawDescData -} - -var file_ory_keto_acl_v1alpha1_write_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_ory_keto_acl_v1alpha1_write_service_proto_goTypes = []interface{}{ - (RelationTupleDelta_Action)(0), // 0: ory.keto.acl.v1alpha1.RelationTupleDelta.Action - (*TransactRelationTuplesRequest)(nil), // 1: ory.keto.acl.v1alpha1.TransactRelationTuplesRequest - (*RelationTupleDelta)(nil), // 2: ory.keto.acl.v1alpha1.RelationTupleDelta - (*TransactRelationTuplesResponse)(nil), // 3: ory.keto.acl.v1alpha1.TransactRelationTuplesResponse - (*RelationTuple)(nil), // 4: ory.keto.acl.v1alpha1.RelationTuple -} -var file_ory_keto_acl_v1alpha1_write_service_proto_depIdxs = []int32{ - 2, // 0: ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.relation_tuple_deltas:type_name -> ory.keto.acl.v1alpha1.RelationTupleDelta - 0, // 1: ory.keto.acl.v1alpha1.RelationTupleDelta.action:type_name -> ory.keto.acl.v1alpha1.RelationTupleDelta.Action - 4, // 2: ory.keto.acl.v1alpha1.RelationTupleDelta.relation_tuple:type_name -> ory.keto.acl.v1alpha1.RelationTuple - 1, // 3: ory.keto.acl.v1alpha1.WriteService.TransactRelationTuples:input_type -> ory.keto.acl.v1alpha1.TransactRelationTuplesRequest - 3, // 4: ory.keto.acl.v1alpha1.WriteService.TransactRelationTuples:output_type -> ory.keto.acl.v1alpha1.TransactRelationTuplesResponse - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_ory_keto_acl_v1alpha1_write_service_proto_init() } -func file_ory_keto_acl_v1alpha1_write_service_proto_init() { - if File_ory_keto_acl_v1alpha1_write_service_proto != nil { - return - } - file_ory_keto_acl_v1alpha1_acl_proto_init() - if !protoimpl.UnsafeEnabled { - file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactRelationTuplesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RelationTupleDelta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactRelationTuplesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ory_keto_acl_v1alpha1_write_service_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_ory_keto_acl_v1alpha1_write_service_proto_goTypes, - DependencyIndexes: file_ory_keto_acl_v1alpha1_write_service_proto_depIdxs, - EnumInfos: file_ory_keto_acl_v1alpha1_write_service_proto_enumTypes, - MessageInfos: file_ory_keto_acl_v1alpha1_write_service_proto_msgTypes, - }.Build() - File_ory_keto_acl_v1alpha1_write_service_proto = out.File - file_ory_keto_acl_v1alpha1_write_service_proto_rawDesc = nil - file_ory_keto_acl_v1alpha1_write_service_proto_goTypes = nil - file_ory_keto_acl_v1alpha1_write_service_proto_depIdxs = nil -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.proto b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.proto deleted file mode 100644 index b1e6f999bd1..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service.proto +++ /dev/null @@ -1,63 +0,0 @@ -syntax = "proto3"; - -package ory.keto.acl.v1alpha1; - -import "ory/keto/acl/v1alpha1/acl.proto"; - -option go_package = "github.com/ory/keto/proto/ory/keto/acl/v1alpha1;acl"; -option csharp_namespace = "Ory.Keto.Acl.V1Alpha1"; -option java_multiple_files = true; -option java_outer_classname = "WatchServiceProto"; -option java_package = "sh.ory.keto.acl.v1alpha1"; -option php_namespace = "Ory\\Keto\\Acl\\V1alpha1"; - -// The write service to create and delete Access Control Lists. -// -// This service is part of the [write-APIs](../concepts/api-overview.mdx#write-apis). -service WriteService { - // Writes one or more relation tuples in a single transaction. - rpc TransactRelationTuples(TransactRelationTuplesRequest) returns (TransactRelationTuplesResponse); -} - -// The request of a WriteService.TransactRelationTuples RPC. -message TransactRelationTuplesRequest { - // The write delta for the relation tuples operated in one single transaction. - // Either all actions succeed or no change takes effect on error. - repeated RelationTupleDelta relation_tuple_deltas = 1; -} - -// Write-delta for a TransactRelationTuplesRequest. -message RelationTupleDelta { - enum Action { - // Unspecified. - // The `TransactRelationTuples` RPC ignores this - // RelationTupleDelta if an action was unspecified. - ACTION_UNSPECIFIED = 0; - - // Insertion of a new RelationTuple. - // It is ignored if already existing. - INSERT = 1; - - // Deletion of the RelationTuple. - // It is ignored if it does not exist. - DELETE = 2; - } - // The action to do on the RelationTuple. - Action action = 1; - // The target RelationTuple. - RelationTuple relation_tuple = 2; -} - -// The response of a WriteService.TransactRelationTuples rpc. -message TransactRelationTuplesResponse { - // This field is not implemented yet and has no effect. - // - repeated string snaptokens = 1; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc.pb.go b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc.pb.go deleted file mode 100644 index 809f065c859..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc.pb.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package acl - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// WriteServiceClient is the client API for WriteService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type WriteServiceClient interface { - // Writes one or more relation tuples in a single transaction. - TransactRelationTuples(ctx context.Context, in *TransactRelationTuplesRequest, opts ...grpc.CallOption) (*TransactRelationTuplesResponse, error) -} - -type writeServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewWriteServiceClient(cc grpc.ClientConnInterface) WriteServiceClient { - return &writeServiceClient{cc} -} - -func (c *writeServiceClient) TransactRelationTuples(ctx context.Context, in *TransactRelationTuplesRequest, opts ...grpc.CallOption) (*TransactRelationTuplesResponse, error) { - out := new(TransactRelationTuplesResponse) - err := c.cc.Invoke(ctx, "/ory.keto.acl.v1alpha1.WriteService/TransactRelationTuples", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// WriteServiceServer is the server API for WriteService service. -// All implementations should embed UnimplementedWriteServiceServer -// for forward compatibility -type WriteServiceServer interface { - // Writes one or more relation tuples in a single transaction. - TransactRelationTuples(context.Context, *TransactRelationTuplesRequest) (*TransactRelationTuplesResponse, error) -} - -// UnimplementedWriteServiceServer should be embedded to have forward compatible implementations. -type UnimplementedWriteServiceServer struct { -} - -func (UnimplementedWriteServiceServer) TransactRelationTuples(context.Context, *TransactRelationTuplesRequest) (*TransactRelationTuplesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TransactRelationTuples not implemented") -} - -// UnsafeWriteServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to WriteServiceServer will -// result in compilation errors. -type UnsafeWriteServiceServer interface { - mustEmbedUnimplementedWriteServiceServer() -} - -func RegisterWriteServiceServer(s grpc.ServiceRegistrar, srv WriteServiceServer) { - s.RegisterService(&WriteService_ServiceDesc, srv) -} - -func _WriteService_TransactRelationTuples_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TransactRelationTuplesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WriteServiceServer).TransactRelationTuples(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ory.keto.acl.v1alpha1.WriteService/TransactRelationTuples", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WriteServiceServer).TransactRelationTuples(ctx, req.(*TransactRelationTuplesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// WriteService_ServiceDesc is the grpc.ServiceDesc for WriteService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var WriteService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "ory.keto.acl.v1alpha1.WriteService", - HandlerType: (*WriteServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "TransactRelationTuples", - Handler: _WriteService_TransactRelationTuples_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ory/keto/acl/v1alpha1/write_service.proto", -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.d.ts deleted file mode 100644 index a302c8f3bf5..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/write_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as grpc from "grpc"; -import * as ory_keto_acl_v1alpha1_write_service_pb from "../../../../ory/keto/acl/v1alpha1/write_service_pb"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -interface IWriteServiceService extends grpc.ServiceDefinition { - transactRelationTuples: IWriteServiceService_ITransactRelationTuples; -} - -interface IWriteServiceService_ITransactRelationTuples extends grpc.MethodDefinition { - path: "/ory.keto.acl.v1alpha1.WriteService/TransactRelationTuples"; - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} - -export const WriteServiceService: IWriteServiceService; - -export interface IWriteServiceServer { - transactRelationTuples: grpc.handleUnaryCall; -} - -export interface IWriteServiceClient { - transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; - transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; - transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; -} - -export class WriteServiceClient extends grpc.Client implements IWriteServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); - public transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; - public transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; - public transactRelationTuples(request: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.js deleted file mode 100644 index 944a114ab34..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_grpc_pb.js +++ /dev/null @@ -1,49 +0,0 @@ -// GENERATED CODE -- DO NOT EDIT! - -'use strict'; -var grpc = require('@grpc/grpc-js'); -var ory_keto_acl_v1alpha1_write_service_pb = require('../../../../ory/keto/acl/v1alpha1/write_service_pb.js'); -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); - -function serialize_ory_keto_acl_v1alpha1_TransactRelationTuplesRequest(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.TransactRelationTuplesRequest'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_TransactRelationTuplesRequest(buffer_arg) { - return ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest.deserializeBinary(new Uint8Array(buffer_arg)); -} - -function serialize_ory_keto_acl_v1alpha1_TransactRelationTuplesResponse(arg) { - if (!(arg instanceof ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse)) { - throw new Error('Expected argument of type ory.keto.acl.v1alpha1.TransactRelationTuplesResponse'); - } - return Buffer.from(arg.serializeBinary()); -} - -function deserialize_ory_keto_acl_v1alpha1_TransactRelationTuplesResponse(buffer_arg) { - return ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse.deserializeBinary(new Uint8Array(buffer_arg)); -} - - -// The write service to create and delete Access Control Lists. -// -// This service is part of the [write-APIs](../concepts/api-overview.mdx#write-apis). -var WriteServiceService = exports.WriteServiceService = { - // Writes one or more relation tuples in a single transaction. -transactRelationTuples: { - path: '/ory.keto.acl.v1alpha1.WriteService/TransactRelationTuples', - requestStream: false, - responseStream: false, - requestType: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesRequest, - responseType: ory_keto_acl_v1alpha1_write_service_pb.TransactRelationTuplesResponse, - requestSerialize: serialize_ory_keto_acl_v1alpha1_TransactRelationTuplesRequest, - requestDeserialize: deserialize_ory_keto_acl_v1alpha1_TransactRelationTuplesRequest, - responseSerialize: serialize_ory_keto_acl_v1alpha1_TransactRelationTuplesResponse, - responseDeserialize: deserialize_ory_keto_acl_v1alpha1_TransactRelationTuplesResponse, - }, -}; - -exports.WriteServiceClient = grpc.makeGenericClientConstructor(WriteServiceService); diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.d.ts b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.d.ts deleted file mode 100644 index 47cdb40571f..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -// package: ory.keto.acl.v1alpha1 -// file: ory/keto/acl/v1alpha1/write_service.proto - -/* tslint:disable */ -/* eslint-disable */ - -import * as jspb from "google-protobuf"; -import * as ory_keto_acl_v1alpha1_acl_pb from "../../../../ory/keto/acl/v1alpha1/acl_pb"; - -export class TransactRelationTuplesRequest extends jspb.Message { - clearRelationTupleDeltasList(): void; - getRelationTupleDeltasList(): Array; - setRelationTupleDeltasList(value: Array): TransactRelationTuplesRequest; - addRelationTupleDeltas(value?: RelationTupleDelta, index?: number): RelationTupleDelta; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): TransactRelationTuplesRequest.AsObject; - static toObject(includeInstance: boolean, msg: TransactRelationTuplesRequest): TransactRelationTuplesRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: TransactRelationTuplesRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): TransactRelationTuplesRequest; - static deserializeBinaryFromReader(message: TransactRelationTuplesRequest, reader: jspb.BinaryReader): TransactRelationTuplesRequest; -} - -export namespace TransactRelationTuplesRequest { - export type AsObject = { - relationTupleDeltasList: Array, - } -} - -export class RelationTupleDelta extends jspb.Message { - getAction(): RelationTupleDelta.Action; - setAction(value: RelationTupleDelta.Action): RelationTupleDelta; - - - hasRelationTuple(): boolean; - clearRelationTuple(): void; - getRelationTuple(): ory_keto_acl_v1alpha1_acl_pb.RelationTuple | undefined; - setRelationTuple(value?: ory_keto_acl_v1alpha1_acl_pb.RelationTuple): RelationTupleDelta; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): RelationTupleDelta.AsObject; - static toObject(includeInstance: boolean, msg: RelationTupleDelta): RelationTupleDelta.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: RelationTupleDelta, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): RelationTupleDelta; - static deserializeBinaryFromReader(message: RelationTupleDelta, reader: jspb.BinaryReader): RelationTupleDelta; -} - -export namespace RelationTupleDelta { - export type AsObject = { - action: RelationTupleDelta.Action, - relationTuple?: ory_keto_acl_v1alpha1_acl_pb.RelationTuple.AsObject, - } - - export enum Action { - ACTION_UNSPECIFIED = 0, - INSERT = 1, - DELETE = 2, - } - -} - -export class TransactRelationTuplesResponse extends jspb.Message { - clearSnaptokensList(): void; - getSnaptokensList(): Array; - setSnaptokensList(value: Array): TransactRelationTuplesResponse; - addSnaptokens(value: string, index?: number): string; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): TransactRelationTuplesResponse.AsObject; - static toObject(includeInstance: boolean, msg: TransactRelationTuplesResponse): TransactRelationTuplesResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: TransactRelationTuplesResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): TransactRelationTuplesResponse; - static deserializeBinaryFromReader(message: TransactRelationTuplesResponse, reader: jspb.BinaryReader): TransactRelationTuplesResponse; -} - -export namespace TransactRelationTuplesResponse { - export type AsObject = { - snaptokensList: Array, - } -} diff --git a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.js b/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.js deleted file mode 100644 index ff271e675a5..00000000000 --- a/vendor/github.com/ory/keto/proto/ory/keto/acl/v1alpha1/write_service_pb.js +++ /dev/null @@ -1,590 +0,0 @@ -// source: ory/keto/acl/v1alpha1/write_service.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var ory_keto_acl_v1alpha1_acl_pb = require('../../../../ory/keto/acl/v1alpha1/acl_pb.js'); -goog.object.extend(proto, ory_keto_acl_v1alpha1_acl_pb); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.RelationTupleDelta', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest', null, global); -goog.exportSymbol('proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.repeatedFields_, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.displayName = 'proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.RelationTupleDelta, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.RelationTupleDelta.displayName = 'proto.ory.keto.acl.v1alpha1.RelationTupleDelta'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.repeatedFields_, null); -}; -goog.inherits(proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.displayName = 'proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse'; -} - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.toObject = function(includeInstance, msg) { - var f, obj = { - relationTupleDeltasList: jspb.Message.toObjectList(msg.getRelationTupleDeltasList(), - proto.ory.keto.acl.v1alpha1.RelationTupleDelta.toObject, includeInstance) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest; - return proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new proto.ory.keto.acl.v1alpha1.RelationTupleDelta; - reader.readMessage(value,proto.ory.keto.acl.v1alpha1.RelationTupleDelta.deserializeBinaryFromReader); - msg.addRelationTupleDeltas(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getRelationTupleDeltasList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 1, - f, - proto.ory.keto.acl.v1alpha1.RelationTupleDelta.serializeBinaryToWriter - ); - } -}; - - -/** - * repeated RelationTupleDelta relation_tuple_deltas = 1; - * @return {!Array} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.getRelationTupleDeltasList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.ory.keto.acl.v1alpha1.RelationTupleDelta, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} returns this -*/ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.setRelationTupleDeltasList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); -}; - - -/** - * @param {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta=} opt_value - * @param {number=} opt_index - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.addRelationTupleDeltas = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ory.keto.acl.v1alpha1.RelationTupleDelta, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest} returns this - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesRequest.prototype.clearRelationTupleDeltasList = function() { - return this.setRelationTupleDeltasList([]); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.RelationTupleDelta.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.toObject = function(includeInstance, msg) { - var f, obj = { - action: jspb.Message.getFieldWithDefault(msg, 1, 0), - relationTuple: (f = msg.getRelationTuple()) && ory_keto_acl_v1alpha1_acl_pb.RelationTuple.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.RelationTupleDelta; - return proto.ory.keto.acl.v1alpha1.RelationTupleDelta.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action} */ (reader.readEnum()); - msg.setAction(value); - break; - case 2: - var value = new ory_keto_acl_v1alpha1_acl_pb.RelationTuple; - reader.readMessage(value,ory_keto_acl_v1alpha1_acl_pb.RelationTuple.deserializeBinaryFromReader); - msg.setRelationTuple(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.RelationTupleDelta.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getAction(); - if (f !== 0.0) { - writer.writeEnum( - 1, - f - ); - } - f = message.getRelationTuple(); - if (f != null) { - writer.writeMessage( - 2, - f, - ory_keto_acl_v1alpha1_acl_pb.RelationTuple.serializeBinaryToWriter - ); - } -}; - - -/** - * @enum {number} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action = { - ACTION_UNSPECIFIED: 0, - INSERT: 1, - DELETE: 2 -}; - -/** - * optional Action action = 1; - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.getAction = function() { - return /** @type {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); -}; - - -/** - * @param {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta.Action} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.setAction = function(value) { - return jspb.Message.setProto3EnumField(this, 1, value); -}; - - -/** - * optional RelationTuple relation_tuple = 2; - * @return {?proto.ory.keto.acl.v1alpha1.RelationTuple} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.getRelationTuple = function() { - return /** @type{?proto.ory.keto.acl.v1alpha1.RelationTuple} */ ( - jspb.Message.getWrapperField(this, ory_keto_acl_v1alpha1_acl_pb.RelationTuple, 2)); -}; - - -/** - * @param {?proto.ory.keto.acl.v1alpha1.RelationTuple|undefined} value - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} returns this -*/ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.setRelationTuple = function(value) { - return jspb.Message.setWrapperField(this, 2, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.ory.keto.acl.v1alpha1.RelationTupleDelta} returns this - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.clearRelationTuple = function() { - return this.setRelationTuple(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.ory.keto.acl.v1alpha1.RelationTupleDelta.prototype.hasRelationTuple = function() { - return jspb.Message.getField(this, 2) != null; -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.toObject = function(opt_includeInstance) { - return proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.toObject = function(includeInstance, msg) { - var f, obj = { - snaptokensList: (f = jspb.Message.getRepeatedField(msg, 1)) == null ? undefined : f - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse; - return proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.addSnaptokens(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getSnaptokensList(); - if (f.length > 0) { - writer.writeRepeatedString( - 1, - f - ); - } -}; - - -/** - * repeated string snaptokens = 1; - * @return {!Array} - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.getSnaptokensList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.setSnaptokensList = function(value) { - return jspb.Message.setField(this, 1, value || []); -}; - - -/** - * @param {string} value - * @param {number=} opt_index - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.addSnaptokens = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 1, value, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse} returns this - */ -proto.ory.keto.acl.v1alpha1.TransactRelationTuplesResponse.prototype.clearSnaptokensList = function() { - return this.setSnaptokensList([]); -}; - - -goog.object.extend(exports, proto.ory.keto.acl.v1alpha1); diff --git a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go deleted file mode 100644 index d10ad665333..00000000000 --- a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package field_mask aliases all exported identifiers in -// package "google.golang.org/protobuf/types/known/fieldmaskpb". -package field_mask - -import "google.golang.org/protobuf/types/known/fieldmaskpb" - -type FieldMask = fieldmaskpb.FieldMask - -var File_google_protobuf_field_mask_proto = fieldmaskpb.File_google_protobuf_field_mask_proto diff --git a/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go b/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go deleted file mode 100644 index 1b2085d4690..00000000000 --- a/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go +++ /dev/null @@ -1,591 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google/protobuf/field_mask.proto - -// Package fieldmaskpb contains generated types for google/protobuf/field_mask.proto. -// -// The FieldMask message represents a set of symbolic field paths. -// The paths are specific to some target message type, -// which is not stored within the FieldMask message itself. -// -// -// Constructing a FieldMask -// -// The New function is used construct a FieldMask: -// -// var messageType *descriptorpb.DescriptorProto -// fm, err := fieldmaskpb.New(messageType, "field.name", "field.number") -// if err != nil { -// ... // handle error -// } -// ... // make use of fm -// -// The "field.name" and "field.number" paths are valid paths according to the -// google.protobuf.DescriptorProto message. Use of a path that does not correlate -// to valid fields reachable from DescriptorProto would result in an error. -// -// Once a FieldMask message has been constructed, -// the Append method can be used to insert additional paths to the path set: -// -// var messageType *descriptorpb.DescriptorProto -// if err := fm.Append(messageType, "options"); err != nil { -// ... // handle error -// } -// -// -// Type checking a FieldMask -// -// In order to verify that a FieldMask represents a set of fields that are -// reachable from some target message type, use the IsValid method: -// -// var messageType *descriptorpb.DescriptorProto -// if fm.IsValid(messageType) { -// ... // make use of fm -// } -// -// IsValid needs to be passed the target message type as an input since the -// FieldMask message itself does not store the message type that the set of paths -// are for. -package fieldmaskpb - -import ( - proto "google.golang.org/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sort "sort" - strings "strings" - sync "sync" -) - -// `FieldMask` represents a set of symbolic field paths, for example: -// -// paths: "f.a" -// paths: "f.b.d" -// -// Here `f` represents a field in some root message, `a` and `b` -// fields in the message found in `f`, and `d` a field found in the -// message in `f.b`. -// -// Field masks are used to specify a subset of fields that should be -// returned by a get operation or modified by an update operation. -// Field masks also have a custom JSON encoding (see below). -// -// # Field Masks in Projections -// -// When used in the context of a projection, a response message or -// sub-message is filtered by the API to only contain those fields as -// specified in the mask. For example, if the mask in the previous -// example is applied to a response message as follows: -// -// f { -// a : 22 -// b { -// d : 1 -// x : 2 -// } -// y : 13 -// } -// z: 8 -// -// The result will not contain specific values for fields x,y and z -// (their value will be set to the default, and omitted in proto text -// output): -// -// -// f { -// a : 22 -// b { -// d : 1 -// } -// } -// -// A repeated field is not allowed except at the last position of a -// paths string. -// -// If a FieldMask object is not present in a get operation, the -// operation applies to all fields (as if a FieldMask of all fields -// had been specified). -// -// Note that a field mask does not necessarily apply to the -// top-level response message. In case of a REST get operation, the -// field mask applies directly to the response, but in case of a REST -// list operation, the mask instead applies to each individual message -// in the returned resource list. In case of a REST custom method, -// other definitions may be used. Where the mask applies will be -// clearly documented together with its declaration in the API. In -// any case, the effect on the returned resource/resources is required -// behavior for APIs. -// -// # Field Masks in Update Operations -// -// A field mask in update operations specifies which fields of the -// targeted resource are going to be updated. The API is required -// to only change the values of the fields as specified in the mask -// and leave the others untouched. If a resource is passed in to -// describe the updated values, the API ignores the values of all -// fields not covered by the mask. -// -// If a repeated field is specified for an update operation, new values will -// be appended to the existing repeated field in the target resource. Note that -// a repeated field is only allowed in the last position of a `paths` string. -// -// If a sub-message is specified in the last position of the field mask for an -// update operation, then new value will be merged into the existing sub-message -// in the target resource. -// -// For example, given the target message: -// -// f { -// b { -// d: 1 -// x: 2 -// } -// c: [1] -// } -// -// And an update message: -// -// f { -// b { -// d: 10 -// } -// c: [2] -// } -// -// then if the field mask is: -// -// paths: ["f.b", "f.c"] -// -// then the result will be: -// -// f { -// b { -// d: 10 -// x: 2 -// } -// c: [1, 2] -// } -// -// An implementation may provide options to override this default behavior for -// repeated and message fields. -// -// In order to reset a field's value to the default, the field must -// be in the mask and set to the default value in the provided resource. -// Hence, in order to reset all fields of a resource, provide a default -// instance of the resource and set all fields in the mask, or do -// not provide a mask as described below. -// -// If a field mask is not present on update, the operation applies to -// all fields (as if a field mask of all fields has been specified). -// Note that in the presence of schema evolution, this may mean that -// fields the client does not know and has therefore not filled into -// the request will be reset to their default. If this is unwanted -// behavior, a specific service may require a client to always specify -// a field mask, producing an error if not. -// -// As with get operations, the location of the resource which -// describes the updated values in the request message depends on the -// operation kind. In any case, the effect of the field mask is -// required to be honored by the API. -// -// ## Considerations for HTTP REST -// -// The HTTP kind of an update operation which uses a field mask must -// be set to PATCH instead of PUT in order to satisfy HTTP semantics -// (PUT must only be used for full updates). -// -// # JSON Encoding of Field Masks -// -// In JSON, a field mask is encoded as a single string where paths are -// separated by a comma. Fields name in each path are converted -// to/from lower-camel naming conventions. -// -// As an example, consider the following message declarations: -// -// message Profile { -// User user = 1; -// Photo photo = 2; -// } -// message User { -// string display_name = 1; -// string address = 2; -// } -// -// In proto a field mask for `Profile` may look as such: -// -// mask { -// paths: "user.display_name" -// paths: "photo" -// } -// -// In JSON, the same mask is represented as below: -// -// { -// mask: "user.displayName,photo" -// } -// -// # Field Masks and Oneof Fields -// -// Field masks treat fields in oneofs just as regular fields. Consider the -// following message: -// -// message SampleMessage { -// oneof test_oneof { -// string name = 4; -// SubMessage sub_message = 9; -// } -// } -// -// The field mask can be: -// -// mask { -// paths: "name" -// } -// -// Or: -// -// mask { -// paths: "sub_message" -// } -// -// Note that oneof type names ("test_oneof" in this case) cannot be used in -// paths. -// -// ## Field Mask Verification -// -// The implementation of any API method which has a FieldMask type field in the -// request should verify the included field paths, and return an -// `INVALID_ARGUMENT` error if any path is unmappable. -type FieldMask struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The set of field mask paths. - Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` -} - -// New constructs a field mask from a list of paths and verifies that -// each one is valid according to the specified message type. -func New(m proto.Message, paths ...string) (*FieldMask, error) { - x := new(FieldMask) - return x, x.Append(m, paths...) -} - -// Union returns the union of all the paths in the input field masks. -func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask { - var out []string - out = append(out, mx.GetPaths()...) - out = append(out, my.GetPaths()...) - for _, m := range ms { - out = append(out, m.GetPaths()...) - } - return &FieldMask{Paths: normalizePaths(out)} -} - -// Intersect returns the intersection of all the paths in the input field masks. -func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask { - var ss1, ss2 []string // reused buffers for performance - intersect := func(out, in []string) []string { - ss1 = normalizePaths(append(ss1[:0], in...)) - ss2 = normalizePaths(append(ss2[:0], out...)) - out = out[:0] - for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); { - switch s1, s2 := ss1[i1], ss2[i2]; { - case hasPathPrefix(s1, s2): - out = append(out, s1) - i1++ - case hasPathPrefix(s2, s1): - out = append(out, s2) - i2++ - case lessPath(s1, s2): - i1++ - case lessPath(s2, s1): - i2++ - } - } - return out - } - - out := Union(mx, my, ms...).GetPaths() - out = intersect(out, mx.GetPaths()) - out = intersect(out, my.GetPaths()) - for _, m := range ms { - out = intersect(out, m.GetPaths()) - } - return &FieldMask{Paths: normalizePaths(out)} -} - -// IsValid reports whether all the paths are syntactically valid and -// refer to known fields in the specified message type. -// It reports false for a nil FieldMask. -func (x *FieldMask) IsValid(m proto.Message) bool { - paths := x.GetPaths() - return x != nil && numValidPaths(m, paths) == len(paths) -} - -// Append appends a list of paths to the mask and verifies that each one -// is valid according to the specified message type. -// An invalid path is not appended and breaks insertion of subsequent paths. -func (x *FieldMask) Append(m proto.Message, paths ...string) error { - numValid := numValidPaths(m, paths) - x.Paths = append(x.Paths, paths[:numValid]...) - paths = paths[numValid:] - if len(paths) > 0 { - name := m.ProtoReflect().Descriptor().FullName() - return protoimpl.X.NewError("invalid path %q for message %q", paths[0], name) - } - return nil -} - -func numValidPaths(m proto.Message, paths []string) int { - md0 := m.ProtoReflect().Descriptor() - for i, path := range paths { - md := md0 - if !rangeFields(path, func(field string) bool { - // Search the field within the message. - if md == nil { - return false // not within a message - } - fd := md.Fields().ByName(protoreflect.Name(field)) - // The real field name of a group is the message name. - if fd == nil { - gd := md.Fields().ByName(protoreflect.Name(strings.ToLower(field))) - if gd != nil && gd.Kind() == protoreflect.GroupKind && string(gd.Message().Name()) == field { - fd = gd - } - } else if fd.Kind() == protoreflect.GroupKind && string(fd.Message().Name()) != field { - fd = nil - } - if fd == nil { - return false // message has does not have this field - } - - // Identify the next message to search within. - md = fd.Message() // may be nil - - // Repeated fields are only allowed at the last position. - if fd.IsList() || fd.IsMap() { - md = nil - } - - return true - }) { - return i - } - } - return len(paths) -} - -// Normalize converts the mask to its canonical form where all paths are sorted -// and redundant paths are removed. -func (x *FieldMask) Normalize() { - x.Paths = normalizePaths(x.Paths) -} - -func normalizePaths(paths []string) []string { - sort.Slice(paths, func(i, j int) bool { - return lessPath(paths[i], paths[j]) - }) - - // Elide any path that is a prefix match on the previous. - out := paths[:0] - for _, path := range paths { - if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) { - continue - } - out = append(out, path) - } - return out -} - -// hasPathPrefix is like strings.HasPrefix, but further checks for either -// an exact matche or that the prefix is delimited by a dot. -func hasPathPrefix(path, prefix string) bool { - return strings.HasPrefix(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.') -} - -// lessPath is a lexicographical comparison where dot is specially treated -// as the smallest symbol. -func lessPath(x, y string) bool { - for i := 0; i < len(x) && i < len(y); i++ { - if x[i] != y[i] { - return (x[i] - '.') < (y[i] - '.') - } - } - return len(x) < len(y) -} - -// rangeFields is like strings.Split(path, "."), but avoids allocations by -// iterating over each field in place and calling a iterator function. -func rangeFields(path string, f func(field string) bool) bool { - for { - var field string - if i := strings.IndexByte(path, '.'); i >= 0 { - field, path = path[:i], path[i:] - } else { - field, path = path, "" - } - - if !f(field) { - return false - } - - if len(path) == 0 { - return true - } - path = strings.TrimPrefix(path, ".") - } -} - -func (x *FieldMask) Reset() { - *x = FieldMask{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_field_mask_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FieldMask) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FieldMask) ProtoMessage() {} - -func (x *FieldMask) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_field_mask_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FieldMask.ProtoReflect.Descriptor instead. -func (*FieldMask) Descriptor() ([]byte, []int) { - return file_google_protobuf_field_mask_proto_rawDescGZIP(), []int{0} -} - -func (x *FieldMask) GetPaths() []string { - if x != nil { - return x.Paths - } - return nil -} - -var File_google_protobuf_field_mask_proto protoreflect.FileDescriptor - -var file_google_protobuf_field_mask_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x22, 0x21, 0x0a, 0x09, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, - 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x42, 0x85, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x0e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x32, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, - 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x6d, 0x61, - 0x73, 0x6b, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1e, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_google_protobuf_field_mask_proto_rawDescOnce sync.Once - file_google_protobuf_field_mask_proto_rawDescData = file_google_protobuf_field_mask_proto_rawDesc -) - -func file_google_protobuf_field_mask_proto_rawDescGZIP() []byte { - file_google_protobuf_field_mask_proto_rawDescOnce.Do(func() { - file_google_protobuf_field_mask_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_field_mask_proto_rawDescData) - }) - return file_google_protobuf_field_mask_proto_rawDescData -} - -var file_google_protobuf_field_mask_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_google_protobuf_field_mask_proto_goTypes = []interface{}{ - (*FieldMask)(nil), // 0: google.protobuf.FieldMask -} -var file_google_protobuf_field_mask_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_google_protobuf_field_mask_proto_init() } -func file_google_protobuf_field_mask_proto_init() { - if File_google_protobuf_field_mask_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_google_protobuf_field_mask_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldMask); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_google_protobuf_field_mask_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_google_protobuf_field_mask_proto_goTypes, - DependencyIndexes: file_google_protobuf_field_mask_proto_depIdxs, - MessageInfos: file_google_protobuf_field_mask_proto_msgTypes, - }.Build() - File_google_protobuf_field_mask_proto = out.File - file_google_protobuf_field_mask_proto_rawDesc = nil - file_google_protobuf_field_mask_proto_goTypes = nil - file_google_protobuf_field_mask_proto_depIdxs = nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index cc2da54f236..87bf8ec156a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -159,9 +159,6 @@ github.com/gofrs/uuid # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 github.com/gogo/protobuf/proto -# github.com/golang-jwt/jwt/v4 v4.4.2 -## explicit; go 1.16 -github.com/golang-jwt/jwt/v4 # github.com/golang/protobuf v1.5.2 ## explicit; go 1.9 github.com/golang/protobuf/jsonpb @@ -475,9 +472,6 @@ github.com/ory/dockertest/v3/docker/types/network github.com/ory/dockertest/v3/docker/types/registry github.com/ory/dockertest/v3/docker/types/strslice github.com/ory/dockertest/v3/docker/types/versions -# github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9 -## explicit; go 1.16 -github.com/ory/keto/proto/ory/keto/acl/v1alpha1 # github.com/pelletier/go-toml v1.9.5 ## explicit; go 1.12 github.com/pelletier/go-toml @@ -853,7 +847,6 @@ gonum.org/v1/gonum/stat # google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 ## explicit; go 1.19 google.golang.org/genproto/googleapis/rpc/status -google.golang.org/genproto/protobuf/field_mask # google.golang.org/grpc v1.50.1 ## explicit; go 1.17 google.golang.org/grpc @@ -942,7 +935,6 @@ google.golang.org/protobuf/types/descriptorpb google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/emptypb -google.golang.org/protobuf/types/known/fieldmaskpb google.golang.org/protobuf/types/known/timestamppb # gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc ## explicit