diff --git a/Makefile b/Makefile index 4b0bcda7c..bfc8c4635 100644 --- a/Makefile +++ b/Makefile @@ -63,3 +63,7 @@ docker: deps docker build -t oryd/keto:latest . rm keto packr clean + +.PHONY: gen-protobuf +gen-protobuf: + protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative models/*.proto diff --git a/cmd/client/grpc_client.go b/cmd/client/grpc_client.go new file mode 100644 index 000000000..c5223a7a3 --- /dev/null +++ b/cmd/client/grpc_client.go @@ -0,0 +1,26 @@ +package client + +import ( + "context" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "google.golang.org/grpc" + "time" +) + +const ( + FlagRemoteURL = "remote" +) + +func GetGRPCConn(cmd *cobra.Command) (*grpc.ClientConn, error) { + remote, err := cmd.Flags().GetString(FlagRemoteURL) + if err != nil { + return nil, err + } + ctx, _ := context.WithTimeout(context.Background(), 3*time.Second) + return grpc.DialContext(ctx, remote, grpc.WithInsecure(), grpc.WithBlock()) +} + +func RegisterRemoteURLFlag(flags *pflag.FlagSet) { + flags.StringP(FlagRemoteURL, "r", "", "TODO") +} diff --git a/cmd/relation/get.go b/cmd/relation/get.go new file mode 100644 index 000000000..83afb249b --- /dev/null +++ b/cmd/relation/get.go @@ -0,0 +1,37 @@ +package relation + +import ( + "context" + "fmt" + "github.com/ory/keto/cmd/client" + "github.com/ory/keto/models" + "github.com/spf13/cobra" +) + +var getByUserRelationCmd = &cobra.Command{ + Use: "get-by-user ", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + conn, err := client.GetGRPCConn(cmd) + if err != nil { + return err + } + defer conn.Close() + + cl := models.NewGRPCRelationReaderClient(conn) + resp, err := cl.RelationsByUser(context.Background(), &models.GRPCRelationsReadRequest{ + Page: 0, + PerPage: 100, + Id: args[0], + }) + if err != nil { + return err + } + + fmt.Printf("Got %d relations for user %s\n", len(resp.Relations), args[0]) + for _, r := range resp.Relations { + fmt.Printf("%+v\n", r) + } + return nil + }, +} diff --git a/cmd/relation/root.go b/cmd/relation/root.go new file mode 100644 index 000000000..36ec243c0 --- /dev/null +++ b/cmd/relation/root.go @@ -0,0 +1,18 @@ +package relation + +import ( + "github.com/ory/keto/cmd/client" + "github.com/spf13/cobra" +) + +var relationCmd = &cobra.Command{ + Use: "relation", +} + +func RegisterCommandRecursive(parent *cobra.Command) { + parent.AddCommand(relationCmd) + + relationCmd.AddCommand(getByUserRelationCmd) + + client.RegisterRemoteURLFlag(relationCmd.PersistentFlags()) +} diff --git a/cmd/root.go b/cmd/root.go index 7a507d155..f63d01536 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,7 @@ package cmd import ( "fmt" + "github.com/ory/keto/cmd/relation" "os" "path/filepath" "runtime" @@ -63,6 +64,8 @@ func init() { // Cobra also supports local flags, which will only run // when this action is called directly. RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + + relation.RegisterCommandRecursive(RootCmd) } // initConfig reads in config file and ENV variables if set. diff --git a/cmd/serve.go b/cmd/serve.go index 7577ad4e5..56c6fbaae 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -15,13 +15,22 @@ package cmd import ( + "fmt" + "github.com/julienschmidt/httprouter" + "github.com/ory/graceful" + "github.com/ory/keto/driver" + "github.com/ory/keto/models" + "github.com/ory/keto/relation" "github.com/spf13/cobra" + "google.golang.org/grpc" + "net" + "net/http" + "os" + "sync" "github.com/ory/x/viperx" "github.com/ory/x/logrusx" - - "github.com/ory/keto/cmd/server" ) // serveCmd represents the serve command @@ -36,7 +45,49 @@ ORY Keto can be configured using environment variables as well as a configuratio on configuration options, open the configuration documentation: >> https://github.com/ory/keto/blob/` + Version + `/docs/config.yaml <<`, - Run: server.RunServe(logger, Version, Commit, Date), + Run: func(cmd *cobra.Command, args []string) { + lis, err := net.Listen("tcp", ":4467") + if err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%+v\n", err) + os.Exit(1) + } + + reg := &driver.RegistryDefault{} + + wg := &sync.WaitGroup{} + wg.Add(2) + + go func() { + defer wg.Done() + + s := grpc.NewServer() + models.RegisterGRPCRelationReaderServer(s, relation.NewServer(reg)) + fmt.Println("going to serve GRPC on", lis.Addr().String()) + if err := s.Serve(lis); err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%+v\n", err) + } + }() + + go func() { + defer wg.Done() + + router := httprouter.New() + h := relation.NewHandler(reg) + h.RegisterPublicRoutes(router) + + server := graceful.WithDefaults(&http.Server{ + Addr: ":4466", + Handler: router, + }) + + fmt.Println("going to serve REST on", server.Addr) + if err := server.ListenAndServe(); err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "%+v\n", err) + } + }() + + wg.Wait() + }, } func init() { diff --git a/driver/registry.go b/driver/registry.go index 74c075020..9f4c54f39 100644 --- a/driver/registry.go +++ b/driver/registry.go @@ -22,8 +22,8 @@ type Registry interface { BuildDate() string BuildHash() string - x.RegistryLogger - x.RegistryWriter + x.LoggerProvider + x.WriterProvider HealthHandler() *healthx.Handler Tracer() *tracing.Tracer diff --git a/driver/registry_default.go b/driver/registry_default.go new file mode 100644 index 000000000..09eeef802 --- /dev/null +++ b/driver/registry_default.go @@ -0,0 +1,40 @@ +package driver + +import ( + "github.com/ory/herodot" + "github.com/ory/keto/persistence/memory" + "github.com/ory/keto/relation" + "github.com/ory/keto/x" + "github.com/ory/x/logrusx" +) + +var _ relation.ManagerProvider = &RegistryDefault{} +var _ x.WriterProvider = &RegistryDefault{} +var _ x.LoggerProvider = &RegistryDefault{} + +type RegistryDefault struct { + p *memory.Persister + l *logrusx.Logger + w herodot.Writer +} + +func (r *RegistryDefault) Logger() *logrusx.Logger { + if r.l == nil { + r.l = logrusx.New("keto", "dev") + } + return r.l +} + +func (r *RegistryDefault) Writer() herodot.Writer { + if r.w == nil { + r.w = herodot.NewJSONWriter(r.Logger()) + } + return r.w +} + +func (r *RegistryDefault) RelationManager() relation.Manager { + if r.p == nil { + r.p = memory.NewPersister() + } + return r.p +} diff --git a/go.mod b/go.mod index abcd0f42f..49eb5ca43 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,20 @@ module github.com/ory/keto require ( - github.com/akutz/goof v0.1.2 // indirect - github.com/akutz/gotil v0.1.0 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect - github.com/go-errors/errors v1.0.1 github.com/go-openapi/errors v0.19.4 github.com/go-openapi/runtime v0.19.5 github.com/go-openapi/strfmt v0.19.5 github.com/go-openapi/swag v0.19.5 github.com/go-openapi/validate v0.19.3 - github.com/go-sql-driver/mysql v1.5.0 github.com/go-swagger/go-swagger v0.21.1-0.20200107003254-1c98855b472d github.com/gobuffalo/packr v1.24.1 - github.com/gobwas/glob v0.2.3 // indirect - github.com/golang/protobuf v1.4.2 // indirect + github.com/gofrs/uuid v3.2.0+incompatible + github.com/golang/protobuf v1.4.2 github.com/gorilla/sessions v1.1.3 github.com/gorilla/websocket v1.4.2 - github.com/jackc/pgx/v4 v4.4.1 - github.com/jmoiron/sqlx v1.2.0 github.com/julienschmidt/httprouter v1.2.0 - github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 // indirect - github.com/open-policy-agent/opa v0.10.1 github.com/ory/analytics-go/v4 v4.0.1 github.com/ory/cli v0.0.11 github.com/ory/go-acc v0.2.3 @@ -30,25 +22,22 @@ require ( github.com/ory/herodot v0.9.1 github.com/ory/viper v1.7.5 github.com/ory/x v0.0.128 - github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.3.0 // indirect - github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect github.com/rs/cors v1.6.0 - github.com/rubenv/sql-migrate v0.0.0-20190327083759-54bad0a9b051 + github.com/rubenv/sql-migrate v0.0.0-20190327083759-54bad0a9b051 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.0 // indirect github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518 - github.com/stretchr/testify v1.5.1 github.com/tidwall/sjson v1.1.1 // indirect github.com/urfave/negroni v1.0.0 - github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b // indirect go.mongodb.org/mongo-driver v1.3.4 // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/tools v0.0.0-20200401192744-099440627f01 - google.golang.org/grpc v1.29.1 // indirect - google.golang.org/protobuf v1.24.0 // indirect + google.golang.org/grpc v1.33.0 + google.golang.org/protobuf v1.25.0 ) go 1.14 diff --git a/go.sum b/go.sum index 0fe11a4b4..2f988a61f 100644 --- a/go.sum +++ b/go.sum @@ -41,10 +41,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f h1:zvClvFQwU++UpIUBGC8YmDlfhUrweEy1R1Fj1gu5iIM= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/akutz/goof v0.1.2 h1:ZgsmzbhfcFTh1KhkWrWNAvlDobBUBEKAkSpowCuqOn4= -github.com/akutz/goof v0.1.2/go.mod h1:w8jsAAm0/n4Tst8M4xYwGPMzn54u4pCA3wh4e2rNLlk= -github.com/akutz/gotil v0.1.0 h1:CIYFCaONzf0OWdK0hv0bgpQINZ6flgbBl3yhJNmF9cg= -github.com/akutz/gotil v0.1.0/go.mod h1:dQodnbCqWtMZSTC+JdTOerHMrsp0/EQx3qYG0c6PlxA= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -154,8 +150,6 @@ github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7a github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-bindata/go-bindata v3.1.1+incompatible h1:tR4f0e4VTO7LK6B2YWyAoVEzG9ByG1wrXB4TL9+jiYg= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -511,8 +505,6 @@ github.com/gobuffalo/validate/v3 v3.2.0 h1:Zrpkz2kuZ4rGXLaO3IHVlwX512/cUWRvNjw46 github.com/gobuffalo/validate/v3 v3.2.0/go.mod h1:PrhDOdDHxtN8KUgMvF3TDL0r1YZXV4sQnyFX/EmeETY= github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc= github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -561,6 +553,7 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -573,6 +566,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -695,8 +690,6 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro= -github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/karrick/godirwalk v1.7.7/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/karrick/godirwalk v1.7.8/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= @@ -845,8 +838,6 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.6.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/open-policy-agent/opa v0.10.1 h1:1886j/U6WujuEJgkgzxsIg/U8wJYf/lN64Mvrzy6g6k= -github.com/open-policy-agent/opa v0.10.1/go.mod h1:rlfeSeHuZmMEpmrcGla42AjkOUjP4rGIpS96H12un3o= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -944,8 +935,6 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1120,8 +1109,6 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= -github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY= -github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= @@ -1472,6 +1459,8 @@ google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.0 h1:IBKSUNL2uBS2DkJBncPP+TwT0sp9tgA8A75NjHt6umg= +google.golang.org/grpc v1.33.0/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1483,6 +1472,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= diff --git a/models/relation.go b/models/relation.go new file mode 100644 index 000000000..078be7b4f --- /dev/null +++ b/models/relation.go @@ -0,0 +1,30 @@ +package models + +import "google.golang.org/protobuf/runtime/protoimpl" + +type Relation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `json:"user_id"` + Name string `json:"name"` + ObjectID string `json:"object_id"` +} + +var _ = Relation(GRPCRelation{}) +var _ = GRPCRelation(Relation{}) + +func (r *Relation) ImportFromGRPC(gr *GRPCRelation) *Relation { + //goland:noinspection GoVetCopyLock - state is reset afterwards + *r = Relation(*gr) + r.state = protoimpl.MessageState{} + return r +} + +func (x *GRPCRelation) ImportFromNormal(r *Relation) *GRPCRelation { + //goland:noinspection GoVetCopyLock - state is reset afterwards + *x = GRPCRelation(*r) + x.state = protoimpl.MessageState{} + return x +} diff --git a/models/relation.pb.go b/models/relation.pb.go new file mode 100644 index 000000000..fe605b4a3 --- /dev/null +++ b/models/relation.pb.go @@ -0,0 +1,332 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.4 +// source: models/relation.proto + +package models + +import ( + proto "github.com/golang/protobuf/proto" + 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) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type GRPCRelationsReadRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + PerPage int32 `protobuf:"varint,3,opt,name=perPage,proto3" json:"perPage,omitempty"` +} + +func (x *GRPCRelationsReadRequest) Reset() { + *x = GRPCRelationsReadRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GRPCRelationsReadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GRPCRelationsReadRequest) ProtoMessage() {} + +func (x *GRPCRelationsReadRequest) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_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 GRPCRelationsReadRequest.ProtoReflect.Descriptor instead. +func (*GRPCRelationsReadRequest) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{0} +} + +func (x *GRPCRelationsReadRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GRPCRelationsReadRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GRPCRelationsReadRequest) GetPerPage() int32 { + if x != nil { + return x.PerPage + } + return 0 +} + +type GRPCRelation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + ObjectID string `protobuf:"bytes,3,opt,name=objectID,proto3" json:"objectID,omitempty"` +} + +func (x *GRPCRelation) Reset() { + *x = GRPCRelation{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GRPCRelation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GRPCRelation) ProtoMessage() {} + +func (x *GRPCRelation) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_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 GRPCRelation.ProtoReflect.Descriptor instead. +func (*GRPCRelation) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{1} +} + +func (x *GRPCRelation) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +func (x *GRPCRelation) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GRPCRelation) GetObjectID() string { + if x != nil { + return x.ObjectID + } + return "" +} + +type GRPCRelationsReadResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Relations []*GRPCRelation `protobuf:"bytes,1,rep,name=relations,proto3" json:"relations,omitempty"` +} + +func (x *GRPCRelationsReadResponse) Reset() { + *x = GRPCRelationsReadResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GRPCRelationsReadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GRPCRelationsReadResponse) ProtoMessage() {} + +func (x *GRPCRelationsReadResponse) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_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 GRPCRelationsReadResponse.ProtoReflect.Descriptor instead. +func (*GRPCRelationsReadResponse) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{2} +} + +func (x *GRPCRelationsReadResponse) GetRelations() []*GRPCRelation { + if x != nil { + return x.Relations + } + return nil +} + +var File_models_relation_proto protoreflect.FileDescriptor + +var file_models_relation_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x22, + 0x58, 0x0a, 0x18, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x50, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x07, 0x70, 0x65, 0x72, 0x50, 0x61, 0x67, 0x65, 0x22, 0x56, 0x0a, 0x0c, 0x47, 0x52, 0x50, + 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, + 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x44, 0x22, 0x4f, 0x0a, 0x19, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, + 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x32, 0xc6, 0x01, 0x0a, 0x12, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0f, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x58, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, + 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x61, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x73, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x1c, 0x5a, 0x1a, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, + 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_models_relation_proto_rawDescOnce sync.Once + file_models_relation_proto_rawDescData = file_models_relation_proto_rawDesc +) + +func file_models_relation_proto_rawDescGZIP() []byte { + file_models_relation_proto_rawDescOnce.Do(func() { + file_models_relation_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_relation_proto_rawDescData) + }) + return file_models_relation_proto_rawDescData +} + +var file_models_relation_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_models_relation_proto_goTypes = []interface{}{ + (*GRPCRelationsReadRequest)(nil), // 0: models.GRPCRelationsReadRequest + (*GRPCRelation)(nil), // 1: models.GRPCRelation + (*GRPCRelationsReadResponse)(nil), // 2: models.GRPCRelationsReadResponse +} +var file_models_relation_proto_depIdxs = []int32{ + 1, // 0: models.GRPCRelationsReadResponse.relations:type_name -> models.GRPCRelation + 0, // 1: models.GRPCRelationReader.RelationsByUser:input_type -> models.GRPCRelationsReadRequest + 0, // 2: models.GRPCRelationReader.RelationsByObject:input_type -> models.GRPCRelationsReadRequest + 2, // 3: models.GRPCRelationReader.RelationsByUser:output_type -> models.GRPCRelationsReadResponse + 2, // 4: models.GRPCRelationReader.RelationsByObject:output_type -> models.GRPCRelationsReadResponse + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] 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_models_relation_proto_init() } +func file_models_relation_proto_init() { + if File_models_relation_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_models_relation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GRPCRelationsReadRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_models_relation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GRPCRelation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_models_relation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GRPCRelationsReadResponse); 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_models_relation_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_models_relation_proto_goTypes, + DependencyIndexes: file_models_relation_proto_depIdxs, + MessageInfos: file_models_relation_proto_msgTypes, + }.Build() + File_models_relation_proto = out.File + file_models_relation_proto_rawDesc = nil + file_models_relation_proto_goTypes = nil + file_models_relation_proto_depIdxs = nil +} diff --git a/models/relation.proto b/models/relation.proto new file mode 100644 index 000000000..3a0a112b6 --- /dev/null +++ b/models/relation.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +option go_package = "github.com/ory/keto/models"; + +package models; + +service GRPCRelationReader { + rpc RelationsByUser(GRPCRelationsReadRequest) returns (GRPCRelationsReadResponse); + rpc RelationsByObject(GRPCRelationsReadRequest) returns (GRPCRelationsReadResponse); +} + +message GRPCRelationsReadRequest { + string id = 1; + int32 page = 2; + int32 perPage = 3; +} + +message GRPCRelation { + string userID = 1; + string name = 2; + string objectID = 3; +} + +message GRPCRelationsReadResponse { + repeated GRPCRelation relations = 1; +} diff --git a/models/relation_grpc.pb.go b/models/relation_grpc.pb.go new file mode 100644 index 000000000..e944db80b --- /dev/null +++ b/models/relation_grpc.pb.go @@ -0,0 +1,133 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package models + +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. +const _ = grpc.SupportPackageIsVersion7 + +// GRPCRelationReaderClient is the client API for GRPCRelationReader 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 GRPCRelationReaderClient interface { + RelationsByUser(ctx context.Context, in *GRPCRelationsReadRequest, opts ...grpc.CallOption) (*GRPCRelationsReadResponse, error) + RelationsByObject(ctx context.Context, in *GRPCRelationsReadRequest, opts ...grpc.CallOption) (*GRPCRelationsReadResponse, error) +} + +type gRPCRelationReaderClient struct { + cc grpc.ClientConnInterface +} + +func NewGRPCRelationReaderClient(cc grpc.ClientConnInterface) GRPCRelationReaderClient { + return &gRPCRelationReaderClient{cc} +} + +func (c *gRPCRelationReaderClient) RelationsByUser(ctx context.Context, in *GRPCRelationsReadRequest, opts ...grpc.CallOption) (*GRPCRelationsReadResponse, error) { + out := new(GRPCRelationsReadResponse) + err := c.cc.Invoke(ctx, "/models.GRPCRelationReader/RelationsByUser", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gRPCRelationReaderClient) RelationsByObject(ctx context.Context, in *GRPCRelationsReadRequest, opts ...grpc.CallOption) (*GRPCRelationsReadResponse, error) { + out := new(GRPCRelationsReadResponse) + err := c.cc.Invoke(ctx, "/models.GRPCRelationReader/RelationsByObject", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GRPCRelationReaderServer is the server API for GRPCRelationReader service. +// All implementations must embed UnimplementedGRPCRelationReaderServer +// for forward compatibility +type GRPCRelationReaderServer interface { + RelationsByUser(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) + RelationsByObject(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) + mustEmbedUnimplementedGRPCRelationReaderServer() +} + +// UnimplementedGRPCRelationReaderServer must be embedded to have forward compatible implementations. +type UnimplementedGRPCRelationReaderServer struct { +} + +func (UnimplementedGRPCRelationReaderServer) RelationsByUser(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RelationsByUser not implemented") +} +func (UnimplementedGRPCRelationReaderServer) RelationsByObject(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RelationsByObject not implemented") +} +func (UnimplementedGRPCRelationReaderServer) mustEmbedUnimplementedGRPCRelationReaderServer() {} + +// UnsafeGRPCRelationReaderServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GRPCRelationReaderServer will +// result in compilation errors. +type UnsafeGRPCRelationReaderServer interface { + mustEmbedUnimplementedGRPCRelationReaderServer() +} + +func RegisterGRPCRelationReaderServer(s *grpc.Server, srv GRPCRelationReaderServer) { + s.RegisterService(&_GRPCRelationReader_serviceDesc, srv) +} + +func _GRPCRelationReader_RelationsByUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GRPCRelationsReadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GRPCRelationReaderServer).RelationsByUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/models.GRPCRelationReader/RelationsByUser", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GRPCRelationReaderServer).RelationsByUser(ctx, req.(*GRPCRelationsReadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GRPCRelationReader_RelationsByObject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GRPCRelationsReadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GRPCRelationReaderServer).RelationsByObject(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/models.GRPCRelationReader/RelationsByObject", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GRPCRelationReaderServer).RelationsByObject(ctx, req.(*GRPCRelationsReadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _GRPCRelationReader_serviceDesc = grpc.ServiceDesc{ + ServiceName: "models.GRPCRelationReader", + HandlerType: (*GRPCRelationReaderServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RelationsByUser", + Handler: _GRPCRelationReader_RelationsByUser_Handler, + }, + { + MethodName: "RelationsByObject", + Handler: _GRPCRelationReader_RelationsByObject_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "models/relation.proto", +} diff --git a/persistence/memory/definitions.go b/persistence/memory/definitions.go new file mode 100644 index 000000000..1f5bd55a3 --- /dev/null +++ b/persistence/memory/definitions.go @@ -0,0 +1,27 @@ +package memory + +import ( + "github.com/ory/keto/models" + "github.com/ory/keto/relation" + "sync" +) + +type Persister struct { + sync.RWMutex + + relations []*models.Relation +} + +var _ relation.Manager = &Persister{} + +func NewPersister() *Persister { + return &Persister{ + relations: []*models.Relation{ + { + UserID: "1", + Name: "testRelation", + ObjectID: "2", + }, + }, + } +} diff --git a/persistence/memory/relations.go b/persistence/memory/relations.go new file mode 100644 index 000000000..ffa682a00 --- /dev/null +++ b/persistence/memory/relations.go @@ -0,0 +1,47 @@ +package memory + +import ( + "context" + "github.com/ory/keto/models" +) + +func (p *Persister) paginateRelations(rels []*models.Relation, page, perPage int32) []*models.Relation { + if len(rels) == 0 { + return rels + } + + veryLast := int32(len(p.relations)) + start, end := page*perPage, (page+1)*perPage-1 + if veryLast < end { + end = veryLast + } + return rels[start:end] +} + +func (p *Persister) GetRelationsByUser(_ context.Context, userID string, page, perPage int32) ([]*models.Relation, error) { + p.RLock() + defer p.RUnlock() + + var res []*models.Relation + for _, r := range p.relations { + if r.UserID == userID { + res = append(res, r) + } + } + + return p.paginateRelations(res, page, perPage), nil +} + +func (p *Persister) GetRelationsByObject(_ context.Context, objectID string, page, perPage int32) ([]*models.Relation, error) { + p.RLock() + defer p.RUnlock() + + var res []*models.Relation + for _, r := range p.relations { + if r.ObjectID == objectID { + res = append(res, r) + } + } + + return p.paginateRelations(res, page, perPage), nil +} diff --git a/relation/definitions.go b/relation/definitions.go new file mode 100644 index 000000000..fd12e9c08 --- /dev/null +++ b/relation/definitions.go @@ -0,0 +1,16 @@ +package relation + +import ( + "context" + "github.com/ory/keto/models" +) + +type ( + ManagerProvider interface { + RelationManager() Manager + } + Manager interface { + GetRelationsByUser(ctx context.Context, userID string, page, perPage int32) ([]*models.Relation, error) + GetRelationsByObject(ctx context.Context, objectID string, page, perPage int32) ([]*models.Relation, error) + } +) diff --git a/relation/grpc_server.go b/relation/grpc_server.go new file mode 100644 index 000000000..5815923f3 --- /dev/null +++ b/relation/grpc_server.go @@ -0,0 +1,48 @@ +package relation + +import ( + "context" + "github.com/ory/keto/models" +) + +var _ models.GRPCRelationReaderServer = &Server{} + +type ( + serverDependencies interface { + ManagerProvider + } + Server struct { + models.UnimplementedGRPCRelationReaderServer + + d serverDependencies + } +) + +func NewServer(d serverDependencies) *Server { + return &Server{ + d: d, + } +} + +func (_ *Server) relationsHelper(ctx context.Context, queryID string, page, perPage int32, getterFunc func(context.Context, string, int32, int32) ([]*models.Relation, error)) (*models.GRPCRelationsReadResponse, error) { + rels, err := getterFunc(ctx, queryID, page, perPage) + if err != nil { + return nil, err + } + + rpcRels := make([]*models.GRPCRelation, len(rels)) + for i := range rels { + rpcRels[i] = (&models.GRPCRelation{}).ImportFromNormal(rels[i]) + } + return &models.GRPCRelationsReadResponse{ + Relations: rpcRels, + }, nil +} + +func (s *Server) RelationsByObject(ctx context.Context, req *models.GRPCRelationsReadRequest) (*models.GRPCRelationsReadResponse, error) { + return s.relationsHelper(ctx, req.Id, req.Page, req.PerPage, s.d.RelationManager().GetRelationsByObject) +} + +func (s *Server) RelationsByUser(ctx context.Context, req *models.GRPCRelationsReadRequest) (*models.GRPCRelationsReadResponse, error) { + return s.relationsHelper(ctx, req.Id, req.Page, req.PerPage, s.d.RelationManager().GetRelationsByUser) +} diff --git a/relation/handler.go b/relation/handler.go new file mode 100644 index 000000000..5b1894c74 --- /dev/null +++ b/relation/handler.go @@ -0,0 +1,58 @@ +package relation + +import ( + "github.com/julienschmidt/httprouter" + "github.com/ory/herodot" + "github.com/ory/keto/models" + "github.com/ory/keto/x" + "github.com/pkg/errors" + "net/http" +) + +type ( + handlerDependencies interface { + ManagerProvider + x.LoggerProvider + x.WriterProvider + } + handler struct { + d handlerDependencies + } +) + +const ( + routeBase = "/relations" +) + +func NewHandler(d handlerDependencies) *handler { + return &handler{ + d: d, + } +} + +func (h *handler) RegisterPublicRoutes(router *httprouter.Router) { + router.GET(routeBase, h.getRelations) +} + +func (h *handler) getRelations(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + userID := r.URL.Query().Get("user-id") + objectID := r.URL.Query().Get("object-id") + + var rels []*models.Relation + var err error + + if userID != "" { + rels, err = h.d.RelationManager().GetRelationsByUser(r.Context(), userID, 0, 100) + } else if objectID != "" { + rels, err = h.d.RelationManager().GetRelationsByObject(r.Context(), objectID, 0, 100) + } else { + h.d.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest)) + return + } + + if err != nil { + h.d.Writer().WriteError(w, r, err) + return + } + h.d.Writer().Write(w, r, rels) +} diff --git a/x/registry.go b/x/registry.go index 1572e32e9..edfd92219 100644 --- a/x/registry.go +++ b/x/registry.go @@ -7,11 +7,11 @@ import ( "github.com/ory/x/logrusx" ) -type RegistryLogger interface { +type LoggerProvider interface { Logger() *logrusx.Logger } -type RegistryWriter interface { +type WriterProvider interface { Writer() herodot.Writer }