diff --git a/configs/config.yaml b/configs/config.yaml index c0e3bcc4..ea4ee063 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -16,3 +16,4 @@ data: endpoint: "${ENDPOINT:0.0.0.0:50051}" token: "${PRESHARED}" # token takes precedence over tokenFile tokenFile: "${PRESHARED_FILE:.secrets/local-spicedb-secret}" + schemaFile: "${SCHEMA_FILE:deploy/schema.zed}" diff --git a/go.mod b/go.mod index b5ee9ff2..70223d0f 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/cel-go v0.21.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/subcommands v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect @@ -82,11 +83,13 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/mod v0.20.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index d733b58e..8b0bd6c1 100644 --- a/go.sum +++ b/go.sum @@ -105,6 +105,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -238,6 +239,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -317,6 +320,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/conf/conf.pb.go b/internal/conf/conf.pb.go index 7bc947a4..5416146a 100644 --- a/internal/conf/conf.pb.go +++ b/internal/conf/conf.pb.go @@ -388,10 +388,11 @@ type Data_SpiceDb struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UseTLS bool `protobuf:"varint,1,opt,name=useTLS,proto3" json:"useTLS,omitempty"` - Endpoint string `protobuf:"bytes,2,opt,name=endpoint,proto3" json:"endpoint,omitempty"` - Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` - TokenFile string `protobuf:"bytes,4,opt,name=tokenFile,proto3" json:"tokenFile,omitempty"` + UseTLS bool `protobuf:"varint,1,opt,name=useTLS,proto3" json:"useTLS,omitempty"` + Endpoint string `protobuf:"bytes,2,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` + TokenFile string `protobuf:"bytes,4,opt,name=tokenFile,proto3" json:"tokenFile,omitempty"` + SchemaFile string `protobuf:"bytes,5,opt,name=schemaFile,proto3" json:"schemaFile,omitempty"` } func (x *Data_SpiceDb) Reset() { @@ -454,6 +455,13 @@ func (x *Data_SpiceDb) GetTokenFile() string { return "" } +func (x *Data_SpiceDb) GetSchemaFile() string { + if x != nil { + return x.SchemaFile + } + return "" +} + var File_conf_proto protoreflect.FileDescriptor var file_conf_proto_rawDesc = []byte{ @@ -498,22 +506,24 @@ var file_conf_proto_rawDesc = []byte{ 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x75, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6a, 0x77, 0x6b, 0x73, 0x55, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x77, 0x6b, 0x73, 0x55, 0x72, 0x6c, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x6d, 0x69, - 0x6e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xad, 0x01, 0x0a, 0x04, 0x44, 0x61, + 0x6e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xce, 0x01, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x07, 0x73, 0x70, 0x69, 0x63, 0x65, 0x44, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x70, 0x69, 0x63, 0x65, 0x44, 0x62, 0x52, 0x07, 0x73, - 0x70, 0x69, 0x63, 0x65, 0x44, 0x62, 0x1a, 0x71, 0x0a, 0x07, 0x53, 0x70, 0x69, 0x63, 0x65, 0x44, - 0x62, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2d, - 0x6b, 0x65, 0x73, 0x73, 0x65, 0x6c, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f, - 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x69, 0x63, 0x65, 0x44, 0x62, 0x1a, 0x91, 0x01, 0x0a, 0x07, 0x53, 0x70, 0x69, 0x63, 0x65, + 0x44, 0x62, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x2d, 0x6b, 0x65, 0x73, 0x73, 0x65, 0x6c, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, + 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/conf/conf.proto b/internal/conf/conf.proto index 25c747ce..f2d35bfa 100644 --- a/internal/conf/conf.proto +++ b/internal/conf/conf.proto @@ -39,6 +39,7 @@ message Data { string endpoint = 2; string token = 3; string tokenFile = 4; + string schemaFile = 5; } SpiceDb spiceDb = 1; } diff --git a/internal/data/LocalSpiceDbContainer.go b/internal/data/LocalSpiceDbContainer.go index b3a31073..93d1974e 100644 --- a/internal/data/LocalSpiceDbContainer.go +++ b/internal/data/LocalSpiceDbContainer.go @@ -6,12 +6,9 @@ import ( "encoding/base64" "errors" "fmt" + "github.com/authzed/authzed-go/v1" - "github.com/go-kratos/kratos/v2/log" - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" - "github.com/project-kessel/relations-api/internal/conf" "io" "os" "path" @@ -19,9 +16,15 @@ import ( "runtime" "time" + "github.com/go-kratos/kratos/v2/log" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" + "github.com/project-kessel/relations-api/internal/conf" + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/health/grpc_health_v1" ) const ( @@ -30,18 +33,19 @@ const ( // SpicedbVersion is the image version used for containerized spiceDB in tests SpicedbVersion = "v1.22.2" // SpicedbSchemaBootstrapFile specifies an optional bootstrap schema file to be used for testing - SpicedbSchemaBootstrapFile = "spicedb-test-data/basic_schema.yaml" + SpicedbSchemaBootstrapFile = "spicedb-test-data/basic_schema.zed" // SpicedbRelationsBootstrapFile specifies an optional bootstrap file containing relations to be used for testing SpicedbRelationsBootstrapFile = "" ) // LocalSpiceDbContainer struct that holds pointers to the container, dockertest pool and exposes the port type LocalSpiceDbContainer struct { - logger log.Logger - port string - container *dockertest.Resource - pool *dockertest.Pool - name string + logger log.Logger + port string + container *dockertest.Resource + pool *dockertest.Pool + name string + schemaLocation string } type ContainerOptions struct { @@ -65,27 +69,10 @@ func CreateContainer(opts *ContainerOptions) (*LocalSpiceDbContainer, error) { cmd := []string{"serve-testing", "--skip-release-check=true"} - var mounts []string - if SpicedbSchemaBootstrapFile != "" { - cmd = append(cmd, "--load-configs") - cmd = append(cmd, "/mnt/spicedb_bootstrap.yaml") - mounts = append(mounts, path.Join(basepath, SpicedbSchemaBootstrapFile)+":/mnt/spicedb_bootstrap.yaml") - } - if SpicedbRelationsBootstrapFile != "" { - if SpicedbSchemaBootstrapFile != "" { - cmd[len(cmd)-1] = "/mnt/spicedb_bootstrap.yaml,/mnt/spicedb_bootstrap_relations.yaml" - } else { - cmd = append(cmd, "--load-configs") - cmd = append(cmd, "/mnt/spicedb_bootstrap_relations.yaml") - } - mounts = append(mounts, path.Join(basepath, SpicedbRelationsBootstrapFile)+":/mnt/spicedb_bootstrap_relations.yaml") - } - runopt := &dockertest.RunOptions{ Repository: SpicedbImage, Tag: SpicedbVersion, // Replace this with an actual version Cmd: cmd, - Mounts: mounts, ExposedPorts: []string{"50051/tcp", "50052/tcp"}, } if opts.Network != nil { @@ -111,11 +98,10 @@ func CreateContainer(opts *ContainerOptions) (*LocalSpiceDbContainer, error) { return fmt.Errorf("error connecting to spiceDB: %v", err.Error()) } - client := v1.NewSchemaServiceClient(conn) - - //read scheme we add via mount - _, err = client.ReadSchema(context.Background(), &v1.ReadSchemaRequest{}) - + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + client := grpc_health_v1.NewHealthClient(conn) + client.Check(ctx, &grpc_health_v1.HealthCheckRequest{}) return err }) @@ -124,11 +110,12 @@ func CreateContainer(opts *ContainerOptions) (*LocalSpiceDbContainer, error) { } return &LocalSpiceDbContainer{ - name: resource.Container.Name, - logger: opts.Logger, - port: port, - container: resource, - pool: pool, + name: resource.Container.Name, + logger: opts.Logger, + port: port, + container: resource, + pool: pool, + schemaLocation: path.Join(basepath, SpicedbSchemaBootstrapFile), }, nil } @@ -180,9 +167,10 @@ func (l *LocalSpiceDbContainer) CreateSpiceDbRepository() (*SpiceDbRepository, e defer os.RemoveAll(tmpDir) spiceDbConf := &conf.Data_SpiceDb{ - UseTLS: false, - Endpoint: "localhost:" + l.port, - Token: tmpFile.Name(), + UseTLS: false, + Endpoint: "localhost:" + l.port, + Token: tmpFile.Name(), + SchemaFile: l.schemaLocation, } repo, _, err := NewSpiceDbRepository(&conf.Data{SpiceDb: spiceDbConf}, l.logger) if err != nil { diff --git a/internal/data/spicedb-test-data/basic_schema.yaml b/internal/data/spicedb-test-data/basic_schema.yaml deleted file mode 100644 index 3feafb88..00000000 --- a/internal/data/spicedb-test-data/basic_schema.yaml +++ /dev/null @@ -1,30 +0,0 @@ -schema: |- - definition rbac/user {} - - definition rbac/group { - relation member: rbac/user | rbac/group#member - } - - definition rbac/role { - relation view_the_thing: rbac/user:* - } - - definition rbac/role_binding { - relation subject : rbac/user | rbac/group#member - relation granted: rbac/role - - permission view_the_thing = subject & granted->view_the_thing - } - - definition rbac/workspace { - relation parent: rbac/workspace - relation user_grant: rbac/role_binding - - permission view_the_thing = user_grant->view_the_thing - } - - definition rbac/thing { - relation workspace: rbac/workspace - - permission view = workspace->view_the_thing - } \ No newline at end of file diff --git a/internal/data/spicedb-test-data/basic_schema.zed b/internal/data/spicedb-test-data/basic_schema.zed new file mode 100644 index 00000000..fe9e0061 --- /dev/null +++ b/internal/data/spicedb-test-data/basic_schema.zed @@ -0,0 +1,29 @@ +definition rbac/user {} + +definition rbac/group { + relation member: rbac/user | rbac/group#member +} + +definition rbac/role { + relation view_the_thing: rbac/user:* +} + +definition rbac/role_binding { + relation subject : rbac/user | rbac/group#member + relation granted: rbac/role + + permission view_the_thing = subject & granted->view_the_thing +} + +definition rbac/workspace { + relation parent: rbac/workspace + relation user_grant: rbac/role_binding + + permission view_the_thing = user_grant->view_the_thing +} + +definition rbac/thing { + relation workspace: rbac/workspace + + permission view = workspace->view_the_thing +} \ No newline at end of file diff --git a/internal/data/spicedb.go b/internal/data/spicedb.go index 9d538362..af010cbc 100644 --- a/internal/data/spicedb.go +++ b/internal/data/spicedb.go @@ -24,8 +24,10 @@ import ( // SpiceDbRepository . type SpiceDbRepository struct { - client *authzed.Client - healthClient grpc_health_v1.HealthClient + client *authzed.Client + healthClient grpc_health_v1.HealthClient + schemaFilePath string + isInitialized bool } // NewSpiceDbRepository . @@ -41,7 +43,7 @@ func NewSpiceDbRepository(c *conf.Data, logger log.Logger) (*SpiceDbRepository, if c.SpiceDb.Token != "" { token = c.SpiceDb.Token } else if c.SpiceDb.TokenFile != "" { - token, err = readToken(c.SpiceDb.TokenFile) + token, err = readFile(c.SpiceDb.TokenFile) if err != nil { log.NewHelper(logger).Error(err) return nil, nil, fmt.Errorf("error creating spicedb client: error loading token file: %w", err) @@ -83,10 +85,36 @@ func NewSpiceDbRepository(c *conf.Data, logger log.Logger) (*SpiceDbRepository, log.NewHelper(logger).Info("spicedb connection cleanup requested (nothing to clean up)") } - return &SpiceDbRepository{client, healthClient}, cleanup, nil + return &SpiceDbRepository{client, healthClient, c.SpiceDb.SchemaFile, false}, cleanup, nil +} + +func (s *SpiceDbRepository) initialize() error { + if s.isInitialized { + return nil + } + + schema, err := readFile(s.schemaFilePath) + if err != nil { + return fmt.Errorf("failed to load schema file: %w", err) + } + + _, err = s.client.WriteSchema(context.TODO(), &v1.WriteSchemaRequest{ + Schema: schema, + }) + + if err != nil { + return err + } + + s.isInitialized = true + return nil } func (s *SpiceDbRepository) LookupSubjects(ctx context.Context, subject_type *apiV1beta1.ObjectType, subject_relation, relation string, object *apiV1beta1.ObjectReference, limit uint32, continuation biz.ContinuationToken) (chan *biz.SubjectResult, chan error, error) { + if err := s.initialize(); err != nil { + return nil, nil, err + } + var cursor *v1.Cursor = nil if continuation != "" { cursor = &v1.Cursor{ @@ -150,6 +178,10 @@ func (s *SpiceDbRepository) LookupSubjects(ctx context.Context, subject_type *ap } func (s *SpiceDbRepository) LookupResources(ctx context.Context, resouce_type *apiV1beta1.ObjectType, relation string, subject *apiV1beta1.SubjectReference, limit uint32, continuation biz.ContinuationToken) (chan *biz.ResourceResult, chan error, error) { + if err := s.initialize(); err != nil { + return nil, nil, err + } + var cursor *v1.Cursor = nil if continuation != "" { cursor = &v1.Cursor{ @@ -206,6 +238,10 @@ func (s *SpiceDbRepository) LookupResources(ctx context.Context, resouce_type *a } func (s *SpiceDbRepository) CreateRelationships(ctx context.Context, rels []*apiV1beta1.Relationship, touch biz.TouchSemantics) error { + if err := s.initialize(); err != nil { + return err + } + var relationshipUpdates []*v1.RelationshipUpdate var operation v1.RelationshipUpdate_Operation @@ -233,6 +269,10 @@ func (s *SpiceDbRepository) CreateRelationships(ctx context.Context, rels []*api } func (s *SpiceDbRepository) ReadRelationships(ctx context.Context, filter *apiV1beta1.RelationTupleFilter, limit uint32, continuation biz.ContinuationToken) (chan *biz.RelationshipResult, chan error, error) { + if err := s.initialize(); err != nil { + return nil, nil, err + } + var cursor *v1.Cursor = nil if continuation != "" { cursor = &v1.Cursor{ @@ -297,6 +337,10 @@ func (s *SpiceDbRepository) ReadRelationships(ctx context.Context, filter *apiV1 } func (s *SpiceDbRepository) DeleteRelationships(ctx context.Context, filter *apiV1beta1.RelationTupleFilter) error { + if err := s.initialize(); err != nil { + return err + } + req := &v1.DeleteRelationshipsRequest{RelationshipFilter: createSpiceDbRelationshipFilter(filter)} _, err := s.client.DeleteRelationships(ctx, req) @@ -310,6 +354,10 @@ func (s *SpiceDbRepository) DeleteRelationships(ctx context.Context, filter *api } func (s *SpiceDbRepository) Check(ctx context.Context, check *apiV1beta1.CheckRequest) (*apiV1beta1.CheckResponse, error) { + if err := s.initialize(); err != nil { + return nil, err + } + subject := &v1.SubjectReference{ Object: &v1.ObjectReference{ ObjectType: kesselTypeToSpiceDBType(check.GetSubject().GetSubject().Type), @@ -441,7 +489,7 @@ func createSpiceDbRelationship(relationship *apiV1beta1.Relationship) *v1.Relati } } -func readToken(file string) (string, error) { +func readFile(file string) (string, error) { bytes, err := os.ReadFile(file) if err != nil { return "", err diff --git a/internal/data/spicedb_test.go b/internal/data/spicedb_test.go index 222030ce..2c96e2cb 100644 --- a/internal/data/spicedb_test.go +++ b/internal/data/spicedb_test.go @@ -322,6 +322,8 @@ func TestSpiceDbRepository_CheckPermission(t *testing.T) { return } + container.WaitForQuantizationInterval() + subject := &apiV1beta1.SubjectReference{ Subject: &apiV1beta1.ObjectReference{ Type: simple_type("user"),