diff --git a/.bin/go.mod b/.bin/go.mod index 65cc4095f..ef7c01948 100644 --- a/.bin/go.mod +++ b/.bin/go.mod @@ -12,7 +12,7 @@ require ( github.com/mikefarah/yq/v4 v4.27.2 github.com/ory/go-acc v0.2.8 github.com/pseudomuto/protoc-gen-doc v1.5.1 - golang.org/x/tools v0.17.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 google.golang.org/protobuf v1.32.0 ) @@ -138,14 +138,14 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.18.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/.bin/go.sum b/.bin/go.sum index a5f2394c4..e4afae3f5 100644 --- a/.bin/go.sum +++ b/.bin/go.sum @@ -644,8 +644,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -682,8 +682,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -722,8 +722,8 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -746,8 +746,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -805,13 +805,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -822,8 +822,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -885,8 +885,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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/.docker/Dockerfile b/.docker/Dockerfile index 26109213f..ecd6148eb 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.18.4 +FROM alpine:3.21.0 RUN addgroup -S ory; \ adduser -S ory -G ory -D -h /home/ory -s /bin/nologin; \ diff --git a/.docker/Dockerfile-alpine b/.docker/Dockerfile-alpine index b65482ff2..a786a1e4c 100644 --- a/.docker/Dockerfile-alpine +++ b/.docker/Dockerfile-alpine @@ -1,4 +1,4 @@ -FROM alpine:3.18.4 +FROM alpine:3.21.0 RUN addgroup -S ory; \ adduser -S ory -G ory -D -H -s /bin/nologin diff --git a/.docker/Dockerfile-build b/.docker/Dockerfile-build index 8d1a95da1..421dc9227 100644 --- a/.docker/Dockerfile-build +++ b/.docker/Dockerfile-build @@ -1,5 +1,5 @@ # Workaround for https://github.com/GoogleContainerTools/distroless/issues/1342 -FROM golang:1.21-bullseye AS builder +FROM golang:1.23.4-bullseye AS builder WORKDIR /go/src/github.com/ory/keto @@ -23,7 +23,7 @@ RUN go build -buildvcs=false -tags sqlite -o /usr/bin/keto . ######################### -FROM gcr.io/distroless/base-nossl-debian11:nonroot AS runner +FROM gcr.io/distroless/base-nossl-debian12:nonroot AS runner COPY --from=builder --chown=nonroot:nonroot /var/lib/sqlite /var/lib/sqlite COPY --from=builder /usr/bin/keto /usr/bin/keto diff --git a/.docker/Dockerfile-distroless-static b/.docker/Dockerfile-distroless-static index 2cc2b08c5..d61d5529a 100644 --- a/.docker/Dockerfile-distroless-static +++ b/.docker/Dockerfile-distroless-static @@ -1,4 +1,4 @@ -FROM gcr.io/distroless/static-debian11:nonroot +FROM gcr.io/distroless/static-debian12:nonroot COPY keto /usr/bin/keto EXPOSE 4466 4467 diff --git a/.docker/Dockerfile-sqlite b/.docker/Dockerfile-sqlite index 58fdd864a..fcc053c41 100644 --- a/.docker/Dockerfile-sqlite +++ b/.docker/Dockerfile-sqlite @@ -1,4 +1,4 @@ -FROM alpine:3.18.4 +FROM alpine:3.21.0 # Because this image is built for SQLite, we create /home/ory and /home/ory/sqlite which is owned by the ory user # and declare /home/ory/sqlite a volume. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5b703308a..ef90d000d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @zepatrik @hperl +* @aeneasr @ory/product-development diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml index 2dc6d264b..9c128ff23 100644 --- a/.github/ISSUE_TEMPLATE/BUG-REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml @@ -28,7 +28,7 @@ body: "I have joined the [Ory Community Slack](https://slack.ory.sh)." - label: "I am signed up to the [Ory Security Patch - Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)." + Newsletter](https://www.ory.sh/l/sign-up-newsletter)." id: checklist type: checkboxes - attributes: diff --git a/.github/ISSUE_TEMPLATE/DESIGN-DOC.yml b/.github/ISSUE_TEMPLATE/DESIGN-DOC.yml index 8ca3c7b68..9506bc6ef 100644 --- a/.github/ISSUE_TEMPLATE/DESIGN-DOC.yml +++ b/.github/ISSUE_TEMPLATE/DESIGN-DOC.yml @@ -39,7 +39,7 @@ body: "I have joined the [Ory Community Slack](https://slack.ory.sh)." - label: "I am signed up to the [Ory Security Patch - Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)." + Newsletter](https://www.ory.sh/l/sign-up-newsletter)." id: checklist type: checkboxes - attributes: diff --git a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml index c10db4591..35a0a0b75 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml @@ -32,7 +32,7 @@ body: "I have joined the [Ory Community Slack](https://slack.ory.sh)." - label: "I am signed up to the [Ory Security Patch - Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)." + Newsletter](https://www.ory.sh/l/sign-up-newsletter)." id: checklist type: checkboxes - attributes: diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5cc17ef15..4a0178139 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: - uses: ory/ci/checkout@master - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - name: Update npm to a non-buggy version run: sudo npm i -g npm@9.5.0 @@ -33,12 +33,12 @@ jobs: with: githubToken: ${{ secrets.GITHUB_TOKEN }} - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 env: GOGC: 100 with: + version: v1.61.0 args: --timeout 10m0s --issues-exit-code=0 - skip-pkg-cache: true - name: Test documentation examples run: make test-docs-samples - name: Test OPL typelib @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest services: postgres: - image: postgres:11.8 + image: postgres:16 env: POSTGRES_DB: keto POSTGRES_PASSWORD: test @@ -69,13 +69,13 @@ jobs: steps: - run: | docker create --name cockroach -p 26257:26257 \ - cockroachdb/cockroach:v20.2.5 start-single-node --insecure + cockroachdb/cockroach:latest-v24.2 start-single-node --insecure docker start cockroach name: Start CockroachDB - uses: ory/ci/checkout@master - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - name: Prepare Dependencies run: | @@ -102,7 +102,7 @@ jobs: - uses: ory/ci/checkout@master - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - run: | go test -tags sqlite -race -short ./... @@ -250,7 +250,7 @@ jobs: path: current-repo - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/cve-scan.yaml b/.github/workflows/cve-scan.yaml index 39ea559e4..b8aa01971 100644 --- a/.github/workflows/cve-scan.yaml +++ b/.github/workflows/cve-scan.yaml @@ -1,5 +1,9 @@ +# AUTO-GENERATED, DO NOT EDIT! +# Please edit the original at https://github.com/ory/meta/blob/master/templates/repository/server/.github/workflows/cve-scan.yaml + name: Docker Image Scanners on: + workflow_dispatch: push: branches: - "master" @@ -8,32 +12,70 @@ on: pull_request: branches: - "master" - merge_group: + +permissions: + contents: read + security-events: write jobs: scanners: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Env id: vars shell: bash run: | - echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> "${GITHUB_ENV}" + # Store values in local variables + SHA_SHORT=$(git rev-parse --short HEAD) + REPO_NAME=${{ github.event.repository.name }} + + # Append -sqlite to SHA_SHORT if repo is hydra + if [ "${REPO_NAME}" = "hydra" ]; then + echo "Repo is hydra, appending -sqlite to SHA_SHORT" + IMAGE_NAME="oryd/${REPO_NAME}:${SHA_SHORT}-sqlite" + else + echo "Repo is not hydra, using default IMAGE_NAME" + IMAGE_NAME="oryd/${REPO_NAME}:${SHA_SHORT}" + fi + + # Output values for debugging + echo "Values to be set:" + echo "SHA_SHORT: ${SHA_SHORT}" + echo "REPO_NAME: ${REPO_NAME}" + echo "IMAGE_NAME: ${IMAGE_NAME}" + + # Set GitHub Environment variables + echo "SHA_SHORT=${SHA_SHORT}" >> "${GITHUB_ENV}" + echo "IMAGE_NAME=${IMAGE_NAME}" >> "${GITHUB_ENV}" - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build images shell: bash run: | IMAGE_TAG="${{ env.SHA_SHORT }}" make docker + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Trivy + run: | + mkdir -p $HOME/.cache/trivy + echo "TRIVY_USERNAME=${{ github.actor }}" >> $GITHUB_ENV + echo "TRIVY_PASSWORD=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV + - name: Anchore Scanner - uses: anchore/scan-action@v3 + uses: anchore/scan-action@v5 id: grype-scan with: - image: oryd/keto:${{ env.SHA_SHORT }} + image: ${{ env.IMAGE_NAME }} fail-build: true severity-cutoff: high add-cpes-if-none: true @@ -46,25 +88,39 @@ jobs: echo "::endgroup::" - name: Anchore upload scan SARIF report if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ steps.grype-scan.outputs.sarif }} + - name: Kubescape scanner + uses: kubescape/github-action@main + id: kubescape + with: + image: ${{ env.IMAGE_NAME }} + verbose: true + format: pretty-printer + # can't whitelist CVE yet: https://github.com/kubescape/kubescape/pull/1568 + severityThreshold: critical - name: Trivy Scanner uses: aquasecurity/trivy-action@master if: ${{ always() }} with: - image-ref: oryd/keto:${{ env.SHA_SHORT }} + image-ref: ${{ env.IMAGE_NAME }} format: "table" exit-code: "42" ignore-unfixed: true vuln-type: "os,library" severity: "CRITICAL,HIGH" - scanners: "vuln,secret,config" + scanners: "vuln,secret,misconfig" + env: + TRIVY_SKIP_JAVA_DB_UPDATE: "true" + TRIVY_DISABLE_VEX_NOTICE: "true" + TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db + - name: Dockle Linter - uses: erzz/dockle-action@v1.3.2 + uses: erzz/dockle-action@v1 if: ${{ always() }} with: - image: oryd/keto:${{ env.SHA_SHORT }} + image: ${{ env.IMAGE_NAME }} exit-code: 42 failure-threshold: high - name: Hadolint @@ -81,5 +137,5 @@ jobs: shell: bash run: | echo "::group::Hadolint Scan Details" - echo "${HADOLINT_RESULTS}" | jq '.' + echo "${HADOLINT_RESULTS}" | jq '.' echo "::endgroup::" diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 879a70444..d728dd55a 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - run: make format - name: Indicate formatting issues diff --git a/.github/workflows/licenses.yml b/.github/workflows/licenses.yml index 35f957d6d..171e01963 100644 --- a/.github/workflows/licenses.yml +++ b/.github/workflows/licenses.yml @@ -1,3 +1,6 @@ +# AUTO-GENERATED, DO NOT EDIT! +# Please edit the original at https://github.com/ory/meta/blob/master/templates/repository/common/.github/workflows/licenses.yml + name: Licenses on: @@ -6,18 +9,26 @@ on: branches: - main - master - merge_group: jobs: - check: + licenses: + name: License compliance runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - name: Install script + uses: ory/ci/licenses/setup@master with: - go-version: "1.21" - check-latest: true - - uses: actions/setup-node@v2 + token: ${{ secrets.ORY_BOT_PAT || secrets.GITHUB_TOKEN }} + - name: Check licenses + uses: ory/ci/licenses/check@master + - name: Write, commit, push licenses + uses: ory/ci/licenses/write@master + if: + ${{ github.ref == 'refs/heads/main' || github.ref == + 'refs/heads/master' }} with: - node-version: "18" - - run: make licenses + author-email: + ${{ secrets.ORY_BOT_PAT && + '60093411+ory-bot@users.noreply.github.com' || + format('{0}@users.noreply.github.com', github.actor) }} + author-name: ${{ secrets.ORY_BOT_PAT && 'ory-bot' || github.actor }} diff --git a/.github/workflows/milestone.yml b/.github/workflows/milestone.yml index 5d25a715d..218b9c6e6 100644 --- a/.github/workflows/milestone.yml +++ b/.github/workflows/milestone.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: token: ${{ secrets.TOKEN_PRIVILEGED }} - name: Milestone Documentation Generator diff --git a/.github/workflows/pm.yml b/.github/workflows/pm.yml new file mode 100644 index 000000000..0c69d71b7 --- /dev/null +++ b/.github/workflows/pm.yml @@ -0,0 +1,29 @@ +name: Synchronize with product board + +on: + issues: + types: + - opened + pull_request: + types: + - opened + - ready_for_review + +jobs: + automate: + if: github.event.pull_request.head.repo.fork == false + name: Add issue to project + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: ory-corp/planning-automation-action@v0.1 + with: + organization: ory-corp + project: 5 + token: ${{ secrets.ORY_BOT_PAT }} + todoLabel: "Needs Triage" + statusName: Status + statusValue: "Needs Triage" + includeEffort: "false" + monthlyMilestoneName: Roadmap Monthly + quarterlyMilestoneName: Roadmap diff --git a/.github/workflows/release-go-grpc-client.yml b/.github/workflows/release-go-grpc-client.yml index ad6669a57..63fd47e27 100644 --- a/.github/workflows/release-go-grpc-client.yml +++ b/.github/workflows/release-go-grpc-client.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - name: Download dependencies run: cd proto; go mod tidy diff --git a/.github/workflows/single-table-migration-e2e.yml b/.github/workflows/single-table-migration-e2e.yml index 9016ee972..2824c76dc 100644 --- a/.github/workflows/single-table-migration-e2e.yml +++ b/.github/workflows/single-table-migration-e2e.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.23.2" check-latest: true - name: Run test script run: ./scripts/single-table-migration-e2e.sh diff --git a/.grype.yaml b/.grype.yaml index bd1a2b69b..cdefcaa86 100644 --- a/.grype.yaml +++ b/.grype.yaml @@ -3,3 +3,8 @@ ignore: # see https://github.com/anchore/grype/issues/558 - vulnerability: CVE-2015-5237 - vulnerability: CVE-2021-22570 + # https://github.com/opencontainers/runc/issues/4233 + - vulnerability: CVE-2024-3154 + - package: + name: github.com/opencontainers/runc + version: v1.1.12 diff --git a/.releaser/LICENSE.txt b/.releaser/LICENSE.txt deleted file mode 100644 index 32734665f..000000000 --- a/.releaser/LICENSE.txt +++ /dev/null @@ -1,84 +0,0 @@ -ORY Keto -Copyright (c) 2019 ORY GmbH - -*** END USER LICENSE AGREEMENT *** - -IMPORTANT: PLEASE READ THIS LICENSE CAREFULLY BEFORE USING THIS SOFTWARE. - -1. LICENSE - -By receiving, opening the file package, and/or using ORY Keto ("Software") containing this software, you agree that -this End User User License Agreement(EULA) is a legally binding and valid contract and agree to be bound by it. -You agree to abide by the intellectual property laws and all of the terms and conditions of this Agreement. - -Unless you have a different license agreement signed by ORY GmbH your use of ORY Keto indicates -your acceptance of this license agreement and warranty. - -Subject to the terms of this Agreement, ORY GmbH grants to you a limited, non-exclusive, non-transferable -license, without right to sub-license, to use ORY Keto in accordance with this Agreement and any other written -agreement with ORY GmbH. ORY GmbH does not transfer the title of ORY Keto to you; the license granted to you is not a -sale. This agreement is a binding legal agreement between ORY GmbH and the purchasers or users of ORY Keto. - -If you do not agree to be bound by this agreement, remove ORY Keto from your computer now and, if applicable, -promptly return to ORY GmbH by mail any copies of ORY Keto and related documentation and packaging in your possession. - -2. DISTRIBUTION - -ORY Keto and the license herein granted shall not be copied, shared, distributed, re-sold, offered for re-sale, -transferred or sub-licensed in whole or in part except that you may make one copy for archive purposes only. For -information about redistribution of ORY Keto contact ORY GmbH. - -3. USER AGREEMENT - -3.1 Use - -Your license to use ORY Keto is limited to the number of licenses purchased by you. You shall not allow others to use, -copy or evaluate copies of ORY Keto. - -3.2 Use Restrictions - -You shall use ORY Keto in compliance with all applicable laws and not for any unlawful purpose. Without limiting the -foregoing, use, display or distribution of ORY Keto together with material that is pornographic, racist, vulgar, -obscene, defamatory, libelous, abusive, promoting hatred, discriminating or displaying prejudice based on religion, -ethnic heritage, race, sexual orientation or age is strictly prohibited. - -Each licensed copy of ORY Keto may be used on one single computer location by one user. Use of ORY Keto means that you have loaded, installed, or run ORY Keto on a computer or similar device. If you install ORY Keto onto a multi-user platform, server or network, each and every individual user of ORY Keto must be licensed separately. - -You may make one copy of ORY Keto for backup purposes, providing you only have one copy installed on one computer being used by one person. Other users may not use your copy of ORY Keto . The assignment, sublicense, networking, sale, or distribution of copies of ORY Keto are strictly forbidden without the prior written consent of ORY GmbH. It is a violation of this agreement to assign, sell, share, loan, rent, lease, borrow, network or transfer the use of ORY Keto. If any person other than yourself uses ORY Keto registered in your name, regardless of whether it is at the same time or different times, then this agreement is being violated and you are responsible for that violation! - -3.3 Copyright Restriction - -This Software contains copyrighted material, trade secrets and other proprietary material. You shall not, and shall not attempt to, modify, reverse engineer, disassemble or decompile ORY Keto. Nor can you create any derivative works or other works that are based upon or derived from ORY Keto in whole or in part. - -ORY GmbH's name, logo and graphics file that represents ORY Keto shall not be used in any way to promote products developed with ORY Keto . ORY GmbH retains sole and exclusive ownership of all right, title and interest in and to ORY Keto and all Intellectual Property rights relating thereto. - -Copyright law and international copyright treaty provisions protect all parts of ORY Keto, products and services. No program, code, part, image, audio sample, or text may be copied or used in any way by the user except as intended within the bounds of the single user program. All rights not expressly granted hereunder are reserved for ORY GmbH. - -3.4 Limitation of Responsibility - -You will indemnify, hold harmless, and defend ORY GmbH , its employees, agents and distributors against any and all claims, proceedings, demand and costs resulting from or in any way connected with your use of ORY GmbH's Software. - -In no event (including, without limitation, in the event of negligence) will ORY GmbH , its employees, agents or distributors be liable for any consequential, incidental, indirect, special or punitive damages whatsoever (including, without limitation, damages for loss of profits, loss of use, business interruption, loss of information or data, or pecuniary loss), in connection with or arising out of or related to this Agreement, ORY Keto or the use or inability to use ORY Keto or the furnishing, performance or use of any other matters hereunder whether based upon contract, tort or any other theory including negligence. - -ORY GmbH's entire liability, without exception, is limited to the customers' reimbursement of the purchase price of the Software (maximum being the lesser of the amount paid by you and the suggested retail price as listed by ORY GmbH ) in exchange for the return of the product, all copies, registration papers and manuals, and all materials that constitute a transfer of license from the customer back to ORY GmbH. - -3.5 Warranties - -Except as expressly stated in writing, ORY GmbH makes no representation or warranties in respect of this Software and expressly excludes all other warranties, expressed or implied, oral or written, including, without limitation, any implied warranties of merchantable quality or fitness for a particular purpose. - -3.6 Governing Law - -This Agreement shall be governed by the law of the Germany applicable therein. You hereby irrevocably attorn and submit to the non-exclusive jurisdiction of the courts of Germany therefrom. If any provision shall be considered unlawful, void or otherwise unenforceable, then that provision shall be deemed severable from this License and not affect the validity and enforceability of any other provisions. - -3.7 Termination - -Any failure to comply with the terms and conditions of this Agreement will result in automatic and immediate termination of this license. Upon termination of this license granted herein for any reason, you agree to immediately cease use of ORY Keto and destroy all copies of ORY Keto supplied under this Agreement. The financial obligations incurred by you shall survive the expiration or termination of this license. - -4. DISCLAIMER OF WARRANTY - -THIS SOFTWARE AND THE ACCOMPANYING FILES ARE SOLD "AS IS" AND WITHOUT WARRANTIES AS TO PERFORMANCE OR MERCHANTABILITY OR ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED. THIS DISCLAIMER CONCERNS ALL FILES GENERATED AND EDITED BY ORY Keto AS WELL. - -5. CONSENT OF USE OF DATA - -You agree that ORY GmbH may collect and use information gathered in any manner as part of the product support services provided to you, if any, related to ORY Keto.ORY GmbH may also use this information to provide notices to you which may be of use or interest to you. - diff --git a/.reports/dep-licenses.csv b/.reports/dep-licenses.csv new file mode 100644 index 000000000..18ef74b8b --- /dev/null +++ b/.reports/dep-licenses.csv @@ -0,0 +1,336 @@ +"github.com/cenkalti/backoff/v3","MIT" +"github.com/cespare/xxhash/v2","MIT" +"github.com/dgraph-io/ristretto","Apache-2.0" +"github.com/dgraph-io/ristretto/z","MIT" +"github.com/dustin/go-humanize","MIT" +"github.com/pkg/errors","BSD-2-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"github.com/ghodss/yaml","MIT" +"github.com/ghodss/yaml","BSD-3-Clause" +"gopkg.in/yaml.v2","Apache-2.0" +"filippo.io/edwards25519","BSD-3-Clause" +"github.com/go-sql-driver/mysql","MPL-2.0" +"github.com/gobuffalo/httptest","MIT" +"github.com/gobuffalo/httptest/internal/takeon/github.com/ajg/form","BSD-3-Clause" +"github.com/gobuffalo/httptest/internal/takeon/github.com/markbates/hmax","MIT" +"filippo.io/edwards25519","BSD-3-Clause" +"github.com/Masterminds/semver/v3","MIT" +"github.com/aymerick/douceur","MIT" +"github.com/fatih/color","MIT" +"github.com/fatih/structs","MIT" +"github.com/go-sql-driver/mysql","MPL-2.0" +"github.com/gobuffalo/envy","MIT" +"github.com/gobuffalo/fizz","MIT" +"github.com/gobuffalo/flect","MIT" +"github.com/gobuffalo/github_flavored_markdown","MIT" +"github.com/gobuffalo/github_flavored_markdown/internal/russross/blackfriday","BSD-2-Clause" +"github.com/gobuffalo/github_flavored_markdown/internal/shurcooL/sanitized_anchor_name","MIT" +"github.com/gobuffalo/helpers","MIT" +"github.com/gobuffalo/nulls","MIT" +"github.com/gobuffalo/plush/v4","MIT" +"github.com/gobuffalo/pop/v6","MIT" +"github.com/gobuffalo/tags/v3","MIT" +"github.com/gobuffalo/validate/v3","MIT" +"github.com/gofrs/uuid","MIT" +"github.com/gorilla/css/scanner","BSD-3-Clause" +"github.com/jackc/chunkreader/v2","MIT" +"github.com/jackc/pgconn","MIT" +"github.com/jackc/pgio","MIT" +"github.com/jackc/pgpassfile","MIT" +"github.com/jackc/pgproto3/v2","MIT" +"github.com/jackc/pgservicefile","MIT" +"github.com/jackc/pgx/v5","MIT" +"github.com/jackc/puddle/v2","MIT" +"github.com/jmoiron/sqlx","MIT" +"github.com/joho/godotenv","MIT" +"github.com/kballard/go-shellquote","MIT" +"github.com/luna-duclos/instrumentedsql","MIT" +"github.com/mattn/go-colorable","MIT" +"github.com/mattn/go-isatty","MIT" +"github.com/microcosm-cc/bluemonday","BSD-3-Clause" +"github.com/rogpeppe/go-internal/modfile","BSD-3-Clause" +"github.com/sergi/go-diff/diffmatchpatch","MIT" +"github.com/sourcegraph/annotate","BSD-3-Clause" +"github.com/sourcegraph/syntaxhighlight","BSD-3-Clause" +"golang.org/x/crypto/pbkdf2","BSD-3-Clause" +"golang.org/x/mod","BSD-3-Clause" +"golang.org/x/net/html","BSD-3-Clause" +"golang.org/x/sync","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"gopkg.in/yaml.v2","Apache-2.0" +"github.com/gofrs/uuid","MIT" +"github.com/grpc-ecosystem/go-grpc-middleware/v2","Apache-2.0" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"google.golang.org/genproto/googleapis/rpc/status","Apache-2.0" +"google.golang.org/grpc","Apache-2.0" +"google.golang.org/protobuf","BSD-3-Clause" +"github.com/julienschmidt/httprouter","BSD-3-Clause" +"github.com/luna-duclos/instrumentedsql","MIT" +"github.com/ory/analytics-go/v5","MIT" +"github.com/segmentio/backo-go","MIT" +"github.com/xtgo/uuid","BSD-3-Clause" +"github.com/ory/graceful","Apache-2.0" +"github.com/pkg/errors","BSD-2-Clause" +"github.com/golang/protobuf/proto","BSD-3-Clause" +"github.com/ory/herodot","Apache-2.0" +"github.com/pkg/errors","BSD-2-Clause" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"google.golang.org/genproto/googleapis/rpc","Apache-2.0" +"google.golang.org/grpc","Apache-2.0" +"google.golang.org/protobuf","BSD-3-Clause" +"github.com/golang/protobuf/proto","BSD-3-Clause" +"github.com/nyaruka/phonenumbers","MIT" +"github.com/ory/jsonschema/v3","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"google.golang.org/protobuf","BSD-3-Clause" +"cloud.google.com/go/compute/metadata","Apache-2.0" +"code.dny.dev/ssrf","MIT" +"dario.cat/mergo","BSD-3-Clause" +"filippo.io/edwards25519","BSD-3-Clause" +"github.com/Masterminds/semver/v3","MIT" +"github.com/Nvveen/Gotty","BSD-2-Clause" +"github.com/avast/retry-go/v4","MIT" +"github.com/aymerick/douceur","MIT" +"github.com/beorn7/perks/quantile","MIT" +"github.com/cenkalti/backoff/v3","MIT" +"github.com/cenkalti/backoff/v4","MIT" +"github.com/cespare/xxhash/v2","MIT" +"github.com/cockroachdb/cockroach-go/v2","Apache-2.0" +"github.com/containerd/continuity/pathdriver","Apache-2.0" +"github.com/davecgh/go-spew/spew","ISC" +"github.com/dgraph-io/ristretto","Apache-2.0" +"github.com/dgraph-io/ristretto/z","MIT" +"github.com/distribution/reference","Apache-2.0" +"github.com/docker/cli","Apache-2.0" +"github.com/docker/docker","Apache-2.0" +"github.com/docker/go-connections","Apache-2.0" +"github.com/docker/go-units","Apache-2.0" +"github.com/dustin/go-humanize","MIT" +"github.com/evanphx/json-patch/v5","BSD-3-Clause" +"github.com/fatih/color","MIT" +"github.com/fatih/structs","MIT" +"github.com/felixge/fgprof","MIT" +"github.com/felixge/httpsnoop","MIT" +"github.com/fsnotify/fsnotify","BSD-3-Clause" +"github.com/ghodss/yaml","MIT" +"github.com/ghodss/yaml","BSD-3-Clause" +"github.com/go-logr/logr","Apache-2.0" +"github.com/go-logr/stdr","Apache-2.0" +"github.com/go-openapi/jsonpointer","Apache-2.0" +"github.com/go-openapi/swag","Apache-2.0" +"github.com/go-sql-driver/mysql","MPL-2.0" +"github.com/gobuffalo/envy","MIT" +"github.com/gobuffalo/fizz","MIT" +"github.com/gobuffalo/flect","MIT" +"github.com/gobuffalo/github_flavored_markdown","MIT" +"github.com/gobuffalo/github_flavored_markdown/internal/russross/blackfriday","BSD-2-Clause" +"github.com/gobuffalo/github_flavored_markdown/internal/shurcooL/sanitized_anchor_name","MIT" +"github.com/gobuffalo/helpers","MIT" +"github.com/gobuffalo/nulls","MIT" +"github.com/gobuffalo/plush/v4","MIT" +"github.com/gobuffalo/pop/v6","MIT" +"github.com/gobuffalo/tags/v3","MIT" +"github.com/gobuffalo/validate/v3","MIT" +"github.com/gobwas/glob","MIT" +"github.com/goccy/go-yaml","MIT" +"github.com/gofrs/flock","BSD-3-Clause" +"github.com/gofrs/uuid","MIT" +"github.com/gogo/protobuf","BSD-3-Clause" +"github.com/golang/protobuf/proto","BSD-3-Clause" +"github.com/google/pprof/profile","Apache-2.0" +"github.com/google/shlex","Apache-2.0" +"github.com/google/uuid","BSD-3-Clause" +"github.com/gorilla/css/scanner","BSD-3-Clause" +"github.com/gorilla/websocket","BSD-2-Clause" +"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors","Apache-2.0" +"github.com/grpc-ecosystem/go-grpc-prometheus","Apache-2.0" +"github.com/grpc-ecosystem/grpc-gateway/v2","BSD-3-Clause" +"github.com/hashicorp/go-cleanhttp","MPL-2.0" +"github.com/hashicorp/go-retryablehttp","MPL-2.0" +"github.com/inhies/go-bytesize","BSD-3-Clause" +"github.com/jackc/chunkreader/v2","MIT" +"github.com/jackc/pgconn","MIT" +"github.com/jackc/pgio","MIT" +"github.com/jackc/pgpassfile","MIT" +"github.com/jackc/pgproto3/v2","MIT" +"github.com/jackc/pgservicefile","MIT" +"github.com/jackc/pgx/v5","MIT" +"github.com/jackc/puddle/v2","MIT" +"github.com/jmoiron/sqlx","MIT" +"github.com/joho/godotenv","MIT" +"github.com/josharian/intern","MIT" +"github.com/julienschmidt/httprouter","BSD-3-Clause" +"github.com/kballard/go-shellquote","MIT" +"github.com/klauspost/compress","MIT" +"github.com/klauspost/compress","Apache-2.0" +"github.com/klauspost/compress","BSD-3-Clause" +"github.com/klauspost/compress/internal/snapref","BSD-3-Clause" +"github.com/klauspost/compress/zstd/internal/xxhash","MIT" +"github.com/knadh/koanf/maps","MIT" +"github.com/knadh/koanf/parsers/json","MIT" +"github.com/knadh/koanf/parsers/toml","MIT" +"github.com/knadh/koanf/parsers/yaml","MIT" +"github.com/knadh/koanf/providers/posflag","MIT" +"github.com/knadh/koanf/v2","MIT" +"github.com/lib/pq","MIT" +"github.com/luna-duclos/instrumentedsql","MIT" +"github.com/mailru/easyjson","MIT" +"github.com/mattn/go-colorable","MIT" +"github.com/mattn/go-isatty","MIT" +"github.com/microcosm-cc/bluemonday","BSD-3-Clause" +"github.com/mitchellh/copystructure","MIT" +"github.com/mitchellh/mapstructure","MIT" +"github.com/mitchellh/reflectwalk","MIT" +"github.com/moby/docker-image-spec/specs-go/v1","Apache-2.0" +"github.com/moby/term","Apache-2.0" +"github.com/munnerz/goautoneg","BSD-3-Clause" +"github.com/nyaruka/phonenumbers","MIT" +"github.com/opencontainers/go-digest","Apache-2.0" +"github.com/opencontainers/image-spec/specs-go","Apache-2.0" +"github.com/opencontainers/runc/libcontainer/user","Apache-2.0" +"github.com/openzipkin/zipkin-go/model","Apache-2.0" +"github.com/ory/analytics-go/v5","MIT" +"github.com/ory/dockertest/v3","Apache-2.0" +"github.com/ory/dockertest/v3/docker","BSD-2-Clause" +"github.com/ory/graceful","Apache-2.0" +"github.com/ory/herodot","Apache-2.0" +"github.com/ory/jsonschema/v3","BSD-3-Clause" +"github.com/ory/keto","Apache-2.0" +"github.com/ory/keto/proto/ory/keto/opl/v1alpha1","Unknown" +"github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2","Unknown" +"github.com/ory/x","Apache-2.0" +"github.com/ory/x/reqlog","MIT" +"github.com/pelletier/go-toml","MIT" +"github.com/pelletier/go-toml","Apache-2.0" +"github.com/pkg/errors","BSD-2-Clause" +"github.com/pkg/profile","BSD-2-Clause" +"github.com/pmezard/go-difflib/difflib","BSD-3-Clause" +"github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil","BSD-3-Clause" +"github.com/prometheus/client_golang/prometheus","Apache-2.0" +"github.com/prometheus/client_model/go","Apache-2.0" +"github.com/prometheus/common","Apache-2.0" +"github.com/prometheus/procfs","Apache-2.0" +"github.com/rogpeppe/go-internal/modfile","BSD-3-Clause" +"github.com/rs/cors","MIT" +"github.com/seatgeek/logrus-gelf-formatter","BSD-3-Clause" +"github.com/segmentio/backo-go","MIT" +"github.com/segmentio/objconv","MIT" +"github.com/sergi/go-diff/diffmatchpatch","MIT" +"github.com/sirupsen/logrus","MIT" +"github.com/soheilhy/cmux","Apache-2.0" +"github.com/sourcegraph/annotate","BSD-3-Clause" +"github.com/sourcegraph/syntaxhighlight","BSD-3-Clause" +"github.com/spf13/cast","MIT" +"github.com/spf13/cobra","Apache-2.0" +"github.com/spf13/pflag","BSD-3-Clause" +"github.com/stretchr/testify","MIT" +"github.com/tidwall/gjson","MIT" +"github.com/tidwall/match","MIT" +"github.com/tidwall/pretty","MIT" +"github.com/tidwall/sjson","MIT" +"github.com/urfave/negroni","MIT" +"github.com/xeipuuv/gojsonpointer","Apache-2.0" +"github.com/xeipuuv/gojsonreference","Apache-2.0" +"github.com/xeipuuv/gojsonschema","Apache-2.0" +"github.com/xtgo/uuid","BSD-3-Clause" +"go.opentelemetry.io/auto/sdk","Apache-2.0" +"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc","Apache-2.0" +"go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace","Apache-2.0" +"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Apache-2.0" +"go.opentelemetry.io/contrib/propagators/b3","Apache-2.0" +"go.opentelemetry.io/contrib/propagators/jaeger","Apache-2.0" +"go.opentelemetry.io/contrib/samplers/jaegerremote","Apache-2.0" +"go.opentelemetry.io/otel","Apache-2.0" +"go.opentelemetry.io/otel/exporters/jaeger","Apache-2.0" +"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift","Apache-2.0" +"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift","GNU-All-permissive-Copying-License" +"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift","BSD-3-Clause" +"go.opentelemetry.io/otel/exporters/otlp/otlptrace","Apache-2.0" +"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp","Apache-2.0" +"go.opentelemetry.io/otel/exporters/zipkin","Apache-2.0" +"go.opentelemetry.io/otel/metric","Apache-2.0" +"go.opentelemetry.io/otel/sdk","Apache-2.0" +"go.opentelemetry.io/otel/trace","Apache-2.0" +"go.opentelemetry.io/proto/otlp","Apache-2.0" +"golang.org/x/crypto/pbkdf2","BSD-3-Clause" +"golang.org/x/exp","BSD-3-Clause" +"golang.org/x/mod","BSD-3-Clause" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/oauth2","BSD-3-Clause" +"golang.org/x/sync","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"golang.org/x/xerrors","BSD-3-Clause" +"google.golang.org/genproto/googleapis/api","Apache-2.0" +"google.golang.org/genproto/googleapis/rpc","Apache-2.0" +"google.golang.org/grpc","Apache-2.0" +"google.golang.org/protobuf","BSD-3-Clause" +"gopkg.in/yaml.v2","Apache-2.0" +"gopkg.in/yaml.v3","MIT" +"github.com/ory/x","Apache-2.0" +"github.com/pelletier/go-toml","MIT" +"github.com/pelletier/go-toml","Apache-2.0" +"github.com/pkg/errors","BSD-2-Clause" +"github.com/rs/cors","MIT" +"github.com/segmentio/objconv","MIT" +"github.com/sirupsen/logrus","MIT" +"golang.org/x/sys/unix","BSD-3-Clause" +"github.com/soheilhy/cmux","Apache-2.0" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"github.com/spf13/cobra","Apache-2.0" +"github.com/spf13/pflag","BSD-3-Clause" +"github.com/spf13/pflag","BSD-3-Clause" +"github.com/stretchr/testify","MIT" +"github.com/tidwall/gjson","MIT" +"github.com/tidwall/match","MIT" +"github.com/tidwall/pretty","MIT" +"github.com/tidwall/gjson","MIT" +"github.com/tidwall/match","MIT" +"github.com/tidwall/pretty","MIT" +"github.com/tidwall/sjson","MIT" +"github.com/urfave/negroni","MIT" +"github.com/go-logr/logr","Apache-2.0" +"github.com/go-logr/stdr","Apache-2.0" +"go.opentelemetry.io/auto/sdk","Apache-2.0" +"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc","Apache-2.0" +"go.opentelemetry.io/otel","Apache-2.0" +"go.opentelemetry.io/otel/metric","Apache-2.0" +"go.opentelemetry.io/otel/trace","Apache-2.0" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"google.golang.org/genproto/googleapis/rpc/status","Apache-2.0" +"google.golang.org/grpc","Apache-2.0" +"google.golang.org/protobuf","BSD-3-Clause" +"github.com/felixge/httpsnoop","MIT" +"github.com/go-logr/logr","Apache-2.0" +"github.com/go-logr/stdr","Apache-2.0" +"go.opentelemetry.io/auto/sdk","Apache-2.0" +"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Apache-2.0" +"go.opentelemetry.io/otel","Apache-2.0" +"go.opentelemetry.io/otel/metric","Apache-2.0" +"go.opentelemetry.io/otel/trace","Apache-2.0" +"github.com/go-logr/logr","Apache-2.0" +"github.com/go-logr/stdr","Apache-2.0" +"go.opentelemetry.io/auto/sdk","Apache-2.0" +"go.opentelemetry.io/otel","Apache-2.0" +"go.opentelemetry.io/otel/metric","Apache-2.0" +"go.opentelemetry.io/otel/trace","Apache-2.0" +"go.opentelemetry.io/otel/sdk","Apache-2.0" +"go.opentelemetry.io/otel","Apache-2.0" +"go.opentelemetry.io/otel/trace","Apache-2.0" +"go.uber.org/goleak","MIT" +"golang.org/x/oauth2","BSD-3-Clause" +"golang.org/x/net","BSD-3-Clause" +"golang.org/x/sys/unix","BSD-3-Clause" +"golang.org/x/text","BSD-3-Clause" +"google.golang.org/genproto/googleapis/rpc/status","Apache-2.0" +"google.golang.org/grpc","Apache-2.0" +"google.golang.org/protobuf","BSD-3-Clause" + diff --git a/.schema/openapi/patches/replacements.sed b/.schema/openapi/patches/replacements.sed index f93c64404..685bfe8d9 100644 --- a/.schema/openapi/patches/replacements.sed +++ b/.schema/openapi/patches/replacements.sed @@ -9,4 +9,6 @@ s/ory.keto.relation_tuples.v1alpha2.ListRelationTuplesResponse/relationships/g s/ory.keto.relation_tuples.v1alpha2.ListNamespacesResponse/relationshipNamespaces/g s/ory.keto.relation_tuples.v1alpha2.CheckRequest/postCheckPermissionBody/g s/ory.keto.relation_tuples.v1alpha2.CheckResponse/checkPermissionResult/g +s/ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody/batchCheckPermissionBody/g +s/ory.keto.relation_tuples.v1alpha2.BatchCheckResponse/batchCheckPermissionResult/g s/ory.keto.opl.v1alpha1.CheckResponse/checkOplSyntaxResult/g diff --git a/.trivyignore b/.trivyignore new file mode 100644 index 000000000..0b7fcae4b --- /dev/null +++ b/.trivyignore @@ -0,0 +1,4 @@ +# Temp ignore, as 2.36-9+deb12u6 is not yet available in debian +CVE-2024-2961 +# opencontainers/runc 1.2.0-rc.1 is incompatible with Go 1.22: https://github.com/opencontainers/runc/issues/4233 +CVE-2024-3154 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c0797275..89f3c9e0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,95 +5,100 @@ **Table of Contents** -- [0.0.0 (2024-02-02)](#000-2024-02-02) -- [0.12.0-alpha.0 (2024-02-01)](#0120-alpha0-2024-02-01) +- [0.0.0 (2024-12-30)](#000-2024-12-30) - [Bug Fixes](#bug-fixes) - - [Code Generation](#code-generation) - - [Documentation](#documentation) - [Features](#features) -- [0.11.1-alpha.0 (2023-03-09)](#0111-alpha0-2023-03-09) +- [0.13.0-alpha.0 (2024-02-27)](#0130-alpha0-2024-02-27) - [Bug Fixes](#bug-fixes-1) + - [Code Generation](#code-generation) +- [0.12.0-alpha.0 (2024-02-01)](#0120-alpha0-2024-02-01) + - [Bug Fixes](#bug-fixes-2) - [Code Generation](#code-generation-1) + - [Documentation](#documentation) - [Features](#features-1) +- [0.11.1-alpha.0 (2023-03-09)](#0111-alpha0-2023-03-09) + - [Bug Fixes](#bug-fixes-3) + - [Code Generation](#code-generation-2) + - [Features](#features-2) - [Tests](#tests) - [0.11.0-alpha.0 (2023-02-23)](#0110-alpha0-2023-02-23) - - [Code Generation](#code-generation-2) -- [0.11.0-alpha.0.pre.1 (2023-02-23)](#0110-alpha0pre1-2023-02-23) - - [Bug Fixes](#bug-fixes-2) - [Code Generation](#code-generation-3) +- [0.11.0-alpha.0.pre.1 (2023-02-23)](#0110-alpha0pre1-2023-02-23) + - [Bug Fixes](#bug-fixes-4) + - [Code Generation](#code-generation-4) - [Code Refactoring](#code-refactoring) - [Documentation](#documentation-1) - - [Features](#features-2) + - [Features](#features-3) - [Tests](#tests-1) - [Unclassified](#unclassified) - [0.10.0-alpha.0 (2022-09-27)](#0100-alpha0-2022-09-27) - - [Bug Fixes](#bug-fixes-3) + - [Bug Fixes](#bug-fixes-5) - [Build System](#build-system) - - [Code Generation](#code-generation-4) + - [Code Generation](#code-generation-5) - [Code Refactoring](#code-refactoring-1) - [Documentation](#documentation-2) - - [Features](#features-3) + - [Features](#features-4) - [Tests](#tests-2) - [0.9.0-alpha.0 (2022-08-01)](#090-alpha0-2022-08-01) - [Breaking Changes](#breaking-changes) - - [Bug Fixes](#bug-fixes-4) - - [Code Generation](#code-generation-5) + - [Bug Fixes](#bug-fixes-6) + - [Code Generation](#code-generation-6) - [Code Refactoring](#code-refactoring-2) - [Documentation](#documentation-3) - - [Features](#features-4) + - [Features](#features-5) - [Tests](#tests-3) - [0.8.0-alpha.2 (2022-03-04)](#080-alpha2-2022-03-04) - - [Bug Fixes](#bug-fixes-5) - - [Code Generation](#code-generation-6) + - [Bug Fixes](#bug-fixes-7) + - [Code Generation](#code-generation-7) - [Documentation](#documentation-4) - [0.8.0-alpha.1 (2022-02-22)](#080-alpha1-2022-02-22) - - [Bug Fixes](#bug-fixes-6) - - [Code Generation](#code-generation-7) + - [Bug Fixes](#bug-fixes-8) + - [Code Generation](#code-generation-8) - [Tests](#tests-4) - [0.8.0-alpha.0 (2022-02-10)](#080-alpha0-2022-02-10) - - [Bug Fixes](#bug-fixes-7) - - [Code Generation](#code-generation-8) + - [Bug Fixes](#bug-fixes-9) + - [Code Generation](#code-generation-9) - [Code Refactoring](#code-refactoring-3) - [Documentation](#documentation-5) - - [Features](#features-5) + - [Features](#features-6) - [0.7.0-alpha.1 (2021-10-19)](#070-alpha1-2021-10-19) - - [Code Generation](#code-generation-9) + - [Code Generation](#code-generation-10) - [Documentation](#documentation-6) - [0.7.0-alpha.0 (2021-10-06)](#070-alpha0-2021-10-06) - [Breaking Changes](#breaking-changes-1) - - [Bug Fixes](#bug-fixes-8) + - [Bug Fixes](#bug-fixes-10) - [Chores](#chores) - - [Code Generation](#code-generation-10) + - [Code Generation](#code-generation-11) - [Code Refactoring](#code-refactoring-4) - [Documentation](#documentation-7) - - [Features](#features-6) + - [Features](#features-7) - [Tests](#tests-5) - [0.6.0-alpha.3 (2021-04-29)](#060-alpha3-2021-04-29) - - [Code Generation](#code-generation-11) -- [0.6.0-alpha.2 (2021-04-29)](#060-alpha2-2021-04-29) - - [Bug Fixes](#bug-fixes-9) - [Code Generation](#code-generation-12) +- [0.6.0-alpha.2 (2021-04-29)](#060-alpha2-2021-04-29) + - [Bug Fixes](#bug-fixes-11) + - [Code Generation](#code-generation-13) - [Documentation](#documentation-8) - - [Features](#features-7) + - [Features](#features-8) - [0.6.0-alpha.1 (2021-04-07)](#060-alpha1-2021-04-07) - - [Bug Fixes](#bug-fixes-10) + - [Bug Fixes](#bug-fixes-12) - [Build System](#build-system-1) - - [Code Generation](#code-generation-13) + - [Code Generation](#code-generation-14) - [Code Refactoring](#code-refactoring-5) - [Documentation](#documentation-9) - - [Features](#features-8) + - [Features](#features-9) - [Tests](#tests-6) - [0.5.6-alpha.1 (2020-05-28)](#056-alpha1-2020-05-28) - - [Bug Fixes](#bug-fixes-11) + - [Bug Fixes](#bug-fixes-13) - [Chores](#chores-1) - [0.5.5-alpha.1 (2020-05-28)](#055-alpha1-2020-05-28) - - [Bug Fixes](#bug-fixes-12) + - [Bug Fixes](#bug-fixes-14) - [Chores](#chores-2) - [Documentation](#documentation-10) - [0.5.4-alpha.1 (2020-04-07)](#054-alpha1-2020-04-07) - - [Bug Fixes](#bug-fixes-13) + - [Bug Fixes](#bug-fixes-15) - [0.5.3-alpha.3 (2020-04-06)](#053-alpha3-2020-04-06) - - [Code Generation](#code-generation-14) + - [Code Generation](#code-generation-15) - [Code Refactoring](#code-refactoring-6) - [Documentation](#documentation-11) - [0.5.3-alpha.1 (2020-04-03)](#053-alpha1-2020-04-03) @@ -101,15 +106,15 @@ - [0.5.2 (2020-04-02)](#052-2020-04-02) - [Documentation](#documentation-12) - [0.5.0 (2020-04-02)](#050-2020-04-02) - - [Bug Fixes](#bug-fixes-14) + - [Bug Fixes](#bug-fixes-16) - [Documentation](#documentation-13) - [0.4.5-alpha.1 (2020-02-29)](#045-alpha1-2020-02-29) - - [Bug Fixes](#bug-fixes-15) + - [Bug Fixes](#bug-fixes-17) - [Documentation](#documentation-14) - [0.4.4-alpha.1 (2020-02-14)](#044-alpha1-2020-02-14) - - [Bug Fixes](#bug-fixes-16) + - [Bug Fixes](#bug-fixes-18) - [Documentation](#documentation-15) - - [Features](#features-9) + - [Features](#features-10) - [Unclassified](#unclassified-1) - [0.4.3-alpha.2 (2020-01-31)](#043-alpha2-2020-01-31) - [Unclassified](#unclassified-2) @@ -156,7 +161,103 @@ -# [0.0.0](https://github.com/ory/keto/compare/v0.12.0-alpha.0...v0.0.0) (2024-02-02) +# [0.0.0](https://github.com/ory/keto/compare/v0.13.0-alpha.0...v0.0.0) (2024-12-30) + +### Bug Fixes + +- Add not to docs ([#1530](https://github.com/ory/keto/issues/1530)) + ([3b3b768](https://github.com/ory/keto/commit/3b3b76854052cf7a00506c35edded19cd5fe3258)) +- Http request metrics([#1611](https://github.com/ory/keto/issues/1611)) + ([#1612](https://github.com/ory/keto/issues/1612)) + ([b2e6d34](https://github.com/ory/keto/commit/b2e6d34d65d03158b6a30f3d2029c7c2c1eaae2b)) +- Missing persister when initializing without network + ([#1525](https://github.com/ory/keto/issues/1525)) + ([e675d5b](https://github.com/ory/keto/commit/e675d5bc230922e8379f87e7f8bbb9360cfee005)): + + - fix: missing persister when initializing without network + - chore: ignore CVE-2024-3154 + +- Typo in error message ([#1520](https://github.com/ory/keto/issues/1520)) + ([4a35588](https://github.com/ory/keto/commit/4a35588d52e9ba0b5779226c4725a8c68c4cfe8c)) +- Unused order ([#1590](https://github.com/ory/keto/issues/1590)) + ([47548c0](https://github.com/ory/keto/commit/47548c058960de272472ccd3eb2e98f08e9c25a9)): + + We filter for `nid = ?` so there is no point in ordering by nid. + + Column `shard_id` is the prefix + (`CONSTRAINT keto_relation_tuples_uuid_pkey PRIMARY KEY (shard_id ASC, nid ASC)`) + so it should not impact the query planner. + +### Features + +- Add ContextKeyDialFunc ([#1534](https://github.com/ory/keto/issues/1534)) + ([567ceb9](https://github.com/ory/keto/commit/567ceb9144b0e1efa4a88820cf23f53e1e8ec77d)) +- Add grpc server opts config ([#1524](https://github.com/ory/keto/issues/1524)) + ([7278e44](https://github.com/ory/keto/commit/7278e44bd0ac94e5f70f3c347a6e9cccfda11df6)): + + - feat: add grpc server opts config + - chore: bump base image + - chore: temp ignore cve + +- Add Inspect option to registry + ([#1523](https://github.com/ory/keto/issues/1523)) + ([213cfa5](https://github.com/ory/keto/commit/213cfa5c7d4a7ebc3957658178a5b1cd24c2669a)): + + - chore: add alnr to codeowners + - feat: add Inspect option + +- Batch check relations ([#1521](https://github.com/ory/keto/issues/1521)) + ([d670d50](https://github.com/ory/keto/commit/d670d508a618f5f881a215085beb6ac5371b8a85)): + + - batch check relations + - rename path + - shared parallelized function. batch size and parallelization configurable + - move check to engine + - fail individual requests + - move parallelization factor to be request parameter + - document and update configurable max batch size + - end to end tests + - unit tests + - cleanup + - run make format + - fix pipeline failures + - PR Feedback: move parallelization factor to config. Use err group + +- Batched and chunked insertion+deletion of relation tuples + ([#1631](https://github.com/ory/keto/issues/1631)) + ([c01b9c3](https://github.com/ory/keto/commit/c01b9c35eb45739e716e2df4e5619689fdde4392)) +- Check migration status in readiness probes + ([#1643](https://github.com/ory/keto/issues/1643)) + ([e270279](https://github.com/ory/keto/commit/e27027925e2c834ef87abcc345688b8455d15a36)) +- Deduplicate UUID mappings before database insert + ([#1654](https://github.com/ory/keto/issues/1654)) + ([ac812ee](https://github.com/ory/keto/commit/ac812ee85c57c3068439b54735de26c20c5fdbd1)) +- Write listen files with actual address + ([#1607](https://github.com/ory/keto/issues/1607)) + ([0ba58c7](https://github.com/ory/keto/commit/0ba58c7cf3dec2d33d0e503fc6a744b8898aba0c)): + + This change improves spinning up test Keto servers that use port `0`. A new + config value enables to set a file path where the server writes the actual + address it listens on after it was assigned a random free port by the OS. + +# [0.13.0-alpha.0](https://github.com/ory/keto/compare/v0.12.0-alpha.0...v0.13.0-alpha.0) (2024-02-27) + +autogen(docs): regenerate and update changelog + +[skip ci] + +### Bug Fixes + +- Make ts declarations depend on grpc-js + ([#1513](https://github.com/ory/keto/issues/1513)) + ([6a75032](https://github.com/ory/keto/commit/6a7503262efff6b24cfa0987453d063ed215837d)) + +### Code Generation + +- **docs:** Regenerate and update changelog + ([c756958](https://github.com/ory/keto/commit/c75695837f170334b526359f28967aa33d61bce6)): + + [skip ci] # [0.12.0-alpha.0](https://github.com/ory/keto/compare/v0.11.1-alpha.0...v0.12.0-alpha.0) (2024-02-01) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f59d807b0..b27814110 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,7 +64,7 @@ won't clash with Ory Keto's direction. A great way to do this is via [a Contributors License Agreement?](https://cla-assistant.io/ory/keto) - I would like updates about new versions of Ory Keto. - [How are new releases announced?](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53) + [How are new releases announced?](https://www.ory.sh/l/sign-up-newsletter) ## How can I contribute? @@ -144,10 +144,12 @@ checklist to contribute an example: not get mixed up. 1. Add a descriptive prefix to commits. This ensures a uniform commit history and helps structure the changelog. Please refer to this - [list of prefixes for Keto](https://github.com/ory/keto/blob/master/.github/semantic.yml) - for an overview. + [Convential Commits configuration](https://github.com/ory/keto/blob/master/.github/workflows/conventional_commits.yml) + for the list of accepted prefixes. You can read more about the Conventional + Commit specification + [at their site](https://www.conventionalcommits.org/en/v1.0.0/). 1. Create a `README.md` that explains how to use the example. (Use - [the README template](https://github.com/ory/examples/blob/master/_common/README)). + [the README template](https://github.com/ory/examples/blob/master/_common/README.md)). 1. Open a pull request and maintainers will review and merge your example. ## Contribute code @@ -172,8 +174,10 @@ request, go through this checklist: 1. Run `make format` 1. Add a descriptive prefix to commits. This ensures a uniform commit history and helps structure the changelog. Please refer to this - [list of prefixes for Keto](https://github.com/ory/keto/blob/master/.github/semantic.yml) - for an overview. + [Convential Commits configuration](https://github.com/ory/keto/blob/master/.github/workflows/conventional_commits.yml) + for the list of accepted prefixes. You can read more about the Conventional + Commit specification + [at their site](https://www.conventionalcommits.org/en/v1.0.0/). If a pull request is not ready to be reviewed yet [it should be marked as a "Draft"](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request). diff --git a/README.md b/README.md index 289bb10e0..32d9688a3 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@

Chat | Discusssions | - Newsletter

+ Newsletter

Guide | API Docs | Code Docs

- Support this project!

+ Support this project!

Work in Open Source, Ory is hiring!

diff --git a/SECURITY.md b/SECURITY.md index 7a05c1cfc..610451480 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,30 +1,56 @@ - - - -- [Security Policy](#security-policy) - - [Supported Versions](#supported-versions) - - [Reporting a Vulnerability](#reporting-a-vulnerability) - - - -# Security Policy - -## Supported Versions - -We release patches for security vulnerabilities. Which versions are eligible for -receiving such patches depends on the CVSS v3.0 Rating: - -| CVSS v3.0 | Supported Versions | -| --------- | ----------------------------------------- | -| 9.0-10.0 | Releases within the previous three months | -| 4.0-8.9 | Most recent release | +# Ory Security Policy + +This policy outlines Ory's security commitments and practices for users across +different licensing and deployment models. + +To learn more about Ory's security service level agreements (SLAs) and +processes, please [contact us](https://www.ory.sh/contact/). + +## Ory Network Users + +- **Security SLA:** Ory addresses vulnerabilities in the Ory Network according + to the following guidelines: + - Critical: Typically addressed within 14 days. + - High: Typically addressed within 30 days. + - Medium: Typically addressed within 90 days. + - Low: Typically addressed within 180 days. + - Informational: Addressed as necessary. + These timelines are targets and may vary based on specific circumstances. +- **Release Schedule:** Updates are deployed to the Ory Network as + vulnerabilities are resolved. +- **Version Support:** The Ory Network always runs the latest version, ensuring + up-to-date security fixes. + +## Ory Enterprise License Customers + +- **Security SLA:** Ory addresses vulnerabilities based on their severity: + - Critical: Typically addressed within 14 days. + - High: Typically addressed within 30 days. + - Medium: Typically addressed within 90 days. + - Low: Typically addressed within 180 days. + - Informational: Addressed as necessary. + These timelines are targets and may vary based on specific circumstances. +- **Release Schedule:** Updates are made available as vulnerabilities are + resolved. Ory works closely with enterprise customers to ensure timely updates + that align with their operational needs. +- **Version Support:** Ory may provide security support for multiple versions, + depending on the terms of the enterprise agreement. + +## Apache 2.0 License Users + +- **Security SLA:** Ory does not provide a formal SLA for security issues under + the Apache 2.0 License. +- **Release Schedule:** Releases prioritize new functionality and include fixes + for known security vulnerabilities at the time of release. While major + releases typically occur one to two times per year, Ory does not guarantee a + fixed release schedule. +- **Version Support:** Security patches are only provided for the latest release + version. ## Reporting a Vulnerability -Please report (suspected) security vulnerabilities to -**[security@ory.sh](mailto:security@ory.sh)**. You will receive a response from -us within 48 hours. If the issue is confirmed, we will release a patch as soon -as possible depending on complexity but historically within a few days. +For details on how to report security vulnerabilities, visit our +[security policy documentation](https://www.ory.sh/docs/ecosystem/security). diff --git a/buf.gen.yaml b/buf.gen.yaml index 5c875b992..3380ae54d 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,11 +1,11 @@ version: v1 plugins: - - plugin: buf.build/protocolbuffers/go + - plugin: buf.build/protocolbuffers/go:v1.36.1 out: proto opt: paths=source_relative - - plugin: buf.build/grpc/go + - plugin: buf.build/grpc/go:v1.5.1 out: proto opt: paths=source_relative,require_unimplemented_servers=false @@ -23,7 +23,7 @@ plugins: - name: ts out: proto - opt: ts_out=proto + opt: grpc_js path: node_modules/.bin/protoc-gen-ts - name: doc @@ -31,10 +31,6 @@ plugins: opt: proto/markdown.tmpl,proto/buf.md strategy: all - - plugin: buf.build/grpc-ecosystem/gateway - out: proto - opt: paths=source_relative - - plugin: buf.build/grpc-ecosystem/openapiv2 opt: - allow_merge=true diff --git a/cmd/client/grpc_client.go b/cmd/client/grpc_client.go index 9c8dcb379..5513eff03 100644 --- a/cmd/client/grpc_client.go +++ b/cmd/client/grpc_client.go @@ -39,7 +39,8 @@ const ( EnvAuthToken = "KETO_BEARER_TOKEN" //nolint:gosec // just the key, not the value EnvAuthority = "KETO_AUTHORITY" - ContextKeyTimeout contextKeys = "timeout" + ContextKeyTimeout contextKeys = "timeout" + ContextKeyDialFunc contextKeys = "dial" ) type connectionDetails struct { @@ -77,7 +78,6 @@ func (d *connectionDetails) dialOptions() (opts []grpc.DialOption) { if d.block { opts = append(opts, grpc.WithBlock()) } - return opts } @@ -138,6 +138,10 @@ func Conn(ctx context.Context, remote string, details connectionDetails) (*grpc. defer cancel() } + if dial, ok := ctx.Value(ContextKeyDialFunc).(func(context.Context, string) (*grpc.ClientConn, error)); ok { + return dial(ctx, remote) + } + return grpc.DialContext( ctx, remote, diff --git a/cmd/status/root_test.go b/cmd/status/root_test.go index b9a160977..a53917145 100644 --- a/cmd/status/root_test.go +++ b/cmd/status/root_test.go @@ -47,7 +47,7 @@ func TestStatusCmd(t *testing.T) { }) t.Run("case=block", func(t *testing.T) { - ctx := context.WithValue(context.Background(), client.ContextKeyTimeout, time.Millisecond) + ctx := context.WithValue(context.Background(), client.ContextKeyTimeout, 100*time.Millisecond) l, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) diff --git a/docs/ory_permission_language_spec.md b/docs/ory_permission_language_spec.md index 03ef4942f..99e732a57 100644 --- a/docs/ory_permission_language_spec.md +++ b/docs/ory_permission_language_spec.md @@ -142,6 +142,7 @@ The following character sequences represent boolean operators: | -------- | -------------- | ------------------------------------ | | `&&` | _x_ `&&` _y_ | true iff. both _x_ and _y_ are true | | `\|\|` | _x_ `\|\|` _y_ | true iff. either _x_ or _y_ are true | +| `!` | `!` _x_ | true iff. _x_ is false | The following character sequences represent miscellaneous operators: @@ -248,7 +249,7 @@ geolocation, the time of day, or the security level of the device making the request. ```ebnf -PermissionBody = ( "(" PermissionBody ")" ) | ( PermissionCheck | { Operator PermissionBody } ) . +PermissionBody = ( "(" PermissionBody ")" ) | ( "!" PermissionBody ) | ( PermissionCheck | { Operator PermissionBody } ) . Operator = "||" | "&&" . PermissionCheck = TransitiveCheck | IncludesCheck . ``` diff --git a/embedx/config.schema.json b/embedx/config.schema.json index 184c135fd..8f46f26a3 100644 --- a/embedx/config.schema.json +++ b/embedx/config.schema.json @@ -211,6 +211,13 @@ "title": "Host", "description": "The network interface to listen on." }, + "write_listen_file": { + "type": "string", + "title": "Read Listen File", + "description": "The path to a file that will be created when the read API is ready to accept connections. The content of the file is the host:port of the read API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.", + "format": "uri", + "examples": ["file:///tmp/keto-read-api"] + }, "cors": { "$ref": "#/definitions/cors" }, @@ -239,6 +246,13 @@ "title": "Host", "description": "The network interface to listen on." }, + "write_listen_file": { + "type": "string", + "title": "Write Listen File", + "description": "The path to a file that will be created when the write API is ready to accept connections. The content of the file is the host:port of the write API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.", + "format": "uri", + "examples": ["file:///tmp/keto-write-api"] + }, "cors": { "$ref": "#/definitions/cors" }, @@ -267,6 +281,13 @@ "title": "Host", "description": "The network interface to listen on." }, + "write_listen_file": { + "type": "string", + "title": "Metrics Listen File", + "description": "The path to a file that will be created when the metrics API is ready to accept connections. The content of the file is the host:port of the metrics API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.", + "format": "uri", + "examples": ["file:///tmp/keto-metrics-api"] + }, "cors": { "$ref": "#/definitions/cors" }, @@ -295,6 +316,13 @@ "title": "Host", "description": "The network interface to listen on." }, + "write_listen_file": { + "type": "string", + "title": "OPL Listen File", + "description": "The path to a file that will be created when the OPL API is ready to accept connections. The content of the file is the host:port of the OPL API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.", + "format": "uri", + "examples": ["file:///tmp/keto-opl-api"] + }, "cors": { "$ref": "#/definitions/cors" }, @@ -380,6 +408,22 @@ "description": "The global maximum width on all read operations. Note that this does not affect how deeply nested the tuples can be. This value can be decreased for a request by a value specified on the request, only if the request-specific value is greater than 1 and less than the global maximum width.", "minimum": 1, "maximum": 65535 + }, + "max_batch_check_size": { + "type": "integer", + "default": 10, + "title": "Maximum batch check size", + "description": "The maximum number of tuples that will be accepted by the batch check endpoint.", + "minimum": 1, + "maximum": 65535 + }, + "batch_check_max_parallelization": { + "type": "integer", + "default": 5, + "title": "Max concurrent checks during batch check", + "description": "The limit for the number of tuples that will be checked concurrently during a batch check.", + "minimum": 1, + "maximum": 65535 } }, "additionalProperties": false diff --git a/go.mod b/go.mod index 4081f0953..86b8f2f51 100644 --- a/go.mod +++ b/go.mod @@ -1,88 +1,94 @@ -go 1.21 +go 1.23 + +toolchain go1.23.2 module github.com/ory/keto replace github.com/ory/keto/proto => ./proto +replace github.com/gobuffalo/pop/v6 => github.com/ory/pop/v6 v6.2.1-0.20241121111754-e5dfc0f3344b + require ( connectrpc.com/vanguard v0.3.0 github.com/cenkalti/backoff/v3 v3.2.2 - github.com/dgraph-io/ristretto v0.1.1 + github.com/dgraph-io/ristretto v0.2.0 github.com/ghodss/yaml v1.0.0 - github.com/go-sql-driver/mysql v1.7.1 + github.com/go-sql-driver/mysql v1.8.1 github.com/gobuffalo/httptest v1.5.2 github.com/gobuffalo/pop/v6 v6.1.1 github.com/gofrs/uuid v4.4.0+incompatible - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 + github.com/gogo/status v1.1.1 + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 github.com/julienschmidt/httprouter v1.3.0 github.com/luna-duclos/instrumentedsql v1.1.3 github.com/ory/analytics-go/v5 v5.0.1 github.com/ory/graceful v0.1.3 github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88 github.com/ory/jsonschema/v3 v3.0.8 - github.com/ory/keto/proto v0.11.1-alpha.0 - github.com/ory/x v0.0.614 + github.com/ory/keto/proto v0.13.0-alpha.0 + github.com/ory/x v0.0.662 github.com/pelletier/go-toml v1.9.5 - github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_model v0.5.0 - github.com/prometheus/common v0.44.0 - github.com/rs/cors v1.10.1 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.61.0 + github.com/rs/cors v1.11.1 github.com/segmentio/objconv v1.0.1 github.com/sirupsen/logrus v1.9.3 github.com/soheilhy/cmux v0.1.5 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.4 - github.com/tidwall/gjson v1.17.0 + github.com/stretchr/testify v1.10.0 + github.com/tidwall/gjson v1.18.0 github.com/tidwall/sjson v1.2.5 github.com/urfave/negroni v1.0.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 - go.opentelemetry.io/otel v1.23.1 - go.opentelemetry.io/otel/sdk v1.21.0 - go.opentelemetry.io/otel/trace v1.23.1 - go.uber.org/goleak v1.2.1 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa - golang.org/x/oauth2 v0.21.0 - golang.org/x/sync v0.7.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.0 - google.golang.org/protobuf v1.34.1 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 + go.opentelemetry.io/otel v1.33.0 + go.opentelemetry.io/otel/sdk v1.32.0 + go.opentelemetry.io/otel/trace v1.33.0 + go.uber.org/goleak v1.3.0 + golang.org/x/net v0.33.0 + golang.org/x/oauth2 v0.24.0 + golang.org/x/sync v0.10.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 + google.golang.org/grpc v1.69.2 + google.golang.org/protobuf v1.36.1 ) require ( - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect code.dny.dev/ssrf v0.2.0 // indirect connectrpc.com/connect v1.16.2 // indirect + dario.cat/mergo v1.0.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/avast/retry-go/v4 v4.5.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bradleyjkemp/cupaloy/v2 v2.8.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/cockroach-go/v2 v2.3.5 // indirect - github.com/containerd/continuity v0.4.1 // indirect + github.com/containerd/continuity v0.4.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v20.10.23+incompatible // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v20.10.24+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/cli v26.1.4+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/evanphx/json-patch/v5 v5.7.0 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/swag v0.22.4 // indirect @@ -92,39 +98,40 @@ require ( github.com/gobuffalo/github_flavored_markdown v1.1.4 // indirect github.com/gobuffalo/helpers v0.6.7 // indirect github.com/gobuffalo/nulls v0.4.2 // indirect - github.com/gobuffalo/plush/v4 v4.1.19 // indirect + github.com/gobuffalo/plush/v4 v4.1.21 // indirect github.com/gobuffalo/tags/v3 v3.1.4 // indirect github.com/gobuffalo/validate/v3 v3.3.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-yaml v1.11.2 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/gorilla/css v1.0.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.4 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.1 // indirect + github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.2 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackc/pgproto3/v2 v2.3.3 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.6.0 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jandelgado/gcov2lcov v1.0.6 // indirect - github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/parsers/json v0.1.0 // indirect github.com/knadh/koanf/parsers/toml v0.1.0 // indirect @@ -136,26 +143,28 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.17 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/microcosm-cc/bluemonday v1.0.26 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nyaruka/phonenumbers v1.1.8 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/opencontainers/runc v1.1.12 // indirect - github.com/openzipkin/zipkin-go v0.4.2 // indirect - github.com/ory/dockertest/v3 v3.10.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/runc v1.1.14 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/ory/dockertest/v3 v3.11.0 // indirect github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 // indirect @@ -174,25 +183,26 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.21.0 // indirect - go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 // indirect - go.opentelemetry.io/contrib/samplers/jaegerremote v0.15.1 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.32.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.32.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.23.1 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/tools v0.23.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect gopkg.in/ini.v1 v1.67.0 // 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 0056bf2c8..50b20f85f 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -41,11 +41,13 @@ code.dny.dev/ssrf v0.2.0 h1:wCBP990rQQ1CYfRpW+YK1+8xhwUjv189AQ3WMo1jQaI= code.dny.dev/ssrf v0.2.0/go.mod h1:B+91l25OnyaLIeCx0WRJN5qfJ/4/ZTZxRXgm0lj/2w8= connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= -connectrpc.com/vanguard v0.2.0 h1:78xAoVKvaOeHN8PvDetlRpJQ1OImLh2jDnWPNaT9dPo= -connectrpc.com/vanguard v0.2.0/go.mod h1:EoRa8q5sbNQua+wH5cr9NBePLFaUKIWLAjc1A8rSfDA= connectrpc.com/vanguard v0.3.0 h1:prUKFm8rYDwvpvnOSoqdUowPMK0tRA0pbSrQoMd6Zng= connectrpc.com/vanguard v0.3.0/go.mod h1:nxQ7+N6qhBiQczqGwdTw4oCqx1rDryIt20cEdECqToM= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -53,8 +55,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= @@ -69,10 +71,9 @@ github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oM github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -82,18 +83,13 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.3.5 h1:Khtm8K6fTTz/ZCWPzU9Ne3aOW9VyAnj4qIPCJgKtwK0= github.com/cockroachdb/cockroach-go/v2 v2.3.5/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8= -github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= -github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -101,21 +97,20 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/cli v20.10.23+incompatible h1:qwyha/T3rXk9lfuVcn533cKFc7n/6IzL5GXVAgMVPBg= -github.com/docker/cli v20.10.23+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= -github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= +github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= +github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -124,13 +119,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= @@ -146,11 +140,9 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= @@ -164,20 +156,15 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/attrs v1.0.3/go.mod h1:KvDJCE0avbufqS0Bw3UV7RQynESY0jjod+572ctX4t8= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/gobuffalo/envy v1.10.2 h1:EIi03p9c3yeuRCFPOKcSfajzkLb3hrRjEpHGI8I2Wo4= github.com/gobuffalo/envy v1.10.2/go.mod h1:qGAGwdvDsaEtPhfBzb3o0SfDea8ByGn9j8bKmVft9z8= github.com/gobuffalo/fizz v1.14.4 h1:8uume7joF6niTNWN582IQ2jhGTUoa9g1fiV/tIoGdBs= github.com/gobuffalo/fizz v1.14.4/go.mod h1:9/2fGNXNeIFOXEEgTPJwiK63e44RjG+Nc4hfMm1ArGM= github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= -github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8XTTlHPQc= github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= -github.com/gobuffalo/genny/v2 v2.1.0/go.mod h1:4yoTNk4bYuP3BMM6uQKYPvtP6WsXFGm2w2EFYZdRls8= github.com/gobuffalo/github_flavored_markdown v1.1.3/go.mod h1:IzgO5xS6hqkDmUh91BW/+Qxo/qYnvfzoz3A7uLkg77I= github.com/gobuffalo/github_flavored_markdown v1.1.4 h1:WacrEGPXUDX+BpU1GM/Y0ADgMzESKNWls9hOTG1MHVs= github.com/gobuffalo/github_flavored_markdown v1.1.4/go.mod h1:Vl9686qrVVQou4GrHRK/KOG3jCZOKLUqV8MMOAYtlso= @@ -187,16 +174,11 @@ github.com/gobuffalo/here v0.6.7 h1:hpfhh+kt2y9JLDfhYUxxCRxQol540jsVfKUZzjlbp8o= github.com/gobuffalo/here v0.6.7/go.mod h1:vuCfanjqckTuRlqAitJz6QC4ABNnS27wLb816UhsPcc= github.com/gobuffalo/httptest v1.5.2 h1:GpGy520SfY1QEmyPvaqmznTpG4gEQqQ82HtHqyNEreM= github.com/gobuffalo/httptest v1.5.2/go.mod h1:FA23yjsWLGj92mVV74Qtc8eqluc11VqcWr8/C1vxt4g= -github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= github.com/gobuffalo/nulls v0.4.2 h1:GAqBR29R3oPY+WCC7JL9KKk9erchaNuV6unsOSZGQkw= github.com/gobuffalo/nulls v0.4.2/go.mod h1:EElw2zmBYafU2R9W4Ii1ByIj177wA/pc0JdjtD0EsH8= -github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= github.com/gobuffalo/plush/v4 v4.1.16/go.mod h1:6t7swVsarJ8qSLw1qyAH/KbrcSTwdun2ASEQkOznakg= -github.com/gobuffalo/plush/v4 v4.1.18/go.mod h1:xi2tJIhFI4UdzIL8sxZtzGYOd2xbBpcFbLZlIPGGZhU= -github.com/gobuffalo/plush/v4 v4.1.19 h1:o0E5gEJw+ozkAwQoCeiaWC6VOU2lEmX+GhtGkwpqZ8o= -github.com/gobuffalo/plush/v4 v4.1.19/go.mod h1:WiKHJx3qBvfaDVlrv8zT7NCd3dEMaVR/fVxW4wqV17M= -github.com/gobuffalo/pop/v6 v6.1.1 h1:eUDBaZcb0gYrmFnKwpuTEUA7t5ZHqNfvS4POqJYXDZY= -github.com/gobuffalo/pop/v6 v6.1.1/go.mod h1:1n7jAmI1i7fxuXPZjZb0VBPQDbksRtCoFnrDV5IsvaI= +github.com/gobuffalo/plush/v4 v4.1.21 h1:YVfauGshxyQ+beh4jHR6Ct3NEXohn+1EboMjzdUDo30= +github.com/gobuffalo/plush/v4 v4.1.21/go.mod h1:WiKHJx3qBvfaDVlrv8zT7NCd3dEMaVR/fVxW4wqV17M= github.com/gobuffalo/tags/v3 v3.1.4 h1:X/ydLLPhgXV4h04Hp2xlbI2oc5MDaa7eub6zw8oHjsM= github.com/gobuffalo/tags/v3 v3.1.4/go.mod h1:ArRNo3ErlHO8BtdA0REaZxijuWnWzF6PUXngmMXd2I0= github.com/gobuffalo/validate/v3 v3.3.3 h1:o7wkIGSvZBYBd6ChQoLxkz2y1pfmhbI4jNJYh6PuNJ4= @@ -207,16 +189,16 @@ github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ= github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a h1:dR8+Q0uO5S2ZBcs2IH6VBKYwSxPo2vYCYq0ot0mu7xA= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= +github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -241,9 +223,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -255,7 +236,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -278,30 +258,32 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 h1:kQ0NI7W1B3HwiN5gAYtY+XFItDPbLBwYRxAqbFTyDes= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0/go.mod h1:zrT2dxOAjNFPRGjTUe2Xmb4q4YdUwVvQFV6xiCSf+z0= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -309,70 +291,38 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= -github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= -github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4= -github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= -github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= +github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= -github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= -github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= +github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jandelgado/gcov2lcov v1.0.6 h1:9ra0LlI1P3zTUC5LgeT48hhDeAAQEZicxPGkJfRjB4s= github.com/jandelgado/gcov2lcov v1.0.6/go.mod h1:zO6+Sxfj8LomaOUzsobA5IrA12/TcWxOgrjl9w/EKno= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -386,6 +336,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/parsers/json v0.1.0 h1:dzSZl5pf5bBcW0Acnu20Djleto19T0CfHcvZ14NJ6fU= @@ -400,27 +352,22 @@ github.com/knadh/koanf/providers/rawbytes v0.1.0 h1:dpzgu2KO6uf6oCb4aP05KDmKmAmI github.com/knadh/koanf/providers/rawbytes v0.1.0/go.mod h1:mMTB1/IcJ/yE++A2iEZbY1MLygX7vttU+C+S/YmPu9c= github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/laher/mergefs v0.1.1 h1:nV2bTS57vrmbMxeR6uvJpI8LyGl3QHj4bLBZO3aUV58= github.com/laher/mergefs v0.1.1/go.mod h1:FSY1hYy94on4Tz60waRMGdO1awwS23BacqJlqf9lJ9Q= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/luna-duclos/instrumentedsql v1.1.3 h1:t7mvC0z1jUt5A0UQ6I/0H31ryymuQRnJcWCiqV3lSAA= @@ -431,25 +378,15 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno= github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/microcosm-cc/bluemonday v1.0.22/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= @@ -460,26 +397,30 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nyaruka/phonenumbers v1.1.8 h1:mjFu85FeoH2Wy18aOMUvxqi1GgAqiQSJsa/cCC5yu2s= github.com/nyaruka/phonenumbers v1.1.8/go.mod h1:DC7jZd321FqUe+qWSNcHi10tyIyGNXGcNbfkPvdp1Vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= -github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA= -github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= +github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/ory/analytics-go/v5 v5.0.1 h1:LX8T5B9FN8KZXOtxgN+R3I4THRRVB6+28IKgKBpXmAM= github.com/ory/analytics-go/v5 v5.0.1/go.mod h1:lWCiCjAaJkKfgR/BN5DCLMol8BjKS1x+4jxBxff/FF0= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= +github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNGuyA= +github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI= github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe h1:rvu4obdvqR0fkSIJ8IfgzKOWwZ5kOT2UNfLq81Qk7rc= github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe/go.mod h1:z4n3u6as84LbV4YmgjHhnwtccQqzf4cZlSk9f1FhygI= github.com/ory/graceful v0.1.3 h1:FaeXcHZh168WzS+bqruqWEw/HgXWLdNv2nJ+fbhxbhc= @@ -488,8 +429,10 @@ github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88 h1:J0CIFKdpUeqKbVMw github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88/go.mod h1:MMNmY6MG1uB6fnXYFaHoqdV23DTWctlPsmRCeq/2+wc= github.com/ory/jsonschema/v3 v3.0.8 h1:Ssdb3eJ4lDZ/+XnGkvQS/te0p+EkolqwTsDOCxr/FmU= github.com/ory/jsonschema/v3 v3.0.8/go.mod h1:ZPzqjDkwd3QTnb2Z6PAS+OTvBE2x5i6m25wCGx54W/0= -github.com/ory/x v0.0.614 h1:amqUBxoY5Z0fN+WqH1sLLtGuJa5GYOBo76LyrwJC0dc= -github.com/ory/x v0.0.614/go.mod h1:uH065puz8neija0neqwIN3PmXXfDsB9VbZTZ20Znoos= +github.com/ory/pop/v6 v6.2.1-0.20241121111754-e5dfc0f3344b h1:BIzoOe2/wynZBQak1po0tzgvARseIKsR2bF6b+SZoKE= +github.com/ory/pop/v6 v6.2.1-0.20241121111754-e5dfc0f3344b/go.mod h1:okVAYKGtgunD/wbW3NGhZTndJCS+6FqO+cA89rQ4doc= +github.com/ory/x v0.0.662 h1:Qah5/f63Kr33Wcqm1S79adcYHaoWeiCDMQiDLuUXBqU= +github.com/ory/x v0.0.662/go.mod h1:tS0FyZXpVeKd1lCcFgV/Rb1GlccI/Xq8DraFS+lmIt8= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -497,7 +440,6 @@ github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= @@ -506,31 +448,27 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= +github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 h1:0b8DF5kR0PhRoRXDiEEdzrgBc8UqVY4JWLkQJCRsLME= github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761/go.mod h1:/THDZYi7F/BsVEcYzYPqdcWFQ+1C2InkawTKfLOAnzg= github.com/segmentio/analytics-go v3.1.0+incompatible/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48= @@ -544,12 +482,6 @@ github.com/segmentio/objconv v1.0.1/go.mod h1:auayaH5k3137Cl4SoXTgrzQcuQDmvuVtZg github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= @@ -564,20 +496,18 @@ github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= 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/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -586,13 +516,14 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= -github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -616,74 +547,60 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 h1:gbhw/u49SS3gkPWiYweQNJGm/uJN5GkI/FrosxSHT7A= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1/go.mod h1:GnOaBaFQ2we3b9AGWJpsBa7v1S5RlQzlC3O7dRMxZhM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/contrib/propagators/b3 v1.21.0 h1:uGdgDPNzwQWRwCXJgw/7h29JaRqcq9B87Iv4hJDKAZw= -go.opentelemetry.io/contrib/propagators/b3 v1.21.0/go.mod h1:D9GQXvVGT2pzyTfp1QBOnD1rzKEWzKjjwu5q2mslCUI= -go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 h1:f4beMGDKiVzg9IcX7/VuWVy+oGdjx3dNJ72YehmtY5k= -go.opentelemetry.io/contrib/propagators/jaeger v1.21.1/go.mod h1:U9jhkEl8d1LL+QXY7q3kneJWJugiN3kZJV2OWz3hkBY= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.15.1 h1:Qb+5A+JbIjXwO7l4HkRUhgIn4Bzz0GNS2q+qdmSx+0c= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.15.1/go.mod h1:G4vNCm7fRk0kjZ6pGNLo5SpLxAUvOfSrcaegnT8TPck= -go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= -go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0 h1:7F3XCD6WYzDkwbi8I8N+oYJWquPVScnRosKGgqjsR8c= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0/go.mod h1:Dk3C0BfIlZDZ5c6eVS7TYiH2vssuyUU3vUsgbrR+5V4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94= +go.opentelemetry.io/contrib/propagators/b3 v1.32.0 h1:MazJBz2Zf6HTN/nK/s3Ru1qme+VhWU5hm83QxEP+dvw= +go.opentelemetry.io/contrib/propagators/b3 v1.32.0/go.mod h1:B0s70QHYPrJwPOwD1o3V/R8vETNOG9N3qZf4LDYvA30= +go.opentelemetry.io/contrib/propagators/jaeger v1.32.0 h1:K/fOyTMD6GELKTIJBaJ9k3ppF2Njt8MeUGBOwfaWXXA= +go.opentelemetry.io/contrib/propagators/jaeger v1.32.0/go.mod h1:ISE6hda//MTWvtngG7p4et3OCngsrTVfl7c6DjN17f8= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0 h1:/SKXyZLAnuj981HVc8G5ZylYK3qD2W6AYR6cJx5kIHw= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0/go.mod h1:cOEzME0M2OKeHB45lJiOKfvUCdg/r75mf7YS5w0tbmE= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/exporters/zipkin v1.21.0 h1:D+Gv6lSfrFBWmQYyxKjDd0Zuld9SRXpIrEsKZvE4DO4= -go.opentelemetry.io/otel/exporters/zipkin v1.21.0/go.mod h1:83oMKR6DzmHisFOW3I+yIMGZUTjxiWaiBI8M8+TU5zE= -go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= -go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= -go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= +go.opentelemetry.io/otel/exporters/zipkin v1.32.0 h1:6O8HgLHPXtXE9QEKEWkBImL9mEKCGEl+m+OncVO53go= +go.opentelemetry.io/otel/exporters/zipkin v1.32.0/go.mod h1:+MFvorlowjy0iWnsKaNxC1kzczSxe71mw85h4p8yEvg= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -694,8 +611,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -720,8 +637,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -734,7 +651,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -759,10 +675,9 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -772,8 +687,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -786,30 +701,22 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -833,7 +740,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -841,15 +747,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -860,8 +763,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,18 +777,14 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -893,7 +792,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -922,10 +820,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= 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= @@ -958,6 +854,7 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -994,10 +891,11 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1014,8 +912,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= +google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/grpc/examples v0.0.0-20210304020650-930c79186c99 h1:qA8rMbz1wQ4DOFfM2ouD29DG9aHWBm6ZOy9BGxiUMmY= google.golang.org/grpc/examples v0.0.0-20210304020650-930c79186c99/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1028,10 +926,10 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1040,7 +938,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/mold.v2 v2.2.0/go.mod h1:XMyyRsGtakkDPbxXbrA5VODo6bUXyvoDjLd5l3T0XoA= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/validator.v2 v2.0.0-20180514200540-135c24b11c19/go.mod h1:o4V0GXN9/CAmCsvJ0oXYZvrZOe7syiDZSN1GWGZTGzc= @@ -1052,8 +949,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= -gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/check/checkgroup/membership_string.go b/internal/check/checkgroup/membership_string.go index e6c36bc9b..a5670b365 100644 --- a/internal/check/checkgroup/membership_string.go +++ b/internal/check/checkgroup/membership_string.go @@ -1,6 +1,3 @@ -// Copyright © 2023 Ory Corp -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "stringer -type Membership"; DO NOT EDIT. package checkgroup diff --git a/internal/check/engine.go b/internal/check/engine.go index 8eea393bb..31508b693 100644 --- a/internal/check/engine.go +++ b/internal/check/engine.go @@ -6,11 +6,11 @@ package check import ( "context" - "github.com/pkg/errors" - "go.opentelemetry.io/otel/trace" - "github.com/ory/herodot" "github.com/ory/x/otelx" + "github.com/pkg/errors" + "go.opentelemetry.io/otel/trace" + "golang.org/x/sync/errgroup" "github.com/ory/keto/x/events" @@ -34,6 +34,7 @@ type ( } EngineDependencies interface { relationtuple.ManagerProvider + relationtuple.MapperProvider persistence.Provider config.Provider x.LoggerProvider @@ -264,3 +265,38 @@ func (e *Engine) astRelationFor(ctx context.Context, r *relationTuple) (*ast.Rel } return namespace.ASTRelationFor(ctx, namespaceManager, r.Namespace, r.Relation) } + +// BatchCheck makes parallelized check requests for tuples. The check results are returned as slice, where the +// result index matches the tuple index of the incoming tuples array. +func (e *Engine) BatchCheck(ctx context.Context, + tuples []*ketoapi.RelationTuple, + maxDepth int) ([]checkgroup.Result, error) { + + eg := &errgroup.Group{} + eg.SetLimit(e.d.Config(ctx).BatchCheckParallelizationLimit()) + + mapper := e.d.ReadOnlyMapper() + results := make([]checkgroup.Result, len(tuples)) + for i, tuple := range tuples { + i := i + tuple := tuple + eg.Go(func() error { + internalTuple, err := mapper.FromTuple(ctx, tuple) + if err != nil { + results[i] = checkgroup.Result{ + Membership: checkgroup.MembershipUnknown, + Err: err, + } + } else { + results[i] = e.CheckRelationTuple(ctx, internalTuple[0], maxDepth) + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return nil, err + } + + return results, nil +} diff --git a/internal/check/engine_test.go b/internal/check/engine_test.go index 14cf83404..f430f23b4 100644 --- a/internal/check/engine_test.go +++ b/internal/check/engine_test.go @@ -8,10 +8,13 @@ import ( "testing" "github.com/gofrs/uuid" + "github.com/ory/herodot" + "github.com/ory/x/pointerx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ory/keto/internal/check" + "github.com/ory/keto/internal/check/checkgroup" "github.com/ory/keto/internal/driver" "github.com/ory/keto/internal/driver/config" "github.com/ory/keto/internal/namespace" @@ -27,6 +30,7 @@ type configProvider = config.Provider // deps are defined to capture engine dependencies in a single struct type deps struct { *relationtuple.ManagerWrapper // managerProvider + relationtuple.MapperProvider persistence.Provider configProvider x.LoggerProvider @@ -41,6 +45,7 @@ func newDepsProvider(t testing.TB, namespaces []*namespace.Namespace, pageOpts . return &deps{ ManagerWrapper: mr, + MapperProvider: reg, Provider: reg, configProvider: reg, LoggerProvider: reg, @@ -576,4 +581,104 @@ func TestEngine(t *testing.T) { assert.True(t, res) } }) + + t.Run("case=batch check", func(t *testing.T) { + reg := newDepsProvider(t, []*namespace.Namespace{ + {Name: "test"}, + }) + + relationtuple.MapAndWriteTuples(t, reg, &ketoapi.RelationTuple{ + Namespace: "test", + Object: "object", + Relation: "admin", + SubjectID: pointerx.Ptr("user"), + }, + &ketoapi.RelationTuple{ + Namespace: "test", + Object: "object", + Relation: "owner", + SubjectSet: &ketoapi.SubjectSet{ + Namespace: "test", + Object: "object", + Relation: "admin", + }, + }, + &ketoapi.RelationTuple{ + Namespace: "test", + Object: "object", + Relation: "access", + SubjectSet: &ketoapi.SubjectSet{ + Namespace: "test", + Object: "object", + Relation: "owner", + }, + }) + + e := check.NewEngine(reg) + + targetTuples := []*ketoapi.RelationTuple{ + { // direct relation + Namespace: "test", + Object: "object", + Relation: "admin", + SubjectID: pointerx.Ptr("user"), + }, + { // indirect relation + Namespace: "test", + Object: "object", + Relation: "owner", + SubjectID: pointerx.Ptr("user"), + }, + { // indirect relation, greater than max depth + Namespace: "test", + Object: "object", + Relation: "access", + SubjectID: pointerx.Ptr("user"), + }, + { // non-existent namespace + Namespace: "test2", + Object: "object", + Relation: "admin", + SubjectID: pointerx.Ptr("user"), + }, + { // unknown subject + Namespace: "test", + Object: "object", + Relation: "admin", + SubjectID: pointerx.Ptr("user2"), + }, + { // relation via subject set + Namespace: "test", + Object: "object", + Relation: "access", + SubjectSet: &ketoapi.SubjectSet{ + Namespace: "test", + Object: "object", + Relation: "owner", + }, + }, + } + + // Batch check with low max depth + results, err := e.BatchCheck(ctx, targetTuples, 2) + require.NoError(t, err) + + require.Equal(t, checkgroup.IsMember, results[0].Membership) + require.NoError(t, results[0].Err) + require.Equal(t, checkgroup.IsMember, results[1].Membership) + require.NoError(t, results[1].Err) + require.Equal(t, checkgroup.NotMember, results[2].Membership) + require.NoError(t, results[2].Err) + require.Equal(t, checkgroup.MembershipUnknown, results[3].Membership) + require.EqualError(t, results[3].Err, herodot.ErrNotFound.Error()) + require.Equal(t, checkgroup.NotMember, results[4].Membership) + require.NoError(t, results[4].Err) + require.Equal(t, checkgroup.IsMember, results[5].Membership) + require.NoError(t, results[5].Err) + + // Check with higher max depth and verify the third tuple is now shown as a member + results, err = e.BatchCheck(ctx, targetTuples, 3) + require.NoError(t, err) + require.Equal(t, checkgroup.IsMember, results[2].Membership) + }) } diff --git a/internal/check/handler.go b/internal/check/handler.go index 5e5069f38..98bfab1a8 100644 --- a/internal/check/handler.go +++ b/internal/check/handler.go @@ -7,16 +7,19 @@ import ( "context" "net/http" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/gogo/status" "github.com/pkg/errors" "github.com/ory/herodot" + "github.com/ory/keto/internal/check/checkgroup" + "github.com/ory/keto/internal/driver/config" "github.com/ory/keto/internal/x/api" "github.com/ory/keto/ketoapi" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "github.com/ory/keto/internal/relationtuple" "github.com/ory/keto/internal/x" @@ -30,6 +33,7 @@ type ( relationtuple.MapperProvider x.LoggerProvider x.WriterProvider + config.Provider } Handler struct { d handlerDependencies @@ -47,19 +51,13 @@ func NewHandler(d handlerDependencies) *Handler { const ( RouteBase = "/relation-tuples/check" OpenAPIRouteBase = RouteBase + "/openapi" + BatchRoute = "/relation-tuples/batch/check" ) func (h *Handler) RegisterReadGRPC(s *grpc.Server) { rts.RegisterCheckServiceServer(s, h) } -func (h *Handler) RegisterReadGRPCGateway(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts ...grpc.DialOption) error { - return rts.RegisterCheckServiceHandlerFromEndpoint(ctx, mux, endpoint, opts) -} -func (h *Handler) RegisterReadGRPCGatewayConn(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return rts.RegisterCheckServiceHandler(ctx, mux, conn) -} - func (h *Handler) Check(ctx context.Context, req *rts.CheckRequest) (res *rts.CheckResponse, err error) { tuple := (&ketoapi.RelationTuple{}).FromCheckRequest(req) @@ -93,3 +91,45 @@ func (h *Handler) Check(ctx context.Context, req *rts.CheckRequest) (res *rts.Ch res = &rts.CheckResponse{Allowed: allowed} return res, nil } + +// BatchCheck is the gRPC entry point for checking batches of tuples +func (h *Handler) BatchCheck(ctx context.Context, req *rts.BatchCheckRequest) (*rts.BatchCheckResponse, error) { + // Handle the case where the tuples are passed in the request body. + if req.RestBody != nil { + if req.Tuples != nil { + return nil, status.Error(codes.InvalidArgument, "either tuples or rest_body should be set, not both") + } + req.Tuples = req.RestBody.Tuples + } + + if len(req.Tuples) > h.d.Config(ctx).BatchCheckMaxBatchSize() { + return nil, status.Errorf(codes.InvalidArgument, + "batch exceeds max size of %v", h.d.Config(ctx).BatchCheckMaxBatchSize()) + } + + ketoTuples := make([]*ketoapi.RelationTuple, len(req.Tuples)) + for i, tuple := range req.Tuples { + ketoTuples[i] = (&ketoapi.RelationTuple{}).FromProto(tuple) + } + + results, err := h.d.PermissionEngine().BatchCheck(ctx, ketoTuples, int(req.MaxDepth)) + if err != nil { + return nil, err + } + + responses := make([]*rts.CheckResponseWithError, len(results)) + for i, result := range results { + errMsg := "" + if result.Err != nil { + errMsg = result.Err.Error() + } + responses[i] = &rts.CheckResponseWithError{ + Allowed: result.Membership == checkgroup.IsMember, + Error: errMsg, + } + } + + return &rts.BatchCheckResponse{ + Results: responses, + }, nil +} diff --git a/internal/check/handler_test.go b/internal/check/handler_test.go index 2696e1910..70eab1eaf 100644 --- a/internal/check/handler_test.go +++ b/internal/check/handler_test.go @@ -4,16 +4,29 @@ package check_test import ( + "bytes" "context" + "encoding/json" + "fmt" "io" + "net" "net/http" "net/url" "strings" "testing" + "github.com/gogo/status" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/test/bufconn" + "github.com/ory/x/pointerx" + rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" + "github.com/ory/keto/internal/driver/config" + client "github.com/ory/keto/internal/httpclient" "github.com/ory/keto/internal/relationtuple" "github.com/ory/keto/internal/x/api" "github.com/ory/keto/ketoapi" @@ -157,3 +170,246 @@ func TestRESTHandler(t *testing.T) { }) } } + +func TestBatchCheckRESTHandler(t *testing.T) { + nspaces := []*namespace.Namespace{{ + Name: "batch-check-handler", + }} + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + reg := driver.NewSqliteTestRegistry(t, false) + require.NoError(t, reg.Config(ctx).Set(config.KeyNamespaces, nspaces)) + + endpoints := api.NewTestServer(t, check.NewHandler(reg)) + ts := endpoints.HTTP + + t.Run("case=returns bad request on non-int max depth", func(t *testing.T) { + resp, err := ts.Client().Post(ts.URL+check.BatchRoute+"?max-depth=foo", + "application/json", nil) + require.NoError(t, err) + + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.Contains(t, string(body), "invalid parameter \\\"max_depth\\\"") + }) + + t.Run("case=returns bad request on invalid request body", func(t *testing.T) { + resp, err := ts.Client().Post(buildBatchURL(ts.URL, "5"), + "application/json", strings.NewReader("not-json")) + require.NoError(t, err) + + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.Contains(t, string(body), "invalid value not-json") + }) + + t.Run("case=returns bad request with too many tuples", func(t *testing.T) { + tuples := make([]client.Relationship, 11) + for i := 0; i < len(tuples); i++ { + tuples[i] = client.Relationship{ + Namespace: "n", + Object: "o", + Relation: "r", + SubjectId: pointerx.Ptr("s"), + } + } + reqBody := client.BatchCheckPermissionBody{Tuples: tuples} + bodyBytes, err := json.Marshal(reqBody) + require.NoError(t, err) + + resp, err := ts.Client().Post(buildBatchURL(ts.URL, "5"), + "application/json", bytes.NewReader(bodyBytes)) + require.NoError(t, err) + + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.Contains(t, string(body), "batch exceeds max size of 10") + }) + + t.Run("case=check tuples", func(t *testing.T) { + rt := &ketoapi.RelationTuple{ + Namespace: nspaces[0].Name, + Object: "o", + Relation: "r", + SubjectID: pointerx.Ptr("s"), + } + relationtuple.MapAndWriteTuples(t, reg, rt) + + reqBody := client.BatchCheckPermissionBody{Tuples: []client.Relationship{ + { // Allowed + Namespace: nspaces[0].Name, + Object: "o", + Relation: "r", + SubjectId: pointerx.Ptr("s"), + }, + { // Not-allowed + Namespace: nspaces[0].Name, + Object: "o2", + Relation: "r", + SubjectId: pointerx.Ptr("s"), + }, + { // Unknown namespace + Namespace: "n2", + Object: "o", + Relation: "r", + SubjectId: pointerx.Ptr("s"), + }, + }} + bodyBytes, err := json.Marshal(reqBody) + require.NoError(t, err) + + resp, err := ts.Client().Post(buildBatchURL(ts.URL, "5"), + "application/json", bytes.NewReader(bodyBytes)) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + var respBody client.BatchCheckPermissionResult + require.NoError(t, json.Unmarshal(body, &respBody)) + require.Equal(t, respBody, client.BatchCheckPermissionResult{ + Results: []client.CheckPermissionResultWithError{ + { + Allowed: true, + Error: pointerx.Ptr(""), + }, + { + Allowed: false, + Error: pointerx.Ptr(""), + }, + { + Allowed: false, + Error: pointerx.Ptr("The requested resource could not be found"), + }, + }, + }) + + // Check again with the default parallelization factor + resp, err = ts.Client().Post(fmt.Sprintf("%s%s?max-depth=%v", ts.URL, check.BatchRoute, 5), + "application/json", bytes.NewReader(bodyBytes)) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + body, err = io.ReadAll(resp.Body) + require.NoError(t, err) + var defaultParallelizationRespBody client.BatchCheckPermissionResult + require.NoError(t, json.Unmarshal(body, &defaultParallelizationRespBody)) + require.Equal(t, respBody, defaultParallelizationRespBody) + }) +} + +func buildBatchURL(baseURL, maxDepth string) string { + return fmt.Sprintf("%s%s?max-depth=%s", + baseURL, check.BatchRoute, maxDepth) +} + +func TestBatchCheckGRPCHandler(t *testing.T) { + ctx := context.Background() + + reg := driver.NewSqliteTestRegistry(t, false) + h := check.NewHandler(reg) + + l := bufconn.Listen(1024 * 1024) + s := grpc.NewServer() + h.RegisterReadGRPC(s) + go func() { + if err := s.Serve(l); err != nil { + t.Logf("Server exited with error: %v", err) + } + }() + t.Cleanup(s.Stop) + + conn, err := grpc.Dial("bufnet", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return l.Dial() }), + ) + require.NoError(t, err) + t.Cleanup(func() { conn.Close() }) + + nspaces := []*namespace.Namespace{{ + Name: "batch-check-grpc", + }} + require.NoError(t, reg.Config(ctx).Set(config.KeyNamespaces, nspaces)) + + checkClient := rts.NewCheckServiceClient(conn) + + t.Run("case=returns bad request when batch too large", func(t *testing.T) { + tuples := make([]*rts.RelationTuple, 11) + for i := 0; i < len(tuples); i++ { + tuples[i] = &rts.RelationTuple{ + Namespace: "n", + Object: "o", + Relation: "r", + Subject: &rts.Subject{ + Ref: &rts.Subject_Id{ + Id: "s", + }, + }, + } + } + _, err := checkClient.BatchCheck(ctx, &rts.BatchCheckRequest{ + Tuples: tuples, + MaxDepth: 5, + }) + statusErr, ok := status.FromError(err) + require.True(t, ok) + require.Equal(t, codes.InvalidArgument, statusErr.Code()) + require.Equal(t, "batch exceeds max size of 10", statusErr.Message()) + }) + + t.Run("case=batch check", func(t *testing.T) { + rt := &ketoapi.RelationTuple{ + Namespace: nspaces[0].Name, + Object: "o", + Relation: "r", + SubjectID: pointerx.Ptr("s"), + } + relationtuple.MapAndWriteTuples(t, reg, rt) + + resp, err := checkClient.BatchCheck(ctx, &rts.BatchCheckRequest{ + Tuples: []*rts.RelationTuple{ + { // Allowed + Namespace: nspaces[0].Name, + Object: "o", + Relation: "r", + Subject: &rts.Subject{ + Ref: &rts.Subject_Id{ + Id: "s", + }, + }, + }, + { // Unknown namespace + Namespace: "n2", + Object: "o", + Relation: "r", + Subject: &rts.Subject{ + Ref: &rts.Subject_Id{ + Id: "s", + }, + }, + }, + { // Not allowed + Namespace: nspaces[0].Name, + Object: "o2", + Relation: "r", + Subject: &rts.Subject{ + Ref: &rts.Subject_Id{ + Id: "s", + }, + }, + }, + }, + MaxDepth: 5, + }) + require.NoError(t, err) + require.Len(t, resp.Results, 3) + require.True(t, resp.Results[0].Allowed) + require.Empty(t, resp.Results[0].Error) + require.False(t, resp.Results[1].Allowed) + require.Equal(t, resp.Results[1].Error, "The requested resource could not be found") + require.False(t, resp.Results[2].Allowed) + require.Empty(t, resp.Results[2].Error) + }) +} diff --git a/internal/driver/config/opl_config_namespace_watcher.go b/internal/driver/config/opl_config_namespace_watcher.go index bca9086a7..5c4b10bc6 100644 --- a/internal/driver/config/opl_config_namespace_watcher.go +++ b/internal/driver/config/opl_config_namespace_watcher.go @@ -12,10 +12,11 @@ import ( "time" "github.com/dgraph-io/ristretto" + "github.com/pkg/errors" + "github.com/ory/x/logrusx" "github.com/ory/x/urlx" "github.com/ory/x/watcherx" - "github.com/pkg/errors" "github.com/ory/keto/internal/namespace" "github.com/ory/keto/internal/schema" diff --git a/internal/driver/config/provider.go b/internal/driver/config/provider.go index f32aae858..ab3be17e4 100644 --- a/internal/driver/config/provider.go +++ b/internal/driver/config/provider.go @@ -40,14 +40,21 @@ const ( KeyLimitMaxReadDepth = "limit.max_read_depth" KeyLimitMaxReadWidth = "limit.max_read_width" - KeyReadAPIHost = "serve." + string(EndpointRead) + ".host" - KeyReadAPIPort = "serve." + string(EndpointRead) + ".port" - KeyWriteAPIHost = "serve." + string(EndpointWrite) + ".host" - KeyWriteAPIPort = "serve." + string(EndpointWrite) + ".port" - KeyOPLSyntaxAPIHost = "serve." + string(EndpointOPLSyntax) + ".host" - KeyOPLSyntaxAPIPort = "serve." + string(EndpointOPLSyntax) + ".port" - KeyMetricsHost = "serve." + string(EndpointMetrics) + ".host" - KeyMetricsPort = "serve." + string(EndpointMetrics) + ".port" + KeyBatchCheckMaxBatchSize = "limit.max_batch_check_size" + KeyBatchCheckParallelizationLimit = "limit.batch_check_max_parallelization" + + KeyReadAPIHost = "serve." + string(EndpointRead) + ".host" + KeyReadAPIPort = "serve." + string(EndpointRead) + ".port" + KeyReadAPIListenFile = "serve." + string(EndpointRead) + ".write_listen_file" + KeyWriteAPIHost = "serve." + string(EndpointWrite) + ".host" + KeyWriteAPIPort = "serve." + string(EndpointWrite) + ".port" + KeyWriteAPIListenFile = "serve." + string(EndpointWrite) + ".write_listen_file" + KeyOPLSyntaxAPIHost = "serve." + string(EndpointOPLSyntax) + ".host" + KeyOPLSyntaxAPIPort = "serve." + string(EndpointOPLSyntax) + ".port" + KeyOPLSyntaxListenFile = "serve." + string(EndpointOPLSyntax) + ".write_listen_file" + KeyMetricsHost = "serve." + string(EndpointMetrics) + ".host" + KeyMetricsPort = "serve." + string(EndpointMetrics) + ".port" + KeyMetricsListenFile = "serve." + string(EndpointMetrics) + ".write_listen_file" KeyNamespaces = "namespaces" KeyNamespacesExperimentalStrictMode = KeyNamespaces + ".experimental_strict_mode" @@ -164,18 +171,26 @@ func (k *Config) Set(key string, v any) error { return nil } -func (k *Config) addressFor(endpoint EndpointType) string { +func (k *Config) addressFor(endpoint EndpointType) (addr string, listenFile string) { return fmt.Sprintf( "%s:%d", k.p.StringF("serve."+string(endpoint)+".host", ""), k.p.IntF("serve."+string(endpoint)+".port", 0), - ) + ), k.p.StringF("serve."+string(endpoint)+".write_listen_file", "") } -func (k *Config) ReadAPIListenOn() string { return k.addressFor(EndpointRead) } -func (k *Config) WriteAPIListenOn() string { return k.addressFor(EndpointWrite) } -func (k *Config) MetricsListenOn() string { return k.addressFor(EndpointMetrics) } -func (k *Config) OPLSyntaxAPIListenOn() string { return k.addressFor(EndpointOPLSyntax) } +func (k *Config) ReadAPIListenOn() (addr string, listenFile string) { + return k.addressFor(EndpointRead) +} +func (k *Config) WriteAPIListenOn() (addr string, listenFile string) { + return k.addressFor(EndpointWrite) +} +func (k *Config) MetricsListenOn() (addr string, listenFile string) { + return k.addressFor(EndpointMetrics) +} +func (k *Config) OPLSyntaxAPIListenOn() (addr string, listenFile string) { + return k.addressFor(EndpointOPLSyntax) +} func (k *Config) MaxReadDepth() int { return k.p.Int(KeyLimitMaxReadDepth) @@ -184,6 +199,14 @@ func (k *Config) MaxReadWidth() int { return k.p.Int(KeyLimitMaxReadWidth) } +func (k *Config) BatchCheckMaxBatchSize() int { + return k.p.Int(KeyBatchCheckMaxBatchSize) +} + +func (k *Config) BatchCheckParallelizationLimit() int { + return k.p.Int(KeyBatchCheckParallelizationLimit) +} + func (k *Config) CORS(iface string) (cors.Options, bool) { switch iface { case "read", "write", "metrics": diff --git a/internal/driver/config/provider_test.go b/internal/driver/config/provider_test.go index 2628b2749..ffba74a55 100644 --- a/internal/driver/config/provider_test.go +++ b/internal/driver/config/provider_test.go @@ -283,5 +283,7 @@ func TestProvider_DefaultReadAPIListenOn(t *testing.T) { ) require.NoError(t, err) - assert.Equal(t, ":4466", config.ReadAPIListenOn()) + addr, listenFile := config.ReadAPIListenOn() + assert.Equal(t, ":4466", addr) + assert.Zero(t, listenFile) } diff --git a/internal/driver/daemon.go b/internal/driver/daemon.go index 17d96561d..71bce7911 100644 --- a/internal/driver/daemon.go +++ b/internal/driver/daemon.go @@ -7,7 +7,9 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" + "net" "net/http" "os" "os/signal" @@ -46,8 +48,6 @@ import ( prometheus "github.com/ory/x/prometheusx" "github.com/ory/x/reqlog" - "github.com/ory/keto/internal/x/api" - "github.com/ory/keto/internal/check" "github.com/ory/keto/internal/driver/config" "github.com/ory/keto/internal/expand" @@ -55,6 +55,7 @@ import ( "github.com/ory/keto/internal/relationtuple" "github.com/ory/keto/internal/schema" "github.com/ory/keto/internal/x" + "github.com/ory/keto/internal/x/api" rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" ) @@ -103,7 +104,14 @@ func (r *RegistryDefault) ServeAll(ctx context.Context) error { innerCtx, cancel := context.WithCancel(ctx) defer cancel() - doneShutdown := make(chan struct{}, 3) + serveFuncs := []func(context.Context, chan<- struct{}) func() error{ + r.serveRead, + r.serveWrite, + r.serveOPLSyntax, + r.serveMetrics, + } + + doneShutdown := make(chan struct{}, len(serveFuncs)) go func() { osSignals := make(chan os.Signal, 1) @@ -115,18 +123,20 @@ func (r *RegistryDefault) ServeAll(ctx context.Context) error { case <-innerCtx.Done(): } - ctx, cancel := context.WithTimeout(context.Background(), graceful.DefaultShutdownTimeout) + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), graceful.DefaultShutdownTimeout) defer cancel() - nWaitingForShutdown := cap(doneShutdown) - select { - case <-ctx.Done(): - return - case <-doneShutdown: - nWaitingForShutdown-- - if nWaitingForShutdown == 0 { - // graceful shutdown done + nWaitingForShutdown := len(serveFuncs) + for { + select { + case <-ctx.Done(): return + case <-doneShutdown: + nWaitingForShutdown-- + if nWaitingForShutdown == 0 { + // graceful shutdown done + return + } } } }() @@ -134,14 +144,9 @@ func (r *RegistryDefault) ServeAll(ctx context.Context) error { eg := &errgroup.Group{} // We need to separate the setup (invoking the functions that return the serve functions) from running the serve - // functions to mitigate race contitions in the HTTP router. - for _, serve := range []func() error{ - r.serveRead(innerCtx, doneShutdown), - r.serveWrite(innerCtx, doneShutdown), - r.serveOPLSyntax(innerCtx, doneShutdown), - r.serveMetrics(innerCtx, doneShutdown), - } { - eg.Go(serve) + // functions to mitigate race conditions in the HTTP router. + for _, serve := range serveFuncs { + eg.Go(serve(innerCtx, doneShutdown)) } return eg.Wait() @@ -164,7 +169,8 @@ func (r *RegistryDefault) serveRead(ctx context.Context, done chan<- struct{}) f } return func() error { - return serve(ctx, r.Logger().WithField("endpoint", "read"), r.Config(ctx).ReadAPIListenOn(), handler, done) + addr, listenFile := r.Config(ctx).ReadAPIListenOn() + return serve(ctx, r.Logger().WithField("endpoint", "read"), addr, listenFile, handler, done) } } @@ -185,7 +191,8 @@ func (r *RegistryDefault) serveWrite(ctx context.Context, done chan<- struct{}) } return func() error { - return serve(ctx, r.Logger().WithField("endpoint", "write"), r.Config(ctx).WriteAPIListenOn(), handler, done) + addr, listenFile := r.Config(ctx).WriteAPIListenOn() + return serve(ctx, r.Logger().WithField("endpoint", "write"), addr, listenFile, handler, done) } } @@ -206,7 +213,8 @@ func (r *RegistryDefault) serveOPLSyntax(ctx context.Context, done chan<- struct } return func() error { - return serve(ctx, r.Logger().WithField("endpoint", "opl"), r.Config(ctx).OPLSyntaxAPIListenOn(), handler, done) + addr, listenFile := r.Config(ctx).OPLSyntaxAPIListenOn() + return serve(ctx, r.Logger().WithField("endpoint", "opl"), addr, listenFile, handler, done) } } @@ -216,16 +224,20 @@ func (r *RegistryDefault) serveMetrics(ctx context.Context, done chan<- struct{} //nolint:gosec // graceful.WithDefaults already sets a timeout s := graceful.WithDefaults(&http.Server{ Handler: r.metricsRouter(ctx), - Addr: r.Config(ctx).MetricsListenOn(), }) return func() error { defer cancel() - eg := &errgroup.Group{} + addr, listenFile := r.Config(ctx).MetricsListenOn() + l, err := listenAndWriteFile(ctx, addr, listenFile) + if err != nil { + return err + } + eg.Go(func() error { - if err := s.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + if err := s.Serve(l); !errors.Is(err, http.ErrServerClosed) { return errors.WithStack(err) } return nil @@ -251,17 +263,22 @@ func (r *RegistryDefault) serveMetrics(ctx context.Context, done chan<- struct{} } } -func serve(ctx context.Context, log *logrusx.Logger, addr string, handler http.Handler, done chan<- struct{}) error { +func serve(ctx context.Context, log *logrusx.Logger, addr string, listenFile string, handler http.Handler, done chan<- struct{}) error { + l, err := listenAndWriteFile(ctx, addr, listenFile) + if err != nil { + return err + } + //nolint:gosec // graceful.WithDefaults already sets a timeout server := graceful.WithDefaults(&http.Server{ - Handler: h2c.NewHandler(handler, &http2.Server{}), - Addr: addr, + WriteTimeout: 120 * time.Second, + Handler: http.MaxBytesHandler(h2c.NewHandler(handler, &http2.Server{}), 1024*1024*4), }) eg := &errgroup.Group{} eg.Go(func() error { - if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) && !errors.Is(err, cmux.ErrServerClosed) { + if err := server.Serve(l); !errors.Is(err, http.ErrServerClosed) && !errors.Is(err, cmux.ErrServerClosed) { return errors.WithStack(err) } return nil @@ -279,7 +296,7 @@ func serve(ctx context.Context, log *logrusx.Logger, addr string, handler http.H <-ctx.Done() - ctx, cancel := context.WithTimeout(context.Background(), graceful.DefaultShutdownTimeout) + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), graceful.DefaultShutdownTimeout) defer cancel() if err := server.Shutdown(ctx); err != nil { @@ -304,6 +321,20 @@ func (r *RegistryDefault) allHandlers() []Handler { return r.handlers } +func listenAndWriteFile(ctx context.Context, addr, listenFile string) (net.Listener, error) { + l, err := (&net.ListenConfig{}).Listen(ctx, "tcp", addr) + if err != nil { + return nil, errors.WithStack(fmt.Errorf("unable to listen on %q: %w", addr, err)) + } + const filePrefix = "file://" + if strings.HasPrefix(listenFile, filePrefix) { + if err := os.WriteFile(listenFile[len(filePrefix):], []byte(l.Addr().String()), 0600); err != nil { + return nil, errors.WithStack(fmt.Errorf("unable to write listen file %q: %w", listenFile, err)) + } + } + return l, nil +} + type RouterOrHandler struct { Router *httprouter.Router Handler http.Handler @@ -480,6 +511,7 @@ func (r *RegistryDefault) newGrpcServer(ctx context.Context) *grpc.Server { grpc.ChainStreamInterceptor(r.streamInterceptors(ctx)...), grpc.ChainUnaryInterceptor(r.unaryInterceptors(ctx)...), } + opts = append(opts, r.defaultGRPCServerOptions...) if r.grpcTransportCredentials != nil { opts = append(opts, grpc.Creds(r.grpcTransportCredentials)) } @@ -491,6 +523,10 @@ func (r *RegistryDefault) newAPIServer(ctx context.Context) *api.Server { opts := []api.ServerOption{ api.WithGRPCOption(grpc.ChainStreamInterceptor(r.streamInterceptors(ctx)...)), api.WithGRPCOption(grpc.ChainUnaryInterceptor(r.unaryInterceptors(ctx)...)), + api.WithGRPCOption(grpc.MaxRecvMsgSize(1024 * 1024 * 8)), + } + for _, o := range r.defaultGRPCServerOptions { + opts = append(opts, api.WithGRPCOption(o)) } if r.grpcTransportCredentials != nil { opts = append(opts, api.WithGRPCOption(grpc.Creds(r.grpcTransportCredentials))) diff --git a/internal/driver/daemon_test.go b/internal/driver/daemon_test.go new file mode 100644 index 000000000..0b4666d63 --- /dev/null +++ b/internal/driver/daemon_test.go @@ -0,0 +1,150 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +package driver + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/prometheus/common/expfmt" + "github.com/stretchr/testify/assert" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/status" + + "context" + + prometheus "github.com/ory/x/prometheusx" + ioprometheusclient "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" +) + +func TestScrapingEndpoint(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + r := NewSqliteTestRegistry(t, false) + getAddr := UseDynamicPorts(ctx, t, r) + + eg := errgroup.Group{} + doneShutdown := make(chan struct{}) + eg.Go(r.serveWrite(ctx, doneShutdown)) + eg.Go(r.serveMetrics(ctx, doneShutdown)) + + _, writePort, _ := getAddr(t, "write") + _, metricsPort, _ := getAddr(t, "metrics") + + t.Logf("write port: %s, metrics port: %s", writePort, metricsPort) + + assert.EventuallyWithT(t, func(t *assert.CollectT) { + conn, err := grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%s", writePort), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + defer conn.Close() + + cl := grpcHealthV1.NewHealthClient(conn) + watcher, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) + require.NoError(t, err) + require.NoError(t, watcher.CloseSend()) + for err := status.Error(codes.Unavailable, "init"); status.Code(err) != codes.Unavailable; _, err = watcher.Recv() { + } + }, 2*time.Second, 10*time.Millisecond) + + promresp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%s", metricsPort) + prometheus.MetricsPrometheusPath) + require.NoError(t, err) + require.EqualValues(t, http.StatusOK, promresp.StatusCode) + + textParser := expfmt.TextParser{} + text, err := textParser.TextToMetricFamilies(promresp.Body) + require.NoError(t, err) + require.EqualValues(t, "grpc_server_handled_total", *text["grpc_server_handled_total"].Name) + require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_handled_total"].Metric)) + require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_handled_total"].Metric)) + + require.EqualValues(t, "grpc_server_msg_sent_total", *text["grpc_server_msg_sent_total"].Name) + require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_msg_sent_total"].Metric)) + require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_msg_sent_total"].Metric)) + + require.EqualValues(t, "grpc_server_msg_received_total", *text["grpc_server_msg_received_total"].Name) + require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_msg_received_total"].Metric)) + require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_msg_received_total"].Metric)) + + cancel() + <-doneShutdown + <-doneShutdown + require.NoError(t, eg.Wait()) +} + +func TestPanicRecovery(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + unaryPanicInterceptor := func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error) { + panic("test panic") + } + streamPanicInterceptor := func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error) { + panic("test panic") + } + + r := NewSqliteTestRegistry(t, false, WithGRPCUnaryInterceptors(unaryPanicInterceptor), WithGRPCUnaryInterceptors(streamPanicInterceptor)) + getAddr := UseDynamicPorts(ctx, t, r) + + eg := errgroup.Group{} + doneShutdown := make(chan struct{}) + eg.Go(r.serveWrite(ctx, doneShutdown)) + + _, port, _ := getAddr(t, "write") + + conn, err := grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%s", port), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + defer conn.Close() + + assert.EventuallyWithT(t, func(t *assert.CollectT) { + cl := grpcHealthV1.NewHealthClient(conn) + + watcher, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) + require.NoError(t, err) + require.NoError(t, watcher.CloseSend()) + for err := status.Error(codes.Unavailable, "init"); status.Code(err) != codes.Unavailable; _, err = watcher.Recv() { + } + }, 2*time.Second, 10*time.Millisecond) + + cl := grpcHealthV1.NewHealthClient(conn) + // we want to ensure the server is still running after the panic + for range 10 { + // Unary call + resp, err := cl.Check(ctx, &grpcHealthV1.HealthCheckRequest{}) + require.Error(t, err, "%+v", resp) + assert.Equal(t, codes.Internal, status.Code(err)) + + // Streaming call + wResp, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) + require.NoError(t, err) + err = wResp.RecvMsg(nil) + require.Error(t, err) + assert.Equal(t, codes.Internal, status.Code(err)) + } + + cancel() + <-doneShutdown + require.NoError(t, eg.Wait()) +} + +func getLabelValue(name string, metric []*ioprometheusclient.Metric) string { + for _, label := range metric[0].Label { + if *label.Name == name { + return *label.Value + } + } + + return "" +} diff --git a/internal/driver/registry.go b/internal/driver/registry.go index a343d776c..16712e046 100644 --- a/internal/driver/registry.go +++ b/internal/driver/registry.go @@ -5,7 +5,6 @@ package driver import ( "context" - "net/http" "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" @@ -45,8 +44,8 @@ type ( MetricsHandler() *prometheus.Handler PrometheusManager() *prometheus.MetricsManager - ReadRouter(ctx context.Context, apiHandler http.Handler) http.Handler - WriteRouter(ctx context.Context, apiHandler http.Handler) http.Handler + //ReadRouter(ctx context.Context, apiHandler http.Handler) http.Handler + //WriteRouter(ctx context.Context, apiHandler http.Handler) http.Handler ReadGRPCServer(ctx context.Context) *grpc.Server WriteGRPCServer(ctx context.Context) *grpc.Server diff --git a/internal/driver/registry_default.go b/internal/driver/registry_default.go index 41f2ca121..02b67dc51 100644 --- a/internal/driver/registry_default.go +++ b/internal/driver/registry_default.go @@ -6,6 +6,7 @@ package driver import ( "context" "io/fs" + "maps" "net/http" "sync" @@ -124,12 +125,33 @@ func (r *RegistryDefault) Config(ctx context.Context) *config.Config { } func (r *RegistryDefault) HealthHandler() *healthx.Handler { - if r.healthH == nil { - if r.healthReadyCheckers == nil { - r.healthReadyCheckers = healthx.ReadyCheckers{} - } - r.healthH = healthx.NewHandler(r.Writer(), config.Version, r.healthReadyCheckers) + if r.healthH != nil { + return r.healthH + } + + h := healthx.ReadyCheckers{ + "database": func(req *http.Request) error { + return r.Persister().Connection(req.Context()).Store.PingContext(req.Context()) + }, + "migrations": func(req *http.Request) error { + mb, err := r.MigrationBox(req.Context()) + if err != nil { + return err + } + status, err := mb.Status(req.Context()) + if err != nil { + return err + } + + if status.HasPending() { + return errors.Errorf("migrations have not yet been fully applied") + } + return nil + }, } + maps.Copy(h, r.healthReadyCheckers) // possibly override default checkers + + r.healthH = healthx.NewHandler(r.Writer(), config.Version, h) return r.healthH } diff --git a/internal/driver/registry_factory.go b/internal/driver/registry_factory.go index 6e22e46ee..d8e06609c 100644 --- a/internal/driver/registry_factory.go +++ b/internal/driver/registry_factory.go @@ -98,6 +98,12 @@ func NewDefaultRegistry(ctx context.Context, flags *pflag.FlagSet, withoutNetwor return nil, errors.Wrap(err, "unable to initialize service registry") } + if inspect := options.Inspect(); inspect != nil { + if err := inspect(r.Persister().Connection(ctx)); err != nil { + return nil, errors.Wrap(err, "inspect") + } + } + return r, nil } diff --git a/internal/driver/testhelpers.go b/internal/driver/testhelpers.go new file mode 100644 index 000000000..2069ec906 --- /dev/null +++ b/internal/driver/testhelpers.go @@ -0,0 +1,63 @@ +package driver + +import ( + "context" + "fmt" + "net" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ory/keto/internal/driver/config" +) + +type GetAddr = func(t testing.TB, endpoint string) (host string, port string, fullAddr string) + +func UseDynamicPorts(ctx context.Context, t testing.TB, r Registry) GetAddr { + t.Helper() + + listenDir := t.TempDir() + readListenFile := fmt.Sprintf("%s/read.addr", listenDir) + writeListenFile := fmt.Sprintf("%s/write.addr", listenDir) + metricsListenFile := fmt.Sprintf("%s/metrics.addr", listenDir) + oplListenFile := fmt.Sprintf("%s/opl.addr", listenDir) + + require.NoError(t, r.Config(ctx).Set(config.KeyReadAPIPort, 0)) + require.NoError(t, r.Config(ctx).Set(config.KeyReadAPIListenFile, "file://"+readListenFile)) + require.NoError(t, r.Config(ctx).Set(config.KeyWriteAPIPort, 0)) + require.NoError(t, r.Config(ctx).Set(config.KeyWriteAPIListenFile, "file://"+writeListenFile)) + require.NoError(t, r.Config(ctx).Set(config.KeyMetricsPort, 0)) + require.NoError(t, r.Config(ctx).Set(config.KeyMetricsListenFile, "file://"+metricsListenFile)) + require.NoError(t, r.Config(ctx).Set(config.KeyOPLSyntaxAPIPort, 0)) + require.NoError(t, r.Config(ctx).Set(config.KeyOPLSyntaxListenFile, "file://"+oplListenFile)) + + return func(t testing.TB, endpoint string) (string, string, string) { + fp := "" + switch endpoint { + case "read": + fp = readListenFile + case "write": + fp = writeListenFile + case "metrics": + fp = metricsListenFile + case "opl": + fp = oplListenFile + default: + t.Fatalf("unknown endpoint: %q", endpoint) + } + + require.EventuallyWithT(t, func(t *assert.CollectT) { + _, err := os.Stat(fp) + require.NoError(t, err) + }, 2*time.Second, 10*time.Millisecond) + + addr, err := os.ReadFile(fp) + require.NoError(t, err) + host, port, err := net.SplitHostPort(string(addr)) + require.NoError(t, err) + return host, port, string(addr) + } +} diff --git a/internal/e2e/cli_client_test.go b/internal/e2e/cli_client_test.go index fe483e073..92704e16c 100644 --- a/internal/e2e/cli_client_test.go +++ b/internal/e2e/cli_client_test.go @@ -12,46 +12,39 @@ import ( "testing" "time" - "github.com/ory/keto/ketoapi" - rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" - - "github.com/ory/herodot" - + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" - "github.com/ory/keto/internal/x" + "github.com/ory/herodot" + "github.com/ory/x/cmdx" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" gprclient "github.com/ory/keto/cmd/client" cliexpand "github.com/ory/keto/cmd/expand" clirelationtuple "github.com/ory/keto/cmd/relationtuple" - - "github.com/ory/x/cmdx" + "github.com/ory/keto/internal/x" + "github.com/ory/keto/ketoapi" ) type cliClient struct { c *cmdx.CommandExecuter } -func (g *cliClient) queryNamespaces(t require.TestingT) (res ketoapi.GetNamespacesResponse) { - if t, ok := t.(*testing.T); ok { - t.Skip("not implemented for the CLI") - } +func (g *cliClient) queryNamespaces(t *testing.T) (res ketoapi.GetNamespacesResponse) { + t.Skip("not implemented for the CLI") return } var _ client = (*cliClient)(nil) -func (g *cliClient) oplCheckSyntax(t require.TestingT, _ []byte) []*ketoapi.ParseError { - if t, ok := t.(*testing.T); ok { - t.Skip("not implemented as a command yet") - } +func (g *cliClient) oplCheckSyntax(t *testing.T, _ []byte) []*ketoapi.ParseError { + t.Skip("not implemented as a command yet") return []*ketoapi.ParseError{} } -func (g *cliClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (g *cliClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { tupleEnc, err := json.Marshal(r) require.NoError(t, err) @@ -87,7 +80,7 @@ func (g *cliClient) assembleQueryFlags(q *ketoapi.RelationQuery, opts []x.Pagina return flags } -func (g *cliClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (g *cliClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { out := g.c.ExecNoErr(t, append(g.assembleQueryFlags(q, opts), "relation-tuple", "get")...) var resp ketoapi.GetResponse @@ -96,13 +89,13 @@ func (g *cliClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opt return &resp } -func (g *cliClient) queryTupleErr(t require.TestingT, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (g *cliClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { stdErr := g.c.ExecExpectedErr(t, append(g.assembleQueryFlags(q, opts), "relation-tuple", "get")...) assert.Contains(t, stdErr, expected.GRPCCodeField.String()) assert.Contains(t, stdErr, expected.Error()) } -func (g *cliClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { +func (g *cliClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { var sub string if r.SubjectID != nil { sub = *r.SubjectID @@ -115,14 +108,23 @@ func (g *cliClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { return res.Allowed } -func (g *cliClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (g *cliClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { + t.Skip("not implemented for the CLI") +} + +func (g *cliClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { + t.Skip("not implemented for the CLI") + return nil +} + +func (g *cliClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { out := g.c.ExecNoErr(t, "expand", r.Relation, r.Namespace, r.Object, "--"+cliexpand.FlagMaxDepth, fmt.Sprintf("%d", depth), "--"+cmdx.FlagFormat, string(cmdx.FormatJSON)) res := ketoapi.Tree[*ketoapi.RelationTuple]{} require.NoError(t, json.Unmarshal([]byte(out), &res)) return &res } -func (g *cliClient) waitUntilLive(t require.TestingT) { +func (g *cliClient) waitUntilLive(t *testing.T) { flags := make([]string, len(g.c.PersistentArgs)) copy(flags, g.c.PersistentArgs) @@ -140,7 +142,7 @@ func (g *cliClient) waitUntilLive(t require.TestingT) { require.Equal(t, grpcHealthV1.HealthCheckResponse_SERVING.String()+"\n", out) } -func (g *cliClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (g *cliClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { tupleEnc, err := json.Marshal(r) require.NoError(t, err) @@ -149,6 +151,6 @@ func (g *cliClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { assert.Len(t, stderr, 0, stdout) } -func (g *cliClient) deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuery) { +func (g *cliClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { _ = g.c.ExecNoErr(t, append(g.assembleQueryFlags(q, nil), "relation-tuple", "delete-all", "--force")...) } diff --git a/internal/e2e/full_suit_test.go b/internal/e2e/full_suit_test.go index 60ec9a9fc..cc03f0828 100644 --- a/internal/e2e/full_suit_test.go +++ b/internal/e2e/full_suit_test.go @@ -28,19 +28,21 @@ import ( type ( transactClient interface { client - transactTuples(t require.TestingT, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) + transactTuples(t *testing.T, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) } client interface { - createTuple(t require.TestingT, r *ketoapi.RelationTuple) - deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) - deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuery) - queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse - queryTupleErr(t require.TestingT, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) - check(t require.TestingT, r *ketoapi.RelationTuple) bool - expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] - oplCheckSyntax(t require.TestingT, content []byte) []*ketoapi.ParseError - waitUntilLive(t require.TestingT) - queryNamespaces(t require.TestingT) ketoapi.GetNamespacesResponse + createTuple(t *testing.T, r *ketoapi.RelationTuple) + deleteTuple(t *testing.T, r *ketoapi.RelationTuple) + deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) + queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse + queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) + check(t *testing.T, r *ketoapi.RelationTuple) bool + batchCheck(t *testing.T, r []*ketoapi.RelationTuple) []checkResponse + batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) + expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] + oplCheckSyntax(t *testing.T, content []byte) []*ketoapi.ParseError + waitUntilLive(t *testing.T) + queryNamespaces(t *testing.T) ketoapi.GetNamespacesResponse } ) @@ -51,28 +53,31 @@ const ( func Test(t *testing.T) { t.Parallel() for _, dsn := range dbx.GetDSNs(t, false) { - dsn := dsn t.Run(fmt.Sprintf("dsn=%s", dsn.Name), func(t *testing.T) { t.Parallel() - ctx, reg, namespaceTestMgr := newInitializedReg(t, dsn, nil) + ctx, reg, namespaceTestMgr, getAddr := newInitializedReg(t, dsn, nil) closeServer := startServer(ctx, t, reg) t.Cleanup(closeServer) + _, _, readAddr := getAddr(t, "read") + _, _, writeAddr := getAddr(t, "write") + _, _, oplAddr := getAddr(t, "opl") + _, _, metricsAddr := getAddr(t, "metrics") + // The test cases start here // We execute every test with all clients available for _, cl := range []client{ - &grpcClient{ - readRemote: reg.Config(ctx).ReadAPIListenOn(), - writeRemote: reg.Config(ctx).WriteAPIListenOn(), - oplSyntaxRemote: reg.Config(ctx).OPLSyntaxAPIListenOn(), - ctx: ctx, - }, + newGrpcClient(t, ctx, + readAddr, + writeAddr, + oplAddr, + ), &restClient{ - readURL: "http://" + reg.Config(ctx).ReadAPIListenOn(), - writeURL: "http://" + reg.Config(ctx).WriteAPIListenOn(), - oplSyntaxURL: "http://" + reg.Config(ctx).OPLSyntaxAPIListenOn(), + readURL: "http://" + readAddr, + writeURL: "http://" + writeAddr, + oplSyntaxURL: "http://" + oplAddr, }, &cliClient{c: &cmdx.CommandExecuter{ New: func() *cobra.Command { @@ -80,19 +85,18 @@ func Test(t *testing.T) { }, Ctx: ctx, PersistentArgs: []string{ - "--" + cliclient.FlagReadRemote, reg.Config(ctx).ReadAPIListenOn(), - "--" + cliclient.FlagWriteRemote, reg.Config(ctx).WriteAPIListenOn(), + "--" + cliclient.FlagReadRemote, readAddr, + "--" + cliclient.FlagWriteRemote, writeAddr, "--insecure-disable-transport-security=true", "--" + cmdx.FlagFormat, string(cmdx.FormatJSON), }, }}, &sdkClient{ - readRemote: reg.Config(ctx).ReadAPIListenOn(), - writeRemote: reg.Config(ctx).WriteAPIListenOn(), - syntaxRemote: reg.Config(ctx).OPLSyntaxAPIListenOn(), + readRemote: readAddr, + writeRemote: writeAddr, + syntaxRemote: oplAddr, }, } { - cl := cl t.Run(fmt.Sprintf("client=%T", cl), runCases(cl, namespaceTestMgr)) if tc, ok := cl.(transactClient); ok { @@ -102,15 +106,15 @@ func Test(t *testing.T) { t.Run("case=metrics are served", func(t *testing.T) { t.Parallel() - (&grpcClient{ - readRemote: reg.Config(ctx).ReadAPIListenOn(), - writeRemote: reg.Config(ctx).WriteAPIListenOn(), - ctx: ctx, - }).waitUntilLive(t) + newGrpcClient(t, ctx, + readAddr, + writeAddr, + oplAddr, + ).waitUntilLive(t) t.Run("case=on "+prometheus.MetricsPrometheusPath, func(t *testing.T) { t.Parallel() - resp, err := http.Get(fmt.Sprintf("http://%s%s", reg.Config(ctx).MetricsListenOn(), prometheus.MetricsPrometheusPath)) + resp, err := http.Get(fmt.Sprintf("http://%s%s", metricsAddr, prometheus.MetricsPrometheusPath)) require.NoError(t, err) require.Equal(t, resp.StatusCode, http.StatusOK) body, err := io.ReadAll(resp.Body) @@ -120,7 +124,7 @@ func Test(t *testing.T) { t.Run("case=not on /", func(t *testing.T) { t.Parallel() - resp, err := http.Get(fmt.Sprintf("http://%s", reg.Config(ctx).MetricsListenOn())) + resp, err := http.Get(fmt.Sprintf("http://%s", metricsAddr)) require.NoError(t, err) require.Equal(t, resp.StatusCode, http.StatusNotFound) }) @@ -132,7 +136,7 @@ func Test(t *testing.T) { func TestServeCORS(t *testing.T) { t.Parallel() - ctx, reg, _ := newInitializedReg(t, dbx.GetSqlite(t, dbx.SQLiteMemory), map[string]interface{}{ + ctx, reg, _, getAddr := newInitializedReg(t, dbx.GetSqlite(t, dbx.SQLiteMemory), map[string]interface{}{ "serve.read.cors.enabled": true, "serve.read.cors.debug": true, "serve.read.cors.allowed_methods": []string{http.MethodGet}, @@ -142,12 +146,15 @@ func TestServeCORS(t *testing.T) { closeServer := startServer(ctx, t, reg) t.Cleanup(closeServer) - for !healthReady(t, "http://"+reg.Config(ctx).ReadAPIListenOn()) { + _, _, readAddr := getAddr(t, "read") + + for !healthReady(t, "http://"+readAddr) { t.Log("Waiting for health check to be ready") time.Sleep(10 * time.Millisecond) } + t.Log("Health check is ready") - req, err := http.NewRequest(http.MethodOptions, "http://"+reg.Config(ctx).ReadAPIListenOn()+relationtuple.ReadRouteBase, nil) + req, err := http.NewRequest(http.MethodOptions, "http://"+readAddr+relationtuple.ReadRouteBase, nil) require.NoError(t, err) req.Header.Set("Origin", "https://ory.sh") req.Header.Set("Access-Control-Request-Method", http.MethodGet) diff --git a/internal/e2e/grpc_client_test.go b/internal/e2e/grpc_client_test.go index 1244dfad0..0326e7c4a 100644 --- a/internal/e2e/grpc_client_test.go +++ b/internal/e2e/grpc_client_test.go @@ -6,6 +6,7 @@ package e2e import ( "context" "encoding/json" + "testing" "time" "github.com/ory/keto/ketoapi" @@ -13,67 +14,59 @@ import ( rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" - "github.com/ory/herodot" "github.com/stretchr/testify/assert" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/status" - "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/status" + + "github.com/ory/herodot" "github.com/ory/keto/internal/x" ) type grpcClient struct { - readRemote, writeRemote, oplSyntaxRemote string - wc, rc, oc *grpc.ClientConn - ctx context.Context + read, write, oplSyntax *grpc.ClientConn + ctx context.Context } -func (g *grpcClient) queryNamespaces(t require.TestingT) (apiResponse ketoapi.GetNamespacesResponse) { - client := rts.NewNamespacesServiceClient(g.readConn(t)) - res, err := client.ListNamespaces(g.ctx, &rts.ListNamespacesRequest{}) +func newGrpcClient(t *testing.T, ctx context.Context, readRemote, writeRemote, oplSyntaxRemote string) *grpcClient { + read, err := grpc.NewClient(readRemote, grpc.WithTransportCredentials(insecure.NewCredentials())) require.NoError(t, err) - require.NoError(t, convert(res, &apiResponse)) - - return -} - -var _ transactClient = (*grpcClient)(nil) + t.Cleanup(func() { read.Close() }) -func (g *grpcClient) conn(t require.TestingT, remote string) *grpc.ClientConn { - ctx, cancel := context.WithTimeout(g.ctx, 3*time.Second) - defer cancel() + write, err := grpc.NewClient(writeRemote, grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { write.Close() }) - conn, err := grpc.DialContext(ctx, remote, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock(), grpc.WithDisableHealthCheck()) + oplSyntax, err := grpc.NewClient(oplSyntaxRemote, grpc.WithTransportCredentials(insecure.NewCredentials())) require.NoError(t, err) + t.Cleanup(func() { oplSyntax.Close() }) - return conn -} + ctx, cancel := context.WithCancel(ctx) + t.Cleanup(cancel) -func (g *grpcClient) readConn(t require.TestingT) *grpc.ClientConn { - if g.rc == nil { - g.rc = g.conn(t, g.readRemote) + return &grpcClient{ + read: read, + write: write, + oplSyntax: oplSyntax, + ctx: ctx, } - return g.rc } -func (g *grpcClient) writeConn(t require.TestingT) *grpc.ClientConn { - if g.wc == nil { - g.wc = g.conn(t, g.writeRemote) - } - return g.wc -} +func (g *grpcClient) queryNamespaces(t *testing.T) (apiResponse ketoapi.GetNamespacesResponse) { + client := rts.NewNamespacesServiceClient(g.read) + res, err := client.ListNamespaces(g.ctx, &rts.ListNamespacesRequest{}) + require.NoError(t, err) + require.NoError(t, convert(res, &apiResponse)) -func (g *grpcClient) oplSyntaxConn(t require.TestingT) *grpc.ClientConn { - if g.oc == nil { - g.oc = g.conn(t, g.oplSyntaxRemote) - } - return g.oc + return } -func (g *grpcClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) { +var _ transactClient = (*grpcClient)(nil) + +func (g *grpcClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { g.transactTuples(t, []*ketoapi.RelationTuple{r}, nil) } @@ -91,8 +84,8 @@ func (*grpcClient) createQuery(q *ketoapi.RelationQuery) *rts.RelationQuery { return query } -func (g *grpcClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { - c := rts.NewReadServiceClient(g.readConn(t)) +func (g *grpcClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { + c := rts.NewReadServiceClient(g.read) pagination := x.GetPaginationOptions(opts...) resp, err := c.ListRelationTuples(g.ctx, &rts.ListRelationTuplesRequest{ @@ -114,8 +107,8 @@ func (g *grpcClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, op } } -func (g *grpcClient) queryTupleErr(t require.TestingT, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { - c := rts.NewReadServiceClient(g.readConn(t)) +func (g *grpcClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { + c := rts.NewReadServiceClient(g.read) pagination := x.GetPaginationOptions(opts...) _, err := c.ListRelationTuples(g.ctx, &rts.ListRelationTuplesRequest{ @@ -129,8 +122,8 @@ func (g *grpcClient) queryTupleErr(t require.TestingT, expected herodot.DefaultE assert.Equal(t, expected.GRPCCodeField, s.Code(), "%+v", err) } -func (g *grpcClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { - c := rts.NewCheckServiceClient(g.readConn(t)) +func (g *grpcClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { + c := rts.NewCheckServiceClient(g.read) req := &rts.CheckRequest{ Tuple: &rts.RelationTuple{ @@ -150,8 +143,65 @@ func (g *grpcClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { return resp.Allowed } -func (g *grpcClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { - c := rts.NewExpandServiceClient(g.readConn(t)) +type checkResponse struct { + allowed bool + errorMessage string +} + +func (g *grpcClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, + expected herodot.DefaultError) { + + _, err := g.doBatchCheck(t, requestTuples) + require.Error(t, err) + s, ok := status.FromError(err) + require.True(t, ok) + assert.Equal(t, expected.GRPCCodeField, s.Code(), "%+v", err) + assert.Contains(t, s.Message(), expected.Reason()) +} + +func (g *grpcClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { + resp, err := g.doBatchCheck(t, requestTuples) + require.NoError(t, err) + + checkResponses := make([]checkResponse, len(resp.Results)) + for i, r := range resp.Results { + checkResponses[i] = checkResponse{ + allowed: r.Allowed, + errorMessage: r.Error, + } + } + + return checkResponses +} + +func (g *grpcClient) doBatchCheck(_ *testing.T, requestTuples []*ketoapi.RelationTuple) (*rts.BatchCheckResponse, error) { + + c := rts.NewCheckServiceClient(g.read) + + tuples := make([]*rts.RelationTuple, len(requestTuples)) + for i, tuple := range requestTuples { + var subject *rts.Subject + if tuple.SubjectID != nil { + subject = rts.NewSubjectID(*tuple.SubjectID) + } else { + subject = rts.NewSubjectSet(tuple.SubjectSet.Namespace, tuple.SubjectSet.Object, tuple.SubjectSet.Relation) + } + tuples[i] = &rts.RelationTuple{ + Namespace: tuple.Namespace, + Object: tuple.Object, + Relation: tuple.Relation, + Subject: subject, + } + } + + req := &rts.BatchCheckRequest{ + Tuples: tuples, + } + return c.BatchCheck(g.ctx, req) +} + +func (g *grpcClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { + c := rts.NewExpandServiceClient(g.read) resp, err := c.Expand(g.ctx, &rts.ExpandRequest{ Subject: rts.NewSubjectSet(r.Namespace, r.Object, r.Relation), @@ -162,37 +212,22 @@ func (g *grpcClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int return ketoapi.TreeFromProto[*ketoapi.RelationTuple](resp.Tree) } -func (g *grpcClient) waitUntilLive(t require.TestingT) { - c := grpcHealthV1.NewHealthClient(g.readConn(t)) - - ctx, cancel := context.WithCancel(g.ctx) - defer cancel() +func (g *grpcClient) waitUntilLive(t *testing.T) { + require.EventuallyWithT(t, func(t *assert.CollectT) { + c := grpcHealthV1.NewHealthClient(g.read) - cl, err := c.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) - require.NoError(t, err) - require.NoError(t, cl.CloseSend()) - - for { - select { - case <-g.ctx.Done(): - return - default: - } - resp, err := cl.Recv() + res, err := c.Check(g.ctx, &grpcHealthV1.HealthCheckRequest{}) require.NoError(t, err) - - if resp.Status == grpcHealthV1.HealthCheckResponse_SERVING { - return - } - } + assert.Equal(t, grpcHealthV1.HealthCheckResponse_SERVING, res.Status) + }, 2*time.Second, 10*time.Millisecond) } -func (g *grpcClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (g *grpcClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { g.transactTuples(t, nil, []*ketoapi.RelationTuple{r}) } -func (g *grpcClient) deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuery) { - c := rts.NewWriteServiceClient(g.writeConn(t)) +func (g *grpcClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { + c := rts.NewWriteServiceClient(g.write) query := &rts.RelationQuery{ Namespace: q.Namespace, Object: q.Object, @@ -210,8 +245,8 @@ func (g *grpcClient) deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuer require.NoError(t, err) } -func (g *grpcClient) transactTuples(t require.TestingT, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) { - c := rts.NewWriteServiceClient(g.writeConn(t)) +func (g *grpcClient) transactTuples(t *testing.T, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) { + c := rts.NewWriteServiceClient(g.write) deltas := make([]*rts.RelationTupleDelta, len(ins)+len(del)) for i := range ins { @@ -227,15 +262,15 @@ func (g *grpcClient) transactTuples(t require.TestingT, ins []*ketoapi.RelationT } } - _, err := c.TransactRelationTuples(g.ctx, &rts.TransactRelationTuplesRequest{ - RelationTupleDeltas: deltas, - }) + _, err := c.TransactRelationTuples(g.ctx, + &rts.TransactRelationTuplesRequest{RelationTupleDeltas: deltas}, + ) require.NoError(t, err) } -func (g *grpcClient) oplCheckSyntax(t require.TestingT, content []byte) (parseErrors []*ketoapi.ParseError) { - c := opl.NewSyntaxServiceClient(g.oplSyntaxConn(t)) +func (g *grpcClient) oplCheckSyntax(t *testing.T, content []byte) (parseErrors []*ketoapi.ParseError) { + c := opl.NewSyntaxServiceClient(g.oplSyntax) res, err := c.Check(g.ctx, &opl.CheckRequest{Content: content}) require.NoError(t, err) diff --git a/internal/e2e/helpers.go b/internal/e2e/helpers.go index 96bcef55a..cd175f92f 100644 --- a/internal/e2e/helpers.go +++ b/internal/e2e/helpers.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/ory/x/configx" - "github.com/phayes/freeport" "github.com/spf13/pflag" "github.com/ory/keto/internal/driver/config" @@ -58,15 +57,12 @@ func (m *namespaceTestManager) remove(t *testing.T, name string) { require.NoError(t, m.reg.Config(m.ctx).Set(config.KeyNamespaces, m.nspaces)) } -func newInitializedReg(t testing.TB, dsn *dbx.DsnT, cfgOverwrites map[string]interface{}) (context.Context, driver.Registry, *namespaceTestManager) { +func newInitializedReg(t testing.TB, dsn *dbx.DsnT, cfgOverwrites map[string]interface{}) (context.Context, driver.Registry, *namespaceTestManager, driver.GetAddr) { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(func() { cancel() }) - ports, err := freeport.GetFreePorts(4) - require.NoError(t, err) - flags := pflag.NewFlagSet("", pflag.ContinueOnError) configx.RegisterConfigFlag(flags, nil) @@ -75,13 +71,9 @@ func newInitializedReg(t testing.TB, dsn *dbx.DsnT, cfgOverwrites map[string]int "log.level": "debug", "log.leak_sensitive_values": true, config.KeyReadAPIHost: "127.0.0.1", - config.KeyReadAPIPort: ports[0], config.KeyWriteAPIHost: "127.0.0.1", - config.KeyWriteAPIPort: ports[1], config.KeyOPLSyntaxAPIHost: "127.0.0.1", - config.KeyOPLSyntaxAPIPort: ports[2], config.KeyMetricsHost: "127.0.0.1", - config.KeyMetricsPort: ports[3], config.KeyNamespaces: []*namespace.Namespace{}, } for k, v := range cfgOverwrites { @@ -94,6 +86,8 @@ func newInitializedReg(t testing.TB, dsn *dbx.DsnT, cfgOverwrites map[string]int reg, err := driver.NewDefaultRegistry(ctx, flags, true, nil) require.NoError(t, err) + getAddr := driver.UseDynamicPorts(ctx, t, reg) + require.NoError(t, reg.MigrateUp(ctx)) assertMigrated(ctx, t, reg) @@ -101,7 +95,7 @@ func newInitializedReg(t testing.TB, dsn *dbx.DsnT, cfgOverwrites map[string]int reg: reg, ctx: ctx, nspaces: []*namespace.Namespace{}, - } + }, getAddr } func assertMigrated(ctx context.Context, t testing.TB, r driver.Registry) { diff --git a/internal/e2e/rest_client_test.go b/internal/e2e/rest_client_test.go index 93351bf21..80e66a29f 100644 --- a/internal/e2e/rest_client_test.go +++ b/internal/e2e/rest_client_test.go @@ -10,23 +10,24 @@ import ( "io" "net/http" "strconv" + "testing" "time" - "github.com/ory/x/healthx" - + httpclient "github.com/ory/keto/internal/httpclient" "github.com/ory/keto/internal/schema" "github.com/ory/keto/ketoapi" rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" "github.com/tidwall/gjson" - "github.com/ory/herodot" - "github.com/ory/keto/internal/x" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/ory/herodot" + "github.com/ory/x/healthx" + "github.com/ory/keto/internal/check" "github.com/ory/keto/internal/expand" "github.com/ory/keto/internal/relationtuple" @@ -38,7 +39,7 @@ type restClient struct { readURL, writeURL, oplSyntaxURL string } -func (rc *restClient) queryNamespaces(t require.TestingT) (res ketoapi.GetNamespacesResponse) { +func (rc *restClient) queryNamespaces(t *testing.T) (res ketoapi.GetNamespacesResponse) { body, code := rc.makeRequest(t, http.MethodGet, "/namespaces", "", rc.readURL) assert.Equal(t, http.StatusOK, code, body) require.NoError(t, json.Unmarshal([]byte(body), &res)) @@ -46,7 +47,7 @@ func (rc *restClient) queryNamespaces(t require.TestingT) (res ketoapi.GetNamesp return } -func (rc *restClient) oplCheckSyntax(t require.TestingT, content []byte) []*ketoapi.ParseError { +func (rc *restClient) oplCheckSyntax(t *testing.T, content []byte) []*ketoapi.ParseError { body, code := rc.makeRequest(t, http.MethodPost, schema.RouteBase, string(content), rc.oplSyntaxURL) assert.Equal(t, http.StatusOK, code, body) var response ketoapi.CheckOPLSyntaxResponse @@ -55,7 +56,7 @@ func (rc *restClient) oplCheckSyntax(t require.TestingT, content []byte) []*keto return response.Errors } -func (rc *restClient) makeRequest(t require.TestingT, method, path, body string, baseURL string) (string, int) { +func (rc *restClient) makeRequest(t *testing.T, method, path, body string, baseURL string) (string, int) { var b io.Reader if body != "" { b = bytes.NewBufferString(body) @@ -73,7 +74,7 @@ func (rc *restClient) makeRequest(t require.TestingT, method, path, body string, return string(respBody), resp.StatusCode } -func (rc *restClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (rc *restClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { tEnc, err := json.Marshal(r) require.NoError(t, err) @@ -81,17 +82,17 @@ func (rc *restClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) assert.Equal(t, http.StatusCreated, code, body) } -func (rc *restClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (rc *restClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { body, code := rc.makeRequest(t, http.MethodDelete, relationtuple.WriteRouteBase+"?"+r.ToURLQuery().Encode(), "", rc.writeURL) require.Equal(t, http.StatusNoContent, code, body) } -func (rc *restClient) deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuery) { +func (rc *restClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { body, code := rc.makeRequest(t, http.MethodDelete, relationtuple.WriteRouteBase+"?"+q.ToURLQuery().Encode(), "", rc.writeURL) require.Equal(t, http.StatusNoContent, code, body) } -func (rc *restClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (rc *restClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { urlQuery := q.ToURLQuery() pagination := x.GetPaginationOptions(opts...) @@ -111,7 +112,7 @@ func (rc *restClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, o return &dec } -func (rc *restClient) queryTupleErr(t require.TestingT, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (rc *restClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { urlQuery := q.ToURLQuery() pagination := x.GetPaginationOptions(opts...) @@ -130,7 +131,7 @@ func (rc *restClient) queryTupleErr(t require.TestingT, expected herodot.Default assert.Equal(t, expected.Error(), gjson.Get(body, "error.message").String(), body) } -func (rc *restClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { +func (rc *restClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { q := r.ToURLQuery() bodyGet, codeGet := rc.makeRequest(t, http.MethodGet, fmt.Sprintf("%s?%s", check.RouteBase, q.Encode()), "", rc.readURL) @@ -157,7 +158,42 @@ func (rc *restClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { return false } -func (rc *restClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (rc *restClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, + expected herodot.DefaultError) { + + req := httpclient.BatchCheckPermissionBody{ + Tuples: tuplesToRelationships(requestTuples), + } + j, err := json.Marshal(req) + require.NoError(t, err) + body, code := rc.makeRequest(t, http.MethodPost, check.BatchRoute, string(j), rc.readURL) + assert.Equal(t, expected.CodeField, code) + assert.Contains(t, body, expected.Reason()) +} + +func (rc *restClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { + req := httpclient.BatchCheckPermissionBody{ + Tuples: tuplesToRelationships(requestTuples), + } + j, err := json.Marshal(req) + require.NoError(t, err) + body, code := rc.makeRequest(t, http.MethodPost, check.BatchRoute, string(j), rc.readURL) + require.Equal(t, http.StatusOK, code, "batch check failed unexpected with error code %d", code) + + var respPost rts.BatchCheckResponse + require.NoError(t, json.Unmarshal([]byte(body), &respPost)) + + responseChecks := make([]checkResponse, len(respPost.Results)) + for i, result := range respPost.Results { + responseChecks[i] = checkResponse{ + allowed: result.Allowed, + errorMessage: result.Error, + } + } + return responseChecks +} + +func (rc *restClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { query := r.ToURLQuery() query.Set("max-depth", fmt.Sprintf("%d", depth)) @@ -170,17 +206,18 @@ func (rc *restClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth in return tree } -func healthReady(t require.TestingT, readURL string) bool { +func healthReady(t *testing.T, readURL string) bool { req, err := http.NewRequest("GET", readURL+healthx.ReadyCheckPath, nil) require.NoError(t, err) resp, err := http.DefaultClient.Do(req) if err != nil { return false } + defer resp.Body.Close() return resp.StatusCode == http.StatusOK } -func (rc *restClient) waitUntilLive(t require.TestingT) { +func (rc *restClient) waitUntilLive(t *testing.T) { // wait for /health/ready for !healthReady(t, rc.readURL) { time.Sleep(10 * time.Millisecond) diff --git a/internal/e2e/scraping_endpoint_test.go b/internal/e2e/scraping_endpoint_test.go deleted file mode 100644 index a4f431d0c..000000000 --- a/internal/e2e/scraping_endpoint_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright © 2023 Ory Corp -// SPDX-License-Identifier: Apache-2.0 - -package e2e - -import ( - "fmt" - "net/http" - "testing" - - ioprometheusclient "github.com/prometheus/client_model/go" - "github.com/prometheus/common/expfmt" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" - "google.golang.org/grpc/status" - - prometheus "github.com/ory/x/prometheusx" - - "github.com/ory/keto/internal/x/dbx" - rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" -) - -func TestScrapingEndpoint(t *testing.T) { - dsn := dbx.GetSqlite(t, dbx.SQLiteMemory) - ctx, reg, _ := newInitializedReg(t, dsn, nil) - closeServer := startServer(ctx, t, reg) - t.Cleanup(closeServer) - - client := &grpcClient{ - readRemote: reg.Config(ctx).ReadAPIListenOn(), - writeRemote: reg.Config(ctx).WriteAPIListenOn(), - ctx: ctx, - } - - client.waitUntilLive(t) - - conn := client.readConn(t) - defer conn.Close() - - versionClient := rts.NewVersionServiceClient(conn) - versionRes, err := versionClient.GetVersion(ctx, &rts.GetVersionRequest{}) - require.NoError(t, err) - assert.Equal(t, "master", versionRes.Version) - - cl := grpcHealthV1.NewHealthClient(conn) - - res, err := cl.Check(ctx, &grpcHealthV1.HealthCheckRequest{}) - require.NoError(t, err) - assert.Equal(t, grpcHealthV1.HealthCheckResponse_SERVING, res.Status) - - watcher, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) - require.NoError(t, err) - require.NoError(t, watcher.CloseSend()) - for err := status.Error(codes.Unavailable, "init"); status.Code(err) != codes.Unavailable; _, err = watcher.Recv() { - } - - promresp, err := http.Get(fmt.Sprintf("http://%s%s", reg.Config(ctx).MetricsListenOn(), prometheus.MetricsPrometheusPath)) - require.NoError(t, err) - require.EqualValues(t, http.StatusOK, promresp.StatusCode) - - textParser := expfmt.TextParser{} - text, err := textParser.TextToMetricFamilies(promresp.Body) - require.NoError(t, err) - require.EqualValues(t, "grpc_server_handled_total", *text["grpc_server_handled_total"].Name) - require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_handled_total"].Metric)) - require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_handled_total"].Metric)) - - require.EqualValues(t, "grpc_server_msg_sent_total", *text["grpc_server_msg_sent_total"].Name) - require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_msg_sent_total"].Metric)) - require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_msg_sent_total"].Metric)) - - require.EqualValues(t, "grpc_server_msg_received_total", *text["grpc_server_msg_received_total"].Name) - require.EqualValues(t, "Check", getLabelValue("grpc_method", text["grpc_server_msg_received_total"].Metric)) - require.EqualValues(t, "grpc.health.v1.Health", getLabelValue("grpc_service", text["grpc_server_msg_received_total"].Metric)) -} - -//func TestPanicRecovery(t *testing.T) { -// ctx, cancel := context.WithCancel(context.Background()) -// defer cancel() -// -// unaryPanicInterceptor := func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error) { -// panic("test panic") -// } -// streamPanicInterceptor := func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error) { -// panic("test panic") -// } -// port, err := freeport.GetFreePort() -// require.NoError(t, err) -// -// r := driver.NewSqliteTestRegistry(t, false, driver.WithGRPCUnaryInterceptors(unaryPanicInterceptor), driver.WithGRPCUnaryInterceptors(streamPanicInterceptor)) -// require.NoError(t, r.Config(ctx).Set(config.KeyWriteAPIPort, port)) -// -// eg := errgroup.Group{} -// doneShutdown := make(chan struct{}) -// eg.Go(r.serveWrite(ctx, doneShutdown)) -// -// conn, err := grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", port), -// grpc.WithTransportCredentials(insecure.NewCredentials()), -// grpc.WithBlock(), -// ) -// require.NoError(t, err) -// defer conn.Close() -// -// cl := grpcHealthV1.NewHealthClient(conn) -// -// watcher, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) -// require.NoError(t, err) -// require.NoError(t, watcher.CloseSend()) -// for err := status.Error(codes.Unavailable, "init"); status.Code(err) != codes.Unavailable; _, err = watcher.Recv() { -// } -// -// // we want to ensure the server is still running after the panic -// for i := 0; i < 10; i++ { -// // Unary call -// resp, err := cl.Check(ctx, &grpcHealthV1.HealthCheckRequest{}) -// require.Error(t, err, "%+v", resp) -// assert.Equal(t, codes.Internal, status.Code(err)) -// -// // Streaming call -// wResp, err := cl.Watch(ctx, &grpcHealthV1.HealthCheckRequest{}) -// require.NoError(t, err) -// err = wResp.RecvMsg(nil) -// require.Error(t, err) -// assert.Equal(t, codes.Internal, status.Code(err)) -// } -// -// cancel() -// <-doneShutdown -// require.NoError(t, eg.Wait()) -//} - -func getLabelValue(name string, metric []*ioprometheusclient.Metric) string { - for _, label := range metric[0].Label { - if *label.Name == name { - return *label.Value - } - } - - return "" -} diff --git a/internal/e2e/sdk_client_test.go b/internal/e2e/sdk_client_test.go index a7451f822..a136c14d6 100644 --- a/internal/e2e/sdk_client_test.go +++ b/internal/e2e/sdk_client_test.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "net/http" + "testing" "time" "github.com/stretchr/testify/assert" @@ -15,6 +16,8 @@ import ( "github.com/ory/herodot" "github.com/ory/x/pointerx" + rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" + httpclient "github.com/ory/keto/internal/httpclient" "github.com/ory/keto/internal/x" "github.com/ory/keto/ketoapi" @@ -31,15 +34,16 @@ var _ client = (*sdkClient)(nil) var requestTimeout = 5 * time.Second -func (c *sdkClient) requestCtx() context.Context { - ctx, _ := context.WithTimeout(context.Background(), requestTimeout) +func (c *sdkClient) requestCtx(t *testing.T) context.Context { + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + t.Cleanup(cancel) return ctx } -func (c *sdkClient) oplCheckSyntax(t require.TestingT, content []byte) (parseErrors []*ketoapi.ParseError) { +func (c *sdkClient) oplCheckSyntax(t *testing.T, content []byte) (parseErrors []*ketoapi.ParseError) { res, _, err := c.getOPLSyntaxClient(). RelationshipApi. - CheckOplSyntax(c.requestCtx()). + CheckOplSyntax(c.requestCtx(t)). Body(string(content)). Execute() require.NoError(t, err) @@ -91,7 +95,7 @@ func (c *sdkClient) getOPLSyntaxClient() *httpclient.APIClient { return c.sc } -func (c *sdkClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (c *sdkClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { payload := httpclient.CreateRelationshipBody{ Namespace: pointerx.Ptr(r.Namespace), Object: pointerx.Ptr(r.Object), @@ -107,7 +111,7 @@ func (c *sdkClient) createTuple(t require.TestingT, r *ketoapi.RelationTuple) { } _, _, err := c.getWriteClient().RelationshipApi. - CreateRelationship(c.requestCtx()). + CreateRelationship(c.requestCtx(t)). CreateRelationshipBody(payload). Execute() require.NoError(t, err) @@ -131,9 +135,9 @@ func withSubject[P interface { return params } -func (c *sdkClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { +func (c *sdkClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { request := c.getWriteClient().RelationshipApi. - DeleteRelationships(c.requestCtx()). + DeleteRelationships(c.requestCtx(t)). Namespace(r.Namespace). Object(r.Object). Relation(r.Relation) @@ -143,8 +147,8 @@ func (c *sdkClient) deleteTuple(t require.TestingT, r *ketoapi.RelationTuple) { require.NoError(t, err) } -func (c *sdkClient) deleteAllTuples(t require.TestingT, q *ketoapi.RelationQuery) { - request := c.getWriteClient().RelationshipApi.DeleteRelationships(c.requestCtx()) +func (c *sdkClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { + request := c.getWriteClient().RelationshipApi.DeleteRelationships(c.requestCtx(t)) if q.Namespace != nil { request = request.Namespace(*q.Namespace) } @@ -190,8 +194,8 @@ func compileParams(req httpclient.RelationshipApiApiGetRelationshipsRequest, q * return req } -func (c *sdkClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { - request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx()) +func (c *sdkClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { + request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx(t)) request = compileParams(request, q, opts) resp, _, err := request.Execute() @@ -222,8 +226,8 @@ func (c *sdkClient) queryTuple(t require.TestingT, q *ketoapi.RelationQuery, opt return getResp } -func (c *sdkClient) queryTupleErr(t require.TestingT, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { - request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx()) +func (c *sdkClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { + request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx(t)) request = compileParams(request, q, opts) _, _, err := request.Execute() @@ -237,8 +241,8 @@ func (c *sdkClient) queryTupleErr(t require.TestingT, expected herodot.DefaultEr } } -func (c *sdkClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { - request := c.getReadClient().PermissionApi.CheckPermission(c.requestCtx()). +func (c *sdkClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { + request := c.getReadClient().PermissionApi.CheckPermission(c.requestCtx(t)). Namespace(r.Namespace). Object(r.Object). Relation(r.Relation) @@ -250,7 +254,76 @@ func (c *sdkClient) check(t require.TestingT, r *ketoapi.RelationTuple) bool { return resp.GetAllowed() } -func buildTree(t require.TestingT, mt *httpclient.ExpandedPermissionTree) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (c *sdkClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { + request := c.getReadClient().PermissionApi.BatchCheckPermission(c.requestCtx(t)). + BatchCheckPermissionBody(httpclient.BatchCheckPermissionBody{ + Tuples: tuplesToRelationships(requestTuples), + }) + + _, _, err := request.Execute() + switch typedErr := err.(type) { + case nil: + require.FailNow(t, "expected error but got nil") + case *httpclient.GenericOpenAPIError: + assert.Contains(t, typedErr.Error(), expected.Reason()) + default: + require.FailNow(t, "got unknown error %+v\nexpected %+v", err, expected) + } +} + +func (c *sdkClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { + request := c.getReadClient().PermissionApi.BatchCheckPermission(c.requestCtx(t)). + BatchCheckPermissionBody(httpclient.BatchCheckPermissionBody{ + Tuples: tuplesToRelationships(requestTuples), + }) + + resp, _, err := request.Execute() + require.NoError(t, err) + + responses := make([]checkResponse, len(resp.Results)) + for i, result := range resp.Results { + errMsg := "" + if result.Error != nil { + errMsg = *result.Error + } + responses[i] = checkResponse{ + allowed: result.Allowed, + errorMessage: errMsg, + } + } + return responses +} + +func tuplesToProto(tuples []*ketoapi.RelationTuple) []*rts.RelationTuple { + relationships := make([]*rts.RelationTuple, len(tuples)) + for i, requestTuple := range tuples { + relationships[i] = requestTuple.ToProto() + } + return relationships +} + +func tuplesToRelationships(tuples []*ketoapi.RelationTuple) []httpclient.Relationship { + relationships := make([]httpclient.Relationship, len(tuples)) + for i, requestTuple := range tuples { + relationship := httpclient.Relationship{ + Namespace: requestTuple.Namespace, + Object: requestTuple.Object, + Relation: requestTuple.Relation, + SubjectId: requestTuple.SubjectID, + } + if requestTuple.SubjectSet != nil { + relationship.SubjectSet = &httpclient.SubjectSet{ + Namespace: requestTuple.SubjectSet.Namespace, + Object: requestTuple.SubjectSet.Object, + Relation: requestTuple.SubjectSet.Relation, + } + } + relationships[i] = relationship + } + return relationships +} + +func buildTree(t *testing.T, mt *httpclient.ExpandedPermissionTree) *ketoapi.Tree[*ketoapi.RelationTuple] { result := &ketoapi.Tree[*ketoapi.RelationTuple]{ Type: ketoapi.TreeNodeType(mt.Type), } @@ -278,8 +351,8 @@ func buildTree(t require.TestingT, mt *httpclient.ExpandedPermissionTree) *ketoa return result } -func (c *sdkClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { - request := c.getReadClient().PermissionApi.ExpandPermissions(c.requestCtx()). +func (c *sdkClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { + request := c.getReadClient().PermissionApi.ExpandPermissions(c.requestCtx(t)). Namespace(r.Namespace). Object(r.Object). Relation(r.Relation). @@ -291,16 +364,16 @@ func (c *sdkClient) expand(t require.TestingT, r *ketoapi.SubjectSet, depth int) return buildTree(t, resp) } -func (c *sdkClient) waitUntilLive(t require.TestingT) { - resp, _, err := c.getReadClient().MetadataApi.IsReady(c.requestCtx()).Execute() +func (c *sdkClient) waitUntilLive(t *testing.T) { + resp, _, err := c.getReadClient().MetadataApi.IsReady(c.requestCtx(t)).Execute() for err != nil { - resp, _, err = c.getReadClient().MetadataApi.IsReady(c.requestCtx()).Execute() + resp, _, err = c.getReadClient().MetadataApi.IsReady(c.requestCtx(t)).Execute() } require.Equal(t, "ok", resp.Status) } -func (c *sdkClient) queryNamespaces(t require.TestingT) (response ketoapi.GetNamespacesResponse) { - res, _, err := c.getReadClient().RelationshipApi.ListRelationshipNamespaces(c.requestCtx()).Execute() +func (c *sdkClient) queryNamespaces(t *testing.T) (response ketoapi.GetNamespacesResponse) { + res, _, err := c.getReadClient().RelationshipApi.ListRelationshipNamespaces(c.requestCtx(t)).Execute() require.NoError(t, err) require.NoError(t, convert(res, &response)) diff --git a/internal/e2e/testcases_test.go b/internal/e2e/testcases_test.go index 1d15aca32..0ee52859f 100644 --- a/internal/e2e/testcases_test.go +++ b/internal/e2e/testcases_test.go @@ -61,6 +61,10 @@ func runCases(c client, m *namespaceTestManager) func(*testing.T) { // try the check API to see whether the tuple is interpreted correctly assert.True(t, c.check(t, tuple)) + batchResult := c.batchCheck(t, []*ketoapi.RelationTuple{tuple}) + require.Len(t, batchResult, 1) + assert.True(t, batchResult[0].allowed) + assert.Empty(t, batchResult[0].errorMessage) }) t.Run("case=creates tuple with empty IDs", func(t *testing.T) { @@ -87,6 +91,10 @@ func runCases(c client, m *namespaceTestManager) func(*testing.T) { c.createTuple(t, tp) // try the check API to see whether the tuple is interpreted correctly assert.True(t, c.check(t, tp)) + batchResult := c.batchCheck(t, []*ketoapi.RelationTuple{tp}) + require.Len(t, batchResult, 1) + assert.True(t, batchResult[0].allowed) + assert.Empty(t, batchResult[0].errorMessage) } resp := c.queryTuple(t, &ketoapi.RelationQuery{Namespace: &n.Name}) @@ -113,6 +121,93 @@ func runCases(c client, m *namespaceTestManager) func(*testing.T) { c.createTuple(t, rt) assert.True(t, c.check(t, rt)) + batchResult := c.batchCheck(t, []*ketoapi.RelationTuple{rt}) + require.Len(t, batchResult, 1) + assert.True(t, batchResult[0].allowed) + assert.Empty(t, batchResult[0].errorMessage) + }) + + t.Run("case=batch check", func(t *testing.T) { + /* + Test batch check with four cases: + - Allowed single subject tuple + - Allowed subject set tuple + - Tuple with unknown namespace (will return an error for this case) + - Dis-allowed tuple + */ + namespace1 := &namespace.Namespace{Name: t.Name()} + namespace2 := &namespace.Namespace{Name: t.Name() + "-2"} + m.add(t, namespace1) + m.add(t, namespace2) + + obj1 := fmt.Sprintf("obj for client %T", c) + obj2 := fmt.Sprintf("another obj for client %T", c) + rel1 := "check" + rel2 := "access" + + tupleSubjectSet := &ketoapi.RelationTuple{ + Namespace: namespace1.Name, + Object: obj1, + Relation: rel1, + SubjectSet: &ketoapi.SubjectSet{ + Namespace: namespace1.Name, + Object: obj1, + Relation: rel1, + }, + } + c.createTuple(t, tupleSubjectSet) + + tupleSingleSubject := &ketoapi.RelationTuple{ + Namespace: namespace2.Name, + Object: obj2, + Relation: rel2, + SubjectID: pointerx.Ptr("sub1"), + } + c.createTuple(t, tupleSingleSubject) + + unknownNamespaceTuple := &ketoapi.RelationTuple{ + Namespace: "unknown-namespace", + Object: obj1, + Relation: rel1, + SubjectID: pointerx.Ptr("sub1"), + } + + unknownSubjectTuple := &ketoapi.RelationTuple{ + Namespace: namespace1.Name, + Object: obj1, + Relation: rel1, + SubjectID: pointerx.Ptr("unknown-sub"), + } + + batchResult := c.batchCheck(t, []*ketoapi.RelationTuple{tupleSubjectSet, tupleSingleSubject, + unknownNamespaceTuple, unknownSubjectTuple}) + require.Len(t, batchResult, 4) + assert.True(t, batchResult[0].allowed) + assert.Empty(t, batchResult[0].errorMessage) + assert.True(t, batchResult[1].allowed) + assert.Empty(t, batchResult[1].errorMessage) + assert.False(t, batchResult[2].allowed) + assert.Contains(t, batchResult[2].errorMessage, "The requested resource could not be found") + assert.False(t, batchResult[3].allowed) + assert.Empty(t, batchResult[3].errorMessage) + + // Verify a call with no tuples returns successfully with no results + emptyResults := c.batchCheck(t, []*ketoapi.RelationTuple{}) + require.Empty(t, emptyResults) + }) + + t.Run("case=batch check validation errors", func(t *testing.T) { + // Pass in 11 tuples to check, more than the default limit of 10, and verify the request is rejected + tuples := make([]*ketoapi.RelationTuple, 11) + for i := range tuples { + tuples[i] = &ketoapi.RelationTuple{ + Namespace: "namespace-name", + Object: "obj", + Relation: "rel", + SubjectID: pointerx.Ptr("sub"), + } + } + c.batchCheckErr(t, tuples, herodot.ErrBadRequest) }) t.Run("case=expand API", func(t *testing.T) { diff --git a/internal/e2e/transaction_cases_test.go b/internal/e2e/transaction_cases_test.go index 4e4e7e5b0..92ea4897d 100644 --- a/internal/e2e/transaction_cases_test.go +++ b/internal/e2e/transaction_cases_test.go @@ -4,15 +4,20 @@ package e2e import ( + "cmp" + "slices" + "strconv" "testing" - - "github.com/ory/x/pointerx" - - "github.com/ory/keto/ketoapi" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ory/x/pointerx" "github.com/ory/keto/internal/namespace" + "github.com/ory/keto/internal/x" + "github.com/ory/keto/ketoapi" ) func runTransactionCases(c transactClient, m *namespaceTestManager) func(*testing.T) { @@ -58,6 +63,104 @@ func runTransactionCases(c transactClient, m *namespaceTestManager) func(*testin assert.Len(t, resp.RelationTuples, 0) }) + t.Run("case=duplicate string representations", func(t *testing.T) { + n := &namespace.Namespace{Name: t.Name()} + m.add(t, n) + c.transactTuples(t, []*ketoapi.RelationTuple{ + { + Namespace: n.Name, + Object: "o", + Relation: "rel", + SubjectID: pointerx.Ptr("sid"), + }, + { + Namespace: n.Name, + Object: "o", + Relation: "rel", + SubjectID: pointerx.Ptr("sid"), + }, + }, nil) + }) + + t.Run("case=large inserts and deletes", func(t *testing.T) { + if !testing.Short() { + t.Skip("This test is fairly expensive, especially the deletion.") + } + + ns := []*namespace.Namespace{ + {Name: t.Name() + "1"}, + {Name: t.Name() + "2"}, + } + m.add(t, ns...) + + var tuples []*ketoapi.RelationTuple + //for i := range 12001 { + for i := range 12001 { + tuples = append(tuples, + &ketoapi.RelationTuple{ + Namespace: ns[0].Name, + Object: "o" + strconv.Itoa(i), + Relation: "rela", + SubjectSet: &ketoapi.SubjectSet{ + Namespace: ns[1].Name, + Object: "o" + strconv.Itoa(i), + Relation: "relx", + }, + }, + &ketoapi.RelationTuple{ + Namespace: ns[0].Name, + Object: "o" + strconv.Itoa(i), + Relation: "relb", + SubjectID: pointerx.Ptr("sid"), + }, + ) + } + + t0 := time.Now() + c.transactTuples(t, tuples, nil) + t.Log("insert", time.Since(t0)) + + t0 = time.Now() + var resp []*ketoapi.RelationTuple + var pt string + for { + r := c.queryTuple(t, &ketoapi.RelationQuery{ + Namespace: &ns[0].Name, + }, x.WithSize(1000), x.WithToken(pt)) + resp = append(resp, r.RelationTuples...) + pt = r.NextPageToken + if pt == "" { + break + } + } + t.Log("query", time.Since(t0)) + + sort := func(a, b *ketoapi.RelationTuple) int { + return cmp.Or( + cmp.Compare(a.Namespace, b.Namespace), + cmp.Compare(a.Object, b.Object), + cmp.Compare(a.Relation, b.Relation), + ) + } + t0 = time.Now() + slices.SortFunc(resp, sort) + slices.SortFunc(tuples, sort) + t.Log("sort", time.Since(t0)) + + t0 = time.Now() + require.Equal(t, tuples, resp) + t.Log("equal", time.Since(t0)) + + t0 = time.Now() + c.transactTuples(t, nil, tuples) + t.Log(t.Name(), "delete took:", time.Since(t0)) + + resp = c.queryTuple(t, &ketoapi.RelationQuery{ + Namespace: &ns[0].Name, + }).RelationTuples + assert.Len(t, resp, 0) + }) + t.Run("case=expand-api-display-access docs code sample", func(t *testing.T) { files := &namespace.Namespace{Name: t.Name() + "files"} directories := &namespace.Namespace{Name: t.Name() + "directories"} diff --git a/internal/httpclient/.openapi-generator/FILES b/internal/httpclient/.openapi-generator/FILES index 70e4141fc..94f736890 100644 --- a/internal/httpclient/.openapi-generator/FILES +++ b/internal/httpclient/.openapi-generator/FILES @@ -8,8 +8,11 @@ api_permission.go api_relationship.go client.go configuration.go +docs/BatchCheckPermissionBody.md +docs/BatchCheckPermissionResult.md docs/CheckOplSyntaxResult.md docs/CheckPermissionResult.md +docs/CheckPermissionResultWithError.md docs/CreateRelationshipBody.md docs/ErrorGeneric.md docs/ErrorGenericError.md @@ -40,8 +43,11 @@ docs/SubjectSetQuery.md git_push.sh go.mod go.sum +model_batch_check_permission_body.go +model_batch_check_permission_result.go model_check_opl_syntax_result.go model_check_permission_result.go +model_check_permission_result_with_error.go model_create_relationship_body.go model_error_generic.go model_error_generic_error.go diff --git a/internal/httpclient/README.md b/internal/httpclient/README.md index fbb514201..b46c78e7c 100644 --- a/internal/httpclient/README.md +++ b/internal/httpclient/README.md @@ -82,6 +82,7 @@ Class | Method | HTTP request | Description *MetadataApi* | [**GetVersion**](docs/MetadataApi.md#getversion) | **Get** /version | Return Running Software Version. *MetadataApi* | [**IsAlive**](docs/MetadataApi.md#isalive) | **Get** /health/alive | Check HTTP Server Status *MetadataApi* | [**IsReady**](docs/MetadataApi.md#isready) | **Get** /health/ready | Check HTTP Server and Database Status +*PermissionApi* | [**BatchCheckPermission**](docs/PermissionApi.md#batchcheckpermission) | **Post** /relation-tuples/batch/check | Performs an authorization check for a batch of tuples. *PermissionApi* | [**CheckPermission**](docs/PermissionApi.md#checkpermission) | **Get** /relation-tuples/check/openapi | Performs an authorization check. *PermissionApi* | [**CheckPermissionOrError**](docs/PermissionApi.md#checkpermissionorerror) | **Get** /relation-tuples/check | Performs an authorization check. *PermissionApi* | [**ExpandPermissions**](docs/PermissionApi.md#expandpermissions) | **Get** /relation-tuples/expand | Expands the subject set into a tree of subjects. @@ -97,8 +98,11 @@ Class | Method | HTTP request | Description ## Documentation For Models + - [BatchCheckPermissionBody](docs/BatchCheckPermissionBody.md) + - [BatchCheckPermissionResult](docs/BatchCheckPermissionResult.md) - [CheckOplSyntaxResult](docs/CheckOplSyntaxResult.md) - [CheckPermissionResult](docs/CheckPermissionResult.md) + - [CheckPermissionResultWithError](docs/CheckPermissionResultWithError.md) - [CreateRelationshipBody](docs/CreateRelationshipBody.md) - [ErrorGeneric](docs/ErrorGeneric.md) - [ErrorGenericError](docs/ErrorGenericError.md) diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index 926bcd3e9..5fcbddd21 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -395,6 +395,56 @@ paths: summary: Lists ACL relationships. tags: - relationship + /relation-tuples/batch/check: + post: + description: "To learn how relationship tuples and the check works, head over\ + \ to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview)." + operationId: batchCheckPermission + parameters: + - description: |- + The maximum depth to search for a relation. + + If the value is less than 1 or greater than the global + max-depth then the global max-depth will be used instead. + explode: true + in: query + name: max-depth + required: false + schema: + format: int32 + type: integer + style: form + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/batchCheckPermissionBody' + description: Batch Check Permission Body. + required: true + x-originalParamName: body + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/batchCheckPermissionResult' + description: "The response of the permission check, in case it is allowed.\ + \ For the `/openapi` endpoints, the status code is always 200." + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/errorGeneric' + description: errorGeneric + default: + content: + application/json: + schema: + $ref: '#/components/schemas/errorGeneric' + description: errorGeneric + summary: Performs an authorization check for a batch of tuples. + tags: + - permission /relation-tuples/check: get: operationId: checkPermissionOrError @@ -802,6 +852,30 @@ components: UUID: format: uuid4 type: string + batchCheckPermissionBody: + properties: + tuples: + items: + $ref: '#/components/schemas/relationship' + type: array + type: object + batchCheckPermissionResult: + description: The response for a CheckService.BatchCheck rpc. + example: + results: + - allowed: true + error: error + - allowed: true + error: error + properties: + results: + description: |- + The results of the batch check. The order of these + results will match the order of the input. + items: + $ref: '#/components/schemas/checkPermissionResultWithError' + type: array + type: object checkOplSyntaxResult: example: parseErrors: @@ -859,6 +933,30 @@ components: required: - allowed type: object + checkPermissionResultWithError: + description: The response for an individual check in the CheckService.BatchCheck + rpc. + example: + allowed: true + error: error + properties: + allowed: + description: |- + Whether the specified subject (id) + is related to the requested object. + + It is false by default if no ACL matches. + type: boolean + error: + description: |- + If there was an error checking the tuple, + this will contain the error message. + + If the check was performed successfully, this will be empty. + type: string + required: + - allowed + type: object createRelationshipBody: properties: namespace: diff --git a/internal/httpclient/api_permission.go b/internal/httpclient/api_permission.go index 65fbc49e4..2da61d835 100644 --- a/internal/httpclient/api_permission.go +++ b/internal/httpclient/api_permission.go @@ -26,6 +26,20 @@ var ( type PermissionApi interface { + /* + * BatchCheckPermission Performs an authorization check for a batch of tuples. + * To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return PermissionApiApiBatchCheckPermissionRequest + */ + BatchCheckPermission(ctx context.Context) PermissionApiApiBatchCheckPermissionRequest + + /* + * BatchCheckPermissionExecute executes the request + * @return BatchCheckPermissionResult + */ + BatchCheckPermissionExecute(r PermissionApiApiBatchCheckPermissionRequest) (*BatchCheckPermissionResult, *http.Response, error) + /* * CheckPermission Performs an authorization check. * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @@ -95,6 +109,143 @@ type PermissionApi interface { // PermissionApiService PermissionApi service type PermissionApiService service +type PermissionApiApiBatchCheckPermissionRequest struct { + ctx context.Context + ApiService PermissionApi + batchCheckPermissionBody *BatchCheckPermissionBody + maxDepth *int32 +} + +func (r PermissionApiApiBatchCheckPermissionRequest) BatchCheckPermissionBody(batchCheckPermissionBody BatchCheckPermissionBody) PermissionApiApiBatchCheckPermissionRequest { + r.batchCheckPermissionBody = &batchCheckPermissionBody + return r +} +func (r PermissionApiApiBatchCheckPermissionRequest) MaxDepth(maxDepth int32) PermissionApiApiBatchCheckPermissionRequest { + r.maxDepth = &maxDepth + return r +} + +func (r PermissionApiApiBatchCheckPermissionRequest) Execute() (*BatchCheckPermissionResult, *http.Response, error) { + return r.ApiService.BatchCheckPermissionExecute(r) +} + +/* + * BatchCheckPermission Performs an authorization check for a batch of tuples. + * To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return PermissionApiApiBatchCheckPermissionRequest + */ +func (a *PermissionApiService) BatchCheckPermission(ctx context.Context) PermissionApiApiBatchCheckPermissionRequest { + return PermissionApiApiBatchCheckPermissionRequest{ + ApiService: a, + ctx: ctx, + } +} + +/* + * Execute executes the request + * @return BatchCheckPermissionResult + */ +func (a *PermissionApiService) BatchCheckPermissionExecute(r PermissionApiApiBatchCheckPermissionRequest) (*BatchCheckPermissionResult, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue *BatchCheckPermissionResult + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PermissionApiService.BatchCheckPermission") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/relation-tuples/batch/check" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.batchCheckPermissionBody == nil { + return localVarReturnValue, nil, reportError("batchCheckPermissionBody is required and must be specified") + } + + if r.maxDepth != nil { + localVarQueryParams.Add("max-depth", parameterToString(*r.maxDepth, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.batchCheckPermissionBody + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ErrorGeneric + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + var v ErrorGeneric + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + type PermissionApiApiCheckPermissionRequest struct { ctx context.Context ApiService PermissionApi diff --git a/internal/httpclient/docs/BatchCheckPermissionBody.md b/internal/httpclient/docs/BatchCheckPermissionBody.md new file mode 100644 index 000000000..a91da96d5 --- /dev/null +++ b/internal/httpclient/docs/BatchCheckPermissionBody.md @@ -0,0 +1,56 @@ +# BatchCheckPermissionBody + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Tuples** | Pointer to [**[]Relationship**](Relationship.md) | | [optional] + +## Methods + +### NewBatchCheckPermissionBody + +`func NewBatchCheckPermissionBody() *BatchCheckPermissionBody` + +NewBatchCheckPermissionBody instantiates a new BatchCheckPermissionBody object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewBatchCheckPermissionBodyWithDefaults + +`func NewBatchCheckPermissionBodyWithDefaults() *BatchCheckPermissionBody` + +NewBatchCheckPermissionBodyWithDefaults instantiates a new BatchCheckPermissionBody object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetTuples + +`func (o *BatchCheckPermissionBody) GetTuples() []Relationship` + +GetTuples returns the Tuples field if non-nil, zero value otherwise. + +### GetTuplesOk + +`func (o *BatchCheckPermissionBody) GetTuplesOk() (*[]Relationship, bool)` + +GetTuplesOk returns a tuple with the Tuples field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetTuples + +`func (o *BatchCheckPermissionBody) SetTuples(v []Relationship)` + +SetTuples sets Tuples field to given value. + +### HasTuples + +`func (o *BatchCheckPermissionBody) HasTuples() bool` + +HasTuples returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/internal/httpclient/docs/BatchCheckPermissionResult.md b/internal/httpclient/docs/BatchCheckPermissionResult.md new file mode 100644 index 000000000..182640cd0 --- /dev/null +++ b/internal/httpclient/docs/BatchCheckPermissionResult.md @@ -0,0 +1,56 @@ +# BatchCheckPermissionResult + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Results** | Pointer to [**[]CheckPermissionResultWithError**](CheckPermissionResultWithError.md) | The results of the batch check. The order of these results will match the order of the input. | [optional] + +## Methods + +### NewBatchCheckPermissionResult + +`func NewBatchCheckPermissionResult() *BatchCheckPermissionResult` + +NewBatchCheckPermissionResult instantiates a new BatchCheckPermissionResult object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewBatchCheckPermissionResultWithDefaults + +`func NewBatchCheckPermissionResultWithDefaults() *BatchCheckPermissionResult` + +NewBatchCheckPermissionResultWithDefaults instantiates a new BatchCheckPermissionResult object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetResults + +`func (o *BatchCheckPermissionResult) GetResults() []CheckPermissionResultWithError` + +GetResults returns the Results field if non-nil, zero value otherwise. + +### GetResultsOk + +`func (o *BatchCheckPermissionResult) GetResultsOk() (*[]CheckPermissionResultWithError, bool)` + +GetResultsOk returns a tuple with the Results field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetResults + +`func (o *BatchCheckPermissionResult) SetResults(v []CheckPermissionResultWithError)` + +SetResults sets Results field to given value. + +### HasResults + +`func (o *BatchCheckPermissionResult) HasResults() bool` + +HasResults returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/internal/httpclient/docs/CheckPermissionResultWithError.md b/internal/httpclient/docs/CheckPermissionResultWithError.md new file mode 100644 index 000000000..645c8f17d --- /dev/null +++ b/internal/httpclient/docs/CheckPermissionResultWithError.md @@ -0,0 +1,77 @@ +# CheckPermissionResultWithError + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Allowed** | **bool** | Whether the specified subject (id) is related to the requested object. It is false by default if no ACL matches. | +**Error** | Pointer to **string** | If there was an error checking the tuple, this will contain the error message. If the check was performed successfully, this will be empty. | [optional] + +## Methods + +### NewCheckPermissionResultWithError + +`func NewCheckPermissionResultWithError(allowed bool, ) *CheckPermissionResultWithError` + +NewCheckPermissionResultWithError instantiates a new CheckPermissionResultWithError object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewCheckPermissionResultWithErrorWithDefaults + +`func NewCheckPermissionResultWithErrorWithDefaults() *CheckPermissionResultWithError` + +NewCheckPermissionResultWithErrorWithDefaults instantiates a new CheckPermissionResultWithError object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetAllowed + +`func (o *CheckPermissionResultWithError) GetAllowed() bool` + +GetAllowed returns the Allowed field if non-nil, zero value otherwise. + +### GetAllowedOk + +`func (o *CheckPermissionResultWithError) GetAllowedOk() (*bool, bool)` + +GetAllowedOk returns a tuple with the Allowed field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetAllowed + +`func (o *CheckPermissionResultWithError) SetAllowed(v bool)` + +SetAllowed sets Allowed field to given value. + + +### GetError + +`func (o *CheckPermissionResultWithError) GetError() string` + +GetError returns the Error field if non-nil, zero value otherwise. + +### GetErrorOk + +`func (o *CheckPermissionResultWithError) GetErrorOk() (*string, bool)` + +GetErrorOk returns a tuple with the Error field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetError + +`func (o *CheckPermissionResultWithError) SetError(v string)` + +SetError sets Error field to given value. + +### HasError + +`func (o *CheckPermissionResultWithError) HasError() bool` + +HasError returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/internal/httpclient/docs/PermissionApi.md b/internal/httpclient/docs/PermissionApi.md index c60fffa32..495fd92ad 100644 --- a/internal/httpclient/docs/PermissionApi.md +++ b/internal/httpclient/docs/PermissionApi.md @@ -4,6 +4,7 @@ All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- +[**BatchCheckPermission**](PermissionApi.md#BatchCheckPermission) | **Post** /relation-tuples/batch/check | Performs an authorization check for a batch of tuples. [**CheckPermission**](PermissionApi.md#CheckPermission) | **Get** /relation-tuples/check/openapi | Performs an authorization check. [**CheckPermissionOrError**](PermissionApi.md#CheckPermissionOrError) | **Get** /relation-tuples/check | Performs an authorization check. [**ExpandPermissions**](PermissionApi.md#ExpandPermissions) | **Get** /relation-tuples/expand | Expands the subject set into a tree of subjects. @@ -12,6 +13,74 @@ Method | HTTP request | Description +## BatchCheckPermission + +> BatchCheckPermissionResult BatchCheckPermission(ctx).BatchCheckPermissionBody(batchCheckPermissionBody).MaxDepth(maxDepth).Execute() + +Performs an authorization check for a batch of tuples. + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openapiclient "./openapi" +) + +func main() { + batchCheckPermissionBody := *openapiclient.NewBatchCheckPermissionBody() // BatchCheckPermissionBody | Batch Check Permission Body. + maxDepth := int32(56) // int32 | The maximum depth to search for a relation. If the value is less than 1 or greater than the global max-depth then the global max-depth will be used instead. (optional) + + configuration := openapiclient.NewConfiguration() + apiClient := openapiclient.NewAPIClient(configuration) + resp, r, err := apiClient.PermissionApi.BatchCheckPermission(context.Background()).BatchCheckPermissionBody(batchCheckPermissionBody).MaxDepth(maxDepth).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `PermissionApi.BatchCheckPermission``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + // response from `BatchCheckPermission`: BatchCheckPermissionResult + fmt.Fprintf(os.Stdout, "Response from `PermissionApi.BatchCheckPermission`: %v\n", resp) +} +``` + +### Path Parameters + + + +### Other Parameters + +Other parameters are passed through a pointer to a apiBatchCheckPermissionRequest struct via the builder pattern + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **batchCheckPermissionBody** | [**BatchCheckPermissionBody**](BatchCheckPermissionBody.md) | Batch Check Permission Body. | + **maxDepth** | **int32** | The maximum depth to search for a relation. If the value is less than 1 or greater than the global max-depth then the global max-depth will be used instead. | + +### Return type + +[**BatchCheckPermissionResult**](BatchCheckPermissionResult.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + + ## CheckPermission > CheckPermissionResult CheckPermission(ctx).Namespace(namespace).Object(object).Relation(relation).SubjectId(subjectId).SubjectSetNamespace(subjectSetNamespace).SubjectSetObject(subjectSetObject).SubjectSetRelation(subjectSetRelation).MaxDepth(maxDepth).Execute() diff --git a/internal/httpclient/model_batch_check_permission_body.go b/internal/httpclient/model_batch_check_permission_body.go new file mode 100644 index 000000000..8fdd8c7b2 --- /dev/null +++ b/internal/httpclient/model_batch_check_permission_body.go @@ -0,0 +1,114 @@ +/* + * Ory Keto API + * + * Documentation for all of Ory Keto's REST APIs. gRPC is documented separately. + * + * API version: + * Contact: hi@ory.sh + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package client + +import ( + "encoding/json" +) + +// BatchCheckPermissionBody struct for BatchCheckPermissionBody +type BatchCheckPermissionBody struct { + Tuples []Relationship `json:"tuples,omitempty"` +} + +// NewBatchCheckPermissionBody instantiates a new BatchCheckPermissionBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBatchCheckPermissionBody() *BatchCheckPermissionBody { + this := BatchCheckPermissionBody{} + return &this +} + +// NewBatchCheckPermissionBodyWithDefaults instantiates a new BatchCheckPermissionBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBatchCheckPermissionBodyWithDefaults() *BatchCheckPermissionBody { + this := BatchCheckPermissionBody{} + return &this +} + +// GetTuples returns the Tuples field value if set, zero value otherwise. +func (o *BatchCheckPermissionBody) GetTuples() []Relationship { + if o == nil || o.Tuples == nil { + var ret []Relationship + return ret + } + return o.Tuples +} + +// GetTuplesOk returns a tuple with the Tuples field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BatchCheckPermissionBody) GetTuplesOk() ([]Relationship, bool) { + if o == nil || o.Tuples == nil { + return nil, false + } + return o.Tuples, true +} + +// HasTuples returns a boolean if a field has been set. +func (o *BatchCheckPermissionBody) HasTuples() bool { + if o != nil && o.Tuples != nil { + return true + } + + return false +} + +// SetTuples gets a reference to the given []Relationship and assigns it to the Tuples field. +func (o *BatchCheckPermissionBody) SetTuples(v []Relationship) { + o.Tuples = v +} + +func (o BatchCheckPermissionBody) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Tuples != nil { + toSerialize["tuples"] = o.Tuples + } + return json.Marshal(toSerialize) +} + +type NullableBatchCheckPermissionBody struct { + value *BatchCheckPermissionBody + isSet bool +} + +func (v NullableBatchCheckPermissionBody) Get() *BatchCheckPermissionBody { + return v.value +} + +func (v *NullableBatchCheckPermissionBody) Set(val *BatchCheckPermissionBody) { + v.value = val + v.isSet = true +} + +func (v NullableBatchCheckPermissionBody) IsSet() bool { + return v.isSet +} + +func (v *NullableBatchCheckPermissionBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBatchCheckPermissionBody(val *BatchCheckPermissionBody) *NullableBatchCheckPermissionBody { + return &NullableBatchCheckPermissionBody{value: val, isSet: true} +} + +func (v NullableBatchCheckPermissionBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBatchCheckPermissionBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/httpclient/model_batch_check_permission_result.go b/internal/httpclient/model_batch_check_permission_result.go new file mode 100644 index 000000000..eb5502f37 --- /dev/null +++ b/internal/httpclient/model_batch_check_permission_result.go @@ -0,0 +1,115 @@ +/* + * Ory Keto API + * + * Documentation for all of Ory Keto's REST APIs. gRPC is documented separately. + * + * API version: + * Contact: hi@ory.sh + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package client + +import ( + "encoding/json" +) + +// BatchCheckPermissionResult The response for a CheckService.BatchCheck rpc. +type BatchCheckPermissionResult struct { + // The results of the batch check. The order of these results will match the order of the input. + Results []CheckPermissionResultWithError `json:"results,omitempty"` +} + +// NewBatchCheckPermissionResult instantiates a new BatchCheckPermissionResult object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBatchCheckPermissionResult() *BatchCheckPermissionResult { + this := BatchCheckPermissionResult{} + return &this +} + +// NewBatchCheckPermissionResultWithDefaults instantiates a new BatchCheckPermissionResult object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBatchCheckPermissionResultWithDefaults() *BatchCheckPermissionResult { + this := BatchCheckPermissionResult{} + return &this +} + +// GetResults returns the Results field value if set, zero value otherwise. +func (o *BatchCheckPermissionResult) GetResults() []CheckPermissionResultWithError { + if o == nil || o.Results == nil { + var ret []CheckPermissionResultWithError + return ret + } + return o.Results +} + +// GetResultsOk returns a tuple with the Results field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BatchCheckPermissionResult) GetResultsOk() ([]CheckPermissionResultWithError, bool) { + if o == nil || o.Results == nil { + return nil, false + } + return o.Results, true +} + +// HasResults returns a boolean if a field has been set. +func (o *BatchCheckPermissionResult) HasResults() bool { + if o != nil && o.Results != nil { + return true + } + + return false +} + +// SetResults gets a reference to the given []CheckPermissionResultWithError and assigns it to the Results field. +func (o *BatchCheckPermissionResult) SetResults(v []CheckPermissionResultWithError) { + o.Results = v +} + +func (o BatchCheckPermissionResult) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Results != nil { + toSerialize["results"] = o.Results + } + return json.Marshal(toSerialize) +} + +type NullableBatchCheckPermissionResult struct { + value *BatchCheckPermissionResult + isSet bool +} + +func (v NullableBatchCheckPermissionResult) Get() *BatchCheckPermissionResult { + return v.value +} + +func (v *NullableBatchCheckPermissionResult) Set(val *BatchCheckPermissionResult) { + v.value = val + v.isSet = true +} + +func (v NullableBatchCheckPermissionResult) IsSet() bool { + return v.isSet +} + +func (v *NullableBatchCheckPermissionResult) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBatchCheckPermissionResult(val *BatchCheckPermissionResult) *NullableBatchCheckPermissionResult { + return &NullableBatchCheckPermissionResult{value: val, isSet: true} +} + +func (v NullableBatchCheckPermissionResult) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBatchCheckPermissionResult) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/httpclient/model_check_permission_result_with_error.go b/internal/httpclient/model_check_permission_result_with_error.go new file mode 100644 index 000000000..b7661b4f4 --- /dev/null +++ b/internal/httpclient/model_check_permission_result_with_error.go @@ -0,0 +1,145 @@ +/* + * Ory Keto API + * + * Documentation for all of Ory Keto's REST APIs. gRPC is documented separately. + * + * API version: + * Contact: hi@ory.sh + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package client + +import ( + "encoding/json" +) + +// CheckPermissionResultWithError The response for an individual check in the CheckService.BatchCheck rpc. +type CheckPermissionResultWithError struct { + // Whether the specified subject (id) is related to the requested object. It is false by default if no ACL matches. + Allowed bool `json:"allowed"` + // If there was an error checking the tuple, this will contain the error message. If the check was performed successfully, this will be empty. + Error *string `json:"error,omitempty"` +} + +// NewCheckPermissionResultWithError instantiates a new CheckPermissionResultWithError object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCheckPermissionResultWithError(allowed bool) *CheckPermissionResultWithError { + this := CheckPermissionResultWithError{} + this.Allowed = allowed + return &this +} + +// NewCheckPermissionResultWithErrorWithDefaults instantiates a new CheckPermissionResultWithError object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCheckPermissionResultWithErrorWithDefaults() *CheckPermissionResultWithError { + this := CheckPermissionResultWithError{} + return &this +} + +// GetAllowed returns the Allowed field value +func (o *CheckPermissionResultWithError) GetAllowed() bool { + if o == nil { + var ret bool + return ret + } + + return o.Allowed +} + +// GetAllowedOk returns a tuple with the Allowed field value +// and a boolean to check if the value has been set. +func (o *CheckPermissionResultWithError) GetAllowedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Allowed, true +} + +// SetAllowed sets field value +func (o *CheckPermissionResultWithError) SetAllowed(v bool) { + o.Allowed = v +} + +// GetError returns the Error field value if set, zero value otherwise. +func (o *CheckPermissionResultWithError) GetError() string { + if o == nil || o.Error == nil { + var ret string + return ret + } + return *o.Error +} + +// GetErrorOk returns a tuple with the Error field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CheckPermissionResultWithError) GetErrorOk() (*string, bool) { + if o == nil || o.Error == nil { + return nil, false + } + return o.Error, true +} + +// HasError returns a boolean if a field has been set. +func (o *CheckPermissionResultWithError) HasError() bool { + if o != nil && o.Error != nil { + return true + } + + return false +} + +// SetError gets a reference to the given string and assigns it to the Error field. +func (o *CheckPermissionResultWithError) SetError(v string) { + o.Error = &v +} + +func (o CheckPermissionResultWithError) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["allowed"] = o.Allowed + } + if o.Error != nil { + toSerialize["error"] = o.Error + } + return json.Marshal(toSerialize) +} + +type NullableCheckPermissionResultWithError struct { + value *CheckPermissionResultWithError + isSet bool +} + +func (v NullableCheckPermissionResultWithError) Get() *CheckPermissionResultWithError { + return v.value +} + +func (v *NullableCheckPermissionResultWithError) Set(val *CheckPermissionResultWithError) { + v.value = val + v.isSet = true +} + +func (v NullableCheckPermissionResultWithError) IsSet() bool { + return v.isSet +} + +func (v *NullableCheckPermissionResultWithError) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCheckPermissionResultWithError(val *CheckPermissionResultWithError) *NullableCheckPermissionResultWithError { + return &NullableCheckPermissionResultWithError{value: val, isSet: true} +} + +func (v NullableCheckPermissionResultWithError) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCheckPermissionResultWithError) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/namespace/ast/operator_string.go b/internal/namespace/ast/operator_string.go index bc0b7d5ed..74f212cb6 100644 --- a/internal/namespace/ast/operator_string.go +++ b/internal/namespace/ast/operator_string.go @@ -1,6 +1,3 @@ -// Copyright © 2023 Ory Corp -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "stringer -type=Operator -linecomment"; DO NOT EDIT. package ast diff --git a/internal/persistence/definitions.go b/internal/persistence/definitions.go index 9b6a51a8a..876504090 100644 --- a/internal/persistence/definitions.go +++ b/internal/persistence/definitions.go @@ -22,6 +22,7 @@ type ( Connection(ctx context.Context) *pop.Connection NetworkID(ctx context.Context) uuid.UUID + SetNetwork(nid uuid.UUID) Transaction(ctx context.Context, f func(ctx context.Context) error) error } Migrator interface { diff --git a/internal/persistence/sql/migrations/migratest/migration_test.go b/internal/persistence/sql/migrations/migratest/migration_test.go index d6e771d3b..3a8bb7b5a 100644 --- a/internal/persistence/sql/migrations/migratest/migration_test.go +++ b/internal/persistence/sql/migrations/migratest/migration_test.go @@ -178,7 +178,7 @@ func TestMigrations(t *testing.T) { oldRTs := make([]tuplesBeforeUUID, 2000) expected := make([]*ketoapi.RelationTuple, len(oldRTs)) - for i := 0; i < len(oldRTs); i++ { + for i := range oldRTs { oldRTs[i] = tuplesBeforeUUID{ NetworkID: p.NetworkID(ctx), //lint:ignore SA1019 backwards compatibility diff --git a/internal/persistence/sql/migrations/uuidmapping/uuid_mapping_migrator.go b/internal/persistence/sql/migrations/uuidmapping/uuid_mapping_migrator.go index 96b0075aa..59411bd99 100644 --- a/internal/persistence/sql/migrations/uuidmapping/uuid_mapping_migrator.go +++ b/internal/persistence/sql/migrations/uuidmapping/uuid_mapping_migrator.go @@ -15,7 +15,6 @@ import ( "github.com/ory/x/popx" "github.com/ory/x/sqlcon" "github.com/pkg/errors" - "golang.org/x/exp/maps" "github.com/ory/keto/internal/namespace" ) @@ -385,16 +384,19 @@ func BatchReplaceUUIDs(conn *pop.Connection, uuidToTargets map[uuid.UUID][]*stri return nil } - ids := maps.Keys(uuidToTargets) + ids := make([]uuid.UUID, 0, len(uuidToTargets)) + for id := range uuidToTargets { + ids = append(ids, id) + } - mappings := &[]UUIDMapping{} + mappings := make([]UUIDMapping, 0, len(ids)) query := conn.Where("id in (?)", ids) - if err := sqlcon.HandleError(query.All(mappings)); err != nil { + if err := sqlcon.HandleError(query.All(&mappings)); err != nil { return err } // Write the representation to the correct pointer(s). - for _, m := range *mappings { + for _, m := range mappings { for _, target := range uuidToTargets[m.ID] { *target = m.StringRepresentation } diff --git a/internal/persistence/sql/persister.go b/internal/persistence/sql/persister.go index 963142e58..b7fc83098 100644 --- a/internal/persistence/sql/persister.go +++ b/internal/persistence/sql/persister.go @@ -6,11 +6,9 @@ package sql import ( "context" "embed" - "reflect" "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" - "github.com/ory/x/otelx" "github.com/ory/x/popx" "github.com/pkg/errors" @@ -70,24 +68,6 @@ func (p *Persister) Connection(ctx context.Context) *pop.Connection { return popx.GetConnection(ctx, p.conn.WithContext(ctx)) } -func (p *Persister) createWithNetwork(ctx context.Context, v interface{}) (err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.createWithNetwork") - defer otelx.End(span, &err) - - rv := reflect.ValueOf(v) - - if rv.Kind() != reflect.Ptr && rv.Elem().Kind() != reflect.Struct { - panic("expected to get *struct in create") - } - nID := rv.Elem().FieldByName("NetworkID") - if !nID.IsValid() || !nID.CanSet() { - panic("expected struct to have a 'NetworkID uuid.UUID' field") - } - nID.Set(reflect.ValueOf(p.NetworkID(ctx))) - - return p.Connection(ctx).Create(v) -} - func (p *Persister) queryWithNetwork(ctx context.Context) *pop.Query { return p.Connection(ctx).Where("nid = ?", p.NetworkID(ctx)) } @@ -100,6 +80,10 @@ func (p *Persister) NetworkID(ctx context.Context) uuid.UUID { return p.d.Contextualizer().Network(ctx, p.nid) } +func (p *Persister) SetNetwork(nid uuid.UUID) { + p.nid = nid +} + func internalPaginationFromOptions(opts ...x.PaginationOptionSetter) (*internalPagination, error) { xp := x.GetPaginationOptions(opts...) ip := &internalPagination{ diff --git a/internal/persistence/sql/query_test.go b/internal/persistence/sql/query_test.go new file mode 100644 index 000000000..cad24e6ab --- /dev/null +++ b/internal/persistence/sql/query_test.go @@ -0,0 +1,128 @@ +package sql + +import ( + "database/sql" + "testing" + "time" + + "github.com/gofrs/uuid" + "github.com/ory/x/uuidx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ory/keto/internal/relationtuple" +) + +func TestBuildDelete(t *testing.T) { + t.Parallel() + nid := uuidx.NewV4() + + q, args, err := buildDelete(nid, nil) + assert.Error(t, err) + assert.Empty(t, q) + assert.Empty(t, args) + + obj1, obj2, sub1, obj3 := uuidx.NewV4(), uuidx.NewV4(), uuidx.NewV4(), uuidx.NewV4() + + q, args, err = buildDelete(nid, []*relationtuple.RelationTuple{ + { + Namespace: "ns1", + Object: obj1, + Relation: "rel1", + Subject: &relationtuple.SubjectID{ + ID: sub1, + }, + }, + { + Namespace: "ns2", + Object: obj2, + Relation: "rel2", + Subject: &relationtuple.SubjectSet{ + Namespace: "ns3", + Object: obj3, + Relation: "rel3", + }, + }, + }) + require.NoError(t, err) + + // parentheses are important here + assert.Equal(t, q, "DELETE FROM keto_relation_tuples WHERE ((namespace = ? AND object = ? AND relation = ? AND subject_id = ? AND subject_set_namespace IS NULL AND subject_set_object IS NULL AND subject_set_relation IS NULL) OR (namespace = ? AND object = ? AND relation = ? AND subject_id IS NULL AND subject_set_namespace = ? AND subject_set_object = ? AND subject_set_relation = ?)) AND nid = ?") + assert.Equal(t, []any{"ns1", obj1, "rel1", sub1, "ns2", obj2, "rel2", "ns3", obj3, "rel3", nid}, args) +} + +func TestBuildInsert(t *testing.T) { + t.Parallel() + nid := uuidx.NewV4() + + q, args, err := buildInsert(time.Now(), nid, nil) + assert.Error(t, err) + assert.Empty(t, q) + assert.Empty(t, args) + + obj1, obj2, sub1, obj3 := uuidx.NewV4(), uuidx.NewV4(), uuidx.NewV4(), uuidx.NewV4() + + now := time.Now() + + q, args, err = buildInsert(now, nid, []*relationtuple.RelationTuple{ + { + Namespace: "ns1", + Object: obj1, + Relation: "rel1", + Subject: &relationtuple.SubjectID{ + ID: sub1, + }, + }, + { + Namespace: "ns2", + Object: obj2, + Relation: "rel2", + Subject: &relationtuple.SubjectSet{ + Namespace: "ns3", + Object: obj3, + Relation: "rel3", + }, + }, + }) + require.NoError(t, err) + + assert.Equal(t, q, "INSERT INTO keto_relation_tuples (shard_id, nid, namespace, object, relation, subject_id, subject_set_namespace, subject_set_object, subject_set_relation, commit_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + assert.Equal(t, []any{ + args[0], // this is kind of cheating but we generate the shard id in the buildInsert function + nid, + "ns1", + obj1, + "rel1", + uuid.NullUUID{sub1, true}, + sql.NullString{}, uuid.NullUUID{}, sql.NullString{}, + now, + + args[10], // again, cheating + nid, + "ns2", + obj2, + "rel2", + uuid.NullUUID{}, + sql.NullString{"ns3", true}, uuid.NullUUID{obj3, true}, sql.NullString{"rel3", true}, + now, + }, args) +} + +func TestBuildInsertUUIDs(t *testing.T) { + t.Parallel() + + foo, bar, baz := uuidx.NewV4(), uuidx.NewV4(), uuidx.NewV4() + uuids := []UUIDMapping{ + {foo, "foo"}, + {bar, "bar"}, + {baz, "baz"}, + } + + q, args := buildInsertUUIDs(uuids, "mysql") + assert.Equal(t, "INSERT IGNORE INTO keto_uuid_mappings (id, string_representation) VALUES (?,?),(?,?),(?,?)", q) + assert.Equal(t, []any{foo, "foo", bar, "bar", baz, "baz"}, args) + + q, args = buildInsertUUIDs(uuids, "anything else") + assert.Equal(t, "INSERT INTO keto_uuid_mappings (id, string_representation) VALUES (?,?),(?,?),(?,?) ON CONFLICT (id) DO NOTHING", q) + assert.Equal(t, []any{foo, "foo", bar, "bar", baz, "baz"}, args) +} diff --git a/internal/persistence/sql/relationtuples.go b/internal/persistence/sql/relationtuples.go index f36103f57..4daf6ecfc 100644 --- a/internal/persistence/sql/relationtuples.go +++ b/internal/persistence/sql/relationtuples.go @@ -6,18 +6,29 @@ package sql import ( "context" "database/sql" + "fmt" + "slices" + "strings" "time" - "github.com/ory/keto/ketoapi" - "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" "github.com/ory/x/otelx" "github.com/ory/x/sqlcon" "github.com/pkg/errors" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/ory/keto/internal/relationtuple" "github.com/ory/keto/internal/x" + "github.com/ory/keto/ketoapi" +) + +// Typical database limits for placeholders/bind vars are 1<<15 (32k, MySQL, SQLite) and 1<<16 (64k, PostgreSQL, CockroachDB). +const ( + chunkSizeInsertUUIDMappings = 15000 // two placeholders per mapping + chunkSizeInsertTuple = 3000 // ten placeholders per tuple + chunkSizeDeleteTuple = 100 // the database must build an expression tree for each chunk, so we must limit more aggressively ) type ( @@ -71,7 +82,7 @@ func (r *RelationTuple) ToInternal() (*relationtuple.RelationTuple, error) { return rt, nil } -func (r *RelationTuple) insertSubject(_ context.Context, s relationtuple.Subject) error { +func (r *RelationTuple) insertSubject(s relationtuple.Subject) error { switch st := s.(type) { case *relationtuple.SubjectID: r.SubjectID = uuid.NullUUID{ @@ -90,39 +101,12 @@ func (r *RelationTuple) insertSubject(_ context.Context, s relationtuple.Subject return nil } -func (r *RelationTuple) FromInternal(ctx context.Context, p *Persister, rt *relationtuple.RelationTuple) (err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.FromInternal") - defer otelx.End(span, &err) - +func (r *RelationTuple) FromInternal(rt *relationtuple.RelationTuple) (err error) { r.Namespace = rt.Namespace r.Object = rt.Object r.Relation = rt.Relation - return r.insertSubject(ctx, rt.Subject) -} - -func (p *Persister) InsertRelationTuple(ctx context.Context, rel *relationtuple.RelationTuple) (err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.InsertRelationTuple") - defer otelx.End(span, &err) - - if rel.Subject == nil { - return errors.WithStack(ketoapi.ErrNilSubject) - } - - rt := &RelationTuple{ - ID: uuid.Must(uuid.NewV4()), - CommitTime: time.Now(), - } - if err := rt.FromInternal(ctx, p, rel); err != nil { - return err - } - - if err := sqlcon.HandleError( - p.createWithNetwork(ctx, rt), - ); err != nil { - return err - } - return nil + return r.insertSubject(rt.Subject) } func (p *Persister) whereSubject(_ context.Context, q *pop.Query, sub relationtuple.Subject) error { @@ -165,25 +149,53 @@ func (p *Persister) whereQuery(ctx context.Context, q *pop.Query, rq *relationtu return nil } +func buildDelete(nid uuid.UUID, rs []*relationtuple.RelationTuple) (query string, args []any, err error) { + if len(rs) == 0 { + return "", nil, errors.WithStack(ketoapi.ErrMalformedInput) + } + + args = make([]any, 0, 6*len(rs)+1) + ors := make([]string, 0, len(rs)) + for _, rt := range rs { + switch s := rt.Subject.(type) { + case *relationtuple.SubjectID: + ors = append(ors, "(namespace = ? AND object = ? AND relation = ? AND subject_id = ? AND subject_set_namespace IS NULL AND subject_set_object IS NULL AND subject_set_relation IS NULL)") + args = append(args, rt.Namespace, rt.Object, rt.Relation, s.ID) + case *relationtuple.SubjectSet: + ors = append(ors, "(namespace = ? AND object = ? AND relation = ? AND subject_id IS NULL AND subject_set_namespace = ? AND subject_set_object = ? AND subject_set_relation = ?)") + args = append(args, rt.Namespace, rt.Object, rt.Relation, s.Namespace, s.Object, s.Relation) + case nil: + return "", nil, errors.WithStack(ketoapi.ErrNilSubject) + } + } + + query = fmt.Sprintf("DELETE FROM %s WHERE (%s) AND nid = ?", (&RelationTuple{}).TableName(), strings.Join(ors, " OR ")) + args = append(args, nid) + return query, args, nil +} + func (p *Persister) DeleteRelationTuples(ctx context.Context, rs ...*relationtuple.RelationTuple) (err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteRelationTuples") + if len(rs) == 0 { + return nil + } + + ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteRelationTuples", + trace.WithAttributes(attribute.Int("count", len(rs)))) defer otelx.End(span, &err) return p.Transaction(ctx, func(ctx context.Context) error { - for _, r := range rs { - q := p.queryWithNetwork(ctx). - Where("namespace = ?", r.Namespace). - Where("object = ?", r.Object). - Where("relation = ?", r.Relation) - if err := p.whereSubject(ctx, q, r.Subject); err != nil { + for chunk := range slices.Chunk(rs, chunkSizeDeleteTuple) { + q, args, err := buildDelete(p.NetworkID(ctx), chunk) + if err != nil { return err } - - if err := q.Delete(&RelationTuple{}); err != nil { - return err + if q == "" { + continue + } + if err := p.Connection(ctx).RawQuery(q, args...).Exec(); err != nil { + return sqlcon.HandleError(err) } } - return nil }) } @@ -214,7 +226,7 @@ func (p *Persister) GetRelationTuples(ctx context.Context, query *relationtuple. } sqlQuery := p.queryWithNetwork(ctx). - Order("shard_id, nid"). + Order("shard_id"). Where("shard_id > ?", pagination.LastID). Limit(pagination.PerPage + 1) @@ -260,15 +272,63 @@ func (p *Persister) ExistsRelationTuples(ctx context.Context, query *relationtup return exists, sqlcon.HandleError(err) } +func buildInsert(commitTime time.Time, nid uuid.UUID, rs []*relationtuple.RelationTuple) (query string, args []any, err error) { + if len(rs) == 0 { + return "", nil, errors.WithStack(ketoapi.ErrMalformedInput) + } + + var q strings.Builder + fmt.Fprintf(&q, "INSERT INTO %s (shard_id, nid, namespace, object, relation, subject_id, subject_set_namespace, subject_set_object, subject_set_relation, commit_time) VALUES ", (&RelationTuple{}).TableName()) + const placeholders = "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + const separator = ", " + q.Grow(len(rs) * (len(placeholders) + len(separator))) + args = make([]any, 0, 10*len(rs)) + + for i, r := range rs { + if r.Subject == nil { + return "", nil, errors.WithStack(ketoapi.ErrNilSubject) + } + + rt := &RelationTuple{ + ID: uuid.Must(uuid.NewV4()), + NetworkID: nid, + CommitTime: commitTime, + } + if err := rt.FromInternal(r); err != nil { + return "", nil, err + } + + if i > 0 { + q.WriteString(separator) + } + q.WriteString(placeholders) + args = append(args, rt.ID, rt.NetworkID, rt.Namespace, rt.Object, rt.Relation, rt.SubjectID, rt.SubjectSetNamespace, rt.SubjectSetObject, rt.SubjectSetRelation, rt.CommitTime) + } + + query = q.String() + return query, args, nil +} + func (p *Persister) WriteRelationTuples(ctx context.Context, rs ...*relationtuple.RelationTuple) (err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.WriteRelationTuples") + if len(rs) == 0 { + return nil + } + + ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.WriteRelationTuples", + trace.WithAttributes(attribute.Int("count", len(rs)))) defer otelx.End(span, &err) + commitTime := time.Now() + return p.Transaction(ctx, func(ctx context.Context) error { - for _, r := range rs { - if err := p.InsertRelationTuple(ctx, r); err != nil { + for chunk := range slices.Chunk(rs, chunkSizeInsertTuple) { + q, args, err := buildInsert(commitTime, p.NetworkID(ctx), chunk) + if err != nil { return err } + if err := p.Connection(ctx).RawQuery(q, args...).Exec(); err != nil { + return sqlcon.HandleError(err) + } } return nil }) @@ -278,6 +338,10 @@ func (p *Persister) TransactRelationTuples(ctx context.Context, ins []*relationt ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.TransactRelationTuples") defer otelx.End(span, &err) + if len(ins)+len(del) == 0 { + return nil + } + return p.Transaction(ctx, func(ctx context.Context) error { if err := p.WriteRelationTuples(ctx, ins...); err != nil { return err diff --git a/internal/persistence/sql/traverser.go b/internal/persistence/sql/traverser.go index f2a000c2e..33af2402e 100644 --- a/internal/persistence/sql/traverser.go +++ b/internal/persistence/sql/traverser.go @@ -22,7 +22,6 @@ type ( Traverser struct { conn *pop.Connection d dependencies - nid uuid.UUID p *Persister } @@ -86,7 +85,7 @@ WHERE current.nid = ? AND current.object = ? AND current.relation = ? AND current.subject_id IS NULL -ORDER BY current.nid, current.shard_id +ORDER BY current.shard_id LIMIT ? `, targetSubjectSQL), append(targetSubjectArgs, t.p.NetworkID(ctx), shardID, start.Namespace, start.Object, start.Relation, limit)..., @@ -195,7 +194,6 @@ func NewTraverser(p *Persister) *Traverser { return &Traverser{ conn: p.conn, d: p.d, - nid: p.nid, p: p, } } diff --git a/internal/persistence/sql/uuid_mapping.go b/internal/persistence/sql/uuid_mapping.go index 6c0218dd3..633b8db19 100644 --- a/internal/persistence/sql/uuid_mapping.go +++ b/internal/persistence/sql/uuid_mapping.go @@ -4,14 +4,18 @@ package sql import ( + "bytes" "context" + "iter" + "maps" + "slices" "strings" - "golang.org/x/exp/maps" - "github.com/gofrs/uuid" "github.com/ory/x/otelx" "github.com/ory/x/sqlcon" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "github.com/ory/keto/internal/x" ) @@ -32,47 +36,6 @@ func (UUIDMapping) TableName() string { return "keto_uuid_mappings" } -func (p *Persister) batchToUUIDs(ctx context.Context, values []string, readOnly bool) (uuids []uuid.UUID, err error) { - if len(values) == 0 { - return - } - - uuids = make([]uuid.UUID, len(values)) - placeholderArray := make([]string, len(values)) - args := make([]interface{}, 0, len(values)*2) - for i, val := range values { - uuids[i] = uuid.NewV5(p.NetworkID(ctx), val) - placeholderArray[i] = "(?, ?)" - args = append(args, uuids[i], val) - } - placeholders := strings.Join(placeholderArray, ", ") - - p.d.Logger().WithField("values", values).WithField("UUIDs", uuids).Trace("adding UUID mappings") - - if !readOnly { - // We need to write manual SQL here because the INSERT should not fail if - // the UUID already exists, but we still want to return an error if anything - // else goes wrong. - var query string - switch d := p.Connection(ctx).Dialect.Name(); d { - case "mysql": - query = ` - INSERT IGNORE INTO keto_uuid_mappings (id, string_representation) VALUES ` + placeholders - default: - query = ` - INSERT INTO keto_uuid_mappings (id, string_representation) - VALUES ` + placeholders + ` - ON CONFLICT (id) DO NOTHING` - } - - return uuids, sqlcon.HandleError( - p.Connection(ctx).RawQuery(query, args...).Exec(), - ) - } else { - return uuids, nil - } -} - func (p *Persister) batchFromUUIDs(ctx context.Context, ids []uuid.UUID, opts ...x.PaginationOptionSetter) (res []string, err error) { if len(ids) == 0 { return @@ -86,7 +49,7 @@ func (p *Persister) batchFromUUIDs(ctx context.Context, ids []uuid.UUID, opts .. pageSize := pagination.PerPage // Build a map from UUID -> indices in the result. - idIdx := make(map[uuid.UUID][]int) + idIdx := make(map[uuid.UUID][]int, len(ids)) for i, id := range ids { if ids, ok := idIdx[id]; ok { idIdx[id] = append(ids, i) @@ -94,17 +57,24 @@ func (p *Persister) batchFromUUIDs(ctx context.Context, ids []uuid.UUID, opts .. idIdx[id] = []int{i} } } - uniqueIDs := maps.Keys(idIdx) + nextID, stop := iter.Pull(maps.Keys(idIdx)) + defer stop() res = make([]string, len(ids)) - for i := 0; i < len(uniqueIDs); i += pageSize { - end := i + pageSize - if end > len(uniqueIDs) { - end = len(uniqueIDs) + idsToLookup := make([]uuid.UUID, 0, pageSize) + mappings := make([]UUIDMapping, 0, pageSize) + for i := 0; i < len(idIdx); i += pageSize { + idsToLookup = idsToLookup[:0] + mappings = mappings[:0] + + for range pageSize { + id, ok := nextID() + if !ok { + break + } + idsToLookup = append(idsToLookup, id) } - idsToLookup := uniqueIDs[i:end] - var mappings []UUIDMapping query := p.Connection(ctx).Where("id in (?)", idsToLookup) if err := sqlcon.HandleError(query.All(&mappings)); err != nil { return []string{}, err @@ -121,18 +91,61 @@ func (p *Persister) batchFromUUIDs(ctx context.Context, ids []uuid.UUID, opts .. return } -func (p *Persister) MapStringsToUUIDs(ctx context.Context, s ...string) (_ []uuid.UUID, err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MapStringsToUUIDs") +func (p *Persister) MapStringsToUUIDs(ctx context.Context, values ...string) (uuids []uuid.UUID, err error) { + if len(values) == 0 { + return + } + + ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MapStringsToUUIDs", + trace.WithAttributes(attribute.Int("num_values", len(values)))) defer otelx.End(span, &err) - return p.batchToUUIDs(ctx, s, false) + uuids, err = p.MapStringsToUUIDsReadOnly(ctx, values...) + if err != nil { + return nil, err + } + + p.d.Logger().WithField("values", values).WithField("UUIDs", uuids).Trace("adding UUID mappings") + + mappings := make([]UUIDMapping, len(values)) + for i := range values { + mappings[i] = UUIDMapping{ + ID: uuids[i], + StringRepresentation: values[i], + } + } + slices.SortFunc(mappings, func(a, b UUIDMapping) int { + return bytes.Compare(a.ID[:], b.ID[:]) + }) + mappings = slices.CompactFunc(mappings, func(a, b UUIDMapping) bool { + return a.ID == b.ID + }) + + span.SetAttributes(attribute.Int("num_mappings", len(mappings))) + + err = p.Transaction(ctx, func(ctx context.Context) error { + for chunk := range slices.Chunk(mappings, chunkSizeInsertUUIDMappings) { + query, args := buildInsertUUIDs(chunk, p.conn.Dialect.Name()) + if err := p.Connection(ctx).RawQuery(query, args...).Exec(); err != nil { + return sqlcon.HandleError(err) + } + } + return nil + }) + + return uuids, err } -func (p *Persister) MapStringsToUUIDsReadOnly(ctx context.Context, s ...string) (_ []uuid.UUID, err error) { - ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MapStringsToUUIDsReadOnly") - defer otelx.End(span, &err) +func (p *Persister) MapStringsToUUIDsReadOnly(ctx context.Context, ss ...string) (uuids []uuid.UUID, err error) { + // This function doesn't talk to the database or do anything interesting, so we don't need to trace it. + // ctx, span := p.d.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MapStringsToUUIDsReadOnly") + // defer otelx.End(span, &err) - return p.batchToUUIDs(ctx, s, true) + uuids = make([]uuid.UUID, len(ss)) + for i := range ss { + uuids[i] = uuid.NewV5(p.NetworkID(ctx), ss[i]) + } + return uuids, nil } func (p *Persister) MapUUIDsToStrings(ctx context.Context, u ...uuid.UUID) (_ []string, err error) { @@ -141,3 +154,39 @@ func (p *Persister) MapUUIDsToStrings(ctx context.Context, u ...uuid.UUID) (_ [] return p.batchFromUUIDs(ctx, u) } + +func buildInsertUUIDs(values []UUIDMapping, dialect string) (query string, args []any) { + if len(values) == 0 { + return "", nil + } + + const placeholder = "(?,?)" + const separator = "," + + var q strings.Builder + args = make([]any, 0, len(values)*2) + + if dialect == "mysql" { + q.WriteString("INSERT IGNORE INTO keto_uuid_mappings (id, string_representation) VALUES ") + } else { + q.WriteString("INSERT INTO keto_uuid_mappings (id, string_representation) VALUES ") + } + + q.Grow(len(values)*(len(placeholder)+len(separator)) + 100) + + for i, val := range values { + if i > 0 { + q.WriteString(separator) + } + q.WriteString(placeholder) + args = append(args, val.ID, val.StringRepresentation) + } + + if dialect == "mysql" { + // nothing + } else { + q.WriteString(" ON CONFLICT (id) DO NOTHING") + } + + return q.String(), args +} diff --git a/internal/relationtuple/uuid_mapping_test.go b/internal/relationtuple/uuid_mapping_test.go index e7d03d9c2..1f3de80e6 100644 --- a/internal/relationtuple/uuid_mapping_test.go +++ b/internal/relationtuple/uuid_mapping_test.go @@ -6,13 +6,13 @@ package relationtuple_test import ( "context" "fmt" + "slices" "testing" "github.com/ory/herodot" "github.com/ory/x/pointerx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" "github.com/ory/keto/internal/driver" "github.com/ory/keto/internal/driver/config" diff --git a/internal/schema/itemtype_string.go b/internal/schema/itemtype_string.go index c38fa384f..6a24bed49 100644 --- a/internal/schema/itemtype_string.go +++ b/internal/schema/itemtype_string.go @@ -1,6 +1,3 @@ -// Copyright © 2023 Ory Corp -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "stringer -type=itemType -trimprefix item -linecomment"; DO NOT EDIT. package schema diff --git a/internal/x/dbx/dsn_cockroach.go b/internal/x/dbx/dsn_cockroach.go index 098efd900..eb85deb3c 100644 --- a/internal/x/dbx/dsn_cockroach.go +++ b/internal/x/dbx/dsn_cockroach.go @@ -12,7 +12,7 @@ import ( ) func RunCockroach(t testing.TB, testDB string) string { - url := dockertest.RunTestCockroachDB(t) + url := dockertest.RunTestCockroachDBWithVersion(t, "latest-v24.2") if err := createDB(t, url, testDB); err != nil { t.Fatal(err) } diff --git a/internal/x/dbx/dsn_mysql.go b/internal/x/dbx/dsn_mysql.go index 6ab8e4879..99e41bce0 100644 --- a/internal/x/dbx/dsn_mysql.go +++ b/internal/x/dbx/dsn_mysql.go @@ -13,7 +13,7 @@ import ( ) func RunMySQL(t testing.TB, testDB string) string { - url := dockertest.RunTestMySQL(t) + url := dockertest.RunTestMySQLWithVersion(t, "8.0") time.Sleep(1 * time.Second) if err := createDB(t, url, testDB); err != nil { t.Fatal(err) diff --git a/internal/x/dbx/dsn_postgres.go b/internal/x/dbx/dsn_postgres.go index e4a1df529..70560095b 100644 --- a/internal/x/dbx/dsn_postgres.go +++ b/internal/x/dbx/dsn_postgres.go @@ -12,7 +12,7 @@ import ( ) func RunPostgres(t testing.TB, testDB string) string { - url := dockertest.RunTestPostgreSQL(t) + url := dockertest.RunTestPostgreSQLWithVersion(t, "16") if err := createDB(t, url, testDB); err != nil { t.Fatal(err) } diff --git a/internal/x/dbx/dsn_testutils.go b/internal/x/dbx/dsn_testutils.go index 4332ffd0e..af74f5a73 100644 --- a/internal/x/dbx/dsn_testutils.go +++ b/internal/x/dbx/dsn_testutils.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "strings" + "sync" "testing" "time" @@ -17,8 +18,6 @@ import ( "github.com/gobuffalo/pop/v6" "github.com/stretchr/testify/require" "github.com/tidwall/sjson" - - "github.com/ory/x/sqlcon/dockertest" ) type DsnT struct { @@ -111,17 +110,21 @@ func GetDSNs(t testing.TB, debugSqliteOnDisk bool) []*DsnT { var mysql, postgres, cockroach string testDB := dbName(t.Name()) - dockertest.Parallel([]func(){ - func() { - mysql = RunMySQL(t, testDB) - }, - func() { - postgres = RunPostgres(t, testDB) - }, - func() { - cockroach = RunCockroach(t, testDB) - }, - }) + var wg sync.WaitGroup + wg.Add(3) + go func() { + defer wg.Done() + postgres = RunPostgres(t, testDB) + }() + go func() { + defer wg.Done() + mysql = RunMySQL(t, testDB) + }() + go func() { + defer wg.Done() + cockroach = RunCockroach(t, testDB) + }() + wg.Wait() if mysql != "" { dsns = append(dsns, &DsnT{ diff --git a/internal/x/validate/validate.go b/internal/x/validate/validate.go index e29993ac1..4a139c52e 100644 --- a/internal/x/validate/validate.go +++ b/internal/x/validate/validate.go @@ -59,7 +59,7 @@ func QueryParamsContainsOneOf(keys ...string) Validator { return true, "" } } - return false, fmt.Sprintf("quey parameters must specify at least one of the following: %s", strings.Join(keys, ", ")) + return false, fmt.Sprintf("query parameters must specify at least one of the following: %s", strings.Join(keys, ", ")) } } diff --git a/ketoapi/enc_proto.go b/ketoapi/enc_proto.go index 38276375c..e4d5d7630 100644 --- a/ketoapi/enc_proto.go +++ b/ketoapi/enc_proto.go @@ -4,9 +4,10 @@ package ketoapi import ( - "github.com/ory/x/pointerx" "github.com/pkg/errors" + "github.com/ory/x/pointerx" + rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" ) @@ -130,14 +131,28 @@ func (r *RelationTuple) FromProto(proto *rts.RelationTuple) *RelationTuple { Object: proto.Object, Relation: proto.Relation, } - switch subject := proto.Subject.Ref.(type) { - case *rts.Subject_Id: - r.SubjectID = pointerx.Ptr(subject.Id) - case *rts.Subject_Set: - r.SubjectSet = &SubjectSet{ - Namespace: subject.Set.Namespace, - Object: subject.Set.Object, - Relation: subject.Set.Relation, + + if proto.Subject != nil { + switch subject := proto.Subject.Ref.(type) { + case *rts.Subject_Id: + r.SubjectID = pointerx.Ptr(subject.Id) + case *rts.Subject_Set: + r.SubjectSet = &SubjectSet{ + Namespace: subject.Set.Namespace, + Object: subject.Set.Object, + Relation: subject.Set.Relation, + } + } + } else { + switch subject := proto.RestApiSubject.(type) { + case *rts.RelationTuple_SubjectId: + r.SubjectID = pointerx.Ptr(subject.SubjectId) + case *rts.RelationTuple_SubjectSet: + r.SubjectSet = &SubjectSet{ + Namespace: subject.SubjectSet.Namespace, + Object: subject.SubjectSet.Object, + Relation: subject.SubjectSet.Relation, + } } } diff --git a/ketoctx/options.go b/ketoctx/options.go index 226640d53..39e4387df 100644 --- a/ketoctx/options.go +++ b/ketoctx/options.go @@ -7,6 +7,7 @@ import ( "io/fs" "net/http" + "github.com/gobuffalo/pop/v6" "google.golang.org/grpc" "github.com/ory/x/healthx" @@ -27,9 +28,11 @@ type ( migrationOpts []popx.MigrationBoxOption readyCheckers healthx.ReadyCheckers extraMigrations []fs.FS + inspect InspectFunc } Option func(o *opts) TracerWrapper func(*otelx.Tracer) *otelx.Tracer + InspectFunc func(*pop.Connection) error ) // WithLogger sets the logger. @@ -105,6 +108,12 @@ func WithReadinessCheck(name string, rc healthx.ReadyChecker) Option { } } +func Inspect(f InspectFunc) Option { + return func(o *opts) { + o.inspect = f + } +} + func (o *opts) Logger() *logrusx.Logger { return o.logger } @@ -141,6 +150,10 @@ func (o *opts) ReadyCheckers() healthx.ReadyCheckers { return o.readyCheckers } +func (o *opts) Inspect() InspectFunc { + return o.inspect +} + func Options(options ...Option) *opts { o := &opts{ contextualizer: &DefaultContextualizer{}, diff --git a/ketoctx/options_test.go b/ketoctx/options_test.go index 43f25a76c..ee49e522a 100644 --- a/ketoctx/options_test.go +++ b/ketoctx/options_test.go @@ -5,6 +5,10 @@ package ketoctx import ( "testing" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" "github.com/stretchr/testify/assert" ) @@ -23,4 +27,12 @@ func TestOptions(t *testing.T) { opts := Options(WithContextualizer(ctxer)) assert.Equal(t, ctxer, opts.Contextualizer()) }) + t.Run("case=overwrites grpcServerOpts", func(t *testing.T) { + sp := keepalive.ServerParameters{ + MaxConnectionAge: time.Second * 30, + MaxConnectionAgeGrace: time.Second * 10, + } + opts := Options(WithGRPCServerOptions(grpc.KeepaliveParams(sp))) + assert.NotNil(t, opts.grpcServerOptions) + }) } diff --git a/package-lock.json b/package-lock.json index daae9ad8b..ea1315061 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "Apache 2.0", "dependencies": { - "@openapitools/openapi-generator-cli": "^2.7.0", + "@openapitools/openapi-generator-cli": "^2.15.3", "grpc_tools_node_protoc_ts": "^5.3.3", "grpc-tools": "^1.12.4" }, @@ -59,42 +59,35 @@ } }, "node_modules/@nestjs/axios": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.1.0.tgz", - "integrity": "sha512-b2TT2X6BFbnNoeteiaxCIiHaFcSbVW+S5yygYqiIq5i6H77yIU3IVuLdpQkHq8/EqOWFwMopLN8jdkUT71Am9w==", - "dependencies": { - "axios": "0.27.2" - }, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", + "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", - "reflect-metadata": "^0.1.12", + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", "rxjs": "^6.0.0 || ^7.0.0" } }, "node_modules/@nestjs/common": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.11.tgz", - "integrity": "sha512-IFZ2G/5UKWC2Uo7tJ4SxGed2+aiA+sJyWeWsGTogKVDhq90oxVBToh+uCDeI31HNUpqYGoWmkletfty42zUd8A==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", + "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", "dependencies": { "iterare": "1.2.1", - "tslib": "2.5.0", - "uid": "2.0.1" + "tslib": "2.7.0", + "uid": "2.0.2" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/nest" }, "peerDependencies": { - "cache-manager": "<=5", "class-transformer": "*", "class-validator": "*", - "reflect-metadata": "^0.1.12", + "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, "peerDependenciesMeta": { - "cache-manager": { - "optional": true - }, "class-transformer": { "optional": true }, @@ -104,33 +97,33 @@ } }, "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/@nestjs/core": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.11.tgz", - "integrity": "sha512-CI27a2JFd5rvvbgkalWqsiwQNhcP4EAG5BUK8usjp29wVp1kx30ghfBT8FLqIgmkRVo65A0IcEnWsxeXMntkxQ==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", + "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.5.0", - "uid": "2.0.1" + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@nestjs/common": "^9.0.0", - "@nestjs/microservices": "^9.0.0", - "@nestjs/platform-express": "^9.0.0", - "@nestjs/websockets": "^9.0.0", - "reflect-metadata": "^0.1.12", + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, "peerDependenciesMeta": { @@ -146,9 +139,9 @@ } }, "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -203,39 +196,88 @@ } }, "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.7.0.tgz", - "integrity": "sha512-ieEpHTA/KsDz7ANw03lLPYyjdedDEXYEyYoGBRWdduqXWSX65CJtttjqa8ZaB1mNmIjMtchUHwAYQmTLVQ8HYg==", + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", + "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", "hasInstallScript": true, "dependencies": { - "@nestjs/axios": "0.1.0", - "@nestjs/common": "9.3.11", - "@nestjs/core": "9.3.11", + "@nestjs/axios": "3.1.1", + "@nestjs/common": "10.4.6", + "@nestjs/core": "10.4.6", "@nuxtjs/opencollective": "0.3.2", + "axios": "1.7.7", "chalk": "4.1.2", "commander": "8.3.0", "compare-versions": "4.1.4", "concurrently": "6.5.1", "console.table": "0.10.0", "fs-extra": "10.1.0", - "glob": "7.1.6", - "inquirer": "8.2.5", + "glob": "9.3.5", + "inquirer": "8.2.6", "lodash": "4.17.21", + "proxy-agent": "6.4.0", "reflect-metadata": "0.1.13", - "rxjs": "7.8.0", - "tslib": "2.0.3" + "rxjs": "7.8.1", + "tslib": "2.8.1" }, "bin": { "openapi-generator-cli": "main.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=16" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/openapi_generator" } }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/@ory/keto-namespace-types": { "resolved": "contrib/namespace-type-lib", "link": true @@ -260,12 +302,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@pkgr/utils/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/@textlint/ast-node-types": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.1.1.tgz", @@ -288,6 +324,11 @@ "unified": "^9.2.2" } }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "node_modules/@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -396,18 +437,30 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/bail": { @@ -444,6 +497,14 @@ } ] }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -614,9 +675,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "engines": { "node": ">=6" }, @@ -789,6 +850,14 @@ "node": ">= 8" } }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "engines": { + "node": ">= 14" + } + }, "node_modules/date-fns": { "version": "2.28.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", @@ -880,6 +949,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1090,6 +1172,54 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -1229,9 +1359,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -1248,9 +1378,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1355,6 +1485,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/git-hooks-list": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", @@ -1519,6 +1676,29 @@ "entities": "^3.0.1" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -1594,9 +1774,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -1612,12 +1792,37 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "wrap-ansi": "^6.0.1" }, "engines": { "node": ">=12.0.0" } }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -1849,6 +2054,11 @@ "node": ">=6" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2485,6 +2695,14 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -2686,6 +2904,59 @@ "os-tmpdir": "^1.0.0" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/parse-entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", @@ -2727,10 +2998,38 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" }, "node_modules/path-type": { "version": "4.0.0", @@ -2792,6 +3091,60 @@ } } }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3117,18 +3470,13 @@ } }, "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3219,6 +3567,52 @@ "node": "*" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/sort-object-keys": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", @@ -3328,6 +3722,11 @@ "spdx-ranges": "^2.0.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3416,12 +3815,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -3517,9 +3910,9 @@ } }, "node_modules/tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-fest": { "version": "0.21.3", @@ -3558,9 +3951,9 @@ } }, "node_modules/uid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.1.tgz", - "integrity": "sha512-PF+1AnZgycpAIEmNtjxGBVmKbZAQguaa4pBUq6KNaGEcpzZ2klCNZLM34tsjp76maN00TttiiUf6zkIBpJQm2A==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", "dependencies": { "@lukeed/csprng": "^1.0.0" }, @@ -3846,47 +4239,45 @@ } }, "@nestjs/axios": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.1.0.tgz", - "integrity": "sha512-b2TT2X6BFbnNoeteiaxCIiHaFcSbVW+S5yygYqiIq5i6H77yIU3IVuLdpQkHq8/EqOWFwMopLN8jdkUT71Am9w==", - "requires": { - "axios": "0.27.2" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", + "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "requires": {} }, "@nestjs/common": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.11.tgz", - "integrity": "sha512-IFZ2G/5UKWC2Uo7tJ4SxGed2+aiA+sJyWeWsGTogKVDhq90oxVBToh+uCDeI31HNUpqYGoWmkletfty42zUd8A==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", + "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", "requires": { "iterare": "1.2.1", - "tslib": "2.5.0", - "uid": "2.0.1" + "tslib": "2.7.0", + "uid": "2.0.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" } } }, "@nestjs/core": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.11.tgz", - "integrity": "sha512-CI27a2JFd5rvvbgkalWqsiwQNhcP4EAG5BUK8usjp29wVp1kx30ghfBT8FLqIgmkRVo65A0IcEnWsxeXMntkxQ==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", + "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", "requires": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.5.0", - "uid": "2.0.1" + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" } } }, @@ -3927,26 +4318,62 @@ } }, "@openapitools/openapi-generator-cli": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.7.0.tgz", - "integrity": "sha512-ieEpHTA/KsDz7ANw03lLPYyjdedDEXYEyYoGBRWdduqXWSX65CJtttjqa8ZaB1mNmIjMtchUHwAYQmTLVQ8HYg==", + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", + "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", "requires": { - "@nestjs/axios": "0.1.0", - "@nestjs/common": "9.3.11", - "@nestjs/core": "9.3.11", + "@nestjs/axios": "3.1.1", + "@nestjs/common": "10.4.6", + "@nestjs/core": "10.4.6", "@nuxtjs/opencollective": "0.3.2", + "axios": "1.7.7", "chalk": "4.1.2", "commander": "8.3.0", "compare-versions": "4.1.4", "concurrently": "6.5.1", "console.table": "0.10.0", "fs-extra": "10.1.0", - "glob": "7.1.6", - "inquirer": "8.2.5", + "glob": "9.3.5", + "inquirer": "8.2.6", "lodash": "4.17.21", + "proxy-agent": "6.4.0", "reflect-metadata": "0.1.13", - "rxjs": "7.8.0", - "tslib": "2.0.3" + "rxjs": "7.8.1", + "tslib": "2.8.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + } + }, + "minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==" + } } }, "@ory/keto-namespace-types": { @@ -3968,14 +4395,6 @@ "open": "^9.1.0", "picocolors": "^1.0.0", "tslib": "^2.6.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - } } }, "@textlint/ast-node-types": { @@ -4000,6 +4419,11 @@ "unified": "^9.2.2" } }, + "@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -4084,18 +4508,27 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "requires": { + "tslib": "^2.0.1" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "bail": { @@ -4114,6 +4547,11 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==" + }, "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -4227,9 +4665,9 @@ } }, "cli-spinners": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==" + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==" }, "cli-width": { "version": "3.0.0", @@ -4359,6 +4797,11 @@ "which": "^2.0.1" } }, + "data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==" + }, "date-fns": { "version": "2.28.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", @@ -4414,6 +4857,16 @@ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true }, + "degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "requires": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4571,6 +5024,32 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, "execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -4675,14 +5154,14 @@ } }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==" + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -4757,6 +5236,29 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "requires": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, "git-hooks-list": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", @@ -4874,6 +5376,25 @@ "entities": "^3.0.1" } }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "dependencies": { + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + } + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4923,9 +5444,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -4941,7 +5462,28 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "wrap-ansi": "^6.0.1" + }, + "dependencies": { + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" } }, "is-alphabetical": { @@ -5078,6 +5620,11 @@ "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -5546,6 +6093,11 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -5692,6 +6244,49 @@ "os-tmpdir": "^1.0.0" } }, + "pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "requires": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "dependencies": { + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + } + } + }, + "pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "requires": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + } + }, "parse-entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", @@ -5723,10 +6318,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + } + } + }, "path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" }, "path-type": { "version": "4.0.0", @@ -5762,6 +6378,50 @@ "synckit": "0.8.5" } }, + "proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "requires": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "dependencies": { + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5984,18 +6644,11 @@ } }, "rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "requires": { "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" - } } }, "safe-buffer": { @@ -6053,6 +6706,40 @@ "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", "dev": true }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "requires": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "requires": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "dependencies": { + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + } + } + }, "sort-object-keys": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", @@ -6152,6 +6839,11 @@ "spdx-ranges": "^2.0.0" } }, + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6213,14 +6905,6 @@ "requires": { "@pkgr/utils": "^2.3.1", "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - } } }, "tar": { @@ -6293,9 +6977,9 @@ "dev": true }, "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "type-fest": { "version": "0.21.3", @@ -6315,9 +6999,9 @@ "optional": true }, "uid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.1.tgz", - "integrity": "sha512-PF+1AnZgycpAIEmNtjxGBVmKbZAQguaa4pBUq6KNaGEcpzZ2klCNZLM34tsjp76maN00TttiiUf6zkIBpJQm2A==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", "requires": { "@lukeed/csprng": "^1.0.0" } diff --git a/package.json b/package.json index cec6b4a0d..5d9c7921f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "prettier": "ory-prettier-styles", "dependencies": { - "@openapitools/openapi-generator-cli": "^2.7.0", + "@openapitools/openapi-generator-cli": "^2.15.3", "grpc-tools": "^1.12.4", "grpc_tools_node_protoc_ts": "^5.3.3" }, diff --git a/proto/buf.md b/proto/buf.md index 0d8b98208..279cc67fb 100644 --- a/proto/buf.md +++ b/proto/buf.md @@ -24,8 +24,12 @@ - [SubjectSetQuery](#ory-keto-relation_tuples-v1alpha2-SubjectSetQuery) - [ory/keto/relation_tuples/v1alpha2/check_service.proto](#ory_keto_relation_tuples_v1alpha2_check_service-proto) + - [BatchCheckRequest](#ory-keto-relation_tuples-v1alpha2-BatchCheckRequest) + - [BatchCheckRequestBody](#ory-keto-relation_tuples-v1alpha2-BatchCheckRequestBody) + - [BatchCheckResponse](#ory-keto-relation_tuples-v1alpha2-BatchCheckResponse) - [CheckRequest](#ory-keto-relation_tuples-v1alpha2-CheckRequest) - [CheckResponse](#ory-keto-relation_tuples-v1alpha2-CheckResponse) + - [CheckResponseWithError](#ory-keto-relation_tuples-v1alpha2-CheckResponseWithError) - [CheckService](#ory-keto-relation_tuples-v1alpha2-CheckService) - [ory/keto/relation_tuples/v1alpha2/expand_service.proto](#ory_keto_relation_tuples_v1alpha2_expand_service-proto) @@ -245,6 +249,38 @@ SubjectSetQuery refers to all subjects who have the same `relation` on an ## ory/keto/relation_tuples/v1alpha2/check_service.proto + + +### BatchCheckRequest + +The request for a CheckService.BatchCheck RPC. Checks a batch of relations. + +| Field | Type | Label | Description | +| --------- | --------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| tuples | [RelationTuple](#ory-keto-relation_tuples-v1alpha2-RelationTuple) | repeated | | +| rest_body | [BatchCheckRequestBody](#ory-keto-relation_tuples-v1alpha2-BatchCheckRequestBody) | | **Deprecated.** Batch Check Permission Body. | +| latest | [bool](#bool) | | This field is not implemented yet and has no effect.
| +| snaptoken | [string](#string) | | This field is not implemented yet and has no effect.
| +| max_depth | [int32](#int32) | | The maximum depth to search for a relation.

If the value is less than 1 or greater than the global
max-depth then the global max-depth will be used instead. | + + + +### BatchCheckRequestBody + +| Field | Type | Label | Description | +| ------ | ----------------------------------------------------------------- | -------- | ----------- | +| tuples | [RelationTuple](#ory-keto-relation_tuples-v1alpha2-RelationTuple) | repeated | | + + + +### BatchCheckResponse + +The response for a CheckService.BatchCheck rpc. + +| Field | Type | Label | Description | +| ------- | ----------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- | +| results | [CheckResponseWithError](#ory-keto-relation_tuples-v1alpha2-CheckResponseWithError) | repeated | The results of the batch check. The order of these
results will match the order of the input. | + ### CheckRequest @@ -276,6 +312,18 @@ The response for a permission check. | allowed | [bool](#bool) | | Whether the specified subject (id)
is related to the requested object.

It is false by default if no ACL matches. | | snaptoken | [string](#string) | | This field is not implemented yet and has no effect.
| + + +### CheckResponseWithError + +The response for an individual check in the CheckService.BatchCheck rpc. + +| Field | Type | Label | Description | +| --------- | ----------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| allowed | [bool](#bool) | | Whether the specified subject (id)
is related to the requested object.

It is false by default if no ACL matches. | +| error | [string](#string) | | If there was an error checking the tuple,
this will contain the error message.

If the check was performed successfully, this will be empty. | +| snaptoken | [string](#string) | | This field is not implemented yet and has no effect.
| + @@ -292,9 +340,10 @@ Control Lists. This service is part of the [read-APIs](../concepts/25_api-overview.mdx#read-apis). -| Method Name | Request Type | Response Type | Description | -| ----------- | --------------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------- | -| Check | [CheckRequest](#ory-keto-relation_tuples-v1alpha2-CheckRequest) | [CheckResponse](#ory-keto-relation_tuples-v1alpha2-CheckResponse) | Performs an authorization check. | +| Method Name | Request Type | Response Type | Description | +| ----------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Check | [CheckRequest](#ory-keto-relation_tuples-v1alpha2-CheckRequest) | [CheckResponse](#ory-keto-relation_tuples-v1alpha2-CheckResponse) | Performs an authorization check. | +| BatchCheck | [BatchCheckRequest](#ory-keto-relation_tuples-v1alpha2-BatchCheckRequest) | [BatchCheckResponse](#ory-keto-relation_tuples-v1alpha2-BatchCheckResponse) | Performs an authorization check for a batch of tuples.

To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). | diff --git a/proto/go.mod b/proto/go.mod index 461036eee..a0526597b 100644 --- a/proto/go.mod +++ b/proto/go.mod @@ -1,27 +1,23 @@ module github.com/ory/keto/proto -go 1.21 - -toolchain go1.22.5 +go 1.19 require ( - github.com/envoyproxy/protoc-gen-validate v1.0.4 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 github.com/stretchr/testify v1.8.4 - google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d - google.golang.org/grpc v1.66.0 - google.golang.org/protobuf v1.34.1 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/proto/go.sum b/proto/go.sum index a4568817a..7b687c7b0 100644 --- a/proto/go.sum +++ b/proto/go.sum @@ -1,14 +1,11 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0/go.mod h1:YDZoGHuwE+ov0c8smSH49WLF3F2LaWnYYuDVd+EWrc0= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -19,35 +16,21 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/proto/ory/keto/opl/v1alpha1/syntax_service.pb.go b/proto/ory/keto/opl/v1alpha1/syntax_service.pb.go index 4cd839bff..611b35550 100644 --- a/proto/ory/keto/opl/v1alpha1/syntax_service.pb.go +++ b/proto/ory/keto/opl/v1alpha1/syntax_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/opl/v1alpha1/syntax_service.proto diff --git a/proto/ory/keto/opl/v1alpha1/syntax_service_grpc_pb.d.ts b/proto/ory/keto/opl/v1alpha1/syntax_service_grpc_pb.d.ts index c691c00cc..0e0a33e7a 100644 --- a/proto/ory/keto/opl/v1alpha1/syntax_service_grpc_pb.d.ts +++ b/proto/ory/keto/opl/v1alpha1/syntax_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_opl_v1alpha1_syntax_service_pb from "../../../../ory/keto/opl/v1alpha1/syntax_service_pb"; import * as protoc_gen_openapiv2_options_annotations_pb from "../../../../protoc-gen-openapiv2/options/annotations_pb"; @@ -24,7 +24,7 @@ interface ISyntaxServiceService_ICheck extends grpc.MethodDefinition; } @@ -35,7 +35,7 @@ export interface ISyntaxServiceClient { } export class SyntaxServiceClient extends grpc.Client implements ISyntaxServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public check(request: ory_keto_opl_v1alpha1_syntax_service_pb.CheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_opl_v1alpha1_syntax_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; public check(request: ory_keto_opl_v1alpha1_syntax_service_pb.CheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_opl_v1alpha1_syntax_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; public check(request: ory_keto_opl_v1alpha1_syntax_service_pb.CheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_opl_v1alpha1_syntax_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.go index ffb9649f7..cbf514f6a 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/check_service.proto @@ -311,6 +311,301 @@ func (x *CheckResponse) GetSnaptoken() string { return "" } +// The response for an individual check in the CheckService.BatchCheck rpc. +type CheckResponseWithError struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Whether the specified subject (id) + // is related to the requested object. + // + // It is false by default if no ACL matches. + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + // If there was an error checking the tuple, + // this will contain the error message. + // + // If the check was performed successfully, this will be empty. + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + // This field is not implemented yet and has no effect. + // + Snaptoken string `protobuf:"bytes,3,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckResponseWithError) Reset() { + *x = CheckResponseWithError{} + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckResponseWithError) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckResponseWithError) ProtoMessage() {} + +func (x *CheckResponseWithError) ProtoReflect() protoreflect.Message { + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckResponseWithError.ProtoReflect.Descriptor instead. +func (*CheckResponseWithError) Descriptor() ([]byte, []int) { + return file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescGZIP(), []int{2} +} + +func (x *CheckResponseWithError) GetAllowed() bool { + if x != nil { + return x.Allowed + } + return false +} + +func (x *CheckResponseWithError) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *CheckResponseWithError) GetSnaptoken() string { + if x != nil { + return x.Snaptoken + } + return "" +} + +type BatchCheckRequestBody struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tuples []*RelationTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchCheckRequestBody) Reset() { + *x = BatchCheckRequestBody{} + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchCheckRequestBody) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchCheckRequestBody) ProtoMessage() {} + +func (x *BatchCheckRequestBody) ProtoReflect() protoreflect.Message { + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchCheckRequestBody.ProtoReflect.Descriptor instead. +func (*BatchCheckRequestBody) Descriptor() ([]byte, []int) { + return file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescGZIP(), []int{3} +} + +func (x *BatchCheckRequestBody) GetTuples() []*RelationTuple { + if x != nil { + return x.Tuples + } + return nil +} + +// The request for a CheckService.BatchCheck RPC. +// Checks a batch of relations. +type BatchCheckRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tuples []*RelationTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` + // Batch Check Permission Body. + // + // Deprecated: Marked as deprecated in ory/keto/relation_tuples/v1alpha2/check_service.proto. + RestBody *BatchCheckRequestBody `protobuf:"bytes,5,opt,name=rest_body,json=body,proto3" json:"rest_body,omitempty"` + // This field is not implemented yet and has no effect. + // + Latest bool `protobuf:"varint,2,opt,name=latest,proto3" json:"latest,omitempty"` + // This field is not implemented yet and has no effect. + // + Snaptoken string `protobuf:"bytes,3,opt,name=snaptoken,proto3" json:"snaptoken,omitempty"` + // The maximum depth to search for a relation. + // + // If the value is less than 1 or greater than the global + // max-depth then the global max-depth will be used instead. + MaxDepth int32 `protobuf:"varint,4,opt,name=max_depth,json=max-depth,proto3" json:"max_depth,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchCheckRequest) Reset() { + *x = BatchCheckRequest{} + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchCheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchCheckRequest) ProtoMessage() {} + +func (x *BatchCheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchCheckRequest.ProtoReflect.Descriptor instead. +func (*BatchCheckRequest) Descriptor() ([]byte, []int) { + return file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescGZIP(), []int{4} +} + +func (x *BatchCheckRequest) GetTuples() []*RelationTuple { + if x != nil { + return x.Tuples + } + return nil +} + +// Deprecated: Marked as deprecated in ory/keto/relation_tuples/v1alpha2/check_service.proto. +func (x *BatchCheckRequest) GetRestBody() *BatchCheckRequestBody { + if x != nil { + return x.RestBody + } + return nil +} + +func (x *BatchCheckRequest) GetLatest() bool { + if x != nil { + return x.Latest + } + return false +} + +func (x *BatchCheckRequest) GetSnaptoken() string { + if x != nil { + return x.Snaptoken + } + return "" +} + +func (x *BatchCheckRequest) GetMaxDepth() int32 { + if x != nil { + return x.MaxDepth + } + return 0 +} + +// The response for a CheckService.BatchCheck rpc. +type BatchCheckResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The results of the batch check. The order of these + // results will match the order of the input. + Results []*CheckResponseWithError `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchCheckResponse) Reset() { + *x = BatchCheckResponse{} + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchCheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchCheckResponse) ProtoMessage() {} + +func (x *BatchCheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchCheckResponse.ProtoReflect.Descriptor instead. +func (*BatchCheckResponse) Descriptor() ([]byte, []int) { + return file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescGZIP(), []int{5} +} + +func (x *BatchCheckResponse) GetResults() []*CheckResponseWithError { + if x != nil { + return x.Results + } + return nil +} + var File_ory_keto_relation_tuples_v1alpha2_check_service_proto protoreflect.FileDescriptor var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDesc = []byte{ @@ -373,64 +668,152 @@ var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDesc = []byte{ 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x4e, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x52, - 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xc1, 0x05, 0x0a, 0x0c, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb0, 0x05, 0x0a, 0x05, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x2f, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, + 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x7f, 0x0a, 0x16, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x6e, 0x61, + 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0xfa, 0xd2, + 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x4e, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, + 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x61, 0x0a, 0x15, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0xc4, + 0x02, 0x0a, 0x11, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x42, 0x12, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, + 0x4e, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, + 0x65, 0x73, 0x12, 0x55, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, - 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc3, 0x04, 0x92, 0x41, 0xbd, 0x03, 0x0a, - 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0x21, 0x61, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d, 0x66, - 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x32, 0x10, - 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, - 0x4a, 0xb9, 0x01, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0xb1, 0x01, 0x0a, 0x79, 0x54, 0x68, 0x65, - 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x60, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x60, 0x20, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, - 0x73, 0x20, 0x32, 0x30, 0x30, 0x2e, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0xbd, 0x01, 0x0a, - 0x03, 0x34, 0x30, 0x33, 0x12, 0xb5, 0x01, 0x0a, 0x7d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2c, 0x20, 0x69, - 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x60, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x60, 0x20, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, - 0x73, 0x20, 0x32, 0x30, 0x30, 0x2e, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x7c, 0x5a, 0x20, 0x12, 0x1e, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, - 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2f, 0x6f, 0x70, 0x65, - 0x6e, 0x61, 0x70, 0x69, 0x5a, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x5a, 0x23, 0x3a, 0x01, 0x2a, 0x22, 0x1e, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2f, 0x6f, - 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x12, 0x16, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x42, 0xc2, - 0x01, 0x0a, 0x24, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x42, + 0x02, 0x18, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x6c, 0x61, 0x74, + 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x42, 0x12, 0xfa, 0xd2, 0xe4, 0x93, 0x02, + 0x0c, 0x12, 0x0a, 0x4e, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x52, 0x06, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0c, + 0x12, 0x0a, 0x4e, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x52, 0x09, 0x73, 0x6e, + 0x61, 0x70, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x61, 0x78, 0x2d, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x69, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x07, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x6f, + 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x57, 0x69, + 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x32, 0xa4, 0x0b, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0xce, 0x06, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x2f, 0x2e, 0x6f, 0x72, + 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6f, + 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe1, + 0x05, 0x92, 0x41, 0xdb, 0x04, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x32, 0x21, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, + 0x2d, 0x77, 0x77, 0x77, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x64, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x4a, 0xb9, 0x01, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0xb1, + 0x01, 0x0a, 0x79, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, + 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, + 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x60, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, + 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x32, 0x30, 0x30, 0x2e, 0x12, 0x34, 0x0a, 0x32, + 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x4a, 0x4b, 0x0a, 0x03, 0x34, 0x30, 0x30, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, + 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x32, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, + 0xbd, 0x01, 0x0a, 0x03, 0x34, 0x30, 0x33, 0x12, 0xb5, 0x01, 0x0a, 0x7d, 0x54, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, 0x46, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x60, 0x20, + 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, + 0x77, 0x61, 0x79, 0x73, 0x20, 0x32, 0x30, 0x30, 0x2e, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, + 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x32, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, + 0x4f, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, + 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x32, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x7c, 0x5a, 0x20, 0x12, 0x1e, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x5a, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5a, 0x23, 0x3a, 0x01, 0x2a, 0x22, 0x1e, 0x2f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x12, 0x16, 0x2f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x12, 0xc2, 0x04, 0x0a, 0x0a, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x34, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, + 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc6, + 0x03, 0x92, 0x41, 0x93, 0x03, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2a, 0x14, 0x62, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x4a, 0xbe, 0x01, 0x0a, 0x03, 0x32, 0x30, + 0x30, 0x12, 0xb6, 0x01, 0x0a, 0x79, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x63, + 0x61, 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x60, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x32, 0x30, 0x30, 0x2e, 0x12, + 0x39, 0x0a, 0x37, 0x1a, 0x35, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x42, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, - 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, - 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x3b, 0x72, 0x74, 0x73, 0xaa, 0x02, 0x20, - 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, - 0xca, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, 0x74, 0x6f, 0x5c, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0x4b, 0x0a, 0x03, 0x34, 0x30, + 0x30, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, + 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, + 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0x4f, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, + 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x09, + 0x72, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x1c, 0x2f, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x42, 0xc2, 0x01, 0x0a, 0x24, 0x73, 0x68, 0x2e, 0x6f, + 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, + 0x42, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x32, 0x3b, 0x72, 0x74, 0x73, 0xaa, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, + 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xca, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x5c, + 0x4b, 0x65, 0x74, 0x6f, 0x5c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x73, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -445,25 +828,35 @@ func file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescGZIP() [] return file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDescData } -var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_goTypes = []any{ - (*CheckRequest)(nil), // 0: ory.keto.relation_tuples.v1alpha2.CheckRequest - (*CheckResponse)(nil), // 1: ory.keto.relation_tuples.v1alpha2.CheckResponse - (*Subject)(nil), // 2: ory.keto.relation_tuples.v1alpha2.Subject - (*SubjectSetQuery)(nil), // 3: ory.keto.relation_tuples.v1alpha2.SubjectSetQuery - (*RelationTuple)(nil), // 4: ory.keto.relation_tuples.v1alpha2.RelationTuple + (*CheckRequest)(nil), // 0: ory.keto.relation_tuples.v1alpha2.CheckRequest + (*CheckResponse)(nil), // 1: ory.keto.relation_tuples.v1alpha2.CheckResponse + (*CheckResponseWithError)(nil), // 2: ory.keto.relation_tuples.v1alpha2.CheckResponseWithError + (*BatchCheckRequestBody)(nil), // 3: ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody + (*BatchCheckRequest)(nil), // 4: ory.keto.relation_tuples.v1alpha2.BatchCheckRequest + (*BatchCheckResponse)(nil), // 5: ory.keto.relation_tuples.v1alpha2.BatchCheckResponse + (*Subject)(nil), // 6: ory.keto.relation_tuples.v1alpha2.Subject + (*SubjectSetQuery)(nil), // 7: ory.keto.relation_tuples.v1alpha2.SubjectSetQuery + (*RelationTuple)(nil), // 8: ory.keto.relation_tuples.v1alpha2.RelationTuple } var file_ory_keto_relation_tuples_v1alpha2_check_service_proto_depIdxs = []int32{ - 2, // 0: ory.keto.relation_tuples.v1alpha2.CheckRequest.subject:type_name -> ory.keto.relation_tuples.v1alpha2.Subject - 3, // 1: ory.keto.relation_tuples.v1alpha2.CheckRequest.subject_set:type_name -> ory.keto.relation_tuples.v1alpha2.SubjectSetQuery - 4, // 2: ory.keto.relation_tuples.v1alpha2.CheckRequest.tuple:type_name -> ory.keto.relation_tuples.v1alpha2.RelationTuple - 0, // 3: ory.keto.relation_tuples.v1alpha2.CheckService.Check:input_type -> ory.keto.relation_tuples.v1alpha2.CheckRequest - 1, // 4: ory.keto.relation_tuples.v1alpha2.CheckService.Check:output_type -> ory.keto.relation_tuples.v1alpha2.CheckResponse - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 6, // 0: ory.keto.relation_tuples.v1alpha2.CheckRequest.subject:type_name -> ory.keto.relation_tuples.v1alpha2.Subject + 7, // 1: ory.keto.relation_tuples.v1alpha2.CheckRequest.subject_set:type_name -> ory.keto.relation_tuples.v1alpha2.SubjectSetQuery + 8, // 2: ory.keto.relation_tuples.v1alpha2.CheckRequest.tuple:type_name -> ory.keto.relation_tuples.v1alpha2.RelationTuple + 8, // 3: ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.tuples:type_name -> ory.keto.relation_tuples.v1alpha2.RelationTuple + 8, // 4: ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.tuples:type_name -> ory.keto.relation_tuples.v1alpha2.RelationTuple + 3, // 5: ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.rest_body:type_name -> ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody + 2, // 6: ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.results:type_name -> ory.keto.relation_tuples.v1alpha2.CheckResponseWithError + 0, // 7: ory.keto.relation_tuples.v1alpha2.CheckService.Check:input_type -> ory.keto.relation_tuples.v1alpha2.CheckRequest + 4, // 8: ory.keto.relation_tuples.v1alpha2.CheckService.BatchCheck:input_type -> ory.keto.relation_tuples.v1alpha2.BatchCheckRequest + 1, // 9: ory.keto.relation_tuples.v1alpha2.CheckService.Check:output_type -> ory.keto.relation_tuples.v1alpha2.CheckResponse + 5, // 10: ory.keto.relation_tuples.v1alpha2.CheckService.BatchCheck:output_type -> ory.keto.relation_tuples.v1alpha2.BatchCheckResponse + 9, // [9:11] is the sub-list for method output_type + 7, // [7:9] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_ory_keto_relation_tuples_v1alpha2_check_service_proto_init() } @@ -482,7 +875,7 @@ func file_ory_keto_relation_tuples_v1alpha2_check_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ory_keto_relation_tuples_v1alpha2_check_service_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.gw.go b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.gw.go index 102dc86a9..add3fb315 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.gw.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.gw.go @@ -147,6 +147,44 @@ func local_request_CheckService_Check_3(ctx context.Context, marshaler runtime.M return msg, metadata, err } +var filter_CheckService_BatchCheck_0 = &utilities.DoubleArray{Encoding: map[string]int{"rest_body": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} + +func request_CheckService_BatchCheck_0(ctx context.Context, marshaler runtime.Marshaler, client CheckServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq BatchCheckRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.RestBody); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CheckService_BatchCheck_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.BatchCheck(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_CheckService_BatchCheck_0(ctx context.Context, marshaler runtime.Marshaler, server CheckServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq BatchCheckRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.RestBody); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CheckService_BatchCheck_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.BatchCheck(ctx, &protoReq) + return msg, metadata, err +} + // RegisterCheckServiceHandlerServer registers the http handlers for service CheckService to "mux". // UnaryRPC :call CheckServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -233,6 +271,26 @@ func RegisterCheckServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu } forward_CheckService_Check_3(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_CheckService_BatchCheck_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ory.keto.relation_tuples.v1alpha2.CheckService/BatchCheck", runtime.WithHTTPPathPattern("/relation-tuples/batch/check")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CheckService_BatchCheck_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_CheckService_BatchCheck_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -341,19 +399,38 @@ func RegisterCheckServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu } forward_CheckService_Check_3(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_CheckService_BatchCheck_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ory.keto.relation_tuples.v1alpha2.CheckService/BatchCheck", runtime.WithHTTPPathPattern("/relation-tuples/batch/check")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CheckService_BatchCheck_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_CheckService_BatchCheck_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } var ( - pattern_CheckService_Check_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"relation-tuples", "check"}, "")) - pattern_CheckService_Check_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"relation-tuples", "check", "openapi"}, "")) - pattern_CheckService_Check_2 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"relation-tuples", "check"}, "")) - pattern_CheckService_Check_3 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"relation-tuples", "check", "openapi"}, "")) + pattern_CheckService_Check_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"relation-tuples", "check"}, "")) + pattern_CheckService_Check_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"relation-tuples", "check", "openapi"}, "")) + pattern_CheckService_Check_2 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"relation-tuples", "check"}, "")) + pattern_CheckService_Check_3 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"relation-tuples", "check", "openapi"}, "")) + pattern_CheckService_BatchCheck_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"relation-tuples", "batch", "check"}, "")) ) var ( - forward_CheckService_Check_0 = runtime.ForwardResponseMessage - forward_CheckService_Check_1 = runtime.ForwardResponseMessage - forward_CheckService_Check_2 = runtime.ForwardResponseMessage - forward_CheckService_Check_3 = runtime.ForwardResponseMessage + forward_CheckService_Check_0 = runtime.ForwardResponseMessage + forward_CheckService_Check_1 = runtime.ForwardResponseMessage + forward_CheckService_Check_2 = runtime.ForwardResponseMessage + forward_CheckService_Check_3 = runtime.ForwardResponseMessage + forward_CheckService_BatchCheck_0 = runtime.ForwardResponseMessage ) diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.validate.go b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.validate.go index bfe0caa24..77973d79a 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.validate.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service.pb.validate.go @@ -365,3 +365,554 @@ var _ interface { Cause() error ErrorName() string } = CheckResponseValidationError{} + +// Validate checks the field values on CheckResponseWithError with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *CheckResponseWithError) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on CheckResponseWithError with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// CheckResponseWithErrorMultiError, or nil if none found. +func (m *CheckResponseWithError) ValidateAll() error { + return m.validate(true) +} + +func (m *CheckResponseWithError) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Allowed + + // no validation rules for Error + + // no validation rules for Snaptoken + + if len(errors) > 0 { + return CheckResponseWithErrorMultiError(errors) + } + + return nil +} + +// CheckResponseWithErrorMultiError is an error wrapping multiple validation +// errors returned by CheckResponseWithError.ValidateAll() if the designated +// constraints aren't met. +type CheckResponseWithErrorMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m CheckResponseWithErrorMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m CheckResponseWithErrorMultiError) AllErrors() []error { return m } + +// CheckResponseWithErrorValidationError is the validation error returned by +// CheckResponseWithError.Validate if the designated constraints aren't met. +type CheckResponseWithErrorValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e CheckResponseWithErrorValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e CheckResponseWithErrorValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e CheckResponseWithErrorValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e CheckResponseWithErrorValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e CheckResponseWithErrorValidationError) ErrorName() string { + return "CheckResponseWithErrorValidationError" +} + +// Error satisfies the builtin error interface +func (e CheckResponseWithErrorValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCheckResponseWithError.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = CheckResponseWithErrorValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = CheckResponseWithErrorValidationError{} + +// Validate checks the field values on BatchCheckRequestBody with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *BatchCheckRequestBody) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on BatchCheckRequestBody with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// BatchCheckRequestBodyMultiError, or nil if none found. +func (m *BatchCheckRequestBody) ValidateAll() error { + return m.validate(true) +} + +func (m *BatchCheckRequestBody) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetTuples() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BatchCheckRequestBodyValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BatchCheckRequestBodyValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BatchCheckRequestBodyValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return BatchCheckRequestBodyMultiError(errors) + } + + return nil +} + +// BatchCheckRequestBodyMultiError is an error wrapping multiple validation +// errors returned by BatchCheckRequestBody.ValidateAll() if the designated +// constraints aren't met. +type BatchCheckRequestBodyMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m BatchCheckRequestBodyMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m BatchCheckRequestBodyMultiError) AllErrors() []error { return m } + +// BatchCheckRequestBodyValidationError is the validation error returned by +// BatchCheckRequestBody.Validate if the designated constraints aren't met. +type BatchCheckRequestBodyValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e BatchCheckRequestBodyValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e BatchCheckRequestBodyValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e BatchCheckRequestBodyValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e BatchCheckRequestBodyValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e BatchCheckRequestBodyValidationError) ErrorName() string { + return "BatchCheckRequestBodyValidationError" +} + +// Error satisfies the builtin error interface +func (e BatchCheckRequestBodyValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBatchCheckRequestBody.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = BatchCheckRequestBodyValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = BatchCheckRequestBodyValidationError{} + +// Validate checks the field values on BatchCheckRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *BatchCheckRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on BatchCheckRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// BatchCheckRequestMultiError, or nil if none found. +func (m *BatchCheckRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *BatchCheckRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetTuples() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BatchCheckRequestValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BatchCheckRequestValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BatchCheckRequestValidationError{ + field: fmt.Sprintf("Tuples[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if all { + switch v := interface{}(m.GetRestBody()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BatchCheckRequestValidationError{ + field: "RestBody", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BatchCheckRequestValidationError{ + field: "RestBody", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRestBody()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BatchCheckRequestValidationError{ + field: "RestBody", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Latest + + // no validation rules for Snaptoken + + // no validation rules for MaxDepth + + if len(errors) > 0 { + return BatchCheckRequestMultiError(errors) + } + + return nil +} + +// BatchCheckRequestMultiError is an error wrapping multiple validation errors +// returned by BatchCheckRequest.ValidateAll() if the designated constraints +// aren't met. +type BatchCheckRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m BatchCheckRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m BatchCheckRequestMultiError) AllErrors() []error { return m } + +// BatchCheckRequestValidationError is the validation error returned by +// BatchCheckRequest.Validate if the designated constraints aren't met. +type BatchCheckRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e BatchCheckRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e BatchCheckRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e BatchCheckRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e BatchCheckRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e BatchCheckRequestValidationError) ErrorName() string { + return "BatchCheckRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e BatchCheckRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBatchCheckRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = BatchCheckRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = BatchCheckRequestValidationError{} + +// Validate checks the field values on BatchCheckResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *BatchCheckResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on BatchCheckResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// BatchCheckResponseMultiError, or nil if none found. +func (m *BatchCheckResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *BatchCheckResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetResults() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BatchCheckResponseValidationError{ + field: fmt.Sprintf("Results[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BatchCheckResponseValidationError{ + field: fmt.Sprintf("Results[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BatchCheckResponseValidationError{ + field: fmt.Sprintf("Results[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return BatchCheckResponseMultiError(errors) + } + + return nil +} + +// BatchCheckResponseMultiError is an error wrapping multiple validation errors +// returned by BatchCheckResponse.ValidateAll() if the designated constraints +// aren't met. +type BatchCheckResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m BatchCheckResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m BatchCheckResponseMultiError) AllErrors() []error { return m } + +// BatchCheckResponseValidationError is the validation error returned by +// BatchCheckResponse.Validate if the designated constraints aren't met. +type BatchCheckResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e BatchCheckResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e BatchCheckResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e BatchCheckResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e BatchCheckResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e BatchCheckResponseValidationError) ErrorName() string { + return "BatchCheckResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e BatchCheckResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBatchCheckResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = BatchCheckResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = BatchCheckResponseValidationError{} diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service.proto b/proto/ory/keto/relation_tuples/v1alpha2/check_service.proto index 07a7a6657..a2c2fcd27 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service.proto +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service.proto @@ -56,6 +56,66 @@ service CheckService { } } } + responses: { + key: "400"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; + responses: { + key: "default"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; + }; + } + + // Performs an authorization check for a batch of tuples. + // + // To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). + rpc BatchCheck(BatchCheckRequest) returns (BatchCheckResponse) { + option (google.api.http) = { + post: "/relation-tuples/batch/check" + body: "rest_body" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + consumes: "application/json" + tags: "permission" + operation_id: "batchCheckPermission"; + responses: { + key: "200" + value: { + description: "The response of the permission check, in case it is allowed. For the `/openapi` endpoints, the status code is always 200." + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.BatchCheckResponse"} + } + } + } + responses: { + key: "400"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; + responses: { + key: "default"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; }; } } @@ -162,3 +222,97 @@ message CheckResponse { // --> string snaptoken = 2 [(google.api.field_visibility).restriction = "NO_SWAGGER"]; } + +// The response for an individual check in the CheckService.BatchCheck rpc. +message CheckResponseWithError { + // Whether the specified subject (id) + // is related to the requested object. + // + // It is false by default if no ACL matches. + bool allowed = 1 [(google.api.field_behavior) = REQUIRED]; + // If there was an error checking the tuple, + // this will contain the error message. + // + // If the check was performed successfully, this will be empty. + string error = 2; + // This field is not implemented yet and has no effect. + // + string snaptoken = 3 [(google.api.field_visibility).restriction = "NO_SWAGGER"]; +} + +message BatchCheckRequestBody { + repeated RelationTuple tuples = 1; +} + +// The request for a CheckService.BatchCheck RPC. +// Checks a batch of relations. +message BatchCheckRequest { + repeated RelationTuple tuples = 1 [(google.api.field_visibility).restriction = "NO_SWAGGER"]; + + // Batch Check Permission Body. + BatchCheckRequestBody rest_body = 5 [ + deprecated = true, + json_name = "body" + ]; + + // This field is not implemented yet and has no effect. + // + bool latest = 2 [(google.api.field_visibility).restriction = "NO_SWAGGER"]; + // This field is not implemented yet and has no effect. + // + string snaptoken = 3 [(google.api.field_visibility).restriction = "NO_SWAGGER"]; + // The maximum depth to search for a relation. + // + // If the value is less than 1 or greater than the global + // max-depth then the global max-depth will be used instead. + int32 max_depth = 4 [json_name = "max-depth"]; +} + +// The response for a CheckService.BatchCheck rpc. +message BatchCheckResponse { + // The results of the batch check. The order of these + // results will match the order of the input. + repeated CheckResponseWithError results = 1; +} diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc.pb.go index ee5d6e350..710efbd96 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc.pb.go @@ -19,7 +19,8 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - CheckService_Check_FullMethodName = "/ory.keto.relation_tuples.v1alpha2.CheckService/Check" + CheckService_Check_FullMethodName = "/ory.keto.relation_tuples.v1alpha2.CheckService/Check" + CheckService_BatchCheck_FullMethodName = "/ory.keto.relation_tuples.v1alpha2.CheckService/BatchCheck" ) // CheckServiceClient is the client API for CheckService service. @@ -33,6 +34,10 @@ const ( type CheckServiceClient interface { // Performs an authorization check. Check(ctx context.Context, in *CheckRequest, opts ...grpc.CallOption) (*CheckResponse, error) + // Performs an authorization check for a batch of tuples. + // + // To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). + BatchCheck(ctx context.Context, in *BatchCheckRequest, opts ...grpc.CallOption) (*BatchCheckResponse, error) } type checkServiceClient struct { @@ -53,6 +58,16 @@ func (c *checkServiceClient) Check(ctx context.Context, in *CheckRequest, opts . return out, nil } +func (c *checkServiceClient) BatchCheck(ctx context.Context, in *BatchCheckRequest, opts ...grpc.CallOption) (*BatchCheckResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BatchCheckResponse) + err := c.cc.Invoke(ctx, CheckService_BatchCheck_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // CheckServiceServer is the server API for CheckService service. // All implementations should embed UnimplementedCheckServiceServer // for forward compatibility. @@ -64,6 +79,10 @@ func (c *checkServiceClient) Check(ctx context.Context, in *CheckRequest, opts . type CheckServiceServer interface { // Performs an authorization check. Check(context.Context, *CheckRequest) (*CheckResponse, error) + // Performs an authorization check for a batch of tuples. + // + // To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). + BatchCheck(context.Context, *BatchCheckRequest) (*BatchCheckResponse, error) } // UnimplementedCheckServiceServer should be embedded to have @@ -76,6 +95,9 @@ type UnimplementedCheckServiceServer struct{} func (UnimplementedCheckServiceServer) Check(context.Context, *CheckRequest) (*CheckResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Check not implemented") } +func (UnimplementedCheckServiceServer) BatchCheck(context.Context, *BatchCheckRequest) (*BatchCheckResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BatchCheck not implemented") +} func (UnimplementedCheckServiceServer) testEmbeddedByValue() {} // UnsafeCheckServiceServer may be embedded to opt out of forward compatibility for this service. @@ -114,6 +136,24 @@ func _CheckService_Check_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _CheckService_BatchCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CheckServiceServer).BatchCheck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CheckService_BatchCheck_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CheckServiceServer).BatchCheck(ctx, req.(*BatchCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + // CheckService_ServiceDesc is the grpc.ServiceDesc for CheckService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -125,6 +165,10 @@ var CheckService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Check", Handler: _CheckService_Check_Handler, }, + { + MethodName: "BatchCheck", + Handler: _CheckService_BatchCheck_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "ory/keto/relation_tuples/v1alpha2/check_service.proto", diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.d.ts index 2941eaf38..e65d89122 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_check_service_pb from "../../../../ory/keto/relation_tuples/v1alpha2/check_service_pb"; import * as google_api_field_behavior_pb from "../../../../google/api/field_behavior_pb"; import * as google_api_visibility_pb from "../../../../google/api/visibility_pb"; @@ -13,6 +13,7 @@ import * as protoc_gen_openapiv2_options_annotations_pb from "../../../../protoc interface ICheckServiceService extends grpc.ServiceDefinition { check: ICheckServiceService_ICheck; + batchCheck: ICheckServiceService_IBatchCheck; } interface ICheckServiceService_ICheck extends grpc.MethodDefinition { @@ -24,22 +25,38 @@ interface ICheckServiceService_ICheck extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } +interface ICheckServiceService_IBatchCheck extends grpc.MethodDefinition { + path: "/ory.keto.relation_tuples.v1alpha2.CheckService/BatchCheck"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} export const CheckServiceService: ICheckServiceService; -export interface ICheckServiceServer { +export interface ICheckServiceServer extends grpc.UntypedServiceImplementation { check: grpc.handleUnaryCall; + batchCheck: grpc.handleUnaryCall; } export interface ICheckServiceClient { check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; + batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; + batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; + batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; } export class CheckServiceClient extends grpc.Client implements ICheckServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; public check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; public check(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckResponse) => void): grpc.ClientUnaryCall; + public batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; + public batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; + public batchCheck(request: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse) => void): grpc.ClientUnaryCall; } diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.js b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.js index 33348ac41..48663107e 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.js +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb.js @@ -9,6 +9,28 @@ var google_api_visibility_pb = require('../../../../google/api/visibility_pb.js' var ory_keto_relation_tuples_v1alpha2_relation_tuples_pb = require('../../../../ory/keto/relation_tuples/v1alpha2/relation_tuples_pb.js'); var protoc$gen$openapiv2_options_annotations_pb = require('../../../../protoc-gen-openapiv2/options/annotations_pb.js'); +function serialize_ory_keto_relation_tuples_v1alpha2_BatchCheckRequest(arg) { + if (!(arg instanceof ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest)) { + throw new Error('Expected argument of type ory.keto.relation_tuples.v1alpha2.BatchCheckRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_ory_keto_relation_tuples_v1alpha2_BatchCheckRequest(buffer_arg) { + return ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_ory_keto_relation_tuples_v1alpha2_BatchCheckResponse(arg) { + if (!(arg instanceof ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse)) { + throw new Error('Expected argument of type ory.keto.relation_tuples.v1alpha2.BatchCheckResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_ory_keto_relation_tuples_v1alpha2_BatchCheckResponse(buffer_arg) { + return ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_ory_keto_relation_tuples_v1alpha2_CheckRequest(arg) { if (!(arg instanceof ory_keto_relation_tuples_v1alpha2_check_service_pb.CheckRequest)) { throw new Error('Expected argument of type ory.keto.relation_tuples.v1alpha2.CheckRequest'); @@ -49,6 +71,20 @@ check: { responseSerialize: serialize_ory_keto_relation_tuples_v1alpha2_CheckResponse, responseDeserialize: deserialize_ory_keto_relation_tuples_v1alpha2_CheckResponse, }, + // Performs an authorization check for a batch of tuples. +// +// To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview). +batchCheck: { + path: '/ory.keto.relation_tuples.v1alpha2.CheckService/BatchCheck', + requestStream: false, + responseStream: false, + requestType: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckRequest, + responseType: ory_keto_relation_tuples_v1alpha2_check_service_pb.BatchCheckResponse, + requestSerialize: serialize_ory_keto_relation_tuples_v1alpha2_BatchCheckRequest, + requestDeserialize: deserialize_ory_keto_relation_tuples_v1alpha2_BatchCheckRequest, + responseSerialize: serialize_ory_keto_relation_tuples_v1alpha2_BatchCheckResponse, + responseDeserialize: deserialize_ory_keto_relation_tuples_v1alpha2_BatchCheckResponse, + }, }; exports.CheckServiceClient = grpc.makeGenericClientConstructor(CheckServiceService); diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.d.ts index 461fa6820..c25445edd 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.d.ts @@ -100,3 +100,110 @@ export namespace CheckResponse { snaptoken: string, } } + +export class CheckResponseWithError extends jspb.Message { + getAllowed(): boolean; + setAllowed(value: boolean): CheckResponseWithError; + getError(): string; + setError(value: string): CheckResponseWithError; + getSnaptoken(): string; + setSnaptoken(value: string): CheckResponseWithError; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): CheckResponseWithError.AsObject; + static toObject(includeInstance: boolean, msg: CheckResponseWithError): CheckResponseWithError.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: CheckResponseWithError, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CheckResponseWithError; + static deserializeBinaryFromReader(message: CheckResponseWithError, reader: jspb.BinaryReader): CheckResponseWithError; +} + +export namespace CheckResponseWithError { + export type AsObject = { + allowed: boolean, + error: string, + snaptoken: string, + } +} + +export class BatchCheckRequestBody extends jspb.Message { + clearTuplesList(): void; + getTuplesList(): Array; + setTuplesList(value: Array): BatchCheckRequestBody; + addTuples(value?: ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple, index?: number): ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): BatchCheckRequestBody.AsObject; + static toObject(includeInstance: boolean, msg: BatchCheckRequestBody): BatchCheckRequestBody.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: BatchCheckRequestBody, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): BatchCheckRequestBody; + static deserializeBinaryFromReader(message: BatchCheckRequestBody, reader: jspb.BinaryReader): BatchCheckRequestBody; +} + +export namespace BatchCheckRequestBody { + export type AsObject = { + tuplesList: Array, + } +} + +export class BatchCheckRequest extends jspb.Message { + clearTuplesList(): void; + getTuplesList(): Array; + setTuplesList(value: Array): BatchCheckRequest; + addTuples(value?: ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple, index?: number): ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple; + + hasRestBody(): boolean; + clearRestBody(): void; + getRestBody(): BatchCheckRequestBody | undefined; + setRestBody(value?: BatchCheckRequestBody): BatchCheckRequest; + getLatest(): boolean; + setLatest(value: boolean): BatchCheckRequest; + getSnaptoken(): string; + setSnaptoken(value: string): BatchCheckRequest; + getMaxDepth(): number; + setMaxDepth(value: number): BatchCheckRequest; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): BatchCheckRequest.AsObject; + static toObject(includeInstance: boolean, msg: BatchCheckRequest): BatchCheckRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: BatchCheckRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): BatchCheckRequest; + static deserializeBinaryFromReader(message: BatchCheckRequest, reader: jspb.BinaryReader): BatchCheckRequest; +} + +export namespace BatchCheckRequest { + export type AsObject = { + tuplesList: Array, + restBody?: BatchCheckRequestBody.AsObject, + latest: boolean, + snaptoken: string, + maxDepth: number, + } +} + +export class BatchCheckResponse extends jspb.Message { + clearResultsList(): void; + getResultsList(): Array; + setResultsList(value: Array): BatchCheckResponse; + addResults(value?: CheckResponseWithError, index?: number): CheckResponseWithError; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): BatchCheckResponse.AsObject; + static toObject(includeInstance: boolean, msg: BatchCheckResponse): BatchCheckResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: BatchCheckResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): BatchCheckResponse; + static deserializeBinaryFromReader(message: BatchCheckResponse, reader: jspb.BinaryReader): BatchCheckResponse; +} + +export namespace BatchCheckResponse { + export type AsObject = { + resultsList: Array, + } +} diff --git a/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.js b/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.js index 3bc5476c8..e088bbc6e 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.js +++ b/proto/ory/keto/relation_tuples/v1alpha2/check_service_pb.js @@ -31,9 +31,13 @@ var ory_keto_relation_tuples_v1alpha2_relation_tuples_pb = require('../../../../ goog.object.extend(proto, ory_keto_relation_tuples_v1alpha2_relation_tuples_pb); var protoc$gen$openapiv2_options_annotations_pb = require('../../../../protoc-gen-openapiv2/options/annotations_pb.js'); goog.object.extend(proto, protoc$gen$openapiv2_options_annotations_pb); +goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest', null, global); +goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody', null, global); +goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse', null, global); goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.CheckRequest', null, global); goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.CheckRequest.RestApiSubjectCase', null, global); goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.CheckResponse', null, global); +goog.exportSymbol('proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -76,6 +80,90 @@ if (goog.DEBUG && !COMPILED) { */ proto.ory.keto.relation_tuples.v1alpha2.CheckResponse.displayName = 'proto.ory.keto.relation_tuples.v1alpha2.CheckResponse'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.displayName = 'proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.repeatedFields_, null); +}; +goog.inherits(proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.displayName = 'proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.repeatedFields_, null); +}; +goog.inherits(proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.displayName = 'proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.repeatedFields_, null); +}; +goog.inherits(proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.displayName = 'proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse'; +} /** * Oneof group definitions for this message. Each group defines the field @@ -743,4 +831,815 @@ proto.ory.keto.relation_tuples.v1alpha2.CheckResponse.prototype.setSnaptoken = f }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.toObject = function(opt_includeInstance) { + return proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.toObject = function(includeInstance, msg) { + var f, obj = { +allowed: jspb.Message.getBooleanFieldWithDefault(msg, 1, false), +error: jspb.Message.getFieldWithDefault(msg, 2, ""), +snaptoken: jspb.Message.getFieldWithDefault(msg, 3, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError; + return proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setAllowed(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setError(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setSnaptoken(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getAllowed(); + if (f) { + writer.writeBool( + 1, + f + ); + } + f = message.getError(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getSnaptoken(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } +}; + + +/** + * optional bool allowed = 1; + * @return {boolean} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.getAllowed = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.setAllowed = function(value) { + return jspb.Message.setProto3BooleanField(this, 1, value); +}; + + +/** + * optional string error = 2; + * @return {string} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.getError = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.setError = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string snaptoken = 3; + * @return {string} + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.getSnaptoken = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.prototype.setSnaptoken = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.toObject = function(opt_includeInstance) { + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.toObject = function(includeInstance, msg) { + var f, obj = { +tuplesList: jspb.Message.toObjectList(msg.getTuplesList(), + ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody; + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple; + reader.readMessage(value,ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.deserializeBinaryFromReader); + msg.addTuples(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTuplesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated RelationTuple tuples = 1; + * @return {!Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.getTuplesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} returns this +*/ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.setTuplesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.ory.keto.relation_tuples.v1alpha2.RelationTuple=} opt_value + * @param {number=} opt_index + * @return {!proto.ory.keto.relation_tuples.v1alpha2.RelationTuple} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.addTuples = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ory.keto.relation_tuples.v1alpha2.RelationTuple, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.prototype.clearTuplesList = function() { + return this.setTuplesList([]); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.toObject = function(opt_includeInstance) { + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.toObject = function(includeInstance, msg) { + var f, obj = { +tuplesList: jspb.Message.toObjectList(msg.getTuplesList(), + ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.toObject, includeInstance), +restBody: (f = msg.getRestBody()) && proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.toObject(includeInstance, f), +latest: jspb.Message.getBooleanFieldWithDefault(msg, 2, false), +snaptoken: jspb.Message.getFieldWithDefault(msg, 3, ""), +maxDepth: jspb.Message.getFieldWithDefault(msg, 4, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest; + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple; + reader.readMessage(value,ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.deserializeBinaryFromReader); + msg.addTuples(value); + break; + case 5: + var value = new proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody; + reader.readMessage(value,proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.deserializeBinaryFromReader); + msg.setRestBody(value); + break; + case 2: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setLatest(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setSnaptoken(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt32()); + msg.setMaxDepth(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTuplesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple.serializeBinaryToWriter + ); + } + f = message.getRestBody(); + if (f != null) { + writer.writeMessage( + 5, + f, + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody.serializeBinaryToWriter + ); + } + f = message.getLatest(); + if (f) { + writer.writeBool( + 2, + f + ); + } + f = message.getSnaptoken(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getMaxDepth(); + if (f !== 0) { + writer.writeInt32( + 4, + f + ); + } +}; + + +/** + * repeated RelationTuple tuples = 1; + * @return {!Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.getTuplesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, ory_keto_relation_tuples_v1alpha2_relation_tuples_pb.RelationTuple, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this +*/ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.setTuplesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.ory.keto.relation_tuples.v1alpha2.RelationTuple=} opt_value + * @param {number=} opt_index + * @return {!proto.ory.keto.relation_tuples.v1alpha2.RelationTuple} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.addTuples = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ory.keto.relation_tuples.v1alpha2.RelationTuple, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.clearTuplesList = function() { + return this.setTuplesList([]); +}; + + +/** + * optional BatchCheckRequestBody rest_body = 5; + * @return {?proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.getRestBody = function() { + return /** @type{?proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody} */ ( + jspb.Message.getWrapperField(this, proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody, 5)); +}; + + +/** + * @param {?proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequestBody|undefined} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this +*/ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.setRestBody = function(value) { + return jspb.Message.setWrapperField(this, 5, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.clearRestBody = function() { + return this.setRestBody(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.hasRestBody = function() { + return jspb.Message.getField(this, 5) != null; +}; + + +/** + * optional bool latest = 2; + * @return {boolean} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.getLatest = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.setLatest = function(value) { + return jspb.Message.setProto3BooleanField(this, 2, value); +}; + + +/** + * optional string snaptoken = 3; + * @return {string} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.getSnaptoken = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.setSnaptoken = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional int32 max_depth = 4; + * @return {number} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.getMaxDepth = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckRequest.prototype.setMaxDepth = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.toObject = function(opt_includeInstance) { + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.toObject = function(includeInstance, msg) { + var f, obj = { +resultsList: jspb.Message.toObjectList(msg.getResultsList(), + proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse; + return proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError; + reader.readMessage(value,proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.deserializeBinaryFromReader); + msg.addResults(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getResultsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated CheckResponseWithError results = 1; + * @return {!Array} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.getResultsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} returns this +*/ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.setResultsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError=} opt_value + * @param {number=} opt_index + * @return {!proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError} + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.addResults = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ory.keto.relation_tuples.v1alpha2.CheckResponseWithError, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse} returns this + */ +proto.ory.keto.relation_tuples.v1alpha2.BatchCheckResponse.prototype.clearResultsList = function() { + return this.setResultsList([]); +}; + + goog.object.extend(exports, proto.ory.keto.relation_tuples.v1alpha2); diff --git a/proto/ory/keto/relation_tuples/v1alpha2/expand_service.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/expand_service.pb.go index 7eb4e4e67..8054cbcd6 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/expand_service.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/expand_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/expand_service.proto @@ -468,16 +468,16 @@ var file_ory_keto_relation_tuples_v1alpha2_expand_service_proto_rawDesc = []byte 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x12, 0x07, 0x0a, 0x03, 0x6e, 0x6f, 0x74, 0x10, 0x07, 0x12, 0x25, 0x0a, 0x0d, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x10, 0x07, 0x1a, 0x12, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x4e, 0x4f, 0x5f, - 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x1a, 0x02, 0x10, 0x01, 0x32, 0xa7, 0x03, 0x0a, 0x0d, - 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x95, 0x03, + 0x53, 0x57, 0x41, 0x47, 0x47, 0x45, 0x52, 0x1a, 0x02, 0x10, 0x01, 0x32, 0xc5, 0x04, 0x0a, 0x0d, + 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb3, 0x04, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0x30, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x45, - 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa5, 0x02, - 0x92, 0x41, 0xfc, 0x01, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc3, 0x03, + 0x92, 0x41, 0x9a, 0x03, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x11, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x32, 0x21, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c, 0x65, @@ -493,22 +493,32 @@ var file_ory_keto_relation_tuples_v1alpha2_expand_service_proto_rawDesc = []byte 0x1a, 0x2e, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x72, 0x65, 0x65, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x62, 0x04, 0x74, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2f, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x65, - 0x78, 0x70, 0x61, 0x6e, 0x64, 0x42, 0xc3, 0x01, 0x0a, 0x24, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x42, 0x12, - 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x6f, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x32, 0x3b, 0x72, 0x74, 0x73, 0xaa, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, - 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xca, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x5c, 0x4b, - 0x65, 0x74, 0x6f, 0x5c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, - 0x65, 0x73, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x4a, 0x4b, 0x0a, 0x03, 0x34, 0x30, 0x30, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, 0x72, + 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0x4f, 0x0a, + 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x12, 0x34, 0x0a, 0x32, 0x1a, 0x30, 0x2e, 0x6f, + 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, + 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1f, 0x62, 0x04, 0x74, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x78, 0x70, + 0x61, 0x6e, 0x64, 0x42, 0xc3, 0x01, 0x0a, 0x24, 0x73, 0x68, 0x2e, 0x6f, 0x72, 0x79, 0x2e, 0x6b, + 0x65, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x75, 0x70, + 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x42, 0x12, 0x45, 0x78, + 0x70, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, + 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, + 0x79, 0x2f, 0x6b, 0x65, 0x74, 0x6f, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x3b, + 0x72, 0x74, 0x73, 0xaa, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x74, 0x6f, 0x2e, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xca, 0x02, 0x20, 0x4f, 0x72, 0x79, 0x5c, 0x4b, 0x65, 0x74, + 0x6f, 0x5c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, + 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/proto/ory/keto/relation_tuples/v1alpha2/expand_service.proto b/proto/ory/keto/relation_tuples/v1alpha2/expand_service.proto index dcf3babe2..109e74bf5 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/expand_service.proto +++ b/proto/ory/keto/relation_tuples/v1alpha2/expand_service.proto @@ -39,6 +39,24 @@ service ExpandService { } } } + responses: { + key: "400"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; + responses: { + key: "default"; + value: { + description: "errorGeneric"; + schema: { + json_schema: {ref: ".ory.keto.relation_tuples.v1alpha2.ErrorResponse"} + } + }; + }; }; } } diff --git a/proto/ory/keto/relation_tuples/v1alpha2/expand_service_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/expand_service_grpc_pb.d.ts index 51d7d6213..a0cb7d636 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/expand_service_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/expand_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_expand_service_pb from "../../../../ory/keto/relation_tuples/v1alpha2/expand_service_pb"; import * as google_api_field_behavior_pb from "../../../../google/api/field_behavior_pb"; import * as google_api_visibility_pb from "../../../../google/api/visibility_pb"; @@ -27,7 +27,7 @@ interface IExpandServiceService_IExpand extends grpc.MethodDefinition; } @@ -38,7 +38,7 @@ export interface IExpandServiceClient { } export class ExpandServiceClient extends grpc.Client implements IExpandServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public expand(request: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; public expand(request: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; public expand(request: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_expand_service_pb.ExpandResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service.pb.go index e633b4af4..4ae8fdbe1 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/namespaces_service.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service_grpc_pb.d.ts index 40c569d2a..67c0de6b0 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/namespaces_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_namespaces_service_pb from "../../../../ory/keto/relation_tuples/v1alpha2/namespaces_service_pb"; import * as protoc_gen_openapiv2_options_annotations_pb from "../../../../protoc-gen-openapiv2/options/annotations_pb"; @@ -24,7 +24,7 @@ interface INamespacesServiceService_IListNamespaces extends grpc.MethodDefinitio export const NamespacesServiceService: INamespacesServiceService; -export interface INamespacesServiceServer { +export interface INamespacesServiceServer extends grpc.UntypedServiceImplementation { listNamespaces: grpc.handleUnaryCall; } @@ -35,7 +35,7 @@ export interface INamespacesServiceClient { } export class NamespacesServiceClient extends grpc.Client implements INamespacesServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public listNamespaces(request: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesResponse) => void): grpc.ClientUnaryCall; public listNamespaces(request: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesResponse) => void): grpc.ClientUnaryCall; public listNamespaces(request: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_namespaces_service_pb.ListNamespacesResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/ory/keto/relation_tuples/v1alpha2/openapi.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/openapi.pb.go index 01e58ee38..626c647e8 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/openapi.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/openapi.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/openapi.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/read_service.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/read_service.pb.go index bd95dba89..ffa31d10c 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/read_service.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/read_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/read_service.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/read_service_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/read_service_grpc_pb.d.ts index 822bbda17..24aca514a 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/read_service_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/read_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_read_service_pb from "../../../../ory/keto/relation_tuples/v1alpha2/read_service_pb"; import * as google_api_visibility_pb from "../../../../google/api/visibility_pb"; import * as google_protobuf_field_mask_pb from "google-protobuf/google/protobuf/field_mask_pb"; @@ -27,7 +27,7 @@ interface IReadServiceService_IListRelationTuples extends grpc.MethodDefinition< export const ReadServiceService: IReadServiceService; -export interface IReadServiceServer { +export interface IReadServiceServer extends grpc.UntypedServiceImplementation { listRelationTuples: grpc.handleUnaryCall; } @@ -38,7 +38,7 @@ export interface IReadServiceClient { } export class ReadServiceClient extends grpc.Client implements IReadServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public listRelationTuples(request: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; public listRelationTuples(request: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; public listRelationTuples(request: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_read_service_pb.ListRelationTuplesResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/ory/keto/relation_tuples/v1alpha2/relation_tuples.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/relation_tuples.pb.go index f2a0d7b9e..39ead98ad 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/relation_tuples.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/relation_tuples.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/relation_tuples.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/version.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/version.pb.go index 7f9c1706b..9d875d3f0 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/version.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/version.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/version.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/version_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/version_grpc_pb.d.ts index 32f21f9d9..1224d94a0 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/version_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/version_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_version_pb from "../../../../ory/keto/relation_tuples/v1alpha2/version_pb"; import * as protoc_gen_openapiv2_options_annotations_pb from "../../../../protoc-gen-openapiv2/options/annotations_pb"; @@ -24,7 +24,7 @@ interface IVersionServiceService_IGetVersion extends grpc.MethodDefinition; } @@ -35,7 +35,7 @@ export interface IVersionServiceClient { } export class VersionServiceClient extends grpc.Client implements IVersionServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public getVersion(request: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; public getVersion(request: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; public getVersion(request: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_version_pb.GetVersionResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/ory/keto/relation_tuples/v1alpha2/write_service.pb.go b/proto/ory/keto/relation_tuples/v1alpha2/write_service.pb.go index a08058e54..e6f76336c 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/write_service.pb.go +++ b/proto/ory/keto/relation_tuples/v1alpha2/write_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.0 +// protoc-gen-go v1.36.1 // protoc (unknown) // source: ory/keto/relation_tuples/v1alpha2/write_service.proto diff --git a/proto/ory/keto/relation_tuples/v1alpha2/write_service_grpc_pb.d.ts b/proto/ory/keto/relation_tuples/v1alpha2/write_service_grpc_pb.d.ts index 82f957f6b..22266f36e 100644 --- a/proto/ory/keto/relation_tuples/v1alpha2/write_service_grpc_pb.d.ts +++ b/proto/ory/keto/relation_tuples/v1alpha2/write_service_grpc_pb.d.ts @@ -4,7 +4,7 @@ /* tslint:disable */ /* eslint-disable */ -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import * as ory_keto_relation_tuples_v1alpha2_write_service_pb from "../../../../ory/keto/relation_tuples/v1alpha2/write_service_pb"; import * as google_api_field_behavior_pb from "../../../../google/api/field_behavior_pb"; import * as google_api_visibility_pb from "../../../../google/api/visibility_pb"; @@ -48,7 +48,7 @@ interface IWriteServiceService_IDeleteRelationTuples extends grpc.MethodDefiniti export const WriteServiceService: IWriteServiceService; -export interface IWriteServiceServer { +export interface IWriteServiceServer extends grpc.UntypedServiceImplementation { transactRelationTuples: grpc.handleUnaryCall; createRelationTuple: grpc.handleUnaryCall; deleteRelationTuples: grpc.handleUnaryCall; @@ -67,7 +67,7 @@ export interface IWriteServiceClient { } export class WriteServiceClient extends grpc.Client implements IWriteServiceClient { - constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); public transactRelationTuples(request: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesRequest, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; public transactRelationTuples(request: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; public transactRelationTuples(request: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ory_keto_relation_tuples_v1alpha2_write_service_pb.TransactRelationTuplesResponse) => void): grpc.ClientUnaryCall; diff --git a/proto/package-lock.json b/proto/package-lock.json index ce323f395..102bfea0b 100644 --- a/proto/package-lock.json +++ b/proto/package-lock.json @@ -8,30 +8,30 @@ "name": "@ory/keto-grpc-client", "version": "0.6.0-alpha.1", "dependencies": { - "@grpc/grpc-js": "1.9.6", + "@grpc/grpc-js": "1.12.4", "google-protobuf": "^3.21.2" } }, "node_modules/@grpc/grpc-js": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.6.tgz", - "integrity": "sha512-yq3qTy23u++8zdvf+h4mz4ohDFi681JAkMZZPTKh8zmUVh0AKLisFlgxcn22FMNowXz15oJ6pqgwT7DJ+PdJvg==", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.4.tgz", + "integrity": "sha512-NBhrxEWnFh0FxeA0d//YP95lRFsSx2TNLEUQg4/W+5f/BMxcCjgOOIT24iD+ZB/tZw057j44DaIxja7w4XMrhg==", "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.2.4", + "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { @@ -41,6 +41,15 @@ "node": ">=6" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -96,11 +105,11 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~6.20.0" } }, "node_modules/ansi-regex": { @@ -160,9 +169,9 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -199,9 +208,9 @@ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -254,9 +263,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -310,25 +319,30 @@ }, "dependencies": { "@grpc/grpc-js": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.6.tgz", - "integrity": "sha512-yq3qTy23u++8zdvf+h4mz4ohDFi681JAkMZZPTKh8zmUVh0AKLisFlgxcn22FMNowXz15oJ6pqgwT7DJ+PdJvg==", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.4.tgz", + "integrity": "sha512-NBhrxEWnFh0FxeA0d//YP95lRFsSx2TNLEUQg4/W+5f/BMxcCjgOOIT24iD+ZB/tZw057j44DaIxja7w4XMrhg==", "requires": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" } }, "@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "requires": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.2.4", + "protobufjs": "^7.2.5", "yargs": "^17.7.2" } }, + "@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==" + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -384,11 +398,11 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "requires": { - "undici-types": "~5.25.1" + "undici-types": "~6.20.0" } }, "ansi-regex": { @@ -433,9 +447,9 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "get-caller-file": { "version": "2.0.5", @@ -463,9 +477,9 @@ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -505,9 +519,9 @@ } }, "undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "wrap-ansi": { "version": "7.0.0", diff --git a/proto/package.json b/proto/package.json index 4c8ba1501..bcf6dd9ae 100644 --- a/proto/package.json +++ b/proto/package.json @@ -6,7 +6,7 @@ "bugs": "https://github.com/ory/keto/issues", "main": "./index.js", "dependencies": { - "@grpc/grpc-js": "1.9.6", + "@grpc/grpc-js": "1.12.4", "google-protobuf": "^3.21.2" } } diff --git a/scripts/test-resetdb.sh b/scripts/test-resetdb.sh index 6c03c7f39..8cd99808d 100755 --- a/scripts/test-resetdb.sh +++ b/scripts/test-resetdb.sh @@ -6,9 +6,9 @@ docker rm -f test_keto_postgres || true docker rm -f test_keto_mysql || true docker rm -f test_keto_cockroach || true -postgres_port="$(docker port "$(docker run --name test_keto_postgres -e "POSTGRES_PASSWORD=secret" -e "POSTGRES_DB=postgres" -p 0.0.0.0:0:5432 -d postgres:11.8)" 5432 | sed 's/.*:\([0-9]*\)/\1/')" +postgres_port="$(docker port "$(docker run --name test_keto_postgres -e "POSTGRES_PASSWORD=secret" -e "POSTGRES_DB=postgres" -p 0.0.0.0:0:5432 -d postgres:16)" 5432 | sed 's/.*:\([0-9]*\)/\1/')" mysql_port="$(docker port "$(docker run --name test_keto_mysql -e "MYSQL_ROOT_PASSWORD=secret" -p 0.0.0.0:0:3306 -d mysql:8.0)" 3306 | sed 's/.*:\([0-9]*\)/\1/')" -cockroach_port="$(docker port "$(docker run --name test_keto_cockroach -p 0.0.0.0:0:26257 -d cockroachdb/cockroach:v20.2.4 start-single-node --insecure)" 26257 | sed 's/.*:\([0-9]*\)/\1/')" +cockroach_port="$(docker port "$(docker run --name test_keto_cockroach -p 0.0.0.0:0:26257 -d cockroachdb/cockroach:latest-v23.2 start-single-node --insecure)" 26257 | sed 's/.*:\([0-9]*\)/\1/')" TEST_DATABASE_POSTGRESQL=$(printf "postgres://postgres:secret@localhost:%s/postgres?sslmode=disable" "$postgres_port") TEST_DATABASE_MYSQL=$(printf "mysql://root:secret@(localhost:%s)/mysql?parseTime=true&multiStatements=true" "$mysql_port") diff --git a/spec/api.json b/spec/api.json index 61df46ce5..7ca829698 100644 --- a/spec/api.json +++ b/spec/api.json @@ -5,6 +5,30 @@ "format": "uuid4", "type": "string" }, + "batchCheckPermissionBody": { + "properties": { + "tuples": { + "items": { + "$ref": "#/components/schemas/relationship" + }, + "type": "array" + } + }, + "type": "object" + }, + "batchCheckPermissionResult": { + "description": "The response for a CheckService.BatchCheck rpc.", + "properties": { + "results": { + "description": "The results of the batch check. The order of these\nresults will match the order of the input.", + "items": { + "$ref": "#/components/schemas/checkPermissionResultWithError" + }, + "type": "array" + } + }, + "type": "object" + }, "checkOplSyntaxResult": { "properties": { "errors": { @@ -33,6 +57,21 @@ "required": ["allowed"], "type": "object" }, + "checkPermissionResultWithError": { + "description": "The response for an individual check in the CheckService.BatchCheck rpc.", + "properties": { + "allowed": { + "description": "Whether the specified subject (id)\nis related to the requested object.\n\nIt is false by default if no ACL matches.", + "type": "boolean" + }, + "error": { + "description": "If there was an error checking the tuple,\nthis will contain the error message.\n\nIf the check was performed successfully, this will be empty.", + "type": "string" + } + }, + "required": ["allowed"], + "type": "object" + }, "createRelationshipBody": { "properties": { "namespace": { @@ -888,6 +927,69 @@ "tags": ["relationship"] } }, + "/relation-tuples/batch/check": { + "post": { + "description": "To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview).", + "operationId": "batchCheckPermission", + "parameters": [ + { + "description": "The maximum depth to search for a relation.\n\nIf the value is less than 1 or greater than the global\nmax-depth then the global max-depth will be used instead.", + "in": "query", + "name": "max-depth", + "schema": { + "format": "int32", + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/batchCheckPermissionBody" + } + } + }, + "description": "Batch Check Permission Body.", + "required": true, + "x-originalParamName": "body" + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/batchCheckPermissionResult" + } + } + }, + "description": "The response of the permission check, in case it is allowed. For the `/openapi` endpoints, the status code is always 200." + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errorGeneric" + } + } + }, + "description": "errorGeneric" + }, + "default": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errorGeneric" + } + } + }, + "description": "errorGeneric" + } + }, + "summary": "Performs an authorization check for a batch of tuples.", + "tags": ["permission"] + } + }, "/relation-tuples/check": { "get": { "operationId": "checkPermissionOrError", diff --git a/spec/api.swagger.json b/spec/api.swagger.json index cf6866e87..524751820 100755 --- a/spec/api.swagger.json +++ b/spec/api.swagger.json @@ -352,6 +352,54 @@ "consumes": ["application/x-www-form-urlencoded"] } }, + "/relation-tuples/batch/check": { + "post": { + "summary": "Performs an authorization check for a batch of tuples.", + "description": "To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview).", + "operationId": "batchCheckPermission", + "responses": { + "200": { + "description": "The response of the permission check, in case it is allowed. For the `/openapi` endpoints, the status code is always 200.", + "schema": { + "$ref": "#/definitions/batchCheckPermissionResult" + } + }, + "400": { + "description": "errorGeneric", + "schema": { + "$ref": "#/definitions/errorGeneric" + } + }, + "default": { + "description": "errorGeneric", + "schema": { + "$ref": "#/definitions/errorGeneric" + } + } + }, + "parameters": [ + { + "name": "body", + "description": "Batch Check Permission Body.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/batchCheckPermissionBody" + } + }, + { + "name": "max-depth", + "description": "The maximum depth to search for a relation.\n\nIf the value is less than 1 or greater than the global\nmax-depth then the global max-depth will be used instead.", + "in": "query", + "required": false, + "type": "integer", + "format": "int32" + } + ], + "tags": ["permission"], + "consumes": ["application/json"] + } + }, "/relation-tuples/check": { "get": { "summary": "Performs an authorization check.", @@ -759,6 +807,32 @@ } } }, + "batchCheckPermissionBody": { + "type": "object", + "properties": { + "tuples": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/relationship" + } + } + } + }, + "batchCheckPermissionResult": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/checkPermissionResultWithError" + }, + "description": "The results of the batch check. The order of these\nresults will match the order of the input." + } + }, + "description": "The response for a CheckService.BatchCheck rpc." + }, "postCheckPermissionBody": { "type": "object", "properties": { @@ -801,6 +875,21 @@ "description": "The response for a permission check.", "required": ["allowed"] }, + "checkPermissionResultWithError": { + "type": "object", + "properties": { + "allowed": { + "type": "boolean", + "description": "Whether the specified subject (id)\nis related to the requested object.\n\nIt is false by default if no ACL matches." + }, + "error": { + "type": "string", + "description": "If there was an error checking the tuple,\nthis will contain the error message.\n\nIf the check was performed successfully, this will be empty." + } + }, + "description": "The response for an individual check in the CheckService.BatchCheck rpc.", + "required": ["allowed"] + }, "createRelationshipBody": { "type": "object", "properties": { diff --git a/spec/goswagger.swagger.json b/spec/goswagger.swagger.json index ab82fbd4e..a805b7576 100755 --- a/spec/goswagger.swagger.json +++ b/spec/goswagger.swagger.json @@ -375,6 +375,52 @@ } } }, + "/relation-tuples/batch/check": { + "post": { + "description": "To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview).", + "consumes": ["application/json"], + "produces": ["application/json"], + "schemes": ["http", "https"], + "tags": ["permission"], + "summary": "Batch check permissions", + "operationId": "batchCheckPermission", + "parameters": [ + { + "type": "integer", + "format": "int64", + "name": "max-depth", + "in": "query" + }, + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/batchCheckPermissionBody" + } + } + ], + "responses": { + "200": { + "description": "batchCheckPermissionResult", + "schema": { + "$ref": "#/definitions/batchCheckPermissionResult" + } + }, + "400": { + "description": "errorGeneric", + "schema": { + "$ref": "#/definitions/errorGeneric" + } + }, + "default": { + "description": "errorGeneric", + "schema": { + "$ref": "#/definitions/errorGeneric" + } + } + } + } + }, "/relation-tuples/check": { "get": { "description": "To learn how relationship tuples and the check works, head over to [the documentation](https://www.ory.sh/docs/keto/concepts/api-overview).", @@ -750,6 +796,32 @@ } } }, + "batchCheckPermissionBody": { + "description": "Batch Check Permission Body", + "type": "object", + "properties": { + "tuples": { + "type": "array", + "items": { + "$ref": "#/definitions/relationship" + } + } + } + }, + "batchCheckPermissionResult": { + "description": "Batch Check Permission Result", + "type": "object", + "required": ["results"], + "properties": { + "results": { + "description": "An array of check results. The order aligns with the input order.", + "type": "array", + "items": { + "$ref": "#/definitions/checkPermissionResultWithError" + } + } + } + }, "checkOplSyntaxBody": { "description": "Ory Permission Language Document", "type": "string" @@ -779,6 +851,21 @@ } } }, + "checkPermissionResultWithError": { + "description": "Check Permission Result With Error", + "type": "object", + "required": ["allowed"], + "properties": { + "allowed": { + "description": "whether the relation tuple is allowed", + "type": "boolean" + }, + "error": { + "description": "any error generated while checking the relation tuple", + "type": "string" + } + } + }, "createRelationshipBody": { "description": "Create Relationship Request Body", "type": "object",