authzed / authzed-node Goto Github PK
View Code? Open in Web Editor NEWOfficial SpiceDB client library for NodeJS
Home Page: https://authzed.com/docs/reference/api
License: Apache License 2.0
Official SpiceDB client library for NodeJS
Home Page: https://authzed.com/docs/reference/api
License: Apache License 2.0
Hi Team!
We use the experimental bulk export API in a cron to ensure our main DB and authzed are in sync.
As our relations dataset grows (currently over 400K relations), we're starting to see RST_STREAM
errors pop up when our cron runs.
Error: 13 INTERNAL: Received RST_STREAM with code 0
at Object.callErrorFromStatus (/home/edorivai/work/spot/api/node_modules/@grpc/grpc-js/src/call.ts:81:17)
at Object.onReceiveStatus (/home/edorivai/work/spot/api/node_modules/@grpc/grpc-js/src/client.ts:596:32)
at Object.onReceiveStatus (/home/edorivai/work/spot/api/node_modules/@grpc/grpc-js/src/client-interceptors.ts:424:48)
at /home/edorivai/work/spot/api/node_modules/@grpc/grpc-js/src/call-stream.ts:330:24
at processTicksAndRejections (node:internal/process/task_queues:77:11)
for call at
at Proxy.makeServerStreamRequest (/home/edorivai/work/spot/api/node_modules/@grpc/grpc-js/src/client.ts:580:26)
at Proxy.bulkExportRelationships (/home/edorivai/work/spot/api/node_modules/@authzed/authzed-node/src/authzedapi/authzed/api/v1/experimental_service.grpc-client.ts:93:21)
at /home/edorivai/work/spot/api/node_modules/@authzed/authzed-node/src/util.ts:141:35
at new Promise (<anonymous>)
at Proxy.bulkExportRelationships (/home/edorivai/work/spot/api/node_modules/@authzed/authzed-node/src/util.ts:139:12)
at AuthzedClient.bulkExportRelationships (/home/edorivai/work/spot/api/src/authzed/AuthzedClient.ts:106:39)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at async getAuthzedExport (/home/edorivai/work/spot/api/src/authzed/sync.ts:172:24)
at async /home/edorivai/work/spot/api/src/authzed/sync.ts:60:35
at async Promise.all (index 0)
at async sync (/home/edorivai/work/spot/api/src/authzed/sync.ts:54:7) {
code: 13,
details: 'Received RST_STREAM with code 0',
metadata: Metadata { internalRepr: Map(0) {}, options: {} }
Couple things we noticed:
bulkExportRelationships
would run fine when run in GCP within the same region as our authzed cluster.zed
CLI never run into this error, not even when running from our local dev machines. I think this points to an issue in this node SDK specifically.Ran this again today to confirm - node.js script with bulkExportRelationships
hits RST_STREAM
, zed backup
works fine
$ zed backup authzed-prod
⠏ backing up (3.8 MB, 225 kB/s) [19s]
3:04PM INF finished backup duration=20.028045293s perSecond=20236.373249148513 relationships=405295
Versions:
$ zed version
client: zed v0.15.2
service: v1.30.1-hotfix+enterprise.v1.hotfix.v1
$ yarn list --pattern '@authzed/authzed-node'
yarn list v1.22.19
warning Resolution field "@grpc/[email protected]" is incompatible with requested version "@grpc/grpc-js@^1.8.3"
└─ @authzed/[email protected]
When creating a client with v1.NewClient()
, it would be nice to be able pass an option of whether or not to connect Schema and Watch services. The connection might take non-trivial setup time, and when not necessary, it would be preferable to avoid these.
Currently, in order to use ClientSecurity
as part of the v1.NewClient
constructor, I am having to import the type directly from the /dist
package of the module. Can we elevate this type as a main export since its used in the public constructor?
import { v1 } from '@authzed/authzed-node'
import { ClientSecurity } from '@authzed/authzed-node/dist/src/util'
const client = v1.NewClient('test', 'localhost:50051', ClientSecurity.INSECURE_LOCALHOST_ALLOWED)
Thanks!
I've copied & pasted the example from the example folder but got some type errors from typescript from both the WriteRelationshipsRequest
and checkPermissionRequest
However, if I add "as any" to the parameters just to get it to compile, the functions work as expected, so it appears to be just something wrong with the type defs.
Run the following code
client.writeRelationships({
// optionalPreconditions: [],
updates: [{
relationship: {
relation: "reader",
resource: v1.ObjectReference.create({
objectType: "page",
objectId: "page1",
}),
subject: v1.SubjectReference.create({
object: v1.ObjectReference.create({
objectType: "user",
objectId: "user1,
})
}),
},
operation: v1.RelationshipUpdate_Operation.TOUCH
}]
}, (err, data) => {
if (err) {
console.log('error writing relationship to authorization service', err)
} else {
console.log('success')
}
})
gives me the following error
at Object.callErrorFromStatus (/Users/trungvu/dev/epos/portal/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
at Object.onReceiveStatus (/Users/trungvu/dev/epos/portal/node_modules/@grpc/grpc-js/build/src/client.js:179:52)
at Object.onReceiveStatus (/Users/trungvu/dev/epos/portal/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:336:141)
at Object.onReceiveStatus (/Users/trungvu/dev/epos/portal/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:299:181)
at /Users/trungvu/dev/epos/portal/node_modules/@grpc/grpc-js/build/src/call-stream.js:145:78
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
code: 13,
details: "Request message serialization failure: Cannot read properties of undefined (reading 'length')",
metadata: Metadata { internalRepr: Map(0) {}, options: {} }
Adding
optionalPreconditions: [],
fixes it
Optional parameter should not be required. Otherwise remove the optional in the name
Users should not have to discover which stubs their API calls belong to in order to call them.
This means changing client.acl.check()
into just client.check()
Hi there, thanks for creating the node-client! I was implementing Authzed at work and was trying to get the experimental service's bulkImportRelationships
to throw errors when it fails. Specifically, I was trying to throw an error while using a Writestream
created using the client library v0.13.0
.
^ In the callbacks I actually implemented callbacks in a bunch of places to try and get the error to appear.
However, it seems like these errors do not propagate (or thrown) up to the context where they have been called, even though the code execution managed to log the error. Screenshot attached below:
curl --location 'http://localhost:8443/v1/permissions/expand' \
--data '{
"consistency": {
"minimizeLatency": true
},
"resource": {
"objectType": "document",
"objectId": "topsecret1"
},
"permission": "view"
}'
We need to add permission when we expand the permission on the resource, can we expand without permission or write it as *
?
Protobuf.js has the ability to use reflection on .proto
files in order to give callers a less verbose (although less type-safe) API.
For whatever reason, no matter what i try, i keep getting No connection established
errors from the grpc client. Connecting with the cli and the same exact config works. I assume this is more of an issue with grpc-js than you guys but wondering if anyone had any wisdom. I may just use the spicedb protobufs to generate a new sdk with https://github.com/connectrpc/connect-es if this keeps causing trouble.
heres my code to make the client and connect
const client = v1.NewClient('foobar', 'localhost:50052');
await client.promises.readRelationships({
optionalLimit: 0,
relationshipFilter: {
resourceType: 'user',
optionalRelation: '',
optionalResourceId: '',
},
});
and heres the context of the zed cli im using to successfully connect to a local spice db instance
CURRENT NAME ENDPOINT TOKEN TLS CERT
✓ dev localhost:50052 <redacted> insecure
When creating a client through v1.NewClient
it would be great to allow providing grpc-js
options (i.e. channel-options) to conmfigure e.g. the underlying channel.
After upgrading to v0.12.1 (after previously running 0.10.0) I have noticed random spikes for various calls (CheckPermission, LookupResources). Average response time for the queries being ran is <50ms; however - the spikes result in responses which are >60000ms (for a simple CheckPermission).
Environment:
Troubleshooting steps undertaken:
Conclusion: grpc-js > 1.6.9 is resulting in random performance spikes.
We're diving into SpiceDb and currently focused on syncing relationships from various data sources. Our approach involves an initial "full sync" from relevant databases, creating relationships. Subsequently, we aim to perform continuous updates by handling single new relationships as they occur in our databases. However, we're encountering a challenge during the full sync, where fetching data from an API and creating relationships works fine initially. Still, on subsequent triggers, it fails due to attempting to create an already existing relationship.
One quick, short-term solution to this was to use RelationshipUpdate_Operation.TOUCH
instead of CREATE
, but on the long run, we would like to be able to read existing relationships, so on subsequent triggers, we can control creating new relationships, as well as deleting the ones that are out of sync.
To address this, we've devised a strategy to fetch all existing relationships of a specific type and then appropriately skip existing ones, delete, or create single relationships.
We are currently getting stuck at just reading all the existing relationships of a type…
Here's an overview:
We've defined two entities in our schema - team
and employee
. The team has a member
relation with employee
. Our goal is to read relationships for a specific resource, where the relation is member
, essentially fetching all employees that are members of a particular team.
We've crafted a function utilizing the SpiceDb API to read relationships. The function, responsible for reading existing relationships, follows these steps:
ObjectReference
for the entity using the v1.ObjectReference.create
method.ReadRelationshipsRequest
specifying details about the relationship to be read. It includes the ObjectReference
and sets the relation to member
gRPC
: Invoking client.readRelationships
method with the defined readRelationshipsRequest
.Currently, we get the error: "Cannot read properties of undefined (reading 'create')."
Would be useful to have some documentation available on the correct procedure for this, to be able to assess where I might be going wrong.
I'm currently working through a POC with SpiceDB/Authzed and using the authzed-node client for read/write of relationships and permissions. The node client feels a bit cumbersome to use with having to instantiate a type for each reference to pass into a API call, i.e. checkPermission
.
Are there any thoughts on simplifying the API that is exposed to the user of the node client so that the request objects can be passed in as typed objects instead?
For example, instead of the following:
const proposal1 = v1.ObjectReference.create({
objectType: "proposal",
objectId: "1",
});
// Create the user reference.
const userMike = v1.ObjectReference.create({
objectType: "user",
objectId: "mike",
});
const subject = v1.SubjectReference.create({
object: userMike,
});
const request = v1.CheckPermissionRequest.create({
resource: proposal1,
permission: 'write',
subject
})
this.client.checkPermission(request, (err, response) => {
console.log(response);
console.log(err);
});
Could there be a model that can accept a request object like:
const request: CheckPermissionRequest = {
resource: {
objectType: "proposal",
objectId: "1"
},
permission: "write",
subject: {
objectType: "user",
objectId: "mike",
}
}
this.client.checkPermission(request, (err, response) => {
console.log(response);
console.log(err);
});
A typescript error is generated when using the v1.SubjectFilter type for the SubjectFilter.
Property 'optionalSubjectId' is missing in type '{ subjectType: string; }' but required in type 'SubjectFilter'.ts(2741) permission_service.d.ts(115, 5): 'optionalSubjectId' is declared here.
The type in question that makes the issue is the optionalSubjectId, that is not optional according to the interface generated for v1.SubjectFilter.
There is a workaround by disabling semantic checks by using // @ts-nocheck
at the beginning of the file. However this kind of defeats the purpose of using typescript.
From When Not to Use Lock Files with Node.js (twilio)...
Lock files are super useful if you build an application like a web server. However, if you publish a library or CLI to npm, lock files are never published. Meaning your users and you might use different versions of dependencies if you use lock files.
And given this recent report - it might be a good idea to drop internal usage of lockfiles, so that there's a better chance of catching bugs due to later versions of transitive dependencies.
Getting a syntax error when trying to use the node client in Node 12.18.x. The Nullish coalescing operator wasn't added until Node 14 :(
/app/node_modules/@authzed/authzed-node/dist/src/authzedapi/authzed/api/v1/permission_service.js:73
let message = target ?? this.create(), end = reader.pos + length;
We are using @authzed/[email protected]
and @grpc/[email protected]
with SpiceDB v1.22.2 and are seeing occasional (<0.1% of all calls) internal error responses of the kind below:
Error: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)
at callErrorFromStatus (/app/node_modules/@grpc/grpc-js/src/call.ts:82:17)
at Object.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/client.ts:611:51)
at /app/node_modules/@grpc/grpc-js/src/call-interface.ts:149:27
at Object.onReceiveStatus (/app/node_modules/@gitpod/gitpod-protocol/src/util/grpc.ts:80:29)
at InterceptingListenerImpl.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/call-interface.ts:145:19)
at Object.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/client-interceptors.ts:419:48)
at /app/node_modules/@grpc/grpc-js/src/resolving-call.ts:132:24
at processTicksAndRejections (node:internal/process/task_queues:77:11)
for call at
at Proxy.makeServerStreamRequest (/app/node_modules/@grpc/grpc-js/src/client.ts:594:42)
at Proxy.readRelationships (/app/node_modules/@authzed/authzed-node/src/authzedapi/authzed/api/v1/permission_service.grpc-client.ts:118:21)
at /app/node_modules/@authzed/authzed-node/src/util.ts:141:35
at new Promise (<anonymous>)
at Proxy.<anonymous> (/app/node_modules/@authzed/authzed-node/src/util.ts:139:12)
...
Some of the attributes in types exported by the client are incorrectly typed: they are required when they are supposed to be optional.
For example, the RelationshipFilter
:
/**
* RelationshipFilter is a collection of filters which when applied to a
* relationship will return relationships that have exactly matching fields.
*
* resource_type is required. All other fields are optional and if left
* unspecified will not filter relationships.
*
* @generated from protobuf message authzed.api.v1.RelationshipFilter
*/
export interface RelationshipFilter {
/**
* @generated from protobuf field: string resource_type = 1;
*/
resourceType: string;
/**
* @generated from protobuf field: string optional_resource_id = 2;
*/
optionalResourceId: string;
/**
* @generated from protobuf field: string optional_relation = 3;
*/
optionalRelation: string;
/**
* @generated from protobuf field: authzed.api.v1.SubjectFilter optional_subject_filter = 4;
*/
optionalSubjectFilter?: SubjectFilter;
}
From the docstring and the name of the attributes, optionalResourceId
and optionalRelation
are clearly supposed to be optional, but here they are required in the type declaration.
Note that optionalSubjectFilter
is correctly typed as optional: maybe the proto->TS translator doesn't handle scalar-ish types (eg strings) the same way as objects?
This library relies primarily on protobuf, which itself generates typescript files. But as of right now, these are not exported as part of this module.
We're currently writing the types out ourselves but it'd really help our adoption of SpiceDB and this client library if types were exported.
Right now all API calls follow the callback style that is popular in Node. However, with the wider adoption of async functions and promises, it would be nice to be able to use async API calls as well
Allow users to import specific version clients as a subpath eg import { NewClient} from '@authzed/authzed-node/v1'
While I was going through the experimental service, I stumbled upon this StreamingBulkCheckPermission method and wanted to know if this accessible and if so how can we do that? Any examples would help.
Also from what I understood, all the methods supports promises and wait for the stream to close to collect the data. If there any way to possibly collect the stream data as it is?
Any info would be helpful to understand.
Thank you
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.