From 6246ec701473da334e64e23b6dae215c9a914914 Mon Sep 17 00:00:00 2001 From: Nick Ufer Date: Mon, 26 Oct 2020 23:38:57 +0100 Subject: [PATCH 1/6] Refactors grpc api and structs for atomicity of fields --- cmd/relation/create.go | 4 +- cmd/relation/get.go | 14 +- cmd/serve.go | 3 +- go.mod | 2 - go.sum | 9 +- models/REQUIREMENTS.md | 8 + models/relation.go | 156 ++++++-- models/relation.pb.go | 645 ++++++++++++++++++++++++------ models/relation.proto | 69 +++- models/relation_grpc.pb.go | 181 +++------ persistence/memory/definitions.go | 8 +- persistence/memory/relations.go | 63 ++- relation/definitions.go | 3 +- relation/grpc_server.go | 37 +- relation/handler.go | 21 +- 15 files changed, 843 insertions(+), 380 deletions(-) create mode 100644 models/REQUIREMENTS.md diff --git a/cmd/relation/create.go b/cmd/relation/create.go index 6e78863cb..2d9decbd2 100644 --- a/cmd/relation/create.go +++ b/cmd/relation/create.go @@ -43,9 +43,9 @@ func newCreateCmd() *cobra.Command { return cmdx.FailSilently(cmd) } - cl := models.NewGRPCRelationWriterClient(conn) + cl := models.NewRelationTupleServiceClient(conn) - _, err = cl.WriteRelation(context.Background(), (*models.GRPCRelation)(&r)) + _, err = cl.WriteRelationTuple(context.Background(), &models.WriteRelationTupleRequest{Tuple: (&models.RelationTuple{}).ImportFromNormal(&r)}) if err != nil { _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Error doing the request: %s\n", err) return cmdx.FailSilently(cmd) diff --git a/cmd/relation/get.go b/cmd/relation/get.go index 5d3310aaf..da93486b9 100644 --- a/cmd/relation/get.go +++ b/cmd/relation/get.go @@ -23,18 +23,24 @@ func newGetCmd() *cobra.Command { } defer conn.Close() - cl := models.NewGRPCRelationReaderClient(conn) - resp, err := cl.RelationsByUser(context.Background(), &models.GRPCRelationsReadRequest{ + cl := models.NewRelationTupleServiceClient(conn) + resp, err := cl.ReadRelationTuples(context.Background(), &models.ReadRelationTuplesRequest{ + Tuplesets: []*models.ReadRelationTuplesRequest_Query{ + { + User: &models.ReadRelationTuplesRequest_Query_UserId{ + UserId: args[0], + }, + }, + }, Page: 0, PerPage: 100, - Id: args[0], }) if err != nil { _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Could not make request: %s\n", err) return err } - cmdx.PrintCollection(cmd, models.NewGRPCRelationCollection(resp.Relations)) + cmdx.PrintCollection(cmd, models.NewGRPCRelationCollection(resp.Tuples)) return nil }, } diff --git a/cmd/serve.go b/cmd/serve.go index c801db274..c1f80473d 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -66,8 +66,7 @@ on configuration options, open the configuration documentation: s := grpc.NewServer() relS := relation.NewServer(reg) - models.RegisterGRPCRelationReaderServer(s, relS) - models.RegisterGRPCRelationWriterServer(s, relS) + models.RegisterRelationTupleServiceServer(s, relS) fmt.Println("going to serve GRPC on", lis.Addr().String()) if err := s.Serve(lis); err != nil { fmt.Fprintf(cmd.ErrOrStderr(), "%+v\n", err) diff --git a/go.mod b/go.mod index cffe735e5..8ae9c9e0f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/go-openapi/validate v0.19.3 github.com/go-swagger/go-swagger v0.21.1-0.20200107003254-1c98855b472d github.com/gobuffalo/packr v1.24.1 - 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 @@ -23,7 +22,6 @@ require ( github.com/ory/viper v1.7.5 github.com/ory/x v0.0.154 github.com/pkg/errors v0.9.1 - github.com/pkg/profile v1.3.0 // indirect github.com/rs/cors v1.6.0 github.com/rubenv/sql-migrate v0.0.0-20190327083759-54bad0a9b051 // indirect github.com/shopspring/decimal v1.2.0 // indirect diff --git a/go.sum b/go.sum index adec57390..44d2a4f2f 100644 --- a/go.sum +++ b/go.sum @@ -564,6 +564,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 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= 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= @@ -592,6 +593,7 @@ github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/ github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= @@ -944,8 +946,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/profile v1.3.0 h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI= -github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -1084,6 +1084,7 @@ github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmG github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1488,8 +1489,6 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 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= @@ -1501,8 +1500,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 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/DataDog/dd-trace-go.v1 v1.27.0 h1:WGVt9dwn9vNeWZVdDYzjGQbEW8CghAkJlrC8w80jFVY= diff --git a/models/REQUIREMENTS.md b/models/REQUIREMENTS.md new file mode 100644 index 000000000..922ade776 --- /dev/null +++ b/models/REQUIREMENTS.md @@ -0,0 +1,8 @@ +# Read API + +## Read by tuplesets + +Read request = one or multiple tuplesets + +Tupleset = Keys of one or multiple saved tuples + diff --git a/models/relation.go b/models/relation.go index 1b292acba..568670afb 100644 --- a/models/relation.go +++ b/models/relation.go @@ -1,43 +1,141 @@ package models import ( - "google.golang.org/protobuf/runtime/protoimpl" + "fmt" "github.com/ory/x/cmdx" ) 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"` - } relationCollection struct { - grpcRelations []*GRPCRelation + grpcRelations []*RelationTuple internalRelations []*Relation } + Object struct { + ID string + Namespace string + } + User interface { + String() string + } + UserID struct { + User + ID string + } + UserSet struct { + User + Object Object + Relation string + } + Relation struct { + Object Object + Relation string + User User + } + RelationQuery struct { + Object Object + Relation string + User User + } ) -var _ = Relation(GRPCRelation{}) -var _ = GRPCRelation(Relation{}) -var _ cmdx.OutputEntry = &Relation{} +func (o Object) String() string { + return fmt.Sprintf("%s:%s", o.Namespace, o.ID) +} + +func (u UserID) String() string { + return fmt.Sprintf("%s", u.ID) +} + +func (u UserSet) String() string { + return fmt.Sprintf("%s#%s", u.Object, u.Relation) +} + +func (r Relation) String() string { + return fmt.Sprintf("%s#%s@%s", r.Object, r.Relation, r.User) +} + +func (r *Relation) ImportFromGRPC(gr *RelationTuple) *Relation { + var user User + switch gr.User.(type) { + case *RelationTuple_UserId: + user = UserID{ + ID: gr.GetUserId(), + } + case *RelationTuple_UserSet: + user = UserSet{ + Object: Object{ + gr.GetUserSet().Object.Namespace, + gr.GetUserSet().Object.ObjectId, + }, + Relation: gr.GetUserSet().Relation, + } + } + + r.Object = Object{ + gr.Object.Namespace, + gr.Object.ObjectId, + } + r.Relation = gr.Relation + r.User = user -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 +func (gr *RelationTuple) ImportFromNormal(r *Relation) *RelationTuple { + var user isRelationTuple_User + switch r.User.(type) { + case UserID: + user = &RelationTuple_UserId{ + r.User.(UserID).ID, + } + case UserSet: + userSet := r.User.(UserSet) + user = &RelationTuple_UserSet{ + UserSet: &RelationUserSet{ + Object: &RelationObject{ + ObjectId: userSet.Object.ID, + Namespace: userSet.Object.Namespace, + }, + }, + } + } + + gr.Object = &RelationObject{ + ObjectId: r.Object.ID, + Namespace: r.Object.Namespace, + } + gr.Relation = r.Relation + gr.User = user + + return gr +} + +func (rq *RelationQuery) ImportFromGRPC(rtq *ReadRelationTuplesRequest_Query) *RelationQuery { + var user User + switch rtq.User.(type) { + case *ReadRelationTuplesRequest_Query_UserId: + user = UserID{ + ID: rtq.GetUserId(), + } + case *ReadRelationTuplesRequest_Query_UserSet: + user = UserSet{ + Object: Object{ + rtq.GetUserSet().Object.Namespace, + rtq.GetUserSet().Object.ObjectId, + }, + Relation: rtq.GetUserSet().Relation, + } + } + + rq.Object = Object{ + rtq.Object.Namespace, + rtq.Object.ObjectId, + } + rq.Relation = rtq.Relation + rq.User = user + + return rq } func (r *Relation) Header() []string { @@ -50,9 +148,9 @@ func (r *Relation) Header() []string { func (r *Relation) Fields() []string { return []string{ - r.Name, - r.UserID, - r.ObjectID, + r.Relation, + r.User.String(), + r.Object.String(), } } @@ -60,7 +158,7 @@ func (r *Relation) Interface() interface{} { return r } -func NewGRPCRelationCollection(rels []*GRPCRelation) cmdx.OutputCollection { +func NewGRPCRelationCollection(rels []*RelationTuple) cmdx.OutputCollection { return &relationCollection{ grpcRelations: rels, } @@ -83,13 +181,13 @@ func (r *relationCollection) Header() []string { func (r *relationCollection) Table() [][]string { if r.internalRelations == nil { for _, rel := range r.grpcRelations { - r.internalRelations = append(r.internalRelations, (*Relation)(rel)) + r.internalRelations = append(r.internalRelations, (&Relation{}).ImportFromGRPC(rel)) } } data := make([][]string, len(r.internalRelations)) for i, rel := range r.internalRelations { - data[i] = []string{rel.Name, rel.UserID, rel.ObjectID} + data[i] = []string{rel.Relation, rel.User.String(), rel.Object.String()} } return data diff --git a/models/relation.pb.go b/models/relation.pb.go index 100c4aa56..df8911cb5 100644 --- a/models/relation.pb.go +++ b/models/relation.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.12.4 +// protoc v3.7.1 // source: models/relation.proto package models @@ -26,18 +26,22 @@ const ( // of the legacy proto package is being used. const _ = proto.ProtoPackageIsVersion4 -type GRPCRelationsReadRequest struct { +// Query by partial keys of tuples // TODO even wanted? +type ReadRelationTuplesRequest 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"` + // All conditions are concatenated with + // an OR operator. If any query matches + // the relation will be in the response + Tuplesets []*ReadRelationTuplesRequest_Query `protobuf:"bytes,1,rep,name=tuplesets,proto3" json:"tuplesets,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + PerPage int32 `protobuf:"varint,3,opt,name=per_page,json=perPage,proto3" json:"per_page,omitempty"` } -func (x *GRPCRelationsReadRequest) Reset() { - *x = GRPCRelationsReadRequest{} +func (x *ReadRelationTuplesRequest) Reset() { + *x = ReadRelationTuplesRequest{} if protoimpl.UnsafeEnabled { mi := &file_models_relation_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -45,13 +49,13 @@ func (x *GRPCRelationsReadRequest) Reset() { } } -func (x *GRPCRelationsReadRequest) String() string { +func (x *ReadRelationTuplesRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GRPCRelationsReadRequest) ProtoMessage() {} +func (*ReadRelationTuplesRequest) ProtoMessage() {} -func (x *GRPCRelationsReadRequest) ProtoReflect() protoreflect.Message { +func (x *ReadRelationTuplesRequest) ProtoReflect() protoreflect.Message { mi := &file_models_relation_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -63,44 +67,42 @@ func (x *GRPCRelationsReadRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GRPCRelationsReadRequest.ProtoReflect.Descriptor instead. -func (*GRPCRelationsReadRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use ReadRelationTuplesRequest.ProtoReflect.Descriptor instead. +func (*ReadRelationTuplesRequest) Descriptor() ([]byte, []int) { return file_models_relation_proto_rawDescGZIP(), []int{0} } -func (x *GRPCRelationsReadRequest) GetId() string { +func (x *ReadRelationTuplesRequest) GetTuplesets() []*ReadRelationTuplesRequest_Query { if x != nil { - return x.Id + return x.Tuplesets } - return "" + return nil } -func (x *GRPCRelationsReadRequest) GetPage() int32 { +func (x *ReadRelationTuplesRequest) GetPage() int32 { if x != nil { return x.Page } return 0 } -func (x *GRPCRelationsReadRequest) GetPerPage() int32 { +func (x *ReadRelationTuplesRequest) GetPerPage() int32 { if x != nil { return x.PerPage } return 0 } -type GRPCRelation struct { +type ReadRelationTuplesResponse 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"` + Tuples []*RelationTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` } -func (x *GRPCRelation) Reset() { - *x = GRPCRelation{} +func (x *ReadRelationTuplesResponse) Reset() { + *x = ReadRelationTuplesResponse{} if protoimpl.UnsafeEnabled { mi := &file_models_relation_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -108,13 +110,13 @@ func (x *GRPCRelation) Reset() { } } -func (x *GRPCRelation) String() string { +func (x *ReadRelationTuplesResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GRPCRelation) ProtoMessage() {} +func (*ReadRelationTuplesResponse) ProtoMessage() {} -func (x *GRPCRelation) ProtoReflect() protoreflect.Message { +func (x *ReadRelationTuplesResponse) ProtoReflect() protoreflect.Message { mi := &file_models_relation_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -126,57 +128,233 @@ func (x *GRPCRelation) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GRPCRelation.ProtoReflect.Descriptor instead. -func (*GRPCRelation) Descriptor() ([]byte, []int) { +// Deprecated: Use ReadRelationTuplesResponse.ProtoReflect.Descriptor instead. +func (*ReadRelationTuplesResponse) Descriptor() ([]byte, []int) { return file_models_relation_proto_rawDescGZIP(), []int{1} } -func (x *GRPCRelation) GetUserID() string { +func (x *ReadRelationTuplesResponse) GetTuples() []*RelationTuple { if x != nil { - return x.UserID + return x.Tuples } - return "" + return nil +} + +type WriteRelationTupleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tuple *RelationTuple `protobuf:"bytes,1,opt,name=tuple,proto3" json:"tuple,omitempty"` } -func (x *GRPCRelation) GetName() string { +func (x *WriteRelationTupleRequest) Reset() { + *x = WriteRelationTupleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WriteRelationTupleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WriteRelationTupleRequest) ProtoMessage() {} + +func (x *WriteRelationTupleRequest) 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 WriteRelationTupleRequest.ProtoReflect.Descriptor instead. +func (*WriteRelationTupleRequest) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{2} +} + +func (x *WriteRelationTupleRequest) GetTuple() *RelationTuple { if x != nil { - return x.Name + return x.Tuple } - return "" + return nil +} + +type WriteRelationTupleResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *WriteRelationTupleResponse) Reset() { + *x = WriteRelationTupleResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WriteRelationTupleResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x *GRPCRelation) GetObjectID() string { +func (*WriteRelationTupleResponse) ProtoMessage() {} + +func (x *WriteRelationTupleResponse) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_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 WriteRelationTupleResponse.ProtoReflect.Descriptor instead. +func (*WriteRelationTupleResponse) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{3} +} + +// Represents a relation between +// an object and an user. +type RelationTuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Object *RelationObject `protobuf:"bytes,1,opt,name=object,proto3" json:"object,omitempty"` + // Specifies the relation between an `object` and an `user` + Relation string `protobuf:"bytes,2,opt,name=relation,proto3" json:"relation,omitempty"` + // The user of the tuple can either be + // a single user or a userset + // + // Types that are assignable to User: + // *RelationTuple_UserId + // *RelationTuple_UserSet + User isRelationTuple_User `protobuf_oneof:"user"` +} + +func (x *RelationTuple) Reset() { + *x = RelationTuple{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[4] + 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_models_relation_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 RelationTuple.ProtoReflect.Descriptor instead. +func (*RelationTuple) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{4} +} + +func (x *RelationTuple) GetObject() *RelationObject { if x != nil { - return x.ObjectID + return x.Object + } + return nil +} + +func (x *RelationTuple) GetRelation() string { + if x != nil { + return x.Relation + } + return "" +} + +func (m *RelationTuple) GetUser() isRelationTuple_User { + if m != nil { + return m.User + } + return nil +} + +func (x *RelationTuple) GetUserId() string { + if x, ok := x.GetUser().(*RelationTuple_UserId); ok { + return x.UserId } return "" } -type GRPCRelationsReadResponse struct { +func (x *RelationTuple) GetUserSet() *RelationUserSet { + if x, ok := x.GetUser().(*RelationTuple_UserSet); ok { + return x.UserSet + } + return nil +} + +type isRelationTuple_User interface { + isRelationTuple_User() +} + +type RelationTuple_UserId struct { + UserId string `protobuf:"bytes,3,opt,name=user_id,json=userId,proto3,oneof"` +} + +type RelationTuple_UserSet struct { + UserSet *RelationUserSet `protobuf:"bytes,4,opt,name=user_set,json=userSet,proto3,oneof"` +} + +func (*RelationTuple_UserId) isRelationTuple_User() {} + +func (*RelationTuple_UserSet) isRelationTuple_User() {} + +// Refers to all users which have +// a `relation` with an `object` +type RelationUserSet struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Relations []*GRPCRelation `protobuf:"bytes,1,rep,name=relations,proto3" json:"relations,omitempty"` + Object *RelationObject `protobuf:"bytes,1,opt,name=object,proto3" json:"object,omitempty"` + Relation string `protobuf:"bytes,2,opt,name=relation,proto3" json:"relation,omitempty"` } -func (x *GRPCRelationsReadResponse) Reset() { - *x = GRPCRelationsReadResponse{} +func (x *RelationUserSet) Reset() { + *x = RelationUserSet{} if protoimpl.UnsafeEnabled { - mi := &file_models_relation_proto_msgTypes[2] + mi := &file_models_relation_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GRPCRelationsReadResponse) String() string { +func (x *RelationUserSet) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GRPCRelationsReadResponse) ProtoMessage() {} +func (*RelationUserSet) ProtoMessage() {} -func (x *GRPCRelationsReadResponse) ProtoReflect() protoreflect.Message { - mi := &file_models_relation_proto_msgTypes[2] +func (x *RelationUserSet) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -187,41 +365,52 @@ func (x *GRPCRelationsReadResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GRPCRelationsReadResponse.ProtoReflect.Descriptor instead. -func (*GRPCRelationsReadResponse) Descriptor() ([]byte, []int) { - return file_models_relation_proto_rawDescGZIP(), []int{2} +// Deprecated: Use RelationUserSet.ProtoReflect.Descriptor instead. +func (*RelationUserSet) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{5} } -func (x *GRPCRelationsReadResponse) GetRelations() []*GRPCRelation { +func (x *RelationUserSet) GetObject() *RelationObject { if x != nil { - return x.Relations + return x.Object } return nil } -type GRPCRelationsWriteResponse struct { +func (x *RelationUserSet) GetRelation() string { + if x != nil { + return x.Relation + } + return "" +} + +// Represents a "resource" +type RelationObject struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + ObjectId string `protobuf:"bytes,2,opt,name=object_id,json=objectId,proto3" json:"object_id,omitempty"` } -func (x *GRPCRelationsWriteResponse) Reset() { - *x = GRPCRelationsWriteResponse{} +func (x *RelationObject) Reset() { + *x = RelationObject{} if protoimpl.UnsafeEnabled { - mi := &file_models_relation_proto_msgTypes[3] + mi := &file_models_relation_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GRPCRelationsWriteResponse) String() string { +func (x *RelationObject) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GRPCRelationsWriteResponse) ProtoMessage() {} +func (*RelationObject) ProtoMessage() {} -func (x *GRPCRelationsWriteResponse) ProtoReflect() protoreflect.Message { - mi := &file_models_relation_proto_msgTypes[3] +func (x *RelationObject) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -232,55 +421,200 @@ func (x *GRPCRelationsWriteResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GRPCRelationsWriteResponse.ProtoReflect.Descriptor instead. -func (*GRPCRelationsWriteResponse) Descriptor() ([]byte, []int) { - return file_models_relation_proto_rawDescGZIP(), []int{3} +// Deprecated: Use RelationObject.ProtoReflect.Descriptor instead. +func (*RelationObject) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{6} +} + +func (x *RelationObject) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" } +func (x *RelationObject) GetObjectId() string { + if x != nil { + return x.ObjectId + } + return "" +} + +type ReadRelationTuplesRequest_Query struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional + Object *RelationObject `protobuf:"bytes,1,opt,name=object,proto3" json:"object,omitempty"` + // Optional + Relation string `protobuf:"bytes,2,opt,name=relation,proto3" json:"relation,omitempty"` + // Optional + // + // Types that are assignable to User: + // *ReadRelationTuplesRequest_Query_UserId + // *ReadRelationTuplesRequest_Query_UserSet + User isReadRelationTuplesRequest_Query_User `protobuf_oneof:"user"` +} + +func (x *ReadRelationTuplesRequest_Query) Reset() { + *x = ReadRelationTuplesRequest_Query{} + if protoimpl.UnsafeEnabled { + mi := &file_models_relation_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReadRelationTuplesRequest_Query) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadRelationTuplesRequest_Query) ProtoMessage() {} + +func (x *ReadRelationTuplesRequest_Query) ProtoReflect() protoreflect.Message { + mi := &file_models_relation_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 ReadRelationTuplesRequest_Query.ProtoReflect.Descriptor instead. +func (*ReadRelationTuplesRequest_Query) Descriptor() ([]byte, []int) { + return file_models_relation_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *ReadRelationTuplesRequest_Query) GetObject() *RelationObject { + if x != nil { + return x.Object + } + return nil +} + +func (x *ReadRelationTuplesRequest_Query) GetRelation() string { + if x != nil { + return x.Relation + } + return "" +} + +func (m *ReadRelationTuplesRequest_Query) GetUser() isReadRelationTuplesRequest_Query_User { + if m != nil { + return m.User + } + return nil +} + +func (x *ReadRelationTuplesRequest_Query) GetUserId() string { + if x, ok := x.GetUser().(*ReadRelationTuplesRequest_Query_UserId); ok { + return x.UserId + } + return "" +} + +func (x *ReadRelationTuplesRequest_Query) GetUserSet() *RelationUserSet { + if x, ok := x.GetUser().(*ReadRelationTuplesRequest_Query_UserSet); ok { + return x.UserSet + } + return nil +} + +type isReadRelationTuplesRequest_Query_User interface { + isReadRelationTuplesRequest_Query_User() +} + +type ReadRelationTuplesRequest_Query_UserId struct { + UserId string `protobuf:"bytes,3,opt,name=user_id,json=userId,proto3,oneof"` +} + +type ReadRelationTuplesRequest_Query_UserSet struct { + UserSet *RelationUserSet `protobuf:"bytes,4,opt,name=user_set,json=userSet,proto3,oneof"` +} + +func (*ReadRelationTuplesRequest_Query_UserId) isReadRelationTuplesRequest_Query_User() {} + +func (*ReadRelationTuplesRequest_Query_UserSet) isReadRelationTuplesRequest_Query_User() {} + 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, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 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, 0x32, 0x5f, 0x0a, 0x12, 0x47, 0x52, 0x50, - 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72, 0x12, - 0x49, 0x0a, 0x0d, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x14, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, - 0x47, 0x52, 0x50, 0x43, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x57, 0x72, 0x69, - 0x74, 0x65, 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, + 0xc0, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, + 0x09, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 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, 0x09, 0x74, 0x75, 0x70, 0x6c, 0x65, + 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x72, 0x5f, + 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x65, 0x72, 0x50, + 0x61, 0x67, 0x65, 0x1a, 0xac, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, + 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, + 0x00, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, + 0x48, 0x0a, 0x19, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb4, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x07, 0x75, + 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x5d, + 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, + 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4b, 0x0a, + 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 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, 0x1b, 0x0a, + 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x32, 0xd0, 0x01, 0x0a, 0x14, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x5b, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x75, 0x70, 0x6c, 0x65, 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 ( @@ -295,26 +629,35 @@ func file_models_relation_proto_rawDescGZIP() []byte { return file_models_relation_proto_rawDescData } -var file_models_relation_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_models_relation_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_models_relation_proto_goTypes = []interface{}{ - (*GRPCRelationsReadRequest)(nil), // 0: models.GRPCRelationsReadRequest - (*GRPCRelation)(nil), // 1: models.GRPCRelation - (*GRPCRelationsReadResponse)(nil), // 2: models.GRPCRelationsReadResponse - (*GRPCRelationsWriteResponse)(nil), // 3: models.GRPCRelationsWriteResponse + (*ReadRelationTuplesRequest)(nil), // 0: models.ReadRelationTuplesRequest + (*ReadRelationTuplesResponse)(nil), // 1: models.ReadRelationTuplesResponse + (*WriteRelationTupleRequest)(nil), // 2: models.WriteRelationTupleRequest + (*WriteRelationTupleResponse)(nil), // 3: models.WriteRelationTupleResponse + (*RelationTuple)(nil), // 4: models.RelationTuple + (*RelationUserSet)(nil), // 5: models.RelationUserSet + (*RelationObject)(nil), // 6: models.RelationObject + (*ReadRelationTuplesRequest_Query)(nil), // 7: models.ReadRelationTuplesRequest.Query } 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 - 1, // 3: models.GRPCRelationWriter.WriteRelation:input_type -> models.GRPCRelation - 2, // 4: models.GRPCRelationReader.RelationsByUser:output_type -> models.GRPCRelationsReadResponse - 2, // 5: models.GRPCRelationReader.RelationsByObject:output_type -> models.GRPCRelationsReadResponse - 3, // 6: models.GRPCRelationWriter.WriteRelation:output_type -> models.GRPCRelationsWriteResponse - 4, // [4:7] is the sub-list for method output_type - 1, // [1:4] 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 + 7, // 0: models.ReadRelationTuplesRequest.tuplesets:type_name -> models.ReadRelationTuplesRequest.Query + 4, // 1: models.ReadRelationTuplesResponse.tuples:type_name -> models.RelationTuple + 4, // 2: models.WriteRelationTupleRequest.tuple:type_name -> models.RelationTuple + 6, // 3: models.RelationTuple.object:type_name -> models.RelationObject + 5, // 4: models.RelationTuple.user_set:type_name -> models.RelationUserSet + 6, // 5: models.RelationUserSet.object:type_name -> models.RelationObject + 6, // 6: models.ReadRelationTuplesRequest.Query.object:type_name -> models.RelationObject + 5, // 7: models.ReadRelationTuplesRequest.Query.user_set:type_name -> models.RelationUserSet + 0, // 8: models.RelationTupleService.ReadRelationTuples:input_type -> models.ReadRelationTuplesRequest + 2, // 9: models.RelationTupleService.WriteRelationTuple:input_type -> models.WriteRelationTupleRequest + 1, // 10: models.RelationTupleService.ReadRelationTuples:output_type -> models.ReadRelationTuplesResponse + 3, // 11: models.RelationTupleService.WriteRelationTuple:output_type -> models.WriteRelationTupleResponse + 10, // [10:12] is the sub-list for method output_type + 8, // [8:10] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_models_relation_proto_init() } @@ -324,7 +667,7 @@ func file_models_relation_proto_init() { } if !protoimpl.UnsafeEnabled { file_models_relation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRelationsReadRequest); i { + switch v := v.(*ReadRelationTuplesRequest); i { case 0: return &v.state case 1: @@ -336,7 +679,7 @@ func file_models_relation_proto_init() { } } file_models_relation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRelation); i { + switch v := v.(*ReadRelationTuplesResponse); i { case 0: return &v.state case 1: @@ -348,7 +691,7 @@ func file_models_relation_proto_init() { } } file_models_relation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRelationsReadResponse); i { + switch v := v.(*WriteRelationTupleRequest); i { case 0: return &v.state case 1: @@ -360,7 +703,43 @@ func file_models_relation_proto_init() { } } file_models_relation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRelationsWriteResponse); i { + switch v := v.(*WriteRelationTupleResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_models_relation_proto_msgTypes[4].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_models_relation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationUserSet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_models_relation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationObject); i { case 0: return &v.state case 1: @@ -371,6 +750,26 @@ func file_models_relation_proto_init() { return nil } } + file_models_relation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReadRelationTuplesRequest_Query); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_models_relation_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*RelationTuple_UserId)(nil), + (*RelationTuple_UserSet)(nil), + } + file_models_relation_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*ReadRelationTuplesRequest_Query_UserId)(nil), + (*ReadRelationTuplesRequest_Query_UserSet)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -378,9 +777,9 @@ func file_models_relation_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_models_relation_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 8, NumExtensions: 0, - NumServices: 2, + NumServices: 1, }, GoTypes: file_models_relation_proto_goTypes, DependencyIndexes: file_models_relation_proto_depIdxs, diff --git a/models/relation.proto b/models/relation.proto index 11c26767b..e91bb36c4 100644 --- a/models/relation.proto +++ b/models/relation.proto @@ -4,29 +4,66 @@ option go_package = "github.com/ory/keto/models"; package models; -service GRPCRelationReader { - rpc RelationsByUser(GRPCRelationsReadRequest) returns (GRPCRelationsReadResponse); - rpc RelationsByObject(GRPCRelationsReadRequest) returns (GRPCRelationsReadResponse); +service RelationTupleService { + rpc ReadRelationTuples(ReadRelationTuplesRequest) returns (ReadRelationTuplesResponse); + rpc WriteRelationTuple(WriteRelationTupleRequest) returns (WriteRelationTupleResponse); } -service GRPCRelationWriter { - rpc WriteRelation(GRPCRelation) returns (GRPCRelationsWriteResponse); -} +// Query by partial keys of tuples // TODO even wanted? +message ReadRelationTuplesRequest { + message Query { + // Optional + RelationObject object = 1; + // Optional + string relation = 2; + // Optional + oneof user { + string user_id = 3; + RelationUserSet user_set = 4; + } + } -message GRPCRelationsReadRequest { - string id = 1; + // All conditions are concatenated with + // an OR operator. If any query matches + // the relation will be in the response + repeated Query tuplesets = 1; int32 page = 2; - int32 perPage = 3; + int32 per_page = 3; +} + +message ReadRelationTuplesResponse { + repeated RelationTuple tuples = 1; } -message GRPCRelation { - string userID = 1; - string name = 2; - string objectID = 3; +message WriteRelationTupleRequest { + RelationTuple tuple = 1; } -message GRPCRelationsReadResponse { - repeated GRPCRelation relations = 1; +message WriteRelationTupleResponse {} + +// Represents a relation between +// an object and an user. +message RelationTuple { + RelationObject object = 1; + // Specifies the relation between an `object` and an `user` + string relation = 2; + // The user of the tuple can either be + // a single user or a userset + oneof user { + string user_id = 3; + RelationUserSet user_set = 4; + } } -message GRPCRelationsWriteResponse {} +// Refers to all users which have +// a `relation` with an `object` +message RelationUserSet { + RelationObject object = 1; + string relation = 2; +} + +// Represents a "resource" +message RelationObject { + string namespace = 1; + string object_id = 2; +} diff --git a/models/relation_grpc.pb.go b/models/relation_grpc.pb.go index ac667e80a..06f490371 100644 --- a/models/relation_grpc.pb.go +++ b/models/relation_grpc.pb.go @@ -14,202 +14,119 @@ import ( // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion7 -// GRPCRelationReaderClient is the client API for GRPCRelationReader service. +// RelationTupleServiceClient is the client API for RelationTupleService 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 RelationTupleServiceClient interface { + ReadRelationTuples(ctx context.Context, in *ReadRelationTuplesRequest, opts ...grpc.CallOption) (*ReadRelationTuplesResponse, error) + WriteRelationTuple(ctx context.Context, in *WriteRelationTupleRequest, opts ...grpc.CallOption) (*WriteRelationTupleResponse, error) } -type gRPCRelationReaderClient struct { +type relationTupleServiceClient struct { cc grpc.ClientConnInterface } -func NewGRPCRelationReaderClient(cc grpc.ClientConnInterface) GRPCRelationReaderClient { - return &gRPCRelationReaderClient{cc} +func NewRelationTupleServiceClient(cc grpc.ClientConnInterface) RelationTupleServiceClient { + return &relationTupleServiceClient{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...) +func (c *relationTupleServiceClient) ReadRelationTuples(ctx context.Context, in *ReadRelationTuplesRequest, opts ...grpc.CallOption) (*ReadRelationTuplesResponse, error) { + out := new(ReadRelationTuplesResponse) + err := c.cc.Invoke(ctx, "/models.RelationTupleService/ReadRelationTuples", 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...) +func (c *relationTupleServiceClient) WriteRelationTuple(ctx context.Context, in *WriteRelationTupleRequest, opts ...grpc.CallOption) (*WriteRelationTupleResponse, error) { + out := new(WriteRelationTupleResponse) + err := c.cc.Invoke(ctx, "/models.RelationTupleService/WriteRelationTuple", 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 +// RelationTupleServiceServer is the server API for RelationTupleService service. +// All implementations must embed UnimplementedRelationTupleServiceServer // for forward compatibility -type GRPCRelationReaderServer interface { - RelationsByUser(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) - RelationsByObject(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) - mustEmbedUnimplementedGRPCRelationReaderServer() +type RelationTupleServiceServer interface { + ReadRelationTuples(context.Context, *ReadRelationTuplesRequest) (*ReadRelationTuplesResponse, error) + WriteRelationTuple(context.Context, *WriteRelationTupleRequest) (*WriteRelationTupleResponse, error) + mustEmbedUnimplementedRelationTupleServiceServer() } -// UnimplementedGRPCRelationReaderServer must be embedded to have forward compatible implementations. -type UnimplementedGRPCRelationReaderServer struct { +// UnimplementedRelationTupleServiceServer must be embedded to have forward compatible implementations. +type UnimplementedRelationTupleServiceServer struct { } -func (UnimplementedGRPCRelationReaderServer) RelationsByUser(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RelationsByUser not implemented") +func (UnimplementedRelationTupleServiceServer) ReadRelationTuples(context.Context, *ReadRelationTuplesRequest) (*ReadRelationTuplesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ReadRelationTuples not implemented") } -func (UnimplementedGRPCRelationReaderServer) RelationsByObject(context.Context, *GRPCRelationsReadRequest) (*GRPCRelationsReadResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RelationsByObject not implemented") +func (UnimplementedRelationTupleServiceServer) WriteRelationTuple(context.Context, *WriteRelationTupleRequest) (*WriteRelationTupleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WriteRelationTuple not implemented") } -func (UnimplementedGRPCRelationReaderServer) mustEmbedUnimplementedGRPCRelationReaderServer() {} +func (UnimplementedRelationTupleServiceServer) mustEmbedUnimplementedRelationTupleServiceServer() {} -// 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 +// UnsafeRelationTupleServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RelationTupleServiceServer will // result in compilation errors. -type UnsafeGRPCRelationReaderServer interface { - mustEmbedUnimplementedGRPCRelationReaderServer() +type UnsafeRelationTupleServiceServer interface { + mustEmbedUnimplementedRelationTupleServiceServer() } -func RegisterGRPCRelationReaderServer(s *grpc.Server, srv GRPCRelationReaderServer) { - s.RegisterService(&_GRPCRelationReader_serviceDesc, srv) +func RegisterRelationTupleServiceServer(s *grpc.Server, srv RelationTupleServiceServer) { + s.RegisterService(&_RelationTupleService_serviceDesc, srv) } -func _GRPCRelationReader_RelationsByUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GRPCRelationsReadRequest) +func _RelationTupleService_ReadRelationTuples_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReadRelationTuplesRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(GRPCRelationReaderServer).RelationsByUser(ctx, in) + return srv.(RelationTupleServiceServer).ReadRelationTuples(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/models.GRPCRelationReader/RelationsByUser", + FullMethod: "/models.RelationTupleService/ReadRelationTuples", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(GRPCRelationReaderServer).RelationsByUser(ctx, req.(*GRPCRelationsReadRequest)) + return srv.(RelationTupleServiceServer).ReadRelationTuples(ctx, req.(*ReadRelationTuplesRequest)) } 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) +func _RelationTupleService_WriteRelationTuple_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(WriteRelationTupleRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(GRPCRelationReaderServer).RelationsByObject(ctx, in) + return srv.(RelationTupleServiceServer).WriteRelationTuple(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/models.GRPCRelationReader/RelationsByObject", + FullMethod: "/models.RelationTupleService/WriteRelationTuple", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(GRPCRelationReaderServer).RelationsByObject(ctx, req.(*GRPCRelationsReadRequest)) + return srv.(RelationTupleServiceServer).WriteRelationTuple(ctx, req.(*WriteRelationTupleRequest)) } return interceptor(ctx, in, info, handler) } -var _GRPCRelationReader_serviceDesc = grpc.ServiceDesc{ - ServiceName: "models.GRPCRelationReader", - HandlerType: (*GRPCRelationReaderServer)(nil), +var _RelationTupleService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "models.RelationTupleService", + HandlerType: (*RelationTupleServiceServer)(nil), Methods: []grpc.MethodDesc{ { - MethodName: "RelationsByUser", - Handler: _GRPCRelationReader_RelationsByUser_Handler, + MethodName: "ReadRelationTuples", + Handler: _RelationTupleService_ReadRelationTuples_Handler, }, { - MethodName: "RelationsByObject", - Handler: _GRPCRelationReader_RelationsByObject_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "models/relation.proto", -} - -// GRPCRelationWriterClient is the client API for GRPCRelationWriter 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 GRPCRelationWriterClient interface { - WriteRelation(ctx context.Context, in *GRPCRelation, opts ...grpc.CallOption) (*GRPCRelationsWriteResponse, error) -} - -type gRPCRelationWriterClient struct { - cc grpc.ClientConnInterface -} - -func NewGRPCRelationWriterClient(cc grpc.ClientConnInterface) GRPCRelationWriterClient { - return &gRPCRelationWriterClient{cc} -} - -func (c *gRPCRelationWriterClient) WriteRelation(ctx context.Context, in *GRPCRelation, opts ...grpc.CallOption) (*GRPCRelationsWriteResponse, error) { - out := new(GRPCRelationsWriteResponse) - err := c.cc.Invoke(ctx, "/models.GRPCRelationWriter/WriteRelation", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// GRPCRelationWriterServer is the server API for GRPCRelationWriter service. -// All implementations must embed UnimplementedGRPCRelationWriterServer -// for forward compatibility -type GRPCRelationWriterServer interface { - WriteRelation(context.Context, *GRPCRelation) (*GRPCRelationsWriteResponse, error) - mustEmbedUnimplementedGRPCRelationWriterServer() -} - -// UnimplementedGRPCRelationWriterServer must be embedded to have forward compatible implementations. -type UnimplementedGRPCRelationWriterServer struct { -} - -func (UnimplementedGRPCRelationWriterServer) WriteRelation(context.Context, *GRPCRelation) (*GRPCRelationsWriteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method WriteRelation not implemented") -} -func (UnimplementedGRPCRelationWriterServer) mustEmbedUnimplementedGRPCRelationWriterServer() {} - -// UnsafeGRPCRelationWriterServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to GRPCRelationWriterServer will -// result in compilation errors. -type UnsafeGRPCRelationWriterServer interface { - mustEmbedUnimplementedGRPCRelationWriterServer() -} - -func RegisterGRPCRelationWriterServer(s *grpc.Server, srv GRPCRelationWriterServer) { - s.RegisterService(&_GRPCRelationWriter_serviceDesc, srv) -} - -func _GRPCRelationWriter_WriteRelation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GRPCRelation) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(GRPCRelationWriterServer).WriteRelation(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/models.GRPCRelationWriter/WriteRelation", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(GRPCRelationWriterServer).WriteRelation(ctx, req.(*GRPCRelation)) - } - return interceptor(ctx, in, info, handler) -} - -var _GRPCRelationWriter_serviceDesc = grpc.ServiceDesc{ - ServiceName: "models.GRPCRelationWriter", - HandlerType: (*GRPCRelationWriterServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "WriteRelation", - Handler: _GRPCRelationWriter_WriteRelation_Handler, + MethodName: "WriteRelationTuple", + Handler: _RelationTupleService_WriteRelationTuple_Handler, }, }, Streams: []grpc.StreamDesc{}, diff --git a/persistence/memory/definitions.go b/persistence/memory/definitions.go index 92fc816bd..2aa1267f9 100644 --- a/persistence/memory/definitions.go +++ b/persistence/memory/definitions.go @@ -14,12 +14,6 @@ type Persister struct { func NewPersister() *Persister { return &Persister{ - relations: []*models.Relation{ - { - UserID: "1", - Name: "testRelation", - ObjectID: "2", - }, - }, + relations: []*models.Relation{}, // TODO fill with something? } } diff --git a/persistence/memory/relations.go b/persistence/memory/relations.go index e8656c5e5..48240c1c8 100644 --- a/persistence/memory/relations.go +++ b/persistence/memory/relations.go @@ -23,28 +23,67 @@ func (p *Persister) paginateRelations(rels []*models.Relation, page, perPage int 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) +func BuildRelationQueryFilter(query *models.RelationQuery) func(r *models.Relation) bool { + var filters []func(r *models.Relation) bool + if query.Object.ID != "" && query.Object.Namespace != "" { + filters = append(filters, func(r *models.Relation) bool { + return r.Object.ID == query.Object.ID && + r.Object.Namespace == query.Object.Namespace + }) + } + if query.Relation != "" { + filters = append(filters, func(r *models.Relation) bool { + return r.Relation == query.Relation + }) + } + if query.User != nil { + switch query.User.(type) { + case models.UserID: + filters = append(filters, func(r *models.Relation) bool { + rUserId := r.User.(models.UserID) + relationUserId := query.User.(models.UserID) + return r.User != nil && rUserId.ID == relationUserId.ID + }) + case models.UserSet: + filters = append(filters, func(r *models.Relation) bool { + rUserSet := r.User.(models.UserSet) + relationUserSet := query.User.(models.UserSet) + return rUserSet.Object.ID == relationUserSet.Object.ID && + rUserSet.Object.Namespace == relationUserSet.Object.Namespace && + rUserSet.Relation == relationUserSet.Relation + }) } } - return p.paginateRelations(res, page, perPage), nil + // Create composite filter + return func(r *models.Relation) bool { + for _, filter := range filters { + if !filter(r) { + return false + } + } + return true + } } -func (p *Persister) GetRelationsByObject(_ context.Context, objectID string, page, perPage int32) ([]*models.Relation, error) { +func (p *Persister) GetRelations(_ context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.Relation, error) { p.RLock() defer p.RUnlock() + var filters []func(r *models.Relation) bool + for _, q := range queries { + filters = append(filters, BuildRelationQueryFilter(q)) + } + var res []*models.Relation for _, r := range p.relations { - if r.ObjectID == objectID { - res = append(res, r) + for _, filter := range filters { + if filter(r) { + // If one filter matches add relation to response and break inner loop + // to check next relation + res = append(res, r) + break + } } } diff --git a/relation/definitions.go b/relation/definitions.go index 5fb0857ee..c0669bf4c 100644 --- a/relation/definitions.go +++ b/relation/definitions.go @@ -11,8 +11,7 @@ type ( 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) + GetRelations(ctx context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.Relation, error) WriteRelation(ctx context.Context, r *models.Relation) error } ) diff --git a/relation/grpc_server.go b/relation/grpc_server.go index e8e82659f..db875b2e7 100644 --- a/relation/grpc_server.go +++ b/relation/grpc_server.go @@ -6,23 +6,21 @@ import ( "github.com/ory/keto/models" ) -var _ models.GRPCRelationReaderServer = &Server{} -var _ models.GRPCRelationWriterServer = &Server{} +var _ models.RelationTupleServiceServer = &Server{} type ( serverDependencies interface { ManagerProvider } Server struct { - models.UnimplementedGRPCRelationReaderServer - models.UnimplementedGRPCRelationWriterServer + models.UnimplementedRelationTupleServiceServer d serverDependencies } ) -func (s *Server) WriteRelation(ctx context.Context, r *models.GRPCRelation) (*models.GRPCRelationsWriteResponse, error) { - return &models.GRPCRelationsWriteResponse{}, s.d.RelationManager().WriteRelation(ctx, (*models.Relation)(r)) +func (s *Server) WriteRelation(ctx context.Context, r *models.RelationTuple) (*models.WriteRelationTupleResponse, error) { + return &models.WriteRelationTupleResponse{}, s.d.RelationManager().WriteRelation(ctx, (&models.Relation{}).ImportFromGRPC(r)) } func NewServer(d serverDependencies) *Server { @@ -31,25 +29,18 @@ func NewServer(d serverDependencies) *Server { } } -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 +func (s *Server) ReadTuples(ctx context.Context, req *models.ReadRelationTuplesRequest) (*models.ReadRelationTuplesResponse, error) { + queries := make([]*models.RelationQuery, len(req.Tuplesets)) + for i, tupleset := range req.Tuplesets { + queries[i] = (&models.RelationQuery{}).ImportFromGRPC(tupleset) } - rpcRels := make([]*models.GRPCRelation, len(rels)) - for i := range rels { - rpcRels[i] = (&models.GRPCRelation{}).ImportFromNormal(rels[i]) - } - return &models.GRPCRelationsReadResponse{ - Relations: rpcRels, - }, nil -} + normalRels, _ := s.d.RelationManager().GetRelations(ctx, queries, req.Page, req.PerPage) -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) -} + rpcRels := make([]*models.RelationTuple, len(req.Tuplesets)) + for i, tupleset := range normalRels { + rpcRels[i] = (&models.RelationTuple{}).ImportFromNormal(tupleset) + } -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) + return &models.ReadRelationTuplesResponse{Tuples: rpcRels}, nil } diff --git a/relation/handler.go b/relation/handler.go index 3d4566999..8df70c714 100644 --- a/relation/handler.go +++ b/relation/handler.go @@ -40,26 +40,7 @@ func (h *handler) RegisterPublicRoutes(router *httprouter.Router) { } 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) + // TODO reimplement } func (h *handler) createRelation(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { From cde5acfbc104f3238a0e8e6ee112bea89d222984 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Tue, 27 Oct 2020 13:51:35 +0100 Subject: [PATCH 2/6] refactor: rename user to subject --- models/relation.pb.go | 153 ++++++++++++++++++------------------- models/relation.proto | 6 +- models/relation_grpc.pb.go | 1 - 3 files changed, 79 insertions(+), 81 deletions(-) diff --git a/models/relation.pb.go b/models/relation.pb.go index df8911cb5..cdafd0798 100644 --- a/models/relation.pb.go +++ b/models/relation.pb.go @@ -1,18 +1,17 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.7.1 +// protoc v3.12.4 // source: models/relation.proto package models import ( - reflect "reflect" - sync "sync" - 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 ( @@ -26,7 +25,7 @@ const ( // of the legacy proto package is being used. const _ = proto.ProtoPackageIsVersion4 -// Query by partial keys of tuples // TODO even wanted? +// Query by partial keys of tuples type ReadRelationTuplesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -238,10 +237,10 @@ type RelationTuple struct { // The user of the tuple can either be // a single user or a userset // - // Types that are assignable to User: + // Types that are assignable to Subject: // *RelationTuple_UserId // *RelationTuple_UserSet - User isRelationTuple_User `protobuf_oneof:"user"` + Subject isRelationTuple_Subject `protobuf_oneof:"subject"` } func (x *RelationTuple) Reset() { @@ -290,29 +289,29 @@ func (x *RelationTuple) GetRelation() string { return "" } -func (m *RelationTuple) GetUser() isRelationTuple_User { +func (m *RelationTuple) GetSubject() isRelationTuple_Subject { if m != nil { - return m.User + return m.Subject } return nil } func (x *RelationTuple) GetUserId() string { - if x, ok := x.GetUser().(*RelationTuple_UserId); ok { + if x, ok := x.GetSubject().(*RelationTuple_UserId); ok { return x.UserId } return "" } func (x *RelationTuple) GetUserSet() *RelationUserSet { - if x, ok := x.GetUser().(*RelationTuple_UserSet); ok { + if x, ok := x.GetSubject().(*RelationTuple_UserSet); ok { return x.UserSet } return nil } -type isRelationTuple_User interface { - isRelationTuple_User() +type isRelationTuple_Subject interface { + isRelationTuple_Subject() } type RelationTuple_UserId struct { @@ -323,9 +322,9 @@ type RelationTuple_UserSet struct { UserSet *RelationUserSet `protobuf:"bytes,4,opt,name=user_set,json=userSet,proto3,oneof"` } -func (*RelationTuple_UserId) isRelationTuple_User() {} +func (*RelationTuple_UserId) isRelationTuple_Subject() {} -func (*RelationTuple_UserSet) isRelationTuple_User() {} +func (*RelationTuple_UserSet) isRelationTuple_Subject() {} // Refers to all users which have // a `relation` with an `object` @@ -451,10 +450,10 @@ type ReadRelationTuplesRequest_Query struct { Relation string `protobuf:"bytes,2,opt,name=relation,proto3" json:"relation,omitempty"` // Optional // - // Types that are assignable to User: + // Types that are assignable to Subject: // *ReadRelationTuplesRequest_Query_UserId // *ReadRelationTuplesRequest_Query_UserSet - User isReadRelationTuplesRequest_Query_User `protobuf_oneof:"user"` + Subject isReadRelationTuplesRequest_Query_Subject `protobuf_oneof:"subject"` } func (x *ReadRelationTuplesRequest_Query) Reset() { @@ -503,29 +502,29 @@ func (x *ReadRelationTuplesRequest_Query) GetRelation() string { return "" } -func (m *ReadRelationTuplesRequest_Query) GetUser() isReadRelationTuplesRequest_Query_User { +func (m *ReadRelationTuplesRequest_Query) GetSubject() isReadRelationTuplesRequest_Query_Subject { if m != nil { - return m.User + return m.Subject } return nil } func (x *ReadRelationTuplesRequest_Query) GetUserId() string { - if x, ok := x.GetUser().(*ReadRelationTuplesRequest_Query_UserId); ok { + if x, ok := x.GetSubject().(*ReadRelationTuplesRequest_Query_UserId); ok { return x.UserId } return "" } func (x *ReadRelationTuplesRequest_Query) GetUserSet() *RelationUserSet { - if x, ok := x.GetUser().(*ReadRelationTuplesRequest_Query_UserSet); ok { + if x, ok := x.GetSubject().(*ReadRelationTuplesRequest_Query_UserSet); ok { return x.UserSet } return nil } -type isReadRelationTuplesRequest_Query_User interface { - isReadRelationTuplesRequest_Query_User() +type isReadRelationTuplesRequest_Query_Subject interface { + isReadRelationTuplesRequest_Query_Subject() } type ReadRelationTuplesRequest_Query_UserId struct { @@ -536,16 +535,16 @@ type ReadRelationTuplesRequest_Query_UserSet struct { UserSet *RelationUserSet `protobuf:"bytes,4,opt,name=user_set,json=userSet,proto3,oneof"` } -func (*ReadRelationTuplesRequest_Query_UserId) isReadRelationTuplesRequest_Query_User() {} +func (*ReadRelationTuplesRequest_Query_UserId) isReadRelationTuplesRequest_Query_Subject() {} -func (*ReadRelationTuplesRequest_Query_UserSet) isReadRelationTuplesRequest_Query_User() {} +func (*ReadRelationTuplesRequest_Query_UserSet) isReadRelationTuplesRequest_Query_Subject() {} 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, - 0xc0, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0xc3, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x09, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, @@ -554,7 +553,7 @@ var file_models_relation_proto_rawDesc = []byte{ 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x65, 0x72, 0x50, - 0x61, 0x67, 0x65, 0x1a, 0xac, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, + 0x61, 0x67, 0x65, 0x1a, 0xaf, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, @@ -564,57 +563,57 @@ var file_models_relation_proto_rawDesc = []byte{ 0x65, 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, - 0x00, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, - 0x48, 0x0a, 0x19, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, - 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb4, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, - 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x07, 0x75, - 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x5d, - 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, - 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4b, 0x0a, - 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 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, 0x1b, 0x0a, - 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x32, 0xd0, 0x01, 0x0a, 0x14, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, - 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5b, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, + 0x00, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, + 0x65, 0x73, 0x22, 0x48, 0x0a, 0x19, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2b, 0x0a, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, - 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 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, + 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x0d, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x06, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, 0x00, + 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x22, 0x5d, 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, + 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, + 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x4b, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 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, 0x1b, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, + 0x32, 0xd0, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x61, + 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, + 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 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 ( diff --git a/models/relation.proto b/models/relation.proto index e91bb36c4..6a136a0ac 100644 --- a/models/relation.proto +++ b/models/relation.proto @@ -9,7 +9,7 @@ service RelationTupleService { rpc WriteRelationTuple(WriteRelationTupleRequest) returns (WriteRelationTupleResponse); } -// Query by partial keys of tuples // TODO even wanted? +// Query by partial keys of tuples message ReadRelationTuplesRequest { message Query { // Optional @@ -17,7 +17,7 @@ message ReadRelationTuplesRequest { // Optional string relation = 2; // Optional - oneof user { + oneof subject { string user_id = 3; RelationUserSet user_set = 4; } @@ -49,7 +49,7 @@ message RelationTuple { string relation = 2; // The user of the tuple can either be // a single user or a userset - oneof user { + oneof subject { string user_id = 3; RelationUserSet user_set = 4; } diff --git a/models/relation_grpc.pb.go b/models/relation_grpc.pb.go index 06f490371..7b5d06206 100644 --- a/models/relation_grpc.pb.go +++ b/models/relation_grpc.pb.go @@ -4,7 +4,6 @@ package models import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" From a3a4d11398de14388d707be797204a209219b161 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Tue, 27 Oct 2020 16:51:43 +0100 Subject: [PATCH 3/6] refactor: get new data structures working --- cmd/relation/create.go | 4 +- cmd/relation/get.go | 72 +++++++-- cmd/serve.go | 6 +- driver/registry_default.go | 6 +- go.mod | 1 + models/relation.go | 193 ++++++++++++++++--------- models/relation.pb.go | 133 ++++++++--------- models/relation.proto | 2 +- models/relation_grpc.pb.go | 1 + persistence/memory/definitions.go | 4 +- persistence/memory/relations.go | 69 +++++---- relation/definitions.go | 17 --- relation/grpc_server.go | 46 ------ relationtuple/definitions.go | 17 +++ relationtuple/grpc_server.go | 50 +++++++ {relation => relationtuple}/handler.go | 22 ++- 16 files changed, 392 insertions(+), 251 deletions(-) delete mode 100644 relation/definitions.go delete mode 100644 relation/grpc_server.go create mode 100644 relationtuple/definitions.go create mode 100644 relationtuple/grpc_server.go rename {relation => relationtuple}/handler.go (66%) diff --git a/cmd/relation/create.go b/cmd/relation/create.go index 2d9decbd2..b7a84485f 100644 --- a/cmd/relation/create.go +++ b/cmd/relation/create.go @@ -36,7 +36,7 @@ func newCreateCmd() *cobra.Command { } } - var r models.Relation + var r models.InternalRelationTuple err = json.NewDecoder(f).Decode(&r) if err != nil { _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Could not decode: %s\n", err) @@ -45,7 +45,7 @@ func newCreateCmd() *cobra.Command { cl := models.NewRelationTupleServiceClient(conn) - _, err = cl.WriteRelationTuple(context.Background(), &models.WriteRelationTupleRequest{Tuple: (&models.RelationTuple{}).ImportFromNormal(&r)}) + _, err = cl.WriteRelationTuple(context.Background(), &models.WriteRelationTupleRequest{Tuple: (&models.RelationTuple{}).FromInternal(&r)}) if err != nil { _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Error doing the request: %s\n", err) return cmdx.FailSilently(cmd) diff --git a/cmd/relation/get.go b/cmd/relation/get.go index da93486b9..e1a06e59a 100644 --- a/cmd/relation/get.go +++ b/cmd/relation/get.go @@ -3,6 +3,9 @@ package relation import ( "context" "fmt" + "strings" + + "github.com/spf13/pflag" "github.com/ory/x/cmdx" @@ -12,10 +15,58 @@ import ( "github.com/ory/keto/models" ) +const ( + FlagSubject = "subject" + FlagRelation = "relation" + FlagObject = "object" +) + +func registerRelationTupleFlags(flags *pflag.FlagSet) { + flags.String(FlagSubject, "", "Set the requested subject") + flags.String(FlagRelation, "", "Set the requested relation") + flags.String(FlagObject, "", "Set the requested object") +} + +func readQueryFromFlags(cmd *cobra.Command) (*models.ReadRelationTuplesRequest_Query, error) { + subject, err := cmd.Flags().GetString(FlagSubject) + if err != nil { + return nil, err + } + relation, err := cmd.Flags().GetString(FlagRelation) + if err != nil { + return nil, err + } + object, err := cmd.Flags().GetString(FlagObject) + if err != nil { + return nil, err + } + + query := &models.ReadRelationTuplesRequest_Query{ + Relation: relation, + Object: (&models.RelationObject{}).FromString(object), + } + + subjectParts := strings.Split(subject, "#") + if len(subjectParts) == 2 { + query.Subject = &models.ReadRelationTuplesRequest_Query_UserSet{ + UserSet: &models.RelationUserSet{ + Object: (&models.RelationObject{}).FromString(subjectParts[0]), + Relation: subjectParts[1], + }, + } + } else { + query.Subject = &models.ReadRelationTuplesRequest_Query_UserId{ + UserId: subject, + } + } + + return query, nil +} + func newGetCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "get-by-user ", - Args: cobra.ExactArgs(1), + Use: "get", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { conn, err := client.GetGRPCConn(cmd) if err != nil { @@ -24,16 +75,14 @@ func newGetCmd() *cobra.Command { defer conn.Close() cl := models.NewRelationTupleServiceClient(conn) + query, err := readQueryFromFlags(cmd) + if err != nil { + return err + } resp, err := cl.ReadRelationTuples(context.Background(), &models.ReadRelationTuplesRequest{ - Tuplesets: []*models.ReadRelationTuplesRequest_Query{ - { - User: &models.ReadRelationTuplesRequest_Query_UserId{ - UserId: args[0], - }, - }, - }, - Page: 0, - PerPage: 100, + TupleSets: []*models.ReadRelationTuplesRequest_Query{query}, + Page: 0, + PerPage: 100, }) if err != nil { _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Could not make request: %s\n", err) @@ -46,6 +95,7 @@ func newGetCmd() *cobra.Command { } cmd.Flags().AddFlagSet(packageFlags) + registerRelationTupleFlags(cmd.Flags()) return cmd } diff --git a/cmd/serve.go b/cmd/serve.go index c1f80473d..d354ff8f9 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -29,7 +29,7 @@ import ( "github.com/ory/keto/driver" "github.com/ory/keto/models" - "github.com/ory/keto/relation" + "github.com/ory/keto/relationtuple" "github.com/ory/x/viperx" @@ -65,7 +65,7 @@ on configuration options, open the configuration documentation: defer wg.Done() s := grpc.NewServer() - relS := relation.NewServer(reg) + relS := relationtuple.NewServer(reg) models.RegisterRelationTupleServiceServer(s, relS) fmt.Println("going to serve GRPC on", lis.Addr().String()) if err := s.Serve(lis); err != nil { @@ -77,7 +77,7 @@ on configuration options, open the configuration documentation: defer wg.Done() router := httprouter.New() - h := relation.NewHandler(reg) + h := relationtuple.NewHandler(reg) h.RegisterPublicRoutes(router) server := graceful.WithDefaults(&http.Server{ diff --git a/driver/registry_default.go b/driver/registry_default.go index 474fb26c4..167241f31 100644 --- a/driver/registry_default.go +++ b/driver/registry_default.go @@ -5,11 +5,11 @@ import ( "github.com/ory/x/logrusx" "github.com/ory/keto/persistence/memory" - "github.com/ory/keto/relation" + "github.com/ory/keto/relationtuple" "github.com/ory/keto/x" ) -var _ relation.ManagerProvider = &RegistryDefault{} +var _ relationtuple.ManagerProvider = &RegistryDefault{} var _ x.WriterProvider = &RegistryDefault{} var _ x.LoggerProvider = &RegistryDefault{} @@ -33,7 +33,7 @@ func (r *RegistryDefault) Writer() herodot.Writer { return r.w } -func (r *RegistryDefault) RelationManager() relation.Manager { +func (r *RegistryDefault) RelationTupleManager() relationtuple.Manager { if r.p == nil { r.p = memory.NewPersister() } diff --git a/go.mod b/go.mod index 8ae9c9e0f..62eb64b71 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( 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/tidwall/gjson v1.6.0 github.com/tidwall/sjson v1.1.1 // indirect github.com/urfave/negroni v1.0.0 go.mongodb.org/mongo-driver v1.3.4 // indirect diff --git a/models/relation.go b/models/relation.go index 568670afb..c762d0ced 100644 --- a/models/relation.go +++ b/models/relation.go @@ -2,6 +2,9 @@ package models import ( "fmt" + "strings" + + "github.com/tidwall/gjson" "github.com/ory/x/cmdx" ) @@ -9,62 +12,113 @@ import ( type ( relationCollection struct { grpcRelations []*RelationTuple - internalRelations []*Relation + internalRelations []*InternalRelationTuple } Object struct { ID string Namespace string } - User interface { + Subject interface { String() string + FromString(string) Subject } UserID struct { - User ID string } UserSet struct { - User - Object Object + Object *Object Relation string } - Relation struct { - Object Object - Relation string - User User + InternalRelationTuple struct { + Object *Object `json:"object"` + Relation string `json:"relation"` + Subject Subject `json:"subject"` } RelationQuery struct { - Object Object + Object *Object Relation string - User User + Subject Subject } ) -func (o Object) String() string { +var _, _ Subject = &UserID{}, &UserSet{} + +func SubjectFromString(s string) Subject { + if strings.Contains(s, "#") { + return (&UserSet{}).FromString(s) + } + return (&UserID{}).FromString(s) +} + +func (o *Object) String() string { return fmt.Sprintf("%s:%s", o.Namespace, o.ID) } -func (u UserID) String() string { +func (o *Object) UnmarshalJSON(raw []byte) error { + o.FromString(string(raw)) + return nil +} + +func (o *Object) FromString(s string) *Object { + parts := strings.Split(s, ":") + if len(parts) == 2 { + o.Namespace, o.ID = parts[0], parts[1] + } + return o +} + +func (x *RelationObject) FromString(s string) *RelationObject { + o := (&Object{}).FromString(s) + x.Namespace, x.ObjectId = o.Namespace, o.ID + return x +} + +func (u *UserID) String() string { return fmt.Sprintf("%s", u.ID) } -func (u UserSet) String() string { +func (u *UserSet) String() string { return fmt.Sprintf("%s#%s", u.Object, u.Relation) } -func (r Relation) String() string { - return fmt.Sprintf("%s#%s@%s", r.Object, r.Relation, r.User) +func (u *UserID) FromString(s string) Subject { + u.ID = s + return u } -func (r *Relation) ImportFromGRPC(gr *RelationTuple) *Relation { - var user User - switch gr.User.(type) { +func (u *UserSet) FromString(s string) Subject { + parts := strings.Split(s, "#") + if len(parts) == 2 { + u.Object.FromString(parts[0]) + u.Relation = parts[1] + } + return u +} + +func (r *InternalRelationTuple) String() string { + return fmt.Sprintf("%s#%s@%s", r.Object, r.Relation, r.Subject) +} + +func (r *InternalRelationTuple) UnmarshalJSON(raw []byte) error { + subject := gjson.GetBytes(raw, "subject").Str + r.Subject = SubjectFromString(subject) + object := gjson.GetBytes(raw, "object").Str + r.Object = (&Object{}).FromString(object) + r.Relation = gjson.GetBytes(raw, "relation").Str + + return nil +} + +func (r *InternalRelationTuple) FromGRPC(gr *RelationTuple) *InternalRelationTuple { + var subject Subject + switch gr.Subject.(type) { case *RelationTuple_UserId: - user = UserID{ + subject = &UserID{ ID: gr.GetUserId(), } case *RelationTuple_UserSet: - user = UserSet{ - Object: Object{ + subject = &UserSet{ + Object: &Object{ gr.GetUserSet().Object.Namespace, gr.GetUserSet().Object.ObjectId, }, @@ -72,73 +126,74 @@ func (r *Relation) ImportFromGRPC(gr *RelationTuple) *Relation { } } - r.Object = Object{ - gr.Object.Namespace, - gr.Object.ObjectId, + if gr.Object != nil { + r.Object = &Object{ + gr.Object.Namespace, + gr.Object.ObjectId, + } } r.Relation = gr.Relation - r.User = user + r.Subject = subject return r } -func (gr *RelationTuple) ImportFromNormal(r *Relation) *RelationTuple { - var user isRelationTuple_User - switch r.User.(type) { - case UserID: - user = &RelationTuple_UserId{ - r.User.(UserID).ID, +func (x *RelationTuple) FromInternal(r *InternalRelationTuple) *RelationTuple { + var subject isRelationTuple_Subject + switch s := r.Subject.(type) { + case *UserID: + subject = &RelationTuple_UserId{ + s.ID, } - case UserSet: - userSet := r.User.(UserSet) - user = &RelationTuple_UserSet{ + case *UserSet: + subject = &RelationTuple_UserSet{ UserSet: &RelationUserSet{ Object: &RelationObject{ - ObjectId: userSet.Object.ID, - Namespace: userSet.Object.Namespace, + ObjectId: s.Object.ID, + Namespace: s.Object.Namespace, }, }, } } - gr.Object = &RelationObject{ + x.Object = &RelationObject{ ObjectId: r.Object.ID, Namespace: r.Object.Namespace, } - gr.Relation = r.Relation - gr.User = user + x.Relation = r.Relation + x.Subject = subject - return gr + return x } -func (rq *RelationQuery) ImportFromGRPC(rtq *ReadRelationTuplesRequest_Query) *RelationQuery { - var user User - switch rtq.User.(type) { +func (rq *RelationQuery) FromGRPC(query *ReadRelationTuplesRequest_Query) *RelationQuery { + var subject Subject + switch query.Subject.(type) { case *ReadRelationTuplesRequest_Query_UserId: - user = UserID{ - ID: rtq.GetUserId(), + subject = &UserID{ + ID: query.GetUserId(), } case *ReadRelationTuplesRequest_Query_UserSet: - user = UserSet{ - Object: Object{ - rtq.GetUserSet().Object.Namespace, - rtq.GetUserSet().Object.ObjectId, + subject = &UserSet{ + Object: &Object{ + query.GetUserSet().Object.Namespace, + query.GetUserSet().Object.ObjectId, }, - Relation: rtq.GetUserSet().Relation, + Relation: query.GetUserSet().Relation, } } - rq.Object = Object{ - rtq.Object.Namespace, - rtq.Object.ObjectId, + rq.Object = &Object{ + query.Object.Namespace, + query.Object.ObjectId, } - rq.Relation = rtq.Relation - rq.User = user + rq.Relation = query.Relation + rq.Subject = subject return rq } -func (r *Relation) Header() []string { +func (r *InternalRelationTuple) Header() []string { return []string{ "RELATION NAME", "USER ID", @@ -146,15 +201,15 @@ func (r *Relation) Header() []string { } } -func (r *Relation) Fields() []string { +func (r *InternalRelationTuple) Fields() []string { return []string{ r.Relation, - r.User.String(), + r.Subject.String(), r.Object.String(), } } -func (r *Relation) Interface() interface{} { +func (r *InternalRelationTuple) Interface() interface{} { return r } @@ -164,7 +219,7 @@ func NewGRPCRelationCollection(rels []*RelationTuple) cmdx.OutputCollection { } } -func NewRelationCollection(rels []*Relation) cmdx.OutputCollection { +func NewRelationCollection(rels []*InternalRelationTuple) cmdx.OutputCollection { return &relationCollection{ internalRelations: rels, } @@ -173,21 +228,27 @@ func NewRelationCollection(rels []*Relation) cmdx.OutputCollection { func (r *relationCollection) Header() []string { return []string{ "RELATION NAME", - "USER ID", - "OBJECT ID", + "SUBJECT", + "OBJECT", } } func (r *relationCollection) Table() [][]string { if r.internalRelations == nil { for _, rel := range r.grpcRelations { - r.internalRelations = append(r.internalRelations, (&Relation{}).ImportFromGRPC(rel)) + r.internalRelations = append(r.internalRelations, (&InternalRelationTuple{}).FromGRPC(rel)) } } data := make([][]string, len(r.internalRelations)) for i, rel := range r.internalRelations { - data[i] = []string{rel.Relation, rel.User.String(), rel.Object.String()} + data[i] = []string{rel.Relation, cmdx.None, cmdx.None} + if rel.Subject != nil { + data[i][1] = rel.Subject.String() + } + if rel.Object != nil { + data[i][2] = rel.Object.String() + } } return data @@ -200,7 +261,7 @@ func (r *relationCollection) Interface() interface{} { return r.internalRelations } -func (r relationCollection) Len() int { +func (r *relationCollection) Len() int { // one of them is zero so the sum is always correct return len(r.grpcRelations) + len(r.internalRelations) } diff --git a/models/relation.pb.go b/models/relation.pb.go index cdafd0798..8d6380f45 100644 --- a/models/relation.pb.go +++ b/models/relation.pb.go @@ -7,11 +7,12 @@ package models import ( + reflect "reflect" + sync "sync" + 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 ( @@ -34,7 +35,7 @@ type ReadRelationTuplesRequest struct { // All conditions are concatenated with // an OR operator. If any query matches // the relation will be in the response - Tuplesets []*ReadRelationTuplesRequest_Query `protobuf:"bytes,1,rep,name=tuplesets,proto3" json:"tuplesets,omitempty"` + TupleSets []*ReadRelationTuplesRequest_Query `protobuf:"bytes,1,rep,name=tuple_sets,json=tupleSets,proto3" json:"tuple_sets,omitempty"` Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` PerPage int32 `protobuf:"varint,3,opt,name=per_page,json=perPage,proto3" json:"per_page,omitempty"` } @@ -71,9 +72,9 @@ func (*ReadRelationTuplesRequest) Descriptor() ([]byte, []int) { return file_models_relation_proto_rawDescGZIP(), []int{0} } -func (x *ReadRelationTuplesRequest) GetTuplesets() []*ReadRelationTuplesRequest_Query { +func (x *ReadRelationTuplesRequest) GetTupleSets() []*ReadRelationTuplesRequest_Query { if x != nil { - return x.Tuplesets + return x.TupleSets } return nil } @@ -544,16 +545,39 @@ 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, - 0xc3, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, - 0x09, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 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, 0x09, 0x74, 0x75, 0x70, 0x6c, 0x65, - 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x72, 0x5f, - 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x65, 0x72, 0x50, - 0x61, 0x67, 0x65, 0x1a, 0xaf, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, + 0xc4, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, + 0x0a, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 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, 0x09, 0x74, 0x75, 0x70, 0x6c, + 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x72, + 0x5f, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x65, 0x72, + 0x50, 0x61, 0x67, 0x65, 0x1a, 0xaf, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, + 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, + 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, + 0x48, 0x00, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, + 0x6c, 0x65, 0x73, 0x22, 0x48, 0x0a, 0x19, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2b, 0x0a, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x22, 0x1c, 0x0a, + 0x1a, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, + 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x0d, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, @@ -564,56 +588,33 @@ var file_models_relation_proto_rawDesc = []byte{ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, - 0x65, 0x73, 0x22, 0x48, 0x0a, 0x19, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2b, 0x0a, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x22, 0x1c, 0x0a, 0x1a, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x0d, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x06, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x48, 0x00, - 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x22, 0x5d, 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, - 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, - 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x4b, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 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, 0x1b, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, - 0x32, 0xd0, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x61, - 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x12, - 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x2e, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 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, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x5d, 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4b, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 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, 0x1b, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x64, 0x32, 0xd0, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, + 0x70, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, + 0x61, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, + 0x12, 0x21, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x2e, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 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 ( @@ -640,7 +641,7 @@ var file_models_relation_proto_goTypes = []interface{}{ (*ReadRelationTuplesRequest_Query)(nil), // 7: models.ReadRelationTuplesRequest.Query } var file_models_relation_proto_depIdxs = []int32{ - 7, // 0: models.ReadRelationTuplesRequest.tuplesets:type_name -> models.ReadRelationTuplesRequest.Query + 7, // 0: models.ReadRelationTuplesRequest.tuple_sets:type_name -> models.ReadRelationTuplesRequest.Query 4, // 1: models.ReadRelationTuplesResponse.tuples:type_name -> models.RelationTuple 4, // 2: models.WriteRelationTupleRequest.tuple:type_name -> models.RelationTuple 6, // 3: models.RelationTuple.object:type_name -> models.RelationObject diff --git a/models/relation.proto b/models/relation.proto index 6a136a0ac..588f61e75 100644 --- a/models/relation.proto +++ b/models/relation.proto @@ -26,7 +26,7 @@ message ReadRelationTuplesRequest { // All conditions are concatenated with // an OR operator. If any query matches // the relation will be in the response - repeated Query tuplesets = 1; + repeated Query tuple_sets = 1; int32 page = 2; int32 per_page = 3; } diff --git a/models/relation_grpc.pb.go b/models/relation_grpc.pb.go index 7b5d06206..06f490371 100644 --- a/models/relation_grpc.pb.go +++ b/models/relation_grpc.pb.go @@ -4,6 +4,7 @@ package models import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/persistence/memory/definitions.go b/persistence/memory/definitions.go index 2aa1267f9..3e943519e 100644 --- a/persistence/memory/definitions.go +++ b/persistence/memory/definitions.go @@ -9,11 +9,11 @@ import ( type Persister struct { sync.RWMutex - relations []*models.Relation + relations []*models.InternalRelationTuple } func NewPersister() *Persister { return &Persister{ - relations: []*models.Relation{}, // TODO fill with something? + relations: []*models.InternalRelationTuple{}, } } diff --git a/persistence/memory/relations.go b/persistence/memory/relations.go index 48240c1c8..0e3cd9d30 100644 --- a/persistence/memory/relations.go +++ b/persistence/memory/relations.go @@ -2,20 +2,23 @@ package memory import ( "context" - - "github.com/ory/keto/relation" + "github.com/ory/keto/relationtuple" "github.com/ory/keto/models" ) -var _ relation.Manager = &Persister{} +type ( + queryFilter func(r *models.InternalRelationTuple) bool +) + +var _ relationtuple.Manager = &Persister{} -func (p *Persister) paginateRelations(rels []*models.Relation, page, perPage int32) []*models.Relation { +func (p *Persister) paginateRelations(rels []*models.InternalRelationTuple, page, perPage int32) []*models.InternalRelationTuple { if len(rels) == 0 { return rels } - veryLast := int32(len(p.relations)) - 1 + veryLast := int32(len(p.relations)) start, end := page*perPage, (page+1)*perPage-1 if veryLast < end { end = veryLast @@ -23,40 +26,45 @@ func (p *Persister) paginateRelations(rels []*models.Relation, page, perPage int return rels[start:end] } -func BuildRelationQueryFilter(query *models.RelationQuery) func(r *models.Relation) bool { - var filters []func(r *models.Relation) bool +func buildRelationQueryFilter(query *models.RelationQuery) queryFilter { + var filters []queryFilter + if query.Object.ID != "" && query.Object.Namespace != "" { - filters = append(filters, func(r *models.Relation) bool { + filters = append(filters, func(r *models.InternalRelationTuple) bool { return r.Object.ID == query.Object.ID && r.Object.Namespace == query.Object.Namespace }) } + if query.Relation != "" { - filters = append(filters, func(r *models.Relation) bool { + filters = append(filters, func(r *models.InternalRelationTuple) bool { return r.Relation == query.Relation }) } - if query.User != nil { - switch query.User.(type) { - case models.UserID: - filters = append(filters, func(r *models.Relation) bool { - rUserId := r.User.(models.UserID) - relationUserId := query.User.(models.UserID) - return r.User != nil && rUserId.ID == relationUserId.ID + + if query.Subject != nil { + switch s := query.Subject.(type) { + case *models.UserID: + filters = append(filters, func(r *models.InternalRelationTuple) bool { + rUserId, ok := r.Subject.(*models.UserID) + return ok && + r.Subject != nil && + rUserId.ID == s.ID }) - case models.UserSet: - filters = append(filters, func(r *models.Relation) bool { - rUserSet := r.User.(models.UserSet) - relationUserSet := query.User.(models.UserSet) - return rUserSet.Object.ID == relationUserSet.Object.ID && - rUserSet.Object.Namespace == relationUserSet.Object.Namespace && - rUserSet.Relation == relationUserSet.Relation + case *models.UserSet: + filters = append(filters, func(r *models.InternalRelationTuple) bool { + rUserSet, ok := r.Subject.(*models.UserSet) + return ok && + rUserSet.Object.ID == s.Object.ID && + rUserSet.Object.Namespace == s.Object.Namespace && + rUserSet.Relation == s.Relation }) } } // Create composite filter - return func(r *models.Relation) bool { + return func(r *models.InternalRelationTuple) bool { + // this is lazy-evaluating the AND of all filters for _, filter := range filters { if !filter(r) { return false @@ -66,18 +74,19 @@ func BuildRelationQueryFilter(query *models.RelationQuery) func(r *models.Relati } } -func (p *Persister) GetRelations(_ context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.Relation, error) { +func (p *Persister) GetRelationTuples(_ context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.InternalRelationTuple, error) { p.RLock() defer p.RUnlock() - var filters []func(r *models.Relation) bool - for _, q := range queries { - filters = append(filters, BuildRelationQueryFilter(q)) + filters := make([]queryFilter, len(queries)) + for i, q := range queries { + filters[i] = buildRelationQueryFilter(q) } - var res []*models.Relation + var res []*models.InternalRelationTuple for _, r := range p.relations { for _, filter := range filters { + // this is lazy-evaluating the OR of all filters if filter(r) { // If one filter matches add relation to response and break inner loop // to check next relation @@ -90,7 +99,7 @@ func (p *Persister) GetRelations(_ context.Context, queries []*models.RelationQu return p.paginateRelations(res, page, perPage), nil } -func (p *Persister) WriteRelation(_ context.Context, r *models.Relation) error { +func (p *Persister) WriteRelationTuple(_ context.Context, r *models.InternalRelationTuple) error { p.Lock() defer p.Unlock() diff --git a/relation/definitions.go b/relation/definitions.go deleted file mode 100644 index c0669bf4c..000000000 --- a/relation/definitions.go +++ /dev/null @@ -1,17 +0,0 @@ -package relation - -import ( - "context" - - "github.com/ory/keto/models" -) - -type ( - ManagerProvider interface { - RelationManager() Manager - } - Manager interface { - GetRelations(ctx context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.Relation, error) - WriteRelation(ctx context.Context, r *models.Relation) error - } -) diff --git a/relation/grpc_server.go b/relation/grpc_server.go deleted file mode 100644 index db875b2e7..000000000 --- a/relation/grpc_server.go +++ /dev/null @@ -1,46 +0,0 @@ -package relation - -import ( - "context" - - "github.com/ory/keto/models" -) - -var _ models.RelationTupleServiceServer = &Server{} - -type ( - serverDependencies interface { - ManagerProvider - } - Server struct { - models.UnimplementedRelationTupleServiceServer - - d serverDependencies - } -) - -func (s *Server) WriteRelation(ctx context.Context, r *models.RelationTuple) (*models.WriteRelationTupleResponse, error) { - return &models.WriteRelationTupleResponse{}, s.d.RelationManager().WriteRelation(ctx, (&models.Relation{}).ImportFromGRPC(r)) -} - -func NewServer(d serverDependencies) *Server { - return &Server{ - d: d, - } -} - -func (s *Server) ReadTuples(ctx context.Context, req *models.ReadRelationTuplesRequest) (*models.ReadRelationTuplesResponse, error) { - queries := make([]*models.RelationQuery, len(req.Tuplesets)) - for i, tupleset := range req.Tuplesets { - queries[i] = (&models.RelationQuery{}).ImportFromGRPC(tupleset) - } - - normalRels, _ := s.d.RelationManager().GetRelations(ctx, queries, req.Page, req.PerPage) - - rpcRels := make([]*models.RelationTuple, len(req.Tuplesets)) - for i, tupleset := range normalRels { - rpcRels[i] = (&models.RelationTuple{}).ImportFromNormal(tupleset) - } - - return &models.ReadRelationTuplesResponse{Tuples: rpcRels}, nil -} diff --git a/relationtuple/definitions.go b/relationtuple/definitions.go new file mode 100644 index 000000000..0f6a60b30 --- /dev/null +++ b/relationtuple/definitions.go @@ -0,0 +1,17 @@ +package relationtuple + +import ( + "context" + + "github.com/ory/keto/models" +) + +type ( + ManagerProvider interface { + RelationTupleManager() Manager + } + Manager interface { + GetRelationTuples(ctx context.Context, queries []*models.RelationQuery, page, perPage int32) ([]*models.InternalRelationTuple, error) + WriteRelationTuple(ctx context.Context, r *models.InternalRelationTuple) error + } +) diff --git a/relationtuple/grpc_server.go b/relationtuple/grpc_server.go new file mode 100644 index 000000000..cc2fb0eb4 --- /dev/null +++ b/relationtuple/grpc_server.go @@ -0,0 +1,50 @@ +package relationtuple + +import ( + "context" + + "github.com/ory/keto/models" +) + +var _ models.RelationTupleServiceServer = &Server{} + +type ( + serverDependencies interface { + ManagerProvider + } + Server struct { + models.UnimplementedRelationTupleServiceServer + + d serverDependencies + } +) + +func (s *Server) mustEmbedUnimplementedRelationTupleServiceServer() { + panic("implement me") +} + +func (s *Server) WriteRelationTuple(ctx context.Context, r *models.WriteRelationTupleRequest) (*models.WriteRelationTupleResponse, error) { + return &models.WriteRelationTupleResponse{}, s.d.RelationTupleManager().WriteRelationTuple(ctx, (&models.InternalRelationTuple{}).FromGRPC(r.Tuple)) +} + +func NewServer(d serverDependencies) *Server { + return &Server{ + d: d, + } +} + +func (s *Server) ReadRelationTuples(ctx context.Context, req *models.ReadRelationTuplesRequest) (*models.ReadRelationTuplesResponse, error) { + queries := make([]*models.RelationQuery, len(req.TupleSets)) + for i, tupleset := range req.TupleSets { + queries[i] = (&models.RelationQuery{}).FromGRPC(tupleset) + } + + normalRels, _ := s.d.RelationTupleManager().GetRelationTuples(ctx, queries, req.Page, req.PerPage) + + rpcRels := make([]*models.RelationTuple, len(normalRels)) + for i, tupleset := range normalRels { + rpcRels[i] = (&models.RelationTuple{}).FromInternal(tupleset) + } + + return &models.ReadRelationTuplesResponse{Tuples: rpcRels}, nil +} diff --git a/relation/handler.go b/relationtuple/handler.go similarity index 66% rename from relation/handler.go rename to relationtuple/handler.go index 8df70c714..bd6728267 100644 --- a/relation/handler.go +++ b/relationtuple/handler.go @@ -1,4 +1,4 @@ -package relation +package relationtuple import ( "encoding/json" @@ -40,18 +40,32 @@ func (h *handler) RegisterPublicRoutes(router *httprouter.Router) { } func (h *handler) getRelations(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - // TODO reimplement + params := r.URL.Query() + res, err := h.d.RelationTupleManager().GetRelationTuples(r.Context(), []*models.RelationQuery{ + { + Relation: params.Get("relation"), + Object: (&models.Object{}).FromString(params.Get("object")), + Subject: models.SubjectFromString(params.Get("subject")), + }, + }, 0, 100) + + if err != nil { + h.d.Writer().WriteError(w, r, err) + return + } + + h.d.Writer().Write(w, r, res) } func (h *handler) createRelation(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - var rel models.Relation + var rel models.InternalRelationTuple if err := json.NewDecoder(r.Body).Decode(&rel); err != nil { h.d.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest)) return } - if err := h.d.RelationManager().WriteRelation(r.Context(), &rel); err != nil { + if err := h.d.RelationTupleManager().WriteRelationTuple(r.Context(), &rel); err != nil { h.d.Writer().WriteError(w, r, errors.WithStack(herodot.ErrInternalServerError)) return } From 84e6a693628ec2ee30bbdfc86470930fb03513a9 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Tue, 27 Oct 2020 17:00:12 +0100 Subject: [PATCH 4/6] chore: fix lint issues --- models/relation.go | 2 +- persistence/memory/relations.go | 1 + relationtuple/grpc_server.go | 4 ---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/models/relation.go b/models/relation.go index c762d0ced..e1efb339e 100644 --- a/models/relation.go +++ b/models/relation.go @@ -74,7 +74,7 @@ func (x *RelationObject) FromString(s string) *RelationObject { } func (u *UserID) String() string { - return fmt.Sprintf("%s", u.ID) + return u.ID } func (u *UserSet) String() string { diff --git a/persistence/memory/relations.go b/persistence/memory/relations.go index 0e3cd9d30..2b95db083 100644 --- a/persistence/memory/relations.go +++ b/persistence/memory/relations.go @@ -2,6 +2,7 @@ package memory import ( "context" + "github.com/ory/keto/relationtuple" "github.com/ory/keto/models" diff --git a/relationtuple/grpc_server.go b/relationtuple/grpc_server.go index cc2fb0eb4..c2d3398c7 100644 --- a/relationtuple/grpc_server.go +++ b/relationtuple/grpc_server.go @@ -19,10 +19,6 @@ type ( } ) -func (s *Server) mustEmbedUnimplementedRelationTupleServiceServer() { - panic("implement me") -} - func (s *Server) WriteRelationTuple(ctx context.Context, r *models.WriteRelationTupleRequest) (*models.WriteRelationTupleResponse, error) { return &models.WriteRelationTupleResponse{}, s.d.RelationTupleManager().WriteRelationTuple(ctx, (&models.InternalRelationTuple{}).FromGRPC(r.Tuple)) } From 183c2cb5554dbf3bc5d0d85c6e7a76edf8d1261b Mon Sep 17 00:00:00 2001 From: zepatrik Date: Wed, 4 Nov 2020 14:09:13 +0100 Subject: [PATCH 5/6] chore: rename relation to relationtuple consistently --- cmd/{relation => relationtuple}/create.go | 4 ++-- cmd/{relation => relationtuple}/get.go | 2 +- cmd/{relation => relationtuple}/root.go | 4 ++-- cmd/root.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename cmd/{relation => relationtuple}/create.go (95%) rename cmd/{relation => relationtuple}/get.go (99%) rename cmd/{relation => relationtuple}/root.go (91%) diff --git a/cmd/relation/create.go b/cmd/relationtuple/create.go similarity index 95% rename from cmd/relation/create.go rename to cmd/relationtuple/create.go index b7a84485f..714236952 100644 --- a/cmd/relation/create.go +++ b/cmd/relationtuple/create.go @@ -1,4 +1,4 @@ -package relation +package relationtuple import ( "context" @@ -17,7 +17,7 @@ import ( func newCreateCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "create ", + Use: "create ", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { conn, err := client.GetGRPCConn(cmd) diff --git a/cmd/relation/get.go b/cmd/relationtuple/get.go similarity index 99% rename from cmd/relation/get.go rename to cmd/relationtuple/get.go index e1a06e59a..5dbe2e1b5 100644 --- a/cmd/relation/get.go +++ b/cmd/relationtuple/get.go @@ -1,4 +1,4 @@ -package relation +package relationtuple import ( "context" diff --git a/cmd/relation/root.go b/cmd/relationtuple/root.go similarity index 91% rename from cmd/relation/root.go rename to cmd/relationtuple/root.go index 20b7c7231..744c816d4 100644 --- a/cmd/relation/root.go +++ b/cmd/relationtuple/root.go @@ -1,4 +1,4 @@ -package relation +package relationtuple import ( "github.com/spf13/cobra" @@ -10,7 +10,7 @@ import ( ) var relationCmd = &cobra.Command{ - Use: "relation", + Use: "relation-tuple", } var packageFlags = pflag.NewFlagSet("relation package flags", pflag.ContinueOnError) diff --git a/cmd/root.go b/cmd/root.go index 75069ad97..fcf689bbb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,7 +21,7 @@ import ( "runtime" "strings" - "github.com/ory/keto/cmd/relation" + "github.com/ory/keto/cmd/relationtuple" "github.com/spf13/cobra" @@ -66,7 +66,7 @@ func init() { // when this action is called directly. RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - relation.RegisterCommandRecursive(RootCmd) + relationtuple.RegisterCommandRecursive(RootCmd) } // initConfig reads in config file and ENV variables if set. From 2fd27acd39b808ce4266598a9993fbe9994b3e3b Mon Sep 17 00:00:00 2001 From: zepatrik Date: Thu, 5 Nov 2020 15:00:52 +0100 Subject: [PATCH 6/6] docs: update relation tuple requirements documentation --- models/REQUIREMENTS.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/models/REQUIREMENTS.md b/models/REQUIREMENTS.md index 922ade776..8a9f75b92 100644 --- a/models/REQUIREMENTS.md +++ b/models/REQUIREMENTS.md @@ -1,8 +1,9 @@ -# Read API +# Relation Tuple API -## Read by tuplesets +## Read -Read request = one or multiple tuplesets +Reads tuples paginated, can be filtered by including queries. -Tupleset = Keys of one or multiple saved tuples +## Write +Write one or more tuples.