-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: initial OpenFGA v2beta1
protobuf API development
#127
base: main
Are you sure you want to change the base?
Changes from all commits
f37591f
13a3d11
9938dd0
ba5b256
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
syntax = "proto3"; | ||
|
||
package openfga.v2beta1; | ||
|
||
import "google/protobuf/struct.proto"; | ||
|
||
message RelationshipTuple { | ||
|
||
Subject subject = 1; | ||
|
||
string relation = 2; | ||
|
||
Object object = 3; | ||
|
||
RelationshipCondition condition = 4; | ||
} | ||
|
||
message RelationshipCondition { | ||
string name = 1; | ||
google.protobuf.Struct context = 2; | ||
} | ||
|
||
message RelationshipTupleWithoutCondition { | ||
Subject subject = 1; | ||
string relation = 2; | ||
Object object = 3; | ||
} | ||
|
||
message Subject { | ||
oneof subject_ref{ | ||
Object object = 1; | ||
TypedWildcard typed_wildcard = 2; | ||
SubjectSet subject_set = 3; | ||
} | ||
} | ||
|
||
message Object { | ||
string type = 1; | ||
string id = 2; | ||
} | ||
|
||
// TypedWildcard represents the public wildcard of the specified object type. | ||
// For example, `user:*` represents all objects of the `user` object type. | ||
message TypedWildcard { | ||
string type = 1; | ||
} | ||
|
||
message SubjectSet { | ||
Object object = 1; | ||
string relation = 2; | ||
} | ||
|
||
message AuthorizationModel { | ||
string id = 1; | ||
map<string, Relation> relations = 2; | ||
map<string, Condition> conditions = 3; | ||
} | ||
|
||
message Relation { | ||
|
||
// The name of the relation. | ||
string name = 1; | ||
|
||
// The relationship rewrite rule for the relation. | ||
RelationRewrite rewrite = 2; | ||
|
||
// A list of type restrictions that apply to the relation. | ||
repeated TypeRestriction type_restrictions = 3; | ||
} | ||
|
||
// RelationRewrite represents a relationship rule that is used to rewrite or define a relation | ||
// in terms of a direct relationship or some other rewritten relationship definition including | ||
// through set operations involving union, intersection, and exclusion. | ||
message RelationRewrite { | ||
oneof rewrite_rule { | ||
DirectRelationship direct = 1; | ||
ComputedRelationship computed = 2; | ||
TupleToSubjectSetRelationship tuple_to_subjectset = 3; | ||
// union, intersection, exclusion | ||
} | ||
} | ||
|
||
// DirectRelationship represents a directly assignable relationship. | ||
// | ||
// These relationships are the kinds of relationships that are permissible for writes to an | ||
// OpenFGA store. The kinds of objects that can be assignable to the directly assignable | ||
// relationship are based on the relations type restrictions. | ||
message DirectRelationship {} | ||
|
||
// ComputedRelationship represents a relationship that is rewritten through a recomputed relation. | ||
// | ||
// For example, if a relation `viewer` is rewritten through a computed relationship `editor`. In | ||
// Zanzibar nomenclature this is identical to computed userset rewrites. | ||
message ComputedRelationship { | ||
string relation = 1; | ||
} | ||
|
||
// TupleToSubjectSetRelationship represents a relationship | ||
// | ||
// In Zanzibar nomenclature this is identical to tuple to userset rewrites. | ||
message TupleToSubjectSetRelationship { | ||
string tupleset_relation = 1; | ||
ComputedRelationship computed_relationship = 2; | ||
} | ||
|
||
// TypeRestriction represents a relationship constraint that applies to a directly | ||
// assignable relationship. A directl relationship is only permissible if the type | ||
// restriction allows it. | ||
message TypeRestriction { | ||
oneof type_reference { | ||
UnconditionedObjectTypeRestriction unconditioned_object_type_reference = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the separation? also all can be conditioned not just object type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes the API more strongly typed. A type restriction can reference a direct object type with no condition or one explicitly with a condition. The later requires the condition to be defined, the former does not. To uniquely distinguish these cases we make the protobuf API strongly typed to represent the difference. |
||
ConditionedObjectTypeRestriction conditioned_object_type_reference = 2; | ||
TypedWildcard typed_wildcard_reference = 3; | ||
SubjectSetTypeRestriction subject_set_reference = 4; | ||
} | ||
} | ||
|
||
// UnconditionedObjectTypeRestriction represents a type restriction that enforces a relationship with | ||
// only a specific object type and is not conditioned on anything. | ||
message UnconditionedObjectTypeRestriction { | ||
string type = 1; | ||
} | ||
|
||
// ConditionedObjectTypeRestriction represents a type restriction that enforces a relationship with | ||
// a specific object type and is conditioned on the provided condition name. | ||
message ConditionedObjectTypeRestriction { | ||
string type = 1; | ||
string condition = 2; | ||
} | ||
|
||
// SubjectSetTypeRestriction represents a type restriction that references a relation defined on a specific | ||
// object type. For example `group#member` or `team#admin`. | ||
message SubjectSetTypeRestriction { | ||
string type = 1; | ||
string relation = 2; | ||
} | ||
|
||
message Condition { | ||
string name = 1; | ||
string expression = 2; | ||
map<string, ConditionParameterTypeRef> parameters = 3; | ||
} | ||
|
||
message ConditionParameterTypeRef { | ||
enum TypeName { | ||
TYPE_NAME_UNSPECIFIED = 0; | ||
TYPE_NAME_ANY = 1; | ||
TYPE_NAME_BOOL = 2; | ||
TYPE_NAME_STRING = 3; | ||
TYPE_NAME_INT = 4; | ||
TYPE_NAME_UINT = 5; | ||
TYPE_NAME_DOUBLE = 6; | ||
TYPE_NAME_DURATION = 7; | ||
TYPE_NAME_TIMESTAMP = 8; | ||
TYPE_NAME_MAP = 9; | ||
TYPE_NAME_LIST = 10; | ||
TYPE_NAME_IPADDRESS = 11; | ||
} | ||
|
||
TypeName type_name = 1; | ||
|
||
repeated ConditionParameterTypeRef generic_types = 2; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
syntax = "proto3"; | ||
|
||
package openfga.v2beta1; | ||
|
||
import "google/protobuf/struct.proto"; | ||
import "google/rpc/status.proto"; | ||
import "openfga/v2beta1/openfga.proto"; | ||
|
||
service OpenFGAService { | ||
rpc Check(CheckRequest) returns (CheckResponse); | ||
rpc BatchCheck(BatchCheckRequest) returns (BatchCheckResponse); | ||
|
||
rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse); | ||
|
||
rpc DeleteRelationshipTuples(DeleteRelationshipTuplesRequest) returns (DeleteRelationshipTuplesResponse); | ||
rpc WriteRelationshipTuples(WriteRelationshipTuplesRequest) returns (WriteRelationshipTuplesResponse); | ||
rpc ReadRelationshipTuples(ReadRelationshipTuplesRequest) returns (ReadRelationshipTuplesResponse); | ||
|
||
rpc WriteModel(WriteModelRequest) returns (WriteModelResponse); | ||
rpc ReadModel(ReadModelRequest) returns (ReadModelResponse); | ||
rpc ListModels(ListModelsRequest) returns (ListModelsResponse); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReadChanges? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More to come 😄 . Just started with some. |
||
} | ||
|
||
message CheckRequest{ | ||
string store_id = 1; | ||
string model_id = 2; | ||
Subject subject = 3; | ||
string relation = 4; | ||
Object object = 5; | ||
repeated RelationshipTuple contextual_tuples = 6; | ||
google.protobuf.Struct context = 7; | ||
} | ||
|
||
message CheckResponse{} | ||
|
||
message BatchCheckRequest { | ||
|
||
// One or more individual Check requests to evaluate in the batch. | ||
repeated BatchCheckRequestItem requests = 1; | ||
} | ||
|
||
message BatchCheckResponse { | ||
|
||
// The response pairings for each request item and the result/response it produced. | ||
repeated BatchCheckResponsePair response_pairs = 1; | ||
} | ||
|
||
// BatchCheckRequestItem represents a single Check request item used in a BatchCheckRequest. | ||
message BatchCheckRequestItem { | ||
Subject subject = 1; | ||
string relation = 2; | ||
Object object = 3; | ||
repeated RelationshipTuple contextual_tuples = 4; | ||
google.protobuf.Struct context = 5; | ||
} | ||
|
||
// BatchCheckResponseItem represents an individual response for a singular BatchCheckRequestItem produced | ||
// by a BatchCheck RPC. | ||
message BatchCheckResponseItem { | ||
CheckResponse response = 1; | ||
} | ||
|
||
// BatchCheckResponsePair represents the pairing of an individual BatchCheckRequestItem in a | ||
// BatchCheckRequest and the result which the individual request produced. Each BatchCheckRequestItem | ||
// can produce either a response item or an error. | ||
message BatchCheckResponsePair { | ||
BatchCheckRequestItem request = 1; | ||
|
||
oneof result { | ||
BatchCheckResponseItem response_item = 2; | ||
google.rpc.Status error = 3; | ||
} | ||
} | ||
|
||
message ListObjectsRequest{ | ||
string store_id = 1; | ||
string model_id = 2; | ||
Subject subject = 3; | ||
string relation = 4; | ||
string object_type = 5; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency, maybe: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would imply another message definition of the form
That's a bit overloaded and adds message level indirection for little to no gain. |
||
RelationshipTuple contextual_tuples = 6; | ||
google.protobuf.Struct context = 7; | ||
} | ||
message ListObjectsResponse{} | ||
|
||
message DeleteRelationshipTuplesRequest{ | ||
string store_id = 1; | ||
} | ||
message DeleteRelationshipTuplesResponse{} | ||
|
||
message WriteRelationshipTuplesRequest{ | ||
string store_id = 1; | ||
} | ||
message WriteRelationshipTuplesResponse{} | ||
|
||
message ReadRelationshipTuplesRequest { | ||
string store_id = 1; | ||
} | ||
|
||
message ReadRelationshipTuplesResponse { | ||
repeated RelationshipTuple relationship_tuples = 1; | ||
} | ||
|
||
message WriteModelRequest{ | ||
string store_id = 1; | ||
} | ||
message WriteModelResponse{} | ||
|
||
message ReadModelRequest{ | ||
string store_id = 1; | ||
string model_id = 2; | ||
} | ||
message ReadModelResponse{} | ||
|
||
message ListModelsRequest{ | ||
string store_id = 1; | ||
} | ||
message ListModelsResponse{} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
syntax = "proto3"; | ||
|
||
package watch.v2beta1; | ||
Check failure on line 3 in openfga/v2beta1/watch_service.proto GitHub Actions / build
|
||
|
||
service WatchService { | ||
|
||
// WatchChanges implements a streaming watch over an FGA store's changelog | ||
rpc WatchChanges(WatchChangesRequest) returns (stream WatchChangesResponse); | ||
} | ||
|
||
message WatchChangesRequest {} | ||
message WatchChangesResponse {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WHat do you think about naming them
RelationshipTuple
andRelationshipTupleWithCondition
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So invert them?
I think the API more unanymously operates on a RelationshipTuple which can optionally have a condition. For example the
WriteRelationshipTuples
API, theReadRelationshipTuples
API, etc.. The exception are those APIs that do not need a condition in the tuple representation whatsoever. So I think I lean toward leaving as is.