Skip to content

Commit

Permalink
refactor: make subject sets and subject IDs unambiguous (#729)
Browse files Browse the repository at this point in the history
BREAKING CHANGES: This patch changes the payload of the REST API. The gRPC API is **not** affected. The parameter `subject` was previously an encoded string. With this change clients have to explicitly use either `subject_id` or (`subject_set.namespace` and `subject_set.object` and `subject_set.relation`). The same is true for REST responses returned by Keto. An error with a hint will be returned if `subject` is still used.
  • Loading branch information
zepatrik authored Sep 24, 2021
1 parent 79bf9dd commit 5a1b0ba
Show file tree
Hide file tree
Showing 55 changed files with 2,944 additions and 519 deletions.
16 changes: 12 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ orbs:
jobs:
test:
docker:
- image: cimg/go:1.16
- image: cimg/go:1.17
environment:
TEST_DATABASE_POSTGRESQL: postgres://test:test@localhost:5432/keto?sslmode=disable
TEST_DATABASE_MYSQL: mysql://root:test@(localhost:3306)/mysql?parseTime=true&multiStatements=true
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:

test-race:
docker:
- image: cimg/go:1.16
- image: cimg/go:1.17
steps:
- checkout
- go/load-cache
Expand All @@ -64,7 +64,7 @@ jobs:

validate:
docker:
- image: cimg/go:1.16-node
- image: cimg/go:1.17-node
steps:
- checkout

Expand Down Expand Up @@ -95,6 +95,14 @@ jobs:

# Test documentation examples
- run: make test-docs-samples
clidocs:
docker:
- image: cimg/go:1.17-node
steps:
- checkout
- run:
name: Build and push CLI docs
command: "bash <(curl -s https://raw.githubusercontent.com/ory/ci/master/src/scripts/docs/cli.sh)"

workflows:
version: 2
Expand Down Expand Up @@ -124,7 +132,7 @@ workflows:
only: /v.*/
branches:
only: master
- docs/cli
- clidocs
- docs/build:
requires:
- test
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/buf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.16'
go-version: '1.17'
- uses: actions/setup-node@v2
with:
node-version: '15'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-go-grpc-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.16'
go-version: '1.17'
- name: Download dependencies
run: cd proto; go mod tidy
- name: Test
Expand Down
92 changes: 65 additions & 27 deletions .schema/relation_tuple.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,78 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"required": ["namespace", "relation", "object", "subject"],
"properties": {
"$schema": {
"type": "string",
"format": "uri-reference",
"description": "Add this to allow defining the schema, useful for IDE integration"
},
"namespace": {
"type": "string",
"description": "The namespace of the object and relation in this tuple."
},
"relation": {
"type": "string",
"description": "The relation of the object and subject."
},
"object": {
"type": "string",
"description": "The object affected by this relation."
"allOf": [
{
"required": [
"namespace",
"relation",
"object"
],
"properties": {
"$schema": {
"type": "string",
"format": "uri-reference",
"description": "Add this to allow defining the schema, useful for IDE integration"
},
"namespace": {
"type": "string",
"description": "The namespace of the object and relation in this tuple."
},
"object": {
"type": "string",
"description": "The object affected by this relation."
},
"relation": {
"type": "string",
"description": "The relation of the object and subject."
}
}
},
"subject": {
{
"oneOf": [
{
"type": "string",
"pattern": "^.*:.*#.*$",
"description": "The subject set affected by this relation. Uses the encoding of \"<namespace>:<object>#<relation>\"."
"required": [
"subject_id"
],
"properties": {
"subject_id": {
"type": "string",
"description": "The subject ID affected by this relation."
}
}
},
{
"type": "string",
"description": "The subject affected by this relation. Use \"<namespace>:<object>#<relation>\" to describe a subject set.",
"not": {
"pattern": "^.*:.*#.*$"
"required": [
"subject_set"
],
"properties": {
"subject_set": {
"type": "object",
"description": "The subject set affected by this relation.",
"properties": {
"namespace": {
"type": "string",
"description": "The namespace of the object and relation in this subject set."
},
"object": {
"type": "string",
"description": "The object referenced in this subject set."
},
"relation": {
"type": "string",
"description": "The relation of this subject set."
}
},
"additionalProperties": false,
"required": [
"namespace",
"relation",
"object"
]
}
}
}
]
}
}
]
}
42 changes: 27 additions & 15 deletions cmd/relationtuple/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,44 @@ import (
)

const (
FlagSubject = "subject"
FlagRelation = "relation"
FlagObject = "object"
FlagPageSize = "page-size"
FlagPageToken = "page-token"
FlagSubject = "subject"
FlagSubjectID = "subject-id"
FlagSubjectSet = "subject-set"
FlagRelation = "relation"
FlagObject = "object"
FlagPageSize = "page-size"
FlagPageToken = "page-token"
)

func registerRelationTupleFlags(flags *pflag.FlagSet) {
flags.String(FlagSubject, "", "Set the requested subject")
flags.String(FlagSubjectID, "", "Set the requested subject ID")
flags.String(FlagSubjectSet, "", `Set the requested subject set; format: "namespace:object#relation"`)
flags.String(FlagRelation, "", "Set the requested relation")
flags.String(FlagObject, "", "Set the requested object")

flags.String(FlagSubject, "", "")
if err := flags.MarkHidden(FlagSubject); err != nil {
panic(err.Error())
}
}

func readQueryFromFlags(cmd *cobra.Command, namespace string) (*acl.ListRelationTuplesRequest_Query, error) {
subject := flagx.MustGetString(cmd, FlagSubject)
relation := flagx.MustGetString(cmd, FlagRelation)
object := flagx.MustGetString(cmd, FlagObject)

query := &acl.ListRelationTuplesRequest_Query{
Relation: relation,
Object: object,
Namespace: namespace,
Object: flagx.MustGetString(cmd, FlagObject),
Relation: flagx.MustGetString(cmd, FlagRelation),
}

if subject != "" {
s, err := relationtuple.SubjectFromString(subject)
switch flags := cmd.Flags(); {
case flags.Changed(FlagSubjectID) && flags.Changed(FlagSubjectSet):
return nil, relationtuple.ErrDuplicateSubject
case flags.Changed(FlagSubjectID):
query.Subject = (&relationtuple.SubjectID{ID: flagx.MustGetString(cmd, FlagSubjectID)}).ToProto()
case flags.Changed(FlagSubjectSet):
s, err := (&relationtuple.SubjectSet{}).FromString(flagx.MustGetString(cmd, FlagSubjectSet))
if err != nil {
return nil, err
}

query.Subject = s.ToProto()
}

Expand All @@ -69,6 +77,10 @@ func newGetCmd() *cobra.Command {
"Returns paginated results.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed(FlagSubject) {
return fmt.Errorf("usage of --%s is not supported anymore, use --%s or --%s respectively", FlagSubject, FlagSubjectID, FlagSubjectSet)
}

conn, err := client.GetReadConn(cmd)
if err != nil {
return err
Expand Down
6 changes: 5 additions & 1 deletion contrib/cat-videos-example/relation-tuples/cats1_owner.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"namespace": "videos",
"object": "/cats/1.mp4",
"relation": "owner",
"subject": "videos:/cats#owner"
"subject_set": {
"namespace": "videos",
"object": "/cats",
"relation": "owner"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"namespace": "videos",
"object": "/cats/1.mp4",
"relation": "view",
"subject": "videos:/cats/1.mp4#owner"
"subject_set": {
"namespace": "videos",
"object": "/cats/1.mp4",
"relation": "owner"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"namespace": "videos",
"object": "/cats/1.mp4",
"relation": "view",
"subject": "*"
"subject_id": "*"
}
6 changes: 5 additions & 1 deletion contrib/cat-videos-example/relation-tuples/cats2_owner.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"namespace": "videos",
"object": "/cats/2.mp4",
"relation": "owner",
"subject": "videos:/cats#owner"
"subject_set": {
"namespace": "videos",
"object": "/cats",
"relation": "owner"
}
}
6 changes: 5 additions & 1 deletion contrib/cat-videos-example/relation-tuples/cats2_view.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"namespace": "videos",
"object": "/cats/2.mp4",
"relation": "view",
"subject": "videos:/cats/2.mp4#owner"
"subject_set": {
"namespace": "videos",
"object": "/cats/2.mp4",
"relation": "owner"
}
}
2 changes: 1 addition & 1 deletion contrib/cat-videos-example/relation-tuples/cats_owner.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"namespace": "videos",
"object": "/cats",
"relation": "owner",
"subject": "cat lady"
"subject_id": "cat lady"
}
6 changes: 5 additions & 1 deletion contrib/cat-videos-example/relation-tuples/cats_view.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"namespace": "videos",
"object": "/cats",
"relation": "view",
"subject": "videos:/cats#owner"
"subject_set": {
"namespace": "videos",
"object": "/cats",
"relation": "owner"
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
{
"type": "union",
"subject": "files:/photos/beach.jpg#access",
"children": [
{
"type": "union",
"subject": "files:/photos/beach.jpg#owner",
"children": [
{
"type": "leaf",
"subject": "maureen"
"subject_id": "maureen"
}
]
],
"subject_set": {
"namespace": "files",
"object": "/photos/beach.jpg",
"relation": "owner"
}
},
{
"type": "union",
"subject": "directories:/photos#access",
"children": [
{
"type": "leaf",
"subject": "directories:/photos#owner"
"subject_set": {
"namespace": "directories",
"object": "/photos",
"relation": "owner"
}
},
{
"type": "leaf",
"subject": "laura"
"subject_id": "laura"
}
]
],
"subject_set": {
"namespace": "directories",
"object": "/photos",
"relation": "access"
}
}
]
],
"subject_set": {
"namespace": "files",
"object": "/photos/beach.jpg",
"relation": "access"
}
}
Loading

0 comments on commit 5a1b0ba

Please sign in to comment.