diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..5817bffc67 --- /dev/null +++ b/.envrc @@ -0,0 +1,6 @@ +if ! has nix_direnv_version || ! nix_direnv_version 1.5.0; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/1.5.0/direnvrc" "sha256-carKk9aUFHMuHt+IWh74hFj58nY4K3uywpZbwXX0BTI=" +fi +use flake + +dotenv_if_exists diff --git a/.github/ISSUE_TEMPLATE/.editorconfig b/.github/ISSUE_TEMPLATE/.editorconfig deleted file mode 100644 index d2204156f6..0000000000 --- a/.github/ISSUE_TEMPLATE/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[*.md] -indent_size = 2 diff --git a/.github/dependabot.yml b/.github/dependabot.yaml similarity index 75% rename from .github/dependabot.yml rename to .github/dependabot.yaml index 04ddb265c8..b3129d93cf 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yaml @@ -8,6 +8,13 @@ updates: schedule: interval: "daily" + - package-ecosystem: "gomod" + directory: "/api/v2" + labels: + - "area/dependencies" + schedule: + interval: "daily" + - package-ecosystem: "docker" directory: "/" labels: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..b682e0943e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,51 @@ +name: Build A Branch + +on: + workflow_run: + workflows: ['Run Tests'] + branches: ['master'] + types: [completed] + + workflow_dispatch: + inputs: + img_tag: + description: Docker Image Tag + ref: + description: Revision or Branch to build + default: master + push_latest: + description: Set True if the build is for the latest version + type: boolean + required: false + default: false + platforms: + description: Platforms to build for + type: choice + default: linux/amd64,linux/arm64 + options: + - linux/amd64,linux/arm64 + - linux/amd64 + - linux/arm64 + rebuild: + description: Rebuild this image? + type: boolean + default: false + +jobs: + build-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Build Image + uses: hathitrust/github_actions/build@v1.4.0 + with: + image: ghcr.io/${{ github.repository }}-unstable + dockerfile: Dockerfile + img_tag: ${{ inputs.img_tag }} + tag: ${{ inputs.ref }} + push_latest: ${{ inputs.push_latest}} + registry_token: ${{ github.token }} + rebuild: ${{ inputs.rebuild }} \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml deleted file mode 100644 index 0c0b47c94e..0000000000 --- a/.github/workflows/codeql-analysis.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master, v1 ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '28 10 * * 6' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: [ 'go' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml deleted file mode 100644 index 26c7a334de..0000000000 --- a/.github/workflows/docker.yaml +++ /dev/null @@ -1,94 +0,0 @@ -name: Docker - -on: - push: - branches: - - master - tags: - - v[0-9]+.[0-9]+.[0-9]+ - pull_request: - -jobs: - docker: - name: Docker - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Calculate Docker image tags - id: tags - env: - DOCKER_IMAGES: "ghcr.io/dexidp/dex dexidp/dex" - run: | - case $GITHUB_REF in - refs/tags/*) VERSION=${GITHUB_REF#refs/tags/};; - refs/heads/*) VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g');; - refs/pull/*) VERSION=pr-${{ github.event.number }};; - *) VERSION=sha-${GITHUB_SHA::8};; - esac - - TAGS=() - for image in $DOCKER_IMAGES; do - TAGS+=("${image}:${VERSION}") - - if [[ "${{ github.event.repository.default_branch }}" == "$VERSION" ]]; then - TAGS+=("${image}:latest") - fi - done - - echo ::set-output name=version::${VERSION} - echo ::set-output name=tags::$(IFS=,; echo "${TAGS[*]}") - echo ::set-output name=commit_hash::${GITHUB_SHA::8} - echo ::set-output name=build_date::$(git show -s --format=%cI) - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - with: - platforms: all - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - with: - install: true - version: latest - # TODO: Remove driver-opts once fix is released docker/buildx#386 - driver-opts: image=moby/buildkit:master - - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ github.token }} - if: github.event_name == 'push' - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - if: github.event_name == 'push' - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - platforms: linux/amd64,linux/arm/v7,linux/arm64 - push: ${{ github.event_name == 'push' }} - tags: ${{ steps.tags.outputs.tags }} - build-args: | - VERSION=${{ steps.tags.outputs.version }} - COMMIT_HASH=${{ steps.tags.outputs.commit_hash }} - BUILD_DATE=${{ steps.tags.outputs.build_date }} - labels: | - org.opencontainers.image.title=${{ github.event.repository.name }} - org.opencontainers.image.description=${{ github.event.repository.description }} - org.opencontainers.image.url=${{ github.event.repository.html_url }} - org.opencontainers.image.source=${{ github.event.repository.clone_url }} - org.opencontainers.image.version=${{ steps.tags.outputs.version }} - org.opencontainers.image.created=${{ steps.tags.outputs.build_date }} - org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.licenses=${{ github.event.repository.license.spdx_id }} - org.opencontainers.image.documentation=https://dexidp.io/docs/ diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml new file mode 100644 index 0000000000..5ad7db55a7 --- /dev/null +++ b/.github/workflows/tag-release.yml @@ -0,0 +1,16 @@ +name: Docker Tag Latest Release + +on: + release: + types: [released] + +jobs: + tag-release: + runs-on: ubuntu-latest + steps: + - uses: hathitrust/github_actions/tag-release@v1 + with: + registry_token: ${{ github.token }} + existing_tag: ghcr.io/${{ github.repository }}-unstable:${{ github.sha }} + image: ghcr.io/${{ github.repository }} + new_tag: ${{ github.event.release.tag_name }} \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/tests.yml similarity index 80% rename from .github/workflows/ci.yaml rename to .github/workflows/tests.yml index fe3a035950..caa82866cd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: CI +name: Run Tests on: push: @@ -35,6 +35,15 @@ jobs: - 3306 options: --health-cmd "mysql -proot -e \"show databases;\"" --health-interval 10s --health-timeout 5s --health-retries 5 + mysql-ent: + image: mysql:5.7 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: dex + ports: + - 3306 + options: --health-cmd "mysql -proot -e \"show databases;\"" --health-interval 10s --health-timeout 5s --health-retries 5 + etcd: image: gcr.io/etcd-development/etcd:v3.5.0 ports: @@ -53,9 +62,9 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v1 with: - go-version: 1.16 + go-version: 1.17 - name: Checkout code uses: actions/checkout@v2 @@ -69,35 +78,51 @@ jobs: version: v0.11.1 node_image: kindest/node:v1.19.11@sha256:07db187ae84b4b7de440a73886f008cf903fcf5764ba8106a9fd5243d6f32729 + - name: Download tool dependencies + run: make deps + - name: Test run: make testall env: + DEX_FOO_USER_PASSWORD: $2a$10$33EMT0cVYVlPy6WAMCLsceLYjWhuHpbz5yuZxu/GAFj03J9Lytjuy DEX_MYSQL_DATABASE: dex DEX_MYSQL_USER: root DEX_MYSQL_PASSWORD: root DEX_MYSQL_HOST: 127.0.0.1 DEX_MYSQL_PORT: ${{ job.services.mysql.ports[3306] }} + + DEX_MYSQL_ENT_DATABASE: dex + DEX_MYSQL_ENT_USER: root + DEX_MYSQL_ENT_PASSWORD: root + DEX_MYSQL_ENT_HOST: 127.0.0.1 + DEX_MYSQL_ENT_PORT: ${{ job.services.mysql-ent.ports[3306] }} + DEX_POSTGRES_DATABASE: postgres DEX_POSTGRES_USER: postgres DEX_POSTGRES_PASSWORD: postgres DEX_POSTGRES_HOST: localhost DEX_POSTGRES_PORT: ${{ job.services.postgres.ports[5432] }} + DEX_POSTGRES_ENT_DATABASE: postgres DEX_POSTGRES_ENT_USER: postgres DEX_POSTGRES_ENT_PASSWORD: postgres DEX_POSTGRES_ENT_HOST: localhost DEX_POSTGRES_ENT_PORT: ${{ job.services.postgres-ent.ports[5432] }} + DEX_ETCD_ENDPOINTS: http://localhost:${{ job.services.etcd.ports[2379] }} + DEX_LDAP_HOST: localhost DEX_LDAP_PORT: 389 DEX_LDAP_TLS_PORT: 636 + DEX_KEYSTONE_URL: http://localhost:${{ job.services.keystone.ports[5000] }} DEX_KEYSTONE_ADMIN_URL: http://localhost:${{ job.services.keystone.ports[35357] }} DEX_KEYSTONE_ADMIN_USER: demo DEX_KEYSTONE_ADMIN_PASS: DEMO_PASS + DEX_KUBERNETES_CONFIG_PATH: ~/.kube/config - - name: Lint + - name: Run linter run: make lint # Ensure proto generation doesn't depend on external packages. diff --git a/.gitignore b/.gitignore index f6cd2e19ca..296adfb145 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.direnv/ /.idea/ /bin/ /docker-compose.override.yaml diff --git a/.golangci.yml b/.golangci.yml index 7eca5c3737..494cf5ffae 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,6 +2,13 @@ run: timeout: 2m linters-settings: + depguard: + list-type: blacklist + include-go-root: true + packages: + - io/ioutil + packages-with-error-message: + - io/ioutil: "The 'io/ioutil' package is deprecated. Use corresponding 'os' or 'io' functions instead." gci: local-prefixes: github.com/dexidp/dex goimports: @@ -13,6 +20,7 @@ linters: enable: - bodyclose - deadcode + - depguard - dogsled - exhaustive - exportloopref @@ -64,7 +72,6 @@ linters: # - scopelint # unused - # - depguard # - goheader # - gomodguard diff --git a/ADOPTERS.md b/ADOPTERS.md index 7ea1cccae5..50f9ba988d 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -12,3 +12,4 @@ This is a list of production adopters of Dex (in alphabetical order): - [Kyma](https://kyma-project.io) is using Dex to authenticate access to Kubernetes API server (even for managed Kubernetes like Google Kubernetes Engine or Azure Kubernetes Service) and for protecting web UI of [Kyma Console](https://github.com/kyma-project/console) and other UIs integrated in Kyma ([Grafana](https://github.com/grafana/grafana), [Loki](https://github.com/grafana/loki), and [Jaeger](https://github.com/jaegertracing/jaeger)). Kyma is an open-source project ([`github.com/kyma-project`](https://github.com/kyma-project/kyma)) designed natively on Kubernetes, that allows you to extend and customize your applications in a quick and modern way, using serverless computing or microservice architecture. - [Pusher](https://pusher.com) uses Dex for authenticating users across their Kubernetes infrastructure (using Kubernetes OIDC support) in conjunction with the [OAuth2 Proxy](https://github.com/pusher/oauth2_proxy) for protecting web UIs. - [Pydio](https://pydio.com/) Pydio Cells is an open source sync & share platform written in Go. Cells is using Dex as an OIDC service for authentication and authorizations. Check out [Pydio Cells repository](https://github.com/pydio/cells) for more information and/or to contribute. +- [sigstore](https://sigstore.dev) uses Dex for authentication in their public Fulcio instance, which is a certificate authority for code signing certificates bound to OIDC-based identities. diff --git a/Dockerfile b/Dockerfile index b8d3d5fbb6..09fc36ad5d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ -FROM golang:1.16.6-alpine3.13 AS builder +ARG BASEIMAGE=alpine:3.15.1 + +FROM golang:1.17.8-alpine3.15 AS builder WORKDIR /usr/local/src/dex -RUN apk add --no-cache --update alpine-sdk +RUN apk add --no-cache --update alpine-sdk ca-certificates openssl ARG TARGETOS ARG TARGETARCH @@ -20,47 +22,48 @@ COPY . . RUN make release-binary -FROM alpine:3.14.0 AS gomplate +FROM alpine:3.15.1 AS stager + +RUN mkdir -p /var/dex +RUN mkdir -p /etc/dex +COPY config.docker.yaml /etc/dex/ + +FROM alpine:3.15.1 AS gomplate ARG TARGETOS ARG TARGETARCH ARG TARGETVARIANT -ENV GOMPLATE_VERSION=v3.9.0 +ENV GOMPLATE_VERSION=v3.10.0 RUN wget -O /usr/local/bin/gomplate \ - "https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${TARGETOS:-linux}-${TARGETARCH:-amd64}${TARGETVARIANT}" \ - && chmod +x /usr/local/bin/gomplate + "https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${TARGETOS:-linux}-${TARGETARCH:-amd64}${TARGETVARIANT}" \ + && chmod +x /usr/local/bin/gomplate -FROM alpine:3.14.0 +FROM $BASEIMAGE # Dex connectors, such as GitHub and Google logins require root certificates. # Proper installations should manage those certificates, but it's a bad user # experience when this doesn't work out of the box. # -# OpenSSL is required so wget can query HTTPS endpoints for health checking. -RUN apk add --no-cache --update ca-certificates openssl +# See https://go.dev/src/crypto/x509/root_linux.go for Go root CA bundle locations. +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -RUN mkdir -p /var/dex -RUN chown -R 1001:1001 /var/dex - -RUN mkdir -p /etc/dex -COPY config.docker.yaml /etc/dex/ -RUN chown -R 1001:1001 /etc/dex +COPY --from=stager --chown=1001:1001 /var/dex /var/dex +COPY --from=stager --chown=1001:1001 /etc/dex /etc/dex # Copy module files for CVE scanning / dependency analysis. COPY --from=builder /usr/local/src/dex/go.mod /usr/local/src/dex/go.sum /usr/local/src/dex/ COPY --from=builder /usr/local/src/dex/api/v2/go.mod /usr/local/src/dex/api/v2/go.sum /usr/local/src/dex/api/v2/ COPY --from=builder /go/bin/dex /usr/local/bin/dex +COPY --from=builder /go/bin/docker-entrypoint /usr/local/bin/docker-entrypoint COPY --from=builder /usr/local/src/dex/web /srv/dex/web COPY --from=gomplate /usr/local/bin/gomplate /usr/local/bin/gomplate USER 1001:1001 -COPY docker-entrypoint.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] +ENTRYPOINT ["/usr/local/bin/docker-entrypoint"] CMD ["dex", "serve", "/etc/dex/config.docker.yaml"] diff --git a/Makefile b/Makefile index b0ced741de..32cb9cc5e8 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ OS = $(shell uname | tr A-Z a-z) +export PATH := $(abspath bin/protoc/bin/):$(abspath bin/):${PATH} + PROJ=dex ORG_PATH=github.com/dexidp REPO_PATH=$(ORG_PATH)/$(PROJ) -export PATH := $(PWD)/bin:$(PATH) VERSION ?= $(shell ./scripts/git-version) @@ -20,11 +21,6 @@ export GOBIN=$(PWD)/bin LD_FLAGS="-w -X main.version=$(VERSION)" # Dependency versions -GOLANGCI_VERSION = 1.40.1 - -PROTOC_VERSION = 3.15.6 -PROTOC_GEN_GO_VERSION = 1.26.0 -PROTOC_GEN_GO_GRPC_VERSION = 1.1.0 KIND_NODE_IMAGE = "kindest/node:v1.19.11@sha256:07db187ae84b4b7de440a73886f008cf903fcf5764ba8106a9fd5243d6f32729" KIND_TMP_DIR = "$(PWD)/bin/test/dex-kind-kubeconfig" @@ -50,8 +46,10 @@ bin/example-app: @cd examples/ && go install -v -ldflags $(LD_FLAGS) $(REPO_PATH)/examples/example-app .PHONY: release-binary +release-binary: LD_FLAGS = "-w -X main.version=$(VERSION) -extldflags \"-static\"" release-binary: generate @go build -o /go/bin/dex -v -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/dex + @go build -o /go/bin/docker-entrypoint -v -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/docker-entrypoint docker-compose.override.yaml: cp docker-compose.override.yaml.dist docker-compose.override.yaml @@ -83,42 +81,22 @@ kind-down: kind-tests: export DEX_KUBERNETES_CONFIG_PATH=${KIND_TMP_DIR} kind-tests: testall -bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION} - @ln -sf golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint -bin/golangci-lint-${GOLANGCI_VERSION}: - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION} - @mv bin/golangci-lint $@ - .PHONY: lint lint-fix -lint: bin/golangci-lint ## Run linter - bin/golangci-lint run +lint: ## Run linter + golangci-lint run .PHONY: fix -fix: bin/golangci-lint ## Fix lint violations - bin/golangci-lint run --fix +fix: ## Fix lint violations + golangci-lint run --fix .PHONY: docker-image docker-image: @sudo docker build -t $(DOCKER_IMAGE) . -.PHONY: proto-old -proto-old: bin/protoc-old bin/protoc-gen-go-old - @./bin/protoc-old --go_out=plugins=grpc:. --plugin=protoc-gen-go=./bin/protoc-gen-go-old api/v2/*.proto - @cp api/v2/*.proto api/ - @./bin/protoc-old --go_out=plugins=grpc:. --plugin=protoc-gen-go=./bin/protoc-gen-go-old api/*.proto - .PHONY: verify-proto verify-proto: proto @./scripts/git-diff -bin/protoc-old: scripts/get-protoc - @./scripts/get-protoc bin/protoc-old - -bin/protoc-gen-go-old: - @mkdir -p tmp - @GOBIN=$$PWD/tmp go install -v github.com/golang/protobuf/protoc-gen-go@v1.3.2 - @mv tmp/protoc-gen-go bin/protoc-gen-go-old - clean: @rm -rf bin/ @@ -129,36 +107,56 @@ FORCE: .PHONY: test testrace testall .PHONY: proto -proto: bin/protoc bin/protoc-gen-go bin/protoc-gen-go-grpc - @./bin/protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. --plugin=protoc-gen-go=./bin/protoc-gen-go --plugin=protoc-gen-go-grpc=./bin/protoc-gen-go-grpc api/v2/*.proto - @./bin/protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. --plugin=protoc-gen-go=./bin/protoc-gen-go --plugin=protoc-gen-go-grpc=./bin/protoc-gen-go-grpc api/*.proto +proto: + @protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. api/v2/*.proto + @protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. api/*.proto #@cp api/v2/*.proto api/ .PHONY: proto-internal -proto-internal: bin/protoc bin/protoc-gen-go - @./bin/protoc --go_out=paths=source_relative:. --plugin=protoc-gen-go=./bin/protoc-gen-go server/internal/*.proto - -bin/protoc: bin/protoc-${PROTOC_VERSION} - @ln -sf protoc-${PROTOC_VERSION}/bin/protoc bin/protoc -bin/protoc-${PROTOC_VERSION}: - @mkdir -p bin/protoc-${PROTOC_VERSION} -ifeq (${OS}, darwin) +proto-internal: + @protoc --go_out=paths=source_relative:. server/internal/*.proto + +# Dependency versions +GOLANGCI_VERSION = 1.42.0 +GOTESTSUM_VERSION ?= 1.7.0 +PROTOC_VERSION = 3.15.6 +PROTOC_GEN_GO_VERSION = 1.26.0 +PROTOC_GEN_GO_GRPC_VERSION = 1.1.0 +KIND_VERSION = 0.11.1 + +deps: bin/gotestsum bin/golangci-lint bin/protoc bin/protoc-gen-go bin/protoc-gen-go-grpc bin/kind + +bin/gotestsum: + @mkdir -p bin + curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_$(shell uname | tr A-Z a-z)_amd64.tar.gz | tar -zOxf - gotestsum > ./bin/gotestsum + @chmod +x ./bin/gotestsum + +bin/golangci-lint: + @mkdir -p bin + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION} + +bin/protoc: + @mkdir -p bin/protoc +ifeq ($(shell uname | tr A-Z a-z), darwin) curl -L https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-osx-x86_64.zip > bin/protoc.zip endif -ifeq (${OS}, linux) +ifeq ($(shell uname | tr A-Z a-z), linux) curl -L https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip > bin/protoc.zip endif - unzip bin/protoc.zip -d bin/protoc-${PROTOC_VERSION} + unzip bin/protoc.zip -d bin/protoc rm bin/protoc.zip -bin/protoc-gen-go: bin/protoc-gen-go-${PROTOC_GEN_GO_VERSION} - @ln -sf protoc-gen-go-${PROTOC_GEN_GO_VERSION} bin/protoc-gen-go -bin/protoc-gen-go-${PROTOC_GEN_GO_VERSION}: +bin/protoc-gen-go: + @mkdir -p bin + curl -L https://github.com/protocolbuffers/protobuf-go/releases/download/v${PROTOC_GEN_GO_VERSION}/protoc-gen-go.v${PROTOC_GEN_GO_VERSION}.$(shell uname | tr A-Z a-z).amd64.tar.gz | tar -zOxf - protoc-gen-go > ./bin/protoc-gen-go + @chmod +x ./bin/protoc-gen-go + +bin/protoc-gen-go-grpc: @mkdir -p bin - curl -L https://github.com/protocolbuffers/protobuf-go/releases/download/v${PROTOC_GEN_GO_VERSION}/protoc-gen-go.v${PROTOC_GEN_GO_VERSION}.${OS}.amd64.tar.gz | tar -zOxf - protoc-gen-go > ./bin/protoc-gen-go-${PROTOC_GEN_GO_VERSION} && chmod +x ./bin/protoc-gen-go-${PROTOC_GEN_GO_VERSION} + curl -L https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v${PROTOC_GEN_GO_GRPC_VERSION}/protoc-gen-go-grpc.v${PROTOC_GEN_GO_GRPC_VERSION}.$(shell uname | tr A-Z a-z).amd64.tar.gz | tar -zOxf - ./protoc-gen-go-grpc > ./bin/protoc-gen-go-grpc + @chmod +x ./bin/protoc-gen-go-grpc -bin/protoc-gen-go-grpc: bin/protoc-gen-go-grpc-${PROTOC_GEN_GO_GRPC_VERSION} - @ln -sf protoc-gen-go-grpc-${PROTOC_GEN_GO_GRPC_VERSION} bin/protoc-gen-go-grpc -bin/protoc-gen-go-grpc-${PROTOC_GEN_GO_GRPC_VERSION}: +bin/kind: @mkdir -p bin - curl -L https://github.com/grpc/grpc-go/releases/download/cmd%2Fprotoc-gen-go-grpc%2Fv${PROTOC_GEN_GO_GRPC_VERSION}/protoc-gen-go-grpc.v${PROTOC_GEN_GO_GRPC_VERSION}.${OS}.amd64.tar.gz | tar -zOxf - ./protoc-gen-go-grpc > ./bin/protoc-gen-go-grpc-${PROTOC_GEN_GO_GRPC_VERSION} && chmod +x ./bin/protoc-gen-go-grpc-${PROTOC_GEN_GO_GRPC_VERSION} + curl -L https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-$(shell uname | tr A-Z a-z)-amd64 > ./bin/kind + @chmod +x ./bin/kind diff --git a/README.md b/README.md index 6ae2a7b083..1444c32d00 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Dex implements the following connectors: | [SAML 2.0](https://dexidp.io/docs/connectors/saml/) | no | yes | no | stable | WARNING: Unmaintained and likely vulnerable to auth bypasses ([#1884](https://github.com/dexidp/dex/discussions/1884)) | | [GitLab](https://dexidp.io/docs/connectors/gitlab/) | yes | yes | yes | beta | | | [OpenID Connect](https://dexidp.io/docs/connectors/oidc/) | yes | yes | yes | beta | Includes Salesforce, Azure, etc. | +| [OAuth 2.0](https://dexidp.io/docs/connectors/oauth/) | no | yes | yes | alpha | | | [Google](https://dexidp.io/docs/connectors/google/) | yes | yes | yes | alpha | | | [LinkedIn](https://dexidp.io/docs/connectors/linkedin/) | yes | no | no | beta | | | [Microsoft](https://dexidp.io/docs/connectors/microsoft/) | yes | yes | no | beta | | @@ -124,3 +125,19 @@ Please see our [security policy](.github/SECURITY.md) for details about reportin [go-oidc]: https://github.com/coreos/go-oidc [issue-1065]: https://github.com/dexidp/dex/issues/1065 [release-notes]: https://github.com/dexidp/dex/releases + +## Development + +When all coding and testing is done, please run the test suite: + +```shell +make testall +``` + +For the best developer experience, install [Nix](https://builtwithnix.org/) and [direnv](https://direnv.net/). + +Alternatively, install Go and Docker manually or using a package manager. Install the rest of the dependencies by running `make deps`. + +## License + +The project is licensed under the [Apache License, Version 2.0](LICENSE). diff --git a/api/v2/go.mod b/api/v2/go.mod index 769cb1fd9b..05a8cc48a7 100644 --- a/api/v2/go.mod +++ b/api/v2/go.mod @@ -1,8 +1,16 @@ module github.com/dexidp/dex/api/v2 -go 1.14 +go 1.17 require ( - google.golang.org/grpc v1.36.1 - google.golang.org/protobuf v1.26.0 + google.golang.org/grpc v1.44.0 + google.golang.org/protobuf v1.27.1 +) + +require ( + github.com/golang/protobuf v1.5.2 // indirect + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20220207185906-7721543eae58 // indirect ) diff --git a/api/v2/go.sum b/api/v2/go.sum index 6ee6f61b70..461ed66810 100644 --- a/api/v2/go.sum +++ b/api/v2/go.sum @@ -1,17 +1,33 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -19,8 +35,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 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.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -29,47 +47,80 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc= +golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220207185906-7721543eae58 h1:i67FGOy2/zGfhE3YgHdrOrcFbOBhqdcRoBrsDqSQrOI= +google.golang.org/genproto v0.0.0-20220207185906-7721543eae58/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.36.1 h1:cmUfbeGKnz9+2DD/UYsMQXeqbHZqZDs4eQwW0sFOpBY= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -80,9 +131,12 @@ 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.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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/cmd/dex/config.go b/cmd/dex/config.go index 309fc52c54..37167bb090 100644 --- a/cmd/dex/config.go +++ b/cmd/dex/config.go @@ -183,6 +183,7 @@ var ( _ StorageConfig = (*sql.MySQL)(nil) _ StorageConfig = (*ent.SQLite3)(nil) _ StorageConfig = (*ent.Postgres)(nil) + _ StorageConfig = (*ent.MySQL)(nil) ) func getORMBasedSQLStorage(normal, entBased StorageConfig) func() StorageConfig { @@ -200,9 +201,9 @@ var storages = map[string]func() StorageConfig{ "etcd": func() StorageConfig { return new(etcd.Etcd) }, "kubernetes": func() StorageConfig { return new(kubernetes.Config) }, "memory": func() StorageConfig { return new(memory.Config) }, - "mysql": func() StorageConfig { return new(sql.MySQL) }, "sqlite3": getORMBasedSQLStorage(&sql.SQLite3{}, &ent.SQLite3{}), "postgres": getORMBasedSQLStorage(&sql.Postgres{}, &ent.Postgres{}), + "mysql": getORMBasedSQLStorage(&sql.MySQL{}, &ent.MySQL{}), } // isExpandEnvEnabled returns if os.ExpandEnv should be used for each storage and connector config. diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go index 470303938e..1916f834ae 100644 --- a/cmd/dex/serve.go +++ b/cmd/dex/serve.go @@ -6,10 +6,10 @@ import ( "crypto/x509" "errors" "fmt" - "io/ioutil" "net" "net/http" "os" + "runtime" "strings" "syscall" "time" @@ -76,7 +76,7 @@ func commandServe() *cobra.Command { func runServe(options serveOptions) error { configFile := options.config - configData, err := ioutil.ReadFile(configFile) + configData, err := os.ReadFile(configFile) if err != nil { return fmt.Errorf("failed to read config file %s: %v", configFile, err) } @@ -92,6 +92,15 @@ func runServe(options serveOptions) error { if err != nil { return fmt.Errorf("invalid config: %v", err) } + + logger.Infof( + "Dex Version: %s, Go Version: %s, Go OS/ARCH: %s %s", + version, + runtime.Version(), + runtime.GOOS, + runtime.GOARCH, + ) + if c.Logger.Level != "" { logger.Infof("config using log level: %s", c.Logger.Level) } @@ -148,7 +157,7 @@ func runServe(options serveOptions) error { if c.GRPC.TLSClientCA != "" { // Parse certificates from client CA file to a new CertPool. cPool := x509.NewCertPool() - clientCert, err := ioutil.ReadFile(c.GRPC.TLSClientCA) + clientCert, err := os.ReadFile(c.GRPC.TLSClientCA) if err != nil { return fmt.Errorf("invalid config: reading from client CA file: %v", err) } diff --git a/cmd/docker-entrypoint/main.go b/cmd/docker-entrypoint/main.go new file mode 100644 index 0000000000..0c507d1712 --- /dev/null +++ b/cmd/docker-entrypoint/main.go @@ -0,0 +1,92 @@ +// Package main provides a utility program to launch the Dex container process with an optional +// templating step (provided by gomplate). +// +// This was originally written as a shell script, but we rewrote it as a Go program so that it could +// run as a raw binary in a distroless container. +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" + "syscall" +) + +func main() { + // Note that this docker-entrypoint program is args[0], and it is provided with the true process + // args. + args := os.Args[1:] + + if err := run(args, realExec, realWhich); err != nil { + fmt.Println("error:", err.Error()) + os.Exit(1) + } +} + +func realExec(fork bool, args ...string) error { + if fork { + if output, err := exec.Command(args[0], args[1:]...).CombinedOutput(); err != nil { + return fmt.Errorf("cannot fork/exec command %s: %w (output: %q)", args, err, string(output)) + } + return nil + } + + argv0, err := exec.LookPath(args[0]) + if err != nil { + return fmt.Errorf("cannot lookup path for command %s: %w", args[0], err) + } + + if err := syscall.Exec(argv0, args, os.Environ()); err != nil { + return fmt.Errorf("cannot exec command %s (%q): %w", args, argv0, err) + } + + return nil +} + +func realWhich(path string) string { + fullPath, err := exec.LookPath(path) + if err != nil { + return "" + } + return fullPath +} + +func run(args []string, execFunc func(bool, ...string) error, whichFunc func(string) string) error { + if args[0] != "dex" && args[0] != whichFunc("dex") { + return execFunc(false, args...) + } + + if args[1] != "serve" { + return execFunc(false, args...) + } + + newArgs := []string{} + for _, tplCandidate := range args { + if hasSuffixes(tplCandidate, ".tpl", ".tmpl", ".yaml") { + tmpFile, err := os.CreateTemp("/tmp", "dex.config.yaml-*") + if err != nil { + return fmt.Errorf("cannot create temp file: %w", err) + } + + if err := execFunc(true, "gomplate", "-f", tplCandidate, "-o", tmpFile.Name()); err != nil { + return err + } + + newArgs = append(newArgs, tmpFile.Name()) + } else { + newArgs = append(newArgs, tplCandidate) + } + } + + return execFunc(false, newArgs...) +} + +func hasSuffixes(s string, suffixes ...string) bool { + for _, suffix := range suffixes { + if strings.HasSuffix(s, suffix) { + return true + } + } + return false +} diff --git a/cmd/docker-entrypoint/main_test.go b/cmd/docker-entrypoint/main_test.go new file mode 100644 index 0000000000..c8aef16979 --- /dev/null +++ b/cmd/docker-entrypoint/main_test.go @@ -0,0 +1,113 @@ +package main + +import ( + "strings" + "testing" +) + +type execArgs struct { + fork bool + argPrefixes []string +} + +func TestRun(t *testing.T) { + tests := []struct { + name string + args []string + execReturns error + whichReturns string + wantExecArgs []execArgs + wantErr error + }{ + { + name: "executable not dex", + args: []string{"tuna", "fish"}, + wantExecArgs: []execArgs{{fork: false, argPrefixes: []string{"tuna", "fish"}}}, + }, + { + name: "executable is full path to dex", + args: []string{"/usr/local/bin/dex", "marshmallow", "zelda"}, + whichReturns: "/usr/local/bin/dex", + wantExecArgs: []execArgs{{fork: false, argPrefixes: []string{"/usr/local/bin/dex", "marshmallow", "zelda"}}}, + }, + { + name: "command is not serve", + args: []string{"dex", "marshmallow", "zelda"}, + wantExecArgs: []execArgs{{fork: false, argPrefixes: []string{"dex", "marshmallow", "zelda"}}}, + }, + { + name: "no templates", + args: []string{"dex", "serve", "config.yaml.not-a-template"}, + wantExecArgs: []execArgs{{fork: false, argPrefixes: []string{"dex", "serve", "config.yaml.not-a-template"}}}, + }, + { + name: "no templates", + args: []string{"dex", "serve", "config.yaml.not-a-template"}, + wantExecArgs: []execArgs{{fork: false, argPrefixes: []string{"dex", "serve", "config.yaml.not-a-template"}}}, + }, + { + name: ".tpl template", + args: []string{"dex", "serve", "config.tpl"}, + wantExecArgs: []execArgs{ + {fork: true, argPrefixes: []string{"gomplate", "-f", "config.tpl", "-o", "/tmp/dex.config.yaml-"}}, + {fork: false, argPrefixes: []string{"dex", "serve", "/tmp/dex.config.yaml-"}}, + }, + }, + { + name: ".tmpl template", + args: []string{"dex", "serve", "config.tmpl"}, + wantExecArgs: []execArgs{ + {fork: true, argPrefixes: []string{"gomplate", "-f", "config.tmpl", "-o", "/tmp/dex.config.yaml-"}}, + {fork: false, argPrefixes: []string{"dex", "serve", "/tmp/dex.config.yaml-"}}, + }, + }, + { + name: ".yaml template", + args: []string{"dex", "serve", "some/path/config.yaml"}, + wantExecArgs: []execArgs{ + {fork: true, argPrefixes: []string{"gomplate", "-f", "some/path/config.yaml", "-o", "/tmp/dex.config.yaml-"}}, + {fork: false, argPrefixes: []string{"dex", "serve", "/tmp/dex.config.yaml-"}}, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var gotExecForks []bool + var gotExecArgs [][]string + fakeExec := func(fork bool, args ...string) error { + gotExecForks = append(gotExecForks, fork) + gotExecArgs = append(gotExecArgs, args) + return test.execReturns + } + + fakeWhich := func(_ string) string { return test.whichReturns } + + gotErr := run(test.args, fakeExec, fakeWhich) + if (test.wantErr == nil) != (gotErr == nil) { + t.Errorf("wanted error %s, got %s", test.wantErr, gotErr) + } + if !execArgsMatch(test.wantExecArgs, gotExecForks, gotExecArgs) { + t.Errorf("wanted exec args %+v, got %+v %+v", test.wantExecArgs, gotExecForks, gotExecArgs) + } + }) + } +} + +func execArgsMatch(wantExecArgs []execArgs, gotForks []bool, gotExecArgs [][]string) bool { + if len(wantExecArgs) != len(gotForks) { + return false + } + + for i := range wantExecArgs { + if wantExecArgs[i].fork != gotForks[i] { + return false + } + for j := range wantExecArgs[i].argPrefixes { + if !strings.HasPrefix(gotExecArgs[i][j], wantExecArgs[i].argPrefixes[j]) { + return false + } + } + } + + return true +} diff --git a/connector/atlassiancrowd/atlassiancrowd.go b/connector/atlassiancrowd/atlassiancrowd.go index 6f03406086..e2ca94b0de 100644 --- a/connector/atlassiancrowd/atlassiancrowd.go +++ b/connector/atlassiancrowd/atlassiancrowd.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net" "net/http" "strings" @@ -432,7 +431,7 @@ func (c *crowdConnector) crowdUserManagementRequest(ctx context.Context, method // validateCrowdResponse validates unique not JSON responses from API func (c *crowdConnector) validateCrowdResponse(resp *http.Response) ([]byte, error) { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("crowd: read user body: %v", err) } diff --git a/connector/atlassiancrowd/atlassiancrowd_test.go b/connector/atlassiancrowd/atlassiancrowd_test.go index 3559445d21..36789a3919 100644 --- a/connector/atlassiancrowd/atlassiancrowd_test.go +++ b/connector/atlassiancrowd/atlassiancrowd_test.go @@ -6,7 +6,7 @@ import ( "crypto/tls" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "reflect" @@ -152,7 +152,7 @@ func newTestCrowdConnector(baseURL string) crowdConnector { connector := crowdConnector{} connector.BaseURL = baseURL connector.logger = &logrus.Logger{ - Out: ioutil.Discard, + Out: io.Discard, Level: logrus.DebugLevel, Formatter: &logrus.TextFormatter{DisableColors: true}, } diff --git a/connector/authproxyshib/authproxy_shib.go b/connector/authproxyshib/authproxy_shib.go new file mode 100644 index 0000000000..184bd70793 --- /dev/null +++ b/connector/authproxyshib/authproxy_shib.go @@ -0,0 +1,125 @@ +// Package authproxyshib implements a connector which relies on external +// authentication (e.g. mod_auth in Apache2) and returns an identity with +// claims populated with configurable header values. +// +// The primary use is to proxy a SAML SP running Shibboleth to OIDC +package authproxyshib + +import ( + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/dexidp/dex/connector" + "github.com/dexidp/dex/pkg/log" +) + +// Config holds the configuration parameters for a connector which returns an +// identity with the HTTP header X-Remote-User as verified email. +type Config struct { + UserIDHeader string `json:"userIDHeader"` + UsernameHeader string `json:"usernameHeader"` + PreferredUsernameHeader string `json:"preferredUsernameHeader"` + EmailHeader string `json:"emailHeader"` + EmailVerifiedIfPresent bool `json:"emailVerifiedIfPresent"` + GroupsHeader string `json:"groupsHeader"` + GroupsDelimiter string `json:"groupsDelimiter"` +} + +// Open returns an authentication strategy which requires no user interaction. +func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) { + userIDHeader := c.UserIDHeader + if userIDHeader == "" { + userIDHeader = "X-Remote-User" + } + + groupsDelimiter := c.GroupsDelimiter + if groupsDelimiter == "" { + groupsDelimiter = ";" + } + + return &callback{ + userIDHeader: userIDHeader, + usernameHeader: c.UsernameHeader, + preferredUsernameHeader: c.PreferredUsernameHeader, + emailHeader: c.EmailHeader, + emailVerifiedIfPresent: c.EmailVerifiedIfPresent, + groupsHeader: c.GroupsHeader, + groupsDelimiter: groupsDelimiter, + logger: logger, + pathSuffix: "/" + id, + }, nil +} + +// Callback is a connector which returns an identity with the HTTP header +// X-Remote-User as verified email. +type callback struct { + userIDHeader string + usernameHeader string + preferredUsernameHeader string + emailHeader string + emailVerifiedIfPresent bool + groupsHeader string + groupsDelimiter string + logger log.Logger + pathSuffix string +} + +// LoginURL returns the URL to redirect the user to login with. +func (m *callback) LoginURL(s connector.Scopes, callbackURL, state string) (string, error) { + u, err := url.Parse(callbackURL) + if err != nil { + return "", fmt.Errorf("failed to parse callbackURL %q: %v", callbackURL, err) + } + u.Path += m.pathSuffix + v := u.Query() + v.Set("state", state) + u.RawQuery = v.Encode() + return u.String(), nil +} + +// HandleCallback parses the request and returns the user's identity +func (m *callback) HandleCallback(s connector.Scopes, r *http.Request) (connector.Identity, error) { + m.logger.Debugf("Headers: %v", r.Header) + userID := r.Header.Get(m.userIDHeader) + if userID == "" { + return connector.Identity{}, fmt.Errorf("required HTTP header %s is not set", m.userIDHeader) + } + + identity := connector.Identity{ + UserID: userID, + } + + if m.usernameHeader != "" { + username := r.Header.Get(m.usernameHeader) + if username != "" { + identity.Username = username + } + } + + if m.preferredUsernameHeader != "" { + preferredUsername := r.Header.Get(m.preferredUsernameHeader) + if preferredUsername != "" { + identity.PreferredUsername = preferredUsername + } + } + + if m.emailHeader != "" { + email := r.Header.Get(m.emailHeader) + if email != "" { + identity.Email = email + // TODO: what happens if missing from the config? + identity.EmailVerified = m.emailVerifiedIfPresent + } + } + + if m.groupsHeader != "" { + groups := r.Header.Get(m.groupsHeader) + if groups != "" { + identity.Groups = strings.Split(groups, m.groupsDelimiter) + } + } + + return identity, nil +} diff --git a/connector/bitbucketcloud/bitbucketcloud.go b/connector/bitbucketcloud/bitbucketcloud.go index e81893da07..27eafb5299 100644 --- a/connector/bitbucketcloud/bitbucketcloud.go +++ b/connector/bitbucketcloud/bitbucketcloud.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "sync" "time" @@ -351,7 +351,7 @@ func (b *bitbucketConnector) userEmail(ctx context.Context, client *http.Client) // getGroups retrieves Bitbucket teams a user is in, if any. func (b *bitbucketConnector) getGroups(ctx context.Context, client *http.Client, groupScope bool, userLogin string) ([]string, error) { - bitbucketTeams, err := b.userTeams(ctx, client) + bitbucketTeams, err := b.userWorkspaces(ctx, client) if err != nil { return nil, err } @@ -369,33 +369,33 @@ func (b *bitbucketConnector) getGroups(ctx context.Context, client *http.Client, return nil, nil } -type teamName struct { - Name string `json:"username"` // The "username" from Bitbucket Cloud is actually the team name here +type workspaceSlug struct { + Slug string `json:"slug"` } -type team struct { - Team teamName `json:"team"` +type workspace struct { + Workspace workspaceSlug `json:"workspace"` } -type userTeamsResponse struct { +type userWorkspacesResponse struct { pagedResponse - Values []team + Values []workspace `json:"values"` } -func (b *bitbucketConnector) userTeams(ctx context.Context, client *http.Client) ([]string, error) { +func (b *bitbucketConnector) userWorkspaces(ctx context.Context, client *http.Client) ([]string, error) { var teams []string - apiURL := b.apiURL + "/user/permissions/teams" + apiURL := b.apiURL + "/user/permissions/workspaces" for { - // https://developer.atlassian.com/bitbucket/api/2/reference/resource/user/permissions/teams - var response userTeamsResponse + // https://developer.atlassian.com/cloud/bitbucket/rest/api-group-workspaces/#api-workspaces-get + var response userWorkspacesResponse if err := get(ctx, client, apiURL, &response); err != nil { return nil, fmt.Errorf("bitbucket: get user teams: %v", err) } for _, value := range response.Values { - teams = append(teams, value.Team.Name) + teams = append(teams, value.Workspace.Slug) } if response.Next == nil { @@ -453,7 +453,7 @@ func get(ctx context.Context, client *http.Client, apiURL string, v interface{}) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("bitbucket: read body: %s: %v", resp.Status, err) } diff --git a/connector/bitbucketcloud/bitbucketcloud_test.go b/connector/bitbucketcloud/bitbucketcloud_test.go index 3d984a8fcb..9545ff09c5 100644 --- a/connector/bitbucketcloud/bitbucketcloud_test.go +++ b/connector/bitbucketcloud/bitbucketcloud_test.go @@ -14,28 +14,28 @@ import ( ) func TestUserGroups(t *testing.T) { - teamsResponse := userTeamsResponse{ + teamsResponse := userWorkspacesResponse{ pagedResponse: pagedResponse{ Size: 3, Page: 1, PageLen: 10, }, - Values: []team{ - {Team: teamName{Name: "team-1"}}, - {Team: teamName{Name: "team-2"}}, - {Team: teamName{Name: "team-3"}}, + Values: []workspace{ + {Workspace: workspaceSlug{Slug: "team-1"}}, + {Workspace: workspaceSlug{Slug: "team-2"}}, + {Workspace: workspaceSlug{Slug: "team-3"}}, }, } s := newTestServer(map[string]interface{}{ - "/user/permissions/teams": teamsResponse, - "/groups/team-1": []group{{Slug: "administrators"}, {Slug: "members"}}, - "/groups/team-2": []group{{Slug: "everyone"}}, - "/groups/team-3": []group{}, + "/user/permissions/workspaces": teamsResponse, + "/groups/team-1": []group{{Slug: "administrators"}, {Slug: "members"}}, + "/groups/team-2": []group{{Slug: "everyone"}}, + "/groups/team-3": []group{}, }) connector := bitbucketConnector{apiURL: s.URL, legacyAPIURL: s.URL} - groups, err := connector.userTeams(context.Background(), newClient()) + groups, err := connector.userWorkspaces(context.Background(), newClient()) expectNil(t, err) expectEquals(t, groups, []string{ @@ -45,7 +45,7 @@ func TestUserGroups(t *testing.T) { }) connector.includeTeamGroups = true - groups, err = connector.userTeams(context.Background(), newClient()) + groups, err = connector.userWorkspaces(context.Background(), newClient()) expectNil(t, err) expectEquals(t, groups, []string{ @@ -62,11 +62,11 @@ func TestUserGroups(t *testing.T) { func TestUserWithoutTeams(t *testing.T) { s := newTestServer(map[string]interface{}{ - "/user/permissions/teams": userTeamsResponse{}, + "/user/permissions/workspaces": userWorkspacesResponse{}, }) connector := bitbucketConnector{apiURL: s.URL} - groups, err := connector.userTeams(context.Background(), newClient()) + groups, err := connector.userWorkspaces(context.Background(), newClient()) expectNil(t, err) expectEquals(t, len(groups), 0) diff --git a/connector/gitea/gitea.go b/connector/gitea/gitea.go index 33cc3126e6..cd371d3741 100644 --- a/connector/gitea/gitea.go +++ b/connector/gitea/gitea.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strconv" "sync" @@ -252,7 +252,7 @@ func (c *giteaConnector) user(ctx context.Context, client *http.Client) (giteaUs defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return u, fmt.Errorf("gitea: read body: %v", err) } diff --git a/connector/github/github.go b/connector/github/github.go index 02f2cae804..ef8d418fa8 100644 --- a/connector/github/github.go +++ b/connector/github/github.go @@ -8,9 +8,10 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net" "net/http" + "os" "regexp" "strconv" "strings" @@ -210,7 +211,7 @@ func (e *oauth2Error) Error() string { // newHTTPClient returns a new HTTP client that trusts the custom declared rootCA cert. func newHTTPClient(rootCA string) (*http.Client, error) { tlsConfig := tls.Config{RootCAs: x509.NewCertPool()} - rootCABytes, err := ioutil.ReadFile(rootCA) + rootCABytes, err := os.ReadFile(rootCA) if err != nil { return nil, fmt.Errorf("failed to read root-ca: %v", err) } @@ -488,7 +489,7 @@ func get(ctx context.Context, client *http.Client, apiURL string, v interface{}) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("github: read body: %v", err) } diff --git a/connector/gitlab/gitlab.go b/connector/gitlab/gitlab.go index e40601402d..7d8e83377f 100644 --- a/connector/gitlab/gitlab.go +++ b/connector/gitlab/gitlab.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strconv" @@ -232,7 +232,7 @@ func (c *gitlabConnector) user(ctx context.Context, client *http.Client) (gitlab defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return u, fmt.Errorf("gitlab: read body: %v", err) } @@ -266,7 +266,7 @@ func (c *gitlabConnector) userGroups(ctx context.Context, client *http.Client) ( defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("gitlab: read body: %v", err) } diff --git a/connector/google/google.go b/connector/google/google.go index eccb1fc7d7..1b515b8e42 100644 --- a/connector/google/google.go +++ b/connector/google/google.go @@ -5,8 +5,8 @@ import ( "context" "errors" "fmt" - "io/ioutil" "net/http" + "os" "time" "github.com/coreos/go-oidc/v3/oidc" @@ -49,6 +49,9 @@ type Config struct { // The email of a GSuite super user which the service account will impersonate // when listing groups AdminEmail string + + // If this field is true, fetch direct group membership and transitive group membership + FetchTransitiveGroupMembership bool `json:"fetchTransitiveGroupMembership"` } // Open returns a connector which can be used to login users through Google. @@ -87,13 +90,14 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e verifier: provider.Verifier( &oidc.Config{ClientID: clientID}, ), - logger: logger, - cancel: cancel, - hostedDomains: c.HostedDomains, - groups: c.Groups, - serviceAccountFilePath: c.ServiceAccountFilePath, - adminEmail: c.AdminEmail, - adminSrv: srv, + logger: logger, + cancel: cancel, + hostedDomains: c.HostedDomains, + groups: c.Groups, + serviceAccountFilePath: c.ServiceAccountFilePath, + adminEmail: c.AdminEmail, + fetchTransitiveGroupMembership: c.FetchTransitiveGroupMembership, + adminSrv: srv, }, nil } @@ -103,16 +107,17 @@ var ( ) type googleConnector struct { - redirectURI string - oauth2Config *oauth2.Config - verifier *oidc.IDTokenVerifier - cancel context.CancelFunc - logger log.Logger - hostedDomains []string - groups []string - serviceAccountFilePath string - adminEmail string - adminSrv *admin.Service + redirectURI string + oauth2Config *oauth2.Config + verifier *oidc.IDTokenVerifier + cancel context.CancelFunc + logger log.Logger + hostedDomains []string + groups []string + serviceAccountFilePath string + adminEmail string + fetchTransitiveGroupMembership bool + adminSrv *admin.Service } func (c *googleConnector) Close() error { @@ -214,7 +219,7 @@ func (c *googleConnector) createIdentity(ctx context.Context, identity connector var groups []string if s.Groups && c.adminSrv != nil { - groups, err = c.getGroups(claims.Email) + groups, err = c.getGroups(claims.Email, c.fetchTransitiveGroupMembership) if err != nil { return identity, fmt.Errorf("google: could not retrieve groups: %v", err) } @@ -240,7 +245,7 @@ func (c *googleConnector) createIdentity(ctx context.Context, identity connector // getGroups creates a connection to the admin directory service and lists // all groups the user is a member of -func (c *googleConnector) getGroups(email string) ([]string, error) { +func (c *googleConnector) getGroups(email string, fetchTransitiveGroupMembership bool) ([]string, error) { var userGroups []string var err error groupsList := &admin.Groups{} @@ -254,6 +259,16 @@ func (c *googleConnector) getGroups(email string) ([]string, error) { for _, group := range groupsList.Groups { // TODO (joelspeed): Make desired group key configurable userGroups = append(userGroups, group.Email) + + // getGroups takes a user's email/alias as well as a group's email/alias + if fetchTransitiveGroupMembership { + transitiveGroups, err := c.getGroups(group.Email, fetchTransitiveGroupMembership) + if err != nil { + return nil, fmt.Errorf("could not list transitive groups: %v", err) + } + + userGroups = append(userGroups, transitiveGroups...) + } } if groupsList.NextPageToken == "" { @@ -261,7 +276,7 @@ func (c *googleConnector) getGroups(email string) ([]string, error) { } } - return userGroups, nil + return uniqueGroups(userGroups), nil } // createDirectoryService loads a google service account credentials file, @@ -274,7 +289,7 @@ func createDirectoryService(serviceAccountFilePath string, email string) (*admin if serviceAccountFilePath == "" || email == "" { return nil, fmt.Errorf("directory service requires both serviceAccountFilePath and adminEmail") } - jsonCredentials, err := ioutil.ReadFile(serviceAccountFilePath) + jsonCredentials, err := os.ReadFile(serviceAccountFilePath) if err != nil { return nil, fmt.Errorf("error reading credentials from file: %v", err) } @@ -296,3 +311,16 @@ func createDirectoryService(serviceAccountFilePath string, email string) (*admin } return srv, nil } + +// uniqueGroups returns the unique groups of a slice +func uniqueGroups(groups []string) []string { + keys := make(map[string]struct{}) + unique := []string{} + for _, group := range groups { + if _, exists := keys[group]; !exists { + keys[group] = struct{}{} + unique = append(unique, group) + } + } + return unique +} diff --git a/connector/keystone/keystone.go b/connector/keystone/keystone.go index 3750710e74..c4e98d0569 100644 --- a/connector/keystone/keystone.go +++ b/connector/keystone/keystone.go @@ -6,7 +6,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "github.com/dexidp/dex/connector" @@ -133,7 +133,7 @@ func (p *conn) Login(ctx context.Context, scopes connector.Scopes, username, pas return identity, false, nil } token := resp.Header.Get("X-Subject-Token") - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return identity, false, err } @@ -260,7 +260,7 @@ func (p *conn) getUser(ctx context.Context, userID string, token string) (*userR return nil, err } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } @@ -290,7 +290,7 @@ func (p *conn) getUserGroups(ctx context.Context, userID string, token string) ( return nil, err } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/connector/keystone/keystone_test.go b/connector/keystone/keystone_test.go index b138012426..cf007f19c3 100644 --- a/connector/keystone/keystone_test.go +++ b/connector/keystone/keystone_test.go @@ -5,7 +5,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" "reflect" @@ -78,7 +78,7 @@ func getAdminToken(t *testing.T, adminName, adminPass string) (token, id string) token = resp.Header.Get("X-Subject-Token") - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { t.Fatal(err) } @@ -122,7 +122,7 @@ func createUser(t *testing.T, token, userName, userEmail, userPass string) strin t.Fatal(err) } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { t.Fatal(err) } @@ -183,7 +183,7 @@ func createGroup(t *testing.T, token, description, name string) string { t.Fatal(err) } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { t.Fatal(err) } diff --git a/connector/ldap/ldap.go b/connector/ldap/ldap.go index eaee078d37..df69d60e3c 100644 --- a/connector/ldap/ldap.go +++ b/connector/ldap/ldap.go @@ -7,8 +7,8 @@ import ( "crypto/x509" "encoding/json" "fmt" - "io/ioutil" "net" + "os" "github.com/go-ldap/ldap/v3" @@ -187,11 +187,12 @@ func parseScope(s string) (int, bool) { // Function exists here to allow backward compatibility between old and new // group to user matching implementations. // See "Config.GroupSearch.UserMatchers" comments for the details -func (c *ldapConnector) userMatchers() []UserMatcher { +func userMatchers(c *Config, logger log.Logger) []UserMatcher { if len(c.GroupSearch.UserMatchers) > 0 && c.GroupSearch.UserMatchers[0].UserAttr != "" { return c.GroupSearch.UserMatchers } + log.Deprecated(logger, `LDAP: use groupSearch.userMatchers option instead of "userAttr/groupAttr" fields.`) return []UserMatcher{ { UserAttr: c.GroupSearch.UserAttr, @@ -257,7 +258,7 @@ func (c *Config) openConnector(logger log.Logger) (*ldapConnector, error) { data := c.RootCAData if len(data) == 0 { var err error - if data, err = ioutil.ReadFile(c.RootCA); err != nil { + if data, err = os.ReadFile(c.RootCA); err != nil { return nil, fmt.Errorf("ldap: read ca file: %v", err) } } @@ -283,6 +284,9 @@ func (c *Config) openConnector(logger log.Logger) (*ldapConnector, error) { if !ok { return nil, fmt.Errorf("groupSearch.Scope unknown value %q", c.GroupSearch.Scope) } + + // TODO(nabokihms): remove it after deleting deprecated groupSearch options + c.GroupSearch.UserMatchers = userMatchers(c, logger) return &ldapConnector{*c, userSearchScope, groupSearchScope, tlsConfig, logger}, nil } @@ -418,7 +422,7 @@ func (c *ldapConnector) userEntry(conn *ldap.Conn, username string) (user ldap.E }, } - for _, matcher := range c.userMatchers() { + for _, matcher := range c.GroupSearch.UserMatchers { req.Attributes = append(req.Attributes, matcher.UserAttr) } @@ -575,7 +579,7 @@ func (c *ldapConnector) groups(ctx context.Context, user ldap.Entry) ([]string, } var groups []*ldap.Entry - for _, matcher := range c.userMatchers() { + for _, matcher := range c.GroupSearch.UserMatchers { for _, attr := range getAttrs(user, matcher.UserAttr) { filter := fmt.Sprintf("(%s=%s)", matcher.GroupAttr, ldap.EscapeFilter(attr)) if c.GroupSearch.Filter != "" { diff --git a/connector/ldap/ldap_test.go b/connector/ldap/ldap_test.go index 9ae4567431..83f9f4790c 100644 --- a/connector/ldap/ldap_test.go +++ b/connector/ldap/ldap_test.go @@ -3,7 +3,7 @@ package ldap import ( "context" "fmt" - "io/ioutil" + "io" "os" "testing" @@ -555,7 +555,7 @@ func runTests(t *testing.T, connMethod connectionMethod, config *Config, tests [ c.BindDN = "cn=admin,dc=example,dc=org" c.BindPW = "admin" - l := &logrus.Logger{Out: ioutil.Discard, Formatter: &logrus.TextFormatter{}} + l := &logrus.Logger{Out: io.Discard, Formatter: &logrus.TextFormatter{}} conn, err := c.openConnector(l) if err != nil { diff --git a/connector/linkedin/linkedin.go b/connector/linkedin/linkedin.go index 1c8312c11e..f79f1c49d8 100644 --- a/connector/linkedin/linkedin.go +++ b/connector/linkedin/linkedin.go @@ -5,7 +5,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "strings" @@ -169,7 +169,7 @@ func (c *linkedInConnector) primaryEmail(ctx context.Context, client *http.Clien } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return email, fmt.Errorf("read body: %v", err) } @@ -209,7 +209,7 @@ func (c *linkedInConnector) profile(ctx context.Context, client *http.Client) (p defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return p, fmt.Errorf("read body: %v", err) } diff --git a/connector/oauth/oauth.go b/connector/oauth/oauth.go new file mode 100644 index 0000000000..e37932ad07 --- /dev/null +++ b/connector/oauth/oauth.go @@ -0,0 +1,292 @@ +package oauth + +import ( + "context" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net" + "net/http" + "os" + "strings" + "time" + + "golang.org/x/oauth2" + + "github.com/dexidp/dex/connector" + "github.com/dexidp/dex/pkg/log" +) + +type oauthConnector struct { + clientID string + clientSecret string + redirectURI string + tokenURL string + authorizationURL string + userInfoURL string + scopes []string + userIDKey string + userNameKey string + preferredUsernameKey string + emailKey string + emailVerifiedKey string + groupsKey string + httpClient *http.Client + logger log.Logger +} + +type connectorData struct { + AccessToken string +} + +type Config struct { + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + RedirectURI string `json:"redirectURI"` + TokenURL string `json:"tokenURL"` + AuthorizationURL string `json:"authorizationURL"` + UserInfoURL string `json:"userInfoURL"` + Scopes []string `json:"scopes"` + RootCAs []string `json:"rootCAs"` + InsecureSkipVerify bool `json:"insecureSkipVerify"` + UserIDKey string `json:"userIDKey"` // defaults to "id" + ClaimMapping struct { + UserNameKey string `json:"userNameKey"` // defaults to "user_name" + PreferredUsernameKey string `json:"preferredUsernameKey"` // defaults to "preferred_username" + GroupsKey string `json:"groupsKey"` // defaults to "groups" + EmailKey string `json:"emailKey"` // defaults to "email" + EmailVerifiedKey string `json:"emailVerifiedKey"` // defaults to "email_verified" + } `json:"claimMapping"` +} + +func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) { + var err error + + userIDKey := c.UserIDKey + if userIDKey == "" { + userIDKey = "id" + } + + userNameKey := c.ClaimMapping.UserNameKey + if userNameKey == "" { + userNameKey = "user_name" + } + + preferredUsernameKey := c.ClaimMapping.PreferredUsernameKey + if preferredUsernameKey == "" { + preferredUsernameKey = "preferred_username" + } + + groupsKey := c.ClaimMapping.GroupsKey + if groupsKey == "" { + groupsKey = "groups" + } + + emailKey := c.ClaimMapping.EmailKey + if emailKey == "" { + emailKey = "email" + } + + emailVerifiedKey := c.ClaimMapping.EmailVerifiedKey + if emailVerifiedKey == "" { + emailVerifiedKey = "email_verified" + } + + oauthConn := &oauthConnector{ + clientID: c.ClientID, + clientSecret: c.ClientSecret, + tokenURL: c.TokenURL, + authorizationURL: c.AuthorizationURL, + userInfoURL: c.UserInfoURL, + scopes: c.Scopes, + redirectURI: c.RedirectURI, + logger: logger, + userIDKey: userIDKey, + userNameKey: userNameKey, + preferredUsernameKey: preferredUsernameKey, + groupsKey: groupsKey, + emailKey: emailKey, + emailVerifiedKey: emailVerifiedKey, + } + + oauthConn.httpClient, err = newHTTPClient(c.RootCAs, c.InsecureSkipVerify) + if err != nil { + return nil, err + } + + return oauthConn, err +} + +func newHTTPClient(rootCAs []string, insecureSkipVerify bool) (*http.Client, error) { + pool, err := x509.SystemCertPool() + if err != nil { + return nil, err + } + + tlsConfig := tls.Config{RootCAs: pool, InsecureSkipVerify: insecureSkipVerify} + for _, rootCA := range rootCAs { + rootCABytes, err := os.ReadFile(rootCA) + if err != nil { + return nil, fmt.Errorf("failed to read root-ca: %v", err) + } + if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCABytes) { + return nil, fmt.Errorf("no certs found in root CA file %q", rootCA) + } + } + + return &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tlsConfig, + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + }, + }, nil +} + +func (c *oauthConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) { + if c.redirectURI != callbackURL { + return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, c.redirectURI) + } + + oauth2Config := &oauth2.Config{ + ClientID: c.clientID, + ClientSecret: c.clientSecret, + Endpoint: oauth2.Endpoint{TokenURL: c.tokenURL, AuthURL: c.authorizationURL}, + RedirectURL: c.redirectURI, + Scopes: c.scopes, + } + + return oauth2Config.AuthCodeURL(state), nil +} + +func (c *oauthConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) { + q := r.URL.Query() + if errType := q.Get("error"); errType != "" { + return identity, errors.New(q.Get("error_description")) + } + + oauth2Config := &oauth2.Config{ + ClientID: c.clientID, + ClientSecret: c.clientSecret, + Endpoint: oauth2.Endpoint{TokenURL: c.tokenURL, AuthURL: c.authorizationURL}, + RedirectURL: c.redirectURI, + Scopes: c.scopes, + } + + ctx := context.WithValue(r.Context(), oauth2.HTTPClient, c.httpClient) + + token, err := oauth2Config.Exchange(ctx, q.Get("code")) + if err != nil { + return identity, fmt.Errorf("OAuth connector: failed to get token: %v", err) + } + + client := oauth2.NewClient(ctx, oauth2.StaticTokenSource(token)) + + userInfoResp, err := client.Get(c.userInfoURL) + if err != nil { + return identity, fmt.Errorf("OAuth Connector: failed to execute request to userinfo: %v", err) + } + defer userInfoResp.Body.Close() + + if userInfoResp.StatusCode != http.StatusOK { + return identity, fmt.Errorf("OAuth Connector: failed to execute request to userinfo: status %d", userInfoResp.StatusCode) + } + + var userInfoResult map[string]interface{} + err = json.NewDecoder(userInfoResp.Body).Decode(&userInfoResult) + if err != nil { + return identity, fmt.Errorf("OAuth Connector: failed to parse userinfo: %v", err) + } + + userID, found := userInfoResult[c.userIDKey].(string) + if !found { + return identity, fmt.Errorf("OAuth Connector: not found %v claim", c.userIDKey) + } + + identity.UserID = userID + identity.Username, _ = userInfoResult[c.userNameKey].(string) + identity.PreferredUsername, _ = userInfoResult[c.preferredUsernameKey].(string) + identity.Email, _ = userInfoResult[c.emailKey].(string) + identity.EmailVerified, _ = userInfoResult[c.emailVerifiedKey].(bool) + + if s.Groups { + groups := map[string]struct{}{} + + c.addGroupsFromMap(groups, userInfoResult) + c.addGroupsFromToken(groups, token.AccessToken) + + for groupName := range groups { + identity.Groups = append(identity.Groups, groupName) + } + } + + if s.OfflineAccess { + data := connectorData{AccessToken: token.AccessToken} + connData, err := json.Marshal(data) + if err != nil { + return identity, fmt.Errorf("OAuth Connector: failed to parse connector data for offline access: %v", err) + } + identity.ConnectorData = connData + } + + return identity, nil +} + +func (c *oauthConnector) addGroupsFromMap(groups map[string]struct{}, result map[string]interface{}) error { + groupsClaim, ok := result[c.groupsKey].([]interface{}) + if !ok { + return errors.New("cannot convert to slice") + } + + for _, group := range groupsClaim { + if groupString, ok := group.(string); ok { + groups[groupString] = struct{}{} + } + if groupMap, ok := group.(map[string]interface{}); ok { + if groupName, ok := groupMap["name"].(string); ok { + groups[groupName] = struct{}{} + } + } + } + + return nil +} + +func (c *oauthConnector) addGroupsFromToken(groups map[string]struct{}, token string) error { + parts := strings.Split(token, ".") + if len(parts) < 2 { + return errors.New("invalid token") + } + + decoded, err := decode(parts[1]) + if err != nil { + return err + } + + var claimsMap map[string]interface{} + err = json.Unmarshal(decoded, &claimsMap) + if err != nil { + return err + } + + return c.addGroupsFromMap(groups, claimsMap) +} + +func decode(seg string) ([]byte, error) { + if l := len(seg) % 4; l > 0 { + seg += strings.Repeat("=", 4-l) + } + + return base64.URLEncoding.DecodeString(seg) +} diff --git a/connector/oauth/oauth_test.go b/connector/oauth/oauth_test.go new file mode 100644 index 0000000000..082a3aa51b --- /dev/null +++ b/connector/oauth/oauth_test.go @@ -0,0 +1,271 @@ +package oauth + +import ( + "crypto/rand" + "crypto/rsa" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "sort" + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + jose "gopkg.in/square/go-jose.v2" + + "github.com/dexidp/dex/connector" +) + +func TestOpen(t *testing.T) { + tokenClaims := map[string]interface{}{} + userInfoClaims := map[string]interface{}{} + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + + sort.Strings(conn.scopes) + + assert.Equal(t, conn.clientID, "testClient") + assert.Equal(t, conn.clientSecret, "testSecret") + assert.Equal(t, conn.redirectURI, testServer.URL+"/callback") + assert.Equal(t, conn.tokenURL, testServer.URL+"/token") + assert.Equal(t, conn.authorizationURL, testServer.URL+"/authorize") + assert.Equal(t, conn.userInfoURL, testServer.URL+"/userinfo") + assert.Equal(t, len(conn.scopes), 2) + assert.Equal(t, conn.scopes[0], "groups") + assert.Equal(t, conn.scopes[1], "openid") +} + +func TestLoginURL(t *testing.T) { + tokenClaims := map[string]interface{}{} + userInfoClaims := map[string]interface{}{} + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + + loginURL, err := conn.LoginURL(connector.Scopes{}, conn.redirectURI, "some-state") + assert.Equal(t, err, nil) + + expectedURL, err := url.Parse(testServer.URL + "/authorize") + assert.Equal(t, err, nil) + + values := url.Values{} + values.Add("client_id", "testClient") + values.Add("redirect_uri", conn.redirectURI) + values.Add("response_type", "code") + values.Add("scope", "openid groups") + values.Add("state", "some-state") + expectedURL.RawQuery = values.Encode() + + assert.Equal(t, loginURL, expectedURL.String()) +} + +func TestHandleCallBackForGroupsInUserInfo(t *testing.T) { + tokenClaims := map[string]interface{}{} + + userInfoClaims := map[string]interface{}{ + "name": "test-name", + "user_id_key": "test-user-id", + "user_name_key": "test-username", + "preferred_username": "test-preferred-username", + "mail": "mod_mail", + "has_verified_email": false, + "groups_key": []string{"admin-group", "user-group"}, + } + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + req := newRequestWithAuthCode(t, testServer.URL, "some-code") + + identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req) + assert.Equal(t, err, nil) + + sort.Strings(identity.Groups) + assert.Equal(t, len(identity.Groups), 2) + assert.Equal(t, identity.Groups[0], "admin-group") + assert.Equal(t, identity.Groups[1], "user-group") + assert.Equal(t, identity.UserID, "test-user-id") + assert.Equal(t, identity.Username, "test-username") + assert.Equal(t, identity.PreferredUsername, "test-preferred-username") + assert.Equal(t, identity.Email, "mod_mail") + assert.Equal(t, identity.EmailVerified, false) +} + +func TestHandleCallBackForGroupMapsInUserInfo(t *testing.T) { + tokenClaims := map[string]interface{}{} + + userInfoClaims := map[string]interface{}{ + "name": "test-name", + "user_id_key": "test-user-id", + "user_name_key": "test-username", + "preferred_username": "test-preferred-username", + "mail": "mod_mail", + "has_verified_email": false, + "groups_key": []interface{}{ + map[string]string{"name": "admin-group", "id": "111"}, + map[string]string{"name": "user-group", "id": "222"}, + }, + } + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + req := newRequestWithAuthCode(t, testServer.URL, "some-code") + + identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req) + assert.Equal(t, err, nil) + + sort.Strings(identity.Groups) + assert.Equal(t, len(identity.Groups), 2) + assert.Equal(t, identity.Groups[0], "admin-group") + assert.Equal(t, identity.Groups[1], "user-group") + assert.Equal(t, identity.UserID, "test-user-id") + assert.Equal(t, identity.Username, "test-username") + assert.Equal(t, identity.PreferredUsername, "test-preferred-username") + assert.Equal(t, identity.Email, "mod_mail") + assert.Equal(t, identity.EmailVerified, false) +} + +func TestHandleCallBackForGroupsInToken(t *testing.T) { + tokenClaims := map[string]interface{}{ + "groups_key": []string{"test-group"}, + } + + userInfoClaims := map[string]interface{}{ + "name": "test-name", + "user_id_key": "test-user-id", + "user_name_key": "test-username", + "preferred_username": "test-preferred-username", + "email": "test-email", + "email_verified": true, + } + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + req := newRequestWithAuthCode(t, testServer.URL, "some-code") + + identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req) + assert.Equal(t, err, nil) + + assert.Equal(t, len(identity.Groups), 1) + assert.Equal(t, identity.Groups[0], "test-group") + assert.Equal(t, identity.PreferredUsername, "test-preferred-username") + assert.Equal(t, identity.UserID, "test-user-id") + assert.Equal(t, identity.Username, "test-username") + assert.Equal(t, identity.Email, "") + assert.Equal(t, identity.EmailVerified, false) +} + +func testSetup(t *testing.T, tokenClaims map[string]interface{}, userInfoClaims map[string]interface{}) *httptest.Server { + key, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Fatal("Failed to generate rsa key", err) + } + + jwk := jose.JSONWebKey{ + Key: key, + KeyID: "some-key", + Algorithm: "RSA", + } + + mux := http.NewServeMux() + + mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { + token, err := newToken(&jwk, tokenClaims) + if err != nil { + t.Fatal("unable to generate token", err) + } + + w.Header().Add("Content-Type", "application/json") + json.NewEncoder(w).Encode(&map[string]string{ + "access_token": token, + "id_token": token, + "token_type": "Bearer", + }) + }) + + mux.HandleFunc("/userinfo", func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + json.NewEncoder(w).Encode(userInfoClaims) + }) + + return httptest.NewServer(mux) +} + +func newToken(key *jose.JSONWebKey, claims map[string]interface{}) (string, error) { + signingKey := jose.SigningKey{Key: key, Algorithm: jose.RS256} + + signer, err := jose.NewSigner(signingKey, &jose.SignerOptions{}) + if err != nil { + return "", fmt.Errorf("new signer: %v", err) + } + + payload, err := json.Marshal(claims) + if err != nil { + return "", fmt.Errorf("marshaling claims: %v", err) + } + + signature, err := signer.Sign(payload) + if err != nil { + return "", fmt.Errorf("signing payload: %v", err) + } + + return signature.CompactSerialize() +} + +func newConnector(t *testing.T, serverURL string) *oauthConnector { + testConfig := Config{ + ClientID: "testClient", + ClientSecret: "testSecret", + RedirectURI: serverURL + "/callback", + TokenURL: serverURL + "/token", + AuthorizationURL: serverURL + "/authorize", + UserInfoURL: serverURL + "/userinfo", + Scopes: []string{"openid", "groups"}, + UserIDKey: "user_id_key", + } + + testConfig.ClaimMapping.UserNameKey = "user_name_key" + testConfig.ClaimMapping.GroupsKey = "groups_key" + testConfig.ClaimMapping.EmailKey = "mail" + testConfig.ClaimMapping.EmailVerifiedKey = "has_verified_email" + + log := logrus.New() + + conn, err := testConfig.Open("id", log) + if err != nil { + t.Fatal(err) + } + + oauthConn, ok := conn.(*oauthConnector) + if !ok { + t.Fatal(errors.New("failed to convert to oauthConnector")) + } + + return oauthConn +} + +func newRequestWithAuthCode(t *testing.T, serverURL string, code string) *http.Request { + req, err := http.NewRequest("GET", serverURL, nil) + if err != nil { + t.Fatal("failed to create request", err) + } + + values := req.URL.Query() + values.Add("code", code) + req.URL.RawQuery = values.Encode() + + return req +} diff --git a/connector/oidc/oidc.go b/connector/oidc/oidc.go index b752f9dac5..b0467330d8 100644 --- a/connector/oidc/oidc.go +++ b/connector/oidc/oidc.go @@ -56,6 +56,11 @@ type Config struct { // PromptType will be used fot the prompt parameter (when offline_access, by default prompt=consent) PromptType string `json:"promptType"` + // OverrideClaimMapping will be used to override the options defined in claimMappings. + // i.e. if there are 'email' and `preferred_email` claims available, by default Dex will always use the `email` claim independent of the ClaimMapping.EmailKey. + // This setting allows you to override the default behavior of Dex and enforce the mappings defined in `claimMapping`. + OverrideClaimMapping bool `json:"overrideClaimMapping"` // defaults to false + ClaimMapping struct { // Configurable key which contains the preferred username claims PreferredUsernameKey string `json:"preferred_username"` // defaults to "preferred_username" @@ -153,6 +158,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e promptType: c.PromptType, userIDKey: c.UserIDKey, userNameKey: c.UserNameKey, + overrideClaimMapping: c.OverrideClaimMapping, preferredUsernameKey: c.ClaimMapping.PreferredUsernameKey, emailKey: c.ClaimMapping.EmailKey, groupsKey: c.ClaimMapping.GroupsKey, @@ -178,6 +184,7 @@ type oidcConnector struct { promptType string userIDKey string userNameKey string + overrideClaimMapping bool preferredUsernameKey string emailKey string groupsKey string @@ -289,7 +296,7 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I } preferredUsername, found := claims["preferred_username"].(string) - if !found { + if (!found || c.overrideClaimMapping) && c.preferredUsernameKey != "" { preferredUsername, _ = claims[c.preferredUsernameKey].(string) } @@ -304,7 +311,7 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I var email string emailKey := "email" email, found = claims[emailKey].(string) - if !found && c.emailKey != "" { + if (!found || c.overrideClaimMapping) && c.emailKey != "" { emailKey = c.emailKey email, found = claims[emailKey].(string) } @@ -326,7 +333,7 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I if c.insecureEnableGroups { groupsKey := "groups" vs, found := claims[groupsKey].([]interface{}) - if !found { + if (!found || c.overrideClaimMapping) && c.groupsKey != "" { groupsKey = c.groupsKey vs, found = claims[groupsKey].([]interface{}) } diff --git a/connector/oidc/oidc_test.go b/connector/oidc/oidc_test.go index ae92f70caa..3038cebcf2 100644 --- a/connector/oidc/oidc_test.go +++ b/connector/oidc/oidc_test.go @@ -49,6 +49,7 @@ func TestHandleCallback(t *testing.T) { name string userIDKey string userNameKey string + overrideClaimMapping bool preferredUsernameKey string emailKey string groupsKey string @@ -92,6 +93,23 @@ func TestHandleCallback(t *testing.T) { "email_verified": true, }, }, + { + name: "overrideWithCustomEmailClaim", + userIDKey: "", // not configured + userNameKey: "", // not configured + overrideClaimMapping: true, + emailKey: "custommail", + expectUserID: "subvalue", + expectUserName: "namevalue", + expectedEmailField: "customemailvalue", + token: map[string]interface{}{ + "sub": "subvalue", + "name": "namevalue", + "email": "emailvalue", + "custommail": "customemailvalue", + "email_verified": true, + }, + }, { name: "email_verified not in claims, configured to be skipped", insecureSkipEmailVerified: true, @@ -234,6 +252,25 @@ func TestHandleCallback(t *testing.T) { "cognito:groups": []string{"group3", "group4"}, }, }, + { + name: "customGroupsKeyDespiteGroupsProvidedButOverride", + overrideClaimMapping: true, + groupsKey: "cognito:groups", + expectUserID: "subvalue", + expectUserName: "namevalue", + expectedEmailField: "emailvalue", + expectGroups: []string{"group3", "group4"}, + scopes: []string{"groups"}, + insecureSkipEmailVerified: true, + token: map[string]interface{}{ + "sub": "subvalue", + "name": "namevalue", + "user_name": "username", + "email": "emailvalue", + "groups": []string{"group1", "group2"}, + "cognito:groups": []string{"group3", "group4"}, + }, + }, } for _, tc := range tests { @@ -263,6 +300,7 @@ func TestHandleCallback(t *testing.T) { InsecureSkipEmailVerified: tc.insecureSkipEmailVerified, InsecureEnableGroups: true, BasicAuthUnsupported: &basicAuth, + OverrideClaimMapping: tc.overrideClaimMapping, } config.ClaimMapping.PreferredUsernameKey = tc.preferredUsernameKey config.ClaimMapping.EmailKey = tc.emailKey diff --git a/connector/openshift/openshift.go b/connector/openshift/openshift.go index f06e8f8045..44a03edf39 100644 --- a/connector/openshift/openshift.go +++ b/connector/openshift/openshift.go @@ -6,9 +6,10 @@ import ( "crypto/x509" "encoding/json" "fmt" - "io/ioutil" + "io" "net" "net/http" + "os" "strings" "time" @@ -195,7 +196,7 @@ func (c *openshiftConnector) user(ctx context.Context, client *http.Client) (u u defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return u, fmt.Errorf("read body: %v", err) } @@ -223,7 +224,7 @@ func newHTTPClient(insecureCA bool, rootCA string) (*http.Client, error) { tlsConfig = tls.Config{InsecureSkipVerify: true} } else if rootCA != "" { tlsConfig = tls.Config{RootCAs: x509.NewCertPool()} - rootCABytes, err := ioutil.ReadFile(rootCA) + rootCABytes, err := os.ReadFile(rootCA) if err != nil { return nil, fmt.Errorf("failed to read root-ca: %v", err) } diff --git a/connector/saml/saml.go b/connector/saml/saml.go index 0d52b13116..908ec703c9 100644 --- a/connector/saml/saml.go +++ b/connector/saml/saml.go @@ -8,7 +8,7 @@ import ( "encoding/pem" "encoding/xml" "fmt" - "io/ioutil" + "os" "strings" "sync" "time" @@ -194,7 +194,7 @@ func (c *Config) openConnector(logger log.Logger) (*provider, error) { var caData []byte if c.CA != "" { - data, err := ioutil.ReadFile(c.CA) + data, err := os.ReadFile(c.CA) if err != nil { return nil, fmt.Errorf("read ca file: %v", err) } diff --git a/connector/saml/saml_test.go b/connector/saml/saml_test.go index 67d7efb140..95d513ed19 100644 --- a/connector/saml/saml_test.go +++ b/connector/saml/saml_test.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "encoding/pem" "errors" - "io/ioutil" + "os" "sort" "testing" "time" @@ -392,7 +392,7 @@ func TestTamperedResponseNameID(t *testing.T) { } func loadCert(ca string) (*x509.Certificate, error) { - data, err := ioutil.ReadFile(ca) + data, err := os.ReadFile(ca) if err != nil { return nil, err } @@ -426,7 +426,7 @@ func (r responseTest) run(t *testing.T) { t.Fatal(err) } conn.now = func() time.Time { return now } - resp, err := ioutil.ReadFile(r.respFile) + resp, err := os.ReadFile(r.respFile) if err != nil { t.Fatal(err) } @@ -456,11 +456,11 @@ func (r responseTest) run(t *testing.T) { func TestConfigCAData(t *testing.T) { logger := logrus.New() - validPEM, err := ioutil.ReadFile("testdata/ca.crt") + validPEM, err := os.ReadFile("testdata/ca.crt") if err != nil { t.Fatal(err) } - valid2ndPEM, err := ioutil.ReadFile("testdata/okta-ca.pem") + valid2ndPEM, err := os.ReadFile("testdata/okta-ca.pem") if err != nil { t.Fatal(err) } @@ -551,7 +551,7 @@ func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) { validator := dsig.NewDefaultValidationContext(s) - data, err := ioutil.ReadFile(resp) + data, err := os.ReadFile(resp) if err != nil { t.Fatal(err) } diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index bb12d313b3..0000000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -e - -### Usage: /docker-entrypoint.sh -function main() { - executable=$1 - command=$2 - - if [[ "$executable" != "dex" ]] && [[ "$executable" != "$(which dex)" ]]; then - exec $@ - fi - - if [[ "$command" != "serve" ]]; then - exec $@ - fi - - for tpl_candidate in $@ ; do - case "$tpl_candidate" in - *.tpl|*.tmpl|*.yaml) - tmp_file=$(mktemp /tmp/dex.config.yaml-XXXXXX) - gomplate -f "$tpl_candidate" -o "$tmp_file" - - args="${args} ${tmp_file}" - ;; - *) - args="${args} ${tpl_candidate}" - ;; - esac - done - exec $args -} - -main $@ diff --git a/examples/example-app/main.go b/examples/example-app/main.go index e417c8b26f..451bea5b46 100644 --- a/examples/example-app/main.go +++ b/examples/example-app/main.go @@ -8,7 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "log" "net" "net/http" @@ -43,7 +42,7 @@ type app struct { // return an HTTP client which trusts the provided root CAs. func httpClientForRootCAs(rootCAs string) (*http.Client, error) { tlsConfig := tls.Config{RootCAs: x509.NewCertPool()} - rootCABytes, err := ioutil.ReadFile(rootCAs) + rootCABytes, err := os.ReadFile(rootCAs) if err != nil { return nil, fmt.Errorf("failed to read root-ca: %v", err) } diff --git a/examples/go.mod b/examples/go.mod index fc1405d615..d66c118a7f 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -1,11 +1,25 @@ module github.com/dexidp/dex/examples -go 1.14 +go 1.17 require ( - github.com/coreos/go-oidc/v3 v3.0.0 - github.com/dexidp/dex/api/v2 v2.0.0-20200715135117-cb46a28c3ce2 - github.com/spf13/cobra v1.0.0 - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d - google.golang.org/grpc v1.26.0 + github.com/coreos/go-oidc/v3 v3.1.0 + github.com/dexidp/dex/api/v2 v2.0.0 + github.com/spf13/cobra v1.3.0 + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 + google.golang.org/grpc v1.43.0 +) + +require ( + github.com/golang/protobuf v1.5.2 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect + golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect ) diff --git a/examples/go.sum b/examples/go.sum index f27e7ca36e..7907afde92 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,183 +1,788 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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/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/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ= -github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbrRw= +github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/dexidp/dex/api/v2 v2.0.0-20200715135117-cb46a28c3ce2 h1:7dhZfOv4rPQobAFxxWLnZB2bV9QxSHGnufXeCjzHEos= -github.com/dexidp/dex/api/v2 v2.0.0-20200715135117-cb46a28c3ce2/go.mod h1:k5arBJT1QYvpsEY3sEd0NXJp3hKWKuUUfzJ3BlcqPdM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dexidp/dex/api/v2 v2.0.0 h1:bvge1sRmzVzWPWp4WlMzS04lcNQA+jFzHqKV3066bRw= +github.com/dexidp/dex/api/v2 v2.0.0/go.mod h1:k5arBJT1QYvpsEY3sEd0NXJp3hKWKuUUfzJ3BlcqPdM= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +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/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +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/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +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.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +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 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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.3/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.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/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/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +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/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -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/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +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.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +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.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= 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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +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= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +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.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +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-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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/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= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20190923162816-aa69164e4478/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= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs= +golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +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.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +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-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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/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-20200124204421-9fbb57f87de9/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= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +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-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +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-20190907020128-2ca718005c18/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-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= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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-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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +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 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +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= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0 h1:aCsSLXylHWFno0r4S3joLpiaWayvqd2Mn4iSvx4WZZc= +google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +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.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/examples/grpc-client/client.go b/examples/grpc-client/client.go index 7b3949a1c4..c3a69097dc 100644 --- a/examples/grpc-client/client.go +++ b/examples/grpc-client/client.go @@ -6,8 +6,8 @@ import ( "crypto/x509" "flag" "fmt" - "io/ioutil" "log" + "os" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -17,7 +17,7 @@ import ( func newDexClient(hostAndPort, caPath, clientCrt, clientKey string) (api.DexClient, error) { cPool := x509.NewCertPool() - caCert, err := ioutil.ReadFile(caPath) + caCert, err := os.ReadFile(caPath) if err != nil { return nil, fmt.Errorf("invalid CA crt file: %s", caPath) } diff --git a/examples/k8s/dex.yaml b/examples/k8s/dex.yaml index fc5d84c7f4..89ac40b223 100644 --- a/examples/k8s/dex.yaml +++ b/examples/k8s/dex.yaml @@ -23,7 +23,7 @@ spec: spec: serviceAccountName: dex # This is created below containers: - - image: dexidp/dex:v2.27.0 #or quay.io/dexidp/dex:v2.26.0 + - image: ghcr.io/dexidp/dex:v2.30.0 name: dex command: ["/usr/local/bin/dex", "serve", "/etc/dex/cfg/config.yaml"] diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..715570a3a5 --- /dev/null +++ b/flake.lock @@ -0,0 +1,42 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1636800699, + "narHash": "sha256-SwbyVxXffu3G2ulJIbTf0iQfqhbGbdml4Dyv5j9BiAI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2fa862644fc15ecb525eb8cd0a60276f1c340c7c", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..8f444d5e91 --- /dev/null +++ b/flake.nix @@ -0,0 +1,25 @@ +{ + description = "OpenID Connect (OIDC) identity and OAuth 2.0 provider with pluggable connectors"; + + inputs = { + nixpkgs.url = "nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + buildDeps = with pkgs; [ git go_1_17 gnumake ]; + devDeps = with pkgs; + buildDeps ++ [ + golangci-lint + gotestsum + protobuf + protoc-gen-go + protoc-gen-go-grpc + kind + ]; + in + { devShell = pkgs.mkShell { buildInputs = devDeps; }; }); +} diff --git a/go.mod b/go.mod index f360aa5f03..927408fb1d 100644 --- a/go.mod +++ b/go.mod @@ -1,42 +1,85 @@ module github.com/dexidp/dex -go 1.16 +go 1.17 require ( - entgo.io/ent v0.8.0 - github.com/AppsFlyer/go-sundheit v0.4.0 + entgo.io/ent v0.9.1 + github.com/AppsFlyer/go-sundheit v0.5.0 github.com/Masterminds/semver v1.5.0 github.com/Masterminds/sprig/v3 v3.2.2 github.com/beevik/etree v1.1.0 - github.com/coreos/go-oidc/v3 v3.0.0 - github.com/dexidp/dex/api/v2 v2.0.0 + github.com/coreos/go-oidc/v3 v3.1.0 + github.com/dexidp/dex/api/v2 v2.1.0 github.com/felixge/httpsnoop v1.0.2 github.com/ghodss/yaml v1.0.0 - github.com/go-ldap/ldap/v3 v3.3.0 + github.com/go-ldap/ldap/v3 v3.4.1 github.com/go-sql-driver/mysql v1.6.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/kylelemons/godebug v1.1.0 - github.com/lib/pq v1.10.2 + github.com/lib/pq v1.10.9 github.com/mattermost/xml-roundtrip-validator v0.1.0 - github.com/mattn/go-sqlite3 v1.14.8 + github.com/mattn/go-sqlite3 v1.14.11 github.com/oklog/run v1.1.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.11.0 - github.com/russellhaering/goxmldsig v1.1.0 + github.com/prometheus/client_golang v1.12.1 + github.com/russellhaering/goxmldsig v1.1.1 github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.3.0 github.com/stretchr/testify v1.7.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v3 v3.5.0 - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 - golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 - golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 - google.golang.org/api v0.52.0 - google.golang.org/grpc v1.39.0 + go.etcd.io/etcd/client/pkg/v3 v3.5.2 + go.etcd.io/etcd/client/v3 v3.5.2 + golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 + google.golang.org/api v0.68.0 + google.golang.org/grpc v1.44.0 google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.6.0 ) +require ( + cloud.google.com/go/compute v1.2.0 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/gax-go/v2 v2.1.1 // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.etcd.io/etcd/api/v3 v3.5.2 // indirect + go.opencensus.io v0.23.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220207185906-7721543eae58 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + replace github.com/dexidp/dex/api/v2 => ./api/v2 diff --git a/go.sum b/go.sum index 3752f7ea4d..cd4a8e2cc4 100644 --- a/go.sum +++ b/go.sum @@ -20,17 +20,28 @@ cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.88.0 h1:MZ2cf9Elnv1wqccq8ooKO2MqHQLc+ChCp/+QWObCpxg= -cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 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 v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.2.0 h1:EKki8sSdvDU0OO9mAXGwPXOTOgPz2l08R0/IutDH11I= +cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -41,16 +52,18 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -entgo.io/ent v0.8.0 h1:xirrW//1oda7pp0bz+XssSOv4/C3nmgYQOxjIfljFt8= -entgo.io/ent v0.8.0/go.mod h1:KNjsukat/NJi6zJh1utwRadsbGOZsBbAZNDxkW7tMCc= -github.com/AppsFlyer/go-sundheit v0.4.0 h1:7ECd0YWaXJQ9LzdCFrpGxJVeAgXvNarN6uwxrJsh69A= -github.com/AppsFlyer/go-sundheit v0.4.0/go.mod h1:iZ8zWMS7idcvmqewf5mEymWWgoOiG/0WD4+aeh+heX4= -github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28= +entgo.io/ent v0.9.1 h1:IG8andyeD79GG24U8Q+1Y45hQXj6gY5evSBcva5gtBk= +entgo.io/ent v0.9.1/go.mod h1:6NUeTfUN5mp5YN+5tgoH1SlakSvYPTBOYotSOvaI4ak= +github.com/AppsFlyer/go-sundheit v0.5.0 h1:/VxpyigCfJrq1r97mn9HPiAB2qrhcTFHwNIIDr15CZM= +github.com/AppsFlyer/go-sundheit v0.5.0/go.mod h1:2ZM0BnfqT/mljBQO224VbL5XH06TgWuQ6Cn+cTtCpTY= github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ= +github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -68,33 +81,46 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ= -github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= +github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbrRw= +github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= @@ -103,6 +129,8 @@ github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzA github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -116,19 +144,25 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-asn1-ber/asn1-ber v1.5.3 h1:u7utq56RUFiynqUzgVMFDymapcOtQ/MZkh3H4QYkxag= +github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-bindata/go-bindata v1.0.1-0.20190711162640-ee3c2418e368/go.mod h1:7xCgX1lzlrXPHkfvn3EhumqHkmSlzt8at9q7v0ax19c= 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= @@ -136,8 +170,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ= -github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= +github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU= +github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -155,8 +189,9 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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 h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -198,8 +233,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/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.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -217,15 +253,18 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= @@ -238,13 +277,23 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -252,27 +301,39 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 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/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs= -github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -286,32 +347,50 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -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/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/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/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +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.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +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-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= +github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -320,12 +399,15 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -333,8 +415,10 @@ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DV github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -343,12 +427,15 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -357,26 +444,36 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russellhaering/goxmldsig v1.1.0 h1:lK/zeJie2sqG52ZAlPNn1oBBqsIsEKypUUBGpYYF6lk= -github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM= +github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -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/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -388,20 +485,22 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= 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 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -415,6 +514,7 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -422,13 +522,15 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.2 h1:tXok5yLlKyuQ/SXSjtqHc4uzNaMqZi2XsoSPr/LlJXI= +go.etcd.io/etcd/api/v3 v3.5.2/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.2 h1:4hzqQ6hIb3blLyQ8usCU4h3NghkqcsohEQ3o3VetYxE= +go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.etcd.io/etcd/client/v3 v3.5.2 h1:WdnejrUtQC4nCxK0/dLTMqKOB+U5TP/2Ya0BJL+1otA= +go.etcd.io/etcd/client/v3 v3.5.2/go.mod h1:kOOaWFFgHygyT0WlSmL8TJiXmMysO/nNUlEsSsN6W4o= 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= @@ -439,26 +541,33 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab h1:lnZ4LoV0UMdibeCUfIB2a4uFwRu491WX/VB2reB8xNc= +golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -494,6 +603,7 @@ 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -511,6 +621,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL 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-20190923162816-aa69164e4478/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= @@ -534,8 +645,13 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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= @@ -547,10 +663,13 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -569,6 +688,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -577,14 +697,18 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/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-20200106162015-b016eb3dc98e/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-20200124204421-9fbb57f87de9/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= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -606,6 +730,7 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -616,10 +741,25 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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 h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc= +golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/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= @@ -627,8 +767,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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= @@ -648,6 +789,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190907020128-2ca718005c18/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-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -715,12 +857,21 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.52.0 h1:m5FLEd6dp5CU1F0tMWyqDi2XjchviIz8ntzOSz7w8As= -google.golang.org/api v0.52.0/go.mod h1:Him/adpjt0sxtkWViy0b6xyKW/SD71CwdJ7HqJo7SrU= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= +google.golang.org/api v0.68.0 h1:9eJiHhwJKIYX6sX2fUZxQLi7pDRA/MYu8c12q6WbJik= +google.golang.org/api v0.68.0/go.mod h1:sOM8pTpwgflXRhz+oC8H2Dr+UcbMqkPPWNJo88Q7TH8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -774,9 +925,30 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f h1:YORWxaStkWBnWgELOHTmDrqNlFXuVGEbhwbB5iK94bQ= -google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207185906-7721543eae58 h1:i67FGOy2/zGfhE3YgHdrOrcFbOBhqdcRoBrsDqSQrOI= +google.golang.org/genproto v0.0.0-20220207185906-7721543eae58/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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= @@ -799,8 +971,13 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -819,11 +996,12 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= diff --git a/pkg/log/deprecated.go b/pkg/log/deprecated.go new file mode 100644 index 0000000000..f20e8b4cb8 --- /dev/null +++ b/pkg/log/deprecated.go @@ -0,0 +1,5 @@ +package log + +func Deprecated(logger Logger, f string, args ...interface{}) { + logger.Warnf("Deprecated: "+f, args...) +} diff --git a/scripts/get-protoc b/scripts/get-protoc deleted file mode 100755 index 41b8f54a52..0000000000 --- a/scripts/get-protoc +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -e - -# This is a script to download protoc. Rather than depending on the version on -# a developer's machine, always download a specific version. - -VERSION="3.1.0" - -if [ $# -ne 1 ]; then - echo "Usage: ./get-protoc [dest]" - exit 2 -fi - -# Use the go tool to determine OS. -OS=$( go env GOOS ) - -if [ "$OS" = "darwin" ]; then - OS="osx" -fi - -mkdir -p bin - -# TODO(ericchiang): Architectures other than amd64? -ZIP="protoc-${VERSION}-${OS}-x86_64.zip" -URL="https://github.com/google/protobuf/releases/download/v${VERSION}/${ZIP}" - -wget ${URL} -# Unpack the protoc binary. Later we might want to grab additional data. -unzip -p ${ZIP} bin/protoc > $1 -chmod +x $1 -rm ${ZIP} diff --git a/server/api_test.go b/server/api_test.go index 020613402c..01c59cf875 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -9,6 +9,7 @@ import ( "github.com/sirupsen/logrus" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "github.com/dexidp/dex/api/v2" "github.com/dexidp/dex/pkg/log" @@ -41,7 +42,7 @@ func newAPI(s storage.Storage, logger log.Logger, t *testing.T) *apiClient { // Dial will retry automatically if the serv.Serve() goroutine // hasn't started yet. - conn, err := grpc.Dial(l.Addr().String(), grpc.WithInsecure()) + conn, err := grpc.Dial(l.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { t.Fatal(err) } diff --git a/server/deviceflowhandlers.go b/server/deviceflowhandlers.go index 5ec7eb8e16..fb73f257f2 100644 --- a/server/deviceflowhandlers.go +++ b/server/deviceflowhandlers.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/dexidp/dex/pkg/log" "github.com/dexidp/dex/storage" ) @@ -152,7 +153,7 @@ func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) { } func (s *Server) handleDeviceTokenDeprecated(w http.ResponseWriter, r *http.Request) { - s.logger.Warn(`The deprecated "/device/token" endpoint was called. It will be removed, use "/token" instead.`) + log.Deprecated(s.logger, `The /device/token endpoint was called. It will be removed, use /token instead.`) w.Header().Set("Content-Type", "application/json") switch r.Method { diff --git a/server/deviceflowhandlers_test.go b/server/deviceflowhandlers_test.go index 3898d4fc8e..c387af4337 100644 --- a/server/deviceflowhandlers_test.go +++ b/server/deviceflowhandlers_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/json" - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/url" @@ -101,7 +101,7 @@ func TestHandleDeviceCode(t *testing.T) { t.Errorf("Unexpected Response Type. Expected %v got %v", tc.expectedResponseCode, rr.Code) } - body, err := ioutil.ReadAll(rr.Body) + body, err := io.ReadAll(rr.Body) if err != nil { t.Errorf("Could read token response %v", err) } @@ -541,7 +541,7 @@ func TestDeviceTokenResponse(t *testing.T) { t.Errorf("Unexpected Response Type. Expected %v got %v", tc.expectedResponseCode, rr.Code) } - body, err := ioutil.ReadAll(rr.Body) + body, err := io.ReadAll(rr.Body) if err != nil { t.Errorf("Could read token response %v", err) } diff --git a/server/handlers.go b/server/handlers.go old mode 100644 new mode 100755 index 2a4f8c71de..acbf4ecb73 --- a/server/handlers.go +++ b/server/handlers.go @@ -94,7 +94,6 @@ func (s *Server) discoveryHandler() (http.HandlerFunc, error) { UserInfo: s.absURL("/userinfo"), DeviceEndpoint: s.absURL("/device/code"), Subjects: []string{"public"}, - GrantTypes: []string{grantTypeAuthorizationCode, grantTypeRefreshToken, grantTypeDeviceCode}, IDTokenAlgs: []string{string(jose.RS256)}, CodeChallengeAlgs: []string{codeChallengeMethodS256, codeChallengeMethodPlain}, Scopes: []string{"openid", "email", "groups", "profile", "offline_access"}, @@ -110,6 +109,8 @@ func (s *Server) discoveryHandler() (http.HandlerFunc, error) { } sort.Strings(d.ResponseTypes) + d.GrantTypes = s.supportedGrantTypes + data, err := json.MarshalIndent(d, "", " ") if err != nil { return nil, fmt.Errorf("failed to marshal discovery data: %v", err) @@ -1105,10 +1106,17 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli Groups: identity.Groups, } - accessToken := storage.NewID() + accessToken, err := s.newAccessToken(client.ID, claims, scopes, nonce, connID) + if err != nil { + s.logger.Errorf("password grant failed to create new access token: %v", err) + s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError) + return + } + idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, nonce, accessToken, "", connID) if err != nil { - s.tokenErrHelper(w, errServerError, fmt.Sprintf("failed to create ID token: %v", err), http.StatusInternalServerError) + s.logger.Errorf("password grant failed to create new ID token: %v", err) + s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError) return } diff --git a/server/refreshhandlers.go b/server/refreshhandlers.go index 8ea7ea9ef1..a81653005a 100644 --- a/server/refreshhandlers.go +++ b/server/refreshhandlers.go @@ -76,7 +76,9 @@ func (s *Server) getRefreshTokenFromStorage(clientID string, token *internal.Ref if refresh.ClientID != clientID { s.logger.Errorf("client %s trying to claim token for client %s", clientID, refresh.ClientID) - return nil, invalidErr + // According to https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 Dex should respond with an + // invalid grant error if token has already been claimed by another client. + return nil, &refreshError{msg: errInvalidGrant, desc: invalidErr.desc, code: http.StatusBadRequest} } if refresh.Token != token.Token { @@ -227,16 +229,13 @@ func (s *Server) updateRefreshToken(token *internal.RefreshToken, refresh *stora lastUsed := s.now() - rerr := s.updateOfflineSession(refresh, ident, lastUsed) - if rerr != nil { - return nil, rerr - } - refreshTokenUpdater := func(old storage.RefreshToken) (storage.RefreshToken, error) { if s.refreshTokenPolicy.RotationEnabled() { if old.Token != token.Token { if s.refreshTokenPolicy.AllowedToReuse(old.LastUsed) && old.ObsoleteToken == token.Token { newToken.Token = old.Token + // Do not update last used time for offline session if token is allowed to be reused + lastUsed = old.LastUsed return old, nil } return old, errors.New("refresh token claimed twice") @@ -268,6 +267,11 @@ func (s *Server) updateRefreshToken(token *internal.RefreshToken, refresh *stora return nil, newInternalServerError() } + rerr := s.updateOfflineSession(refresh, ident, lastUsed) + if rerr != nil { + return nil, rerr + } + return newToken, nil } diff --git a/server/server.go b/server/server.go old mode 100644 new mode 100755 index 957b62dc10..646c057ba3 --- a/server/server.go +++ b/server/server.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path" + "sort" "strconv" "strings" "sync" @@ -27,6 +28,7 @@ import ( "github.com/dexidp/dex/connector" "github.com/dexidp/dex/connector/atlassiancrowd" "github.com/dexidp/dex/connector/authproxy" + "github.com/dexidp/dex/connector/authproxyshib" "github.com/dexidp/dex/connector/bitbucketcloud" "github.com/dexidp/dex/connector/gitea" "github.com/dexidp/dex/connector/github" @@ -37,6 +39,7 @@ import ( "github.com/dexidp/dex/connector/linkedin" "github.com/dexidp/dex/connector/microsoft" "github.com/dexidp/dex/connector/mock" + "github.com/dexidp/dex/connector/oauth" "github.com/dexidp/dex/connector/oidc" "github.com/dexidp/dex/connector/openshift" "github.com/dexidp/dex/connector/saml" @@ -169,6 +172,8 @@ type Server struct { supportedResponseTypes map[string]bool + supportedGrantTypes []string + now func() time.Time idTokensValidFor time.Duration @@ -209,15 +214,21 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy) c.SupportedResponseTypes = []string{responseTypeCode} } - supported := make(map[string]bool) + supportedRes := make(map[string]bool) for _, respType := range c.SupportedResponseTypes { switch respType { case responseTypeCode, responseTypeIDToken, responseTypeToken: default: return nil, fmt.Errorf("unsupported response_type %q", respType) } - supported[respType] = true + supportedRes[respType] = true + } + + supportedGrant := []string{grantTypeAuthorizationCode, grantTypeRefreshToken, grantTypeDeviceCode} // default + if c.PasswordConnector != "" { + supportedGrant = append(supportedGrant, grantTypePassword) } + sort.Strings(supportedGrant) webFS := web.FS() if c.Web.Dir != "" { @@ -249,7 +260,8 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy) issuerURL: *issuerURL, connectors: make(map[string]Connector), storage: newKeyCacher(c.Storage, now), - supportedResponseTypes: supported, + supportedResponseTypes: supportedRes, + supportedGrantTypes: supportedGrant, idTokensValidFor: value(c.IDTokensValidFor, 24*time.Hour), authRequestsValidFor: value(c.AuthRequestsValidFor, 24*time.Hour), deviceRequestsValidFor: value(c.DeviceRequestsValidFor, 5*time.Minute), @@ -528,8 +540,10 @@ var ConnectorsConfig = map[string]func() ConnectorConfig{ "gitlab": func() ConnectorConfig { return new(gitlab.Config) }, "google": func() ConnectorConfig { return new(google.Config) }, "oidc": func() ConnectorConfig { return new(oidc.Config) }, + "oauth": func() ConnectorConfig { return new(oauth.Config) }, "saml": func() ConnectorConfig { return new(saml.Config) }, "authproxy": func() ConnectorConfig { return new(authproxy.Config) }, + "authproxy-shib": func() ConnectorConfig { return new(authproxyshib.Config) }, "linkedin": func() ConnectorConfig { return new(linkedin.Config) }, "microsoft": func() ConnectorConfig { return new(microsoft.Config) }, "bitbucket-cloud": func() ConnectorConfig { return new(bitbucketcloud.Config) }, diff --git a/server/server_test.go b/server/server_test.go index 682d16a731..12130dfaad 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -8,7 +8,7 @@ import ( "encoding/pem" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/http/httputil" @@ -481,6 +481,47 @@ func makeOAuth2Tests(clientID string, clientSecret string, now func() time.Time) return nil }, }, + { + name: "refresh with different client id", + scopes: []string{"openid", "email"}, + handleToken: func(ctx context.Context, p *oidc.Provider, config *oauth2.Config, token *oauth2.Token, conn *mock.Callback) error { + v := url.Values{} + v.Add("client_id", clientID) + v.Add("client_secret", clientSecret) + v.Add("grant_type", "refresh_token") + v.Add("refresh_token", "existedrefrestoken") + v.Add("scope", "oidc email") + resp, err := http.PostForm(p.Endpoint().TokenURL, v) + if err != nil { + return err + } + + defer resp.Body.Close() + if resp.StatusCode != http.StatusBadRequest { + return fmt.Errorf("expected status code %d, got %d", http.StatusBadRequest, resp.StatusCode) + } + + var respErr struct { + Error string `json:"error"` + Description string `json:"error_description"` + } + + if err = json.NewDecoder(resp.Body).Decode(&respErr); err != nil { + return fmt.Errorf("cannot decode token response: %v", err) + } + + if respErr.Error != errInvalidGrant { + return fmt.Errorf("expected error %q, got %q", errInvalidGrant, respErr.Error) + } + + expectedMsg := "Refresh token is invalid or has already been claimed by another client." + if respErr.Description != expectedMsg { + return fmt.Errorf("expected error description %q, got %q", expectedMsg, respErr.Description) + } + + return nil + }, + }, { // This test ensures that the connector.RefreshConnector interface is being // used when clients request a refresh token. @@ -792,6 +833,13 @@ func TestOAuth2CodeFlow(t *testing.T) { t.Fatalf("failed to create client: %v", err) } + if err := s.storage.CreateRefresh(storage.RefreshToken{ + ID: "existedrefrestoken", + ClientID: "unexcistedclientid", + }); err != nil { + t.Fatalf("failed to create existed refresh token: %v", err) + } + // Create the OAuth2 config. oauth2Config = &oauth2.Config{ ClientID: client.ID, @@ -1570,6 +1618,13 @@ func TestOAuth2DeviceFlow(t *testing.T) { t.Fatalf("failed to create client: %v", err) } + if err := s.storage.CreateRefresh(storage.RefreshToken{ + ID: "existedrefrestoken", + ClientID: "unexcistedclientid", + }); err != nil { + t.Fatalf("failed to create existed refresh token: %v", err) + } + // Grab the issuer that we'll reuse for the different endpoints to hit issuer, err := url.Parse(s.issuerURL.String()) if err != nil { @@ -1588,7 +1643,7 @@ func TestOAuth2DeviceFlow(t *testing.T) { t.Errorf("Could not request device code: %v", err) } defer resp.Body.Close() - responseBody, err := ioutil.ReadAll(resp.Body) + responseBody, err := io.ReadAll(resp.Body) if err != nil { t.Errorf("Could read device code response %v", err) } @@ -1615,7 +1670,7 @@ func TestOAuth2DeviceFlow(t *testing.T) { t.Errorf("Error Posting Form: %v", err) } defer resp.Body.Close() - responseBody, err = ioutil.ReadAll(resp.Body) + responseBody, err = io.ReadAll(resp.Body) if err != nil { t.Errorf("Could read verification response %v", err) } @@ -1634,7 +1689,7 @@ func TestOAuth2DeviceFlow(t *testing.T) { t.Errorf("Could not request device token: %v", err) } defer resp.Body.Close() - responseBody, err = ioutil.ReadAll(resp.Body) + responseBody, err = io.ReadAll(resp.Body) if err != nil { t.Errorf("Could read device token response %v", err) } diff --git a/server/templates.go b/server/templates.go index e46855b174..9be8019a48 100644 --- a/server/templates.go +++ b/server/templates.go @@ -8,7 +8,6 @@ import ( "net/http" "net/url" "path" - "path/filepath" "sort" "strings" @@ -109,7 +108,7 @@ func loadWebConfig(c webConfig) (http.Handler, http.Handler, *templates, error) if err != nil { return nil, nil, nil, fmt.Errorf("read static dir: %v", err) } - themeFiles, err := fs.Sub(c.webFS, filepath.Join("themes", c.theme)) + themeFiles, err := fs.Sub(c.webFS, path.Join("themes", c.theme)) if err != nil { return nil, nil, nil, fmt.Errorf("read themes dir: %v", err) } @@ -133,7 +132,7 @@ func loadTemplates(c webConfig, templatesDir string) (*templates, error) { if file.IsDir() { continue } - filenames = append(filenames, filepath.Join(templatesDir, file.Name())) + filenames = append(filenames, path.Join(templatesDir, file.Name())) } if len(filenames) == 0 { return nil, fmt.Errorf("no files in template dir %q", templatesDir) diff --git a/storage/conformance/gen_jwks.go b/storage/conformance/gen_jwks.go index 8fb12789ce..0447e32815 100644 --- a/storage/conformance/gen_jwks.go +++ b/storage/conformance/gen_jwks.go @@ -12,8 +12,8 @@ import ( "encoding/json" "go/format" "io" - "io/ioutil" "log" + "os" "text/template" jose "gopkg.in/square/go-jose.v2" @@ -104,7 +104,7 @@ func main() { if err != nil { log.Fatalf("gofmt failed: %v", err) } - if err := ioutil.WriteFile("jwks.go", out, 0644); err != nil { + if err := os.WriteFile("jwks.go", out, 0644); err != nil { log.Fatal(err) } } diff --git a/storage/ent/db/authcode.go b/storage/ent/db/authcode.go index 29b5e4f5b8..9af0ee3b23 100644 --- a/storage/ent/db/authcode.go +++ b/storage/ent/db/authcode.go @@ -90,7 +90,6 @@ func (ac *AuthCode) assignValues(columns []string, values []interface{}) error { ac.ClientID = value.String } case authcode.FieldScopes: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field scopes", values[i]) } else if value != nil && len(*value) > 0 { @@ -135,7 +134,6 @@ func (ac *AuthCode) assignValues(columns []string, values []interface{}) error { ac.ClaimsEmailVerified = value.Bool } case authcode.FieldClaimsGroups: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field claims_groups", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/authcode_create.go b/storage/ent/db/authcode_create.go index a15e682dd2..eaf2f8ac5e 100644 --- a/storage/ent/db/authcode_create.go +++ b/storage/ent/db/authcode_create.go @@ -167,11 +167,17 @@ func (acc *AuthCodeCreate) Save(ctx context.Context) (*AuthCode, error) { return nil, err } acc.mutation = mutation - node, err = acc.sqlSave(ctx) + if node, err = acc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(acc.hooks) - 1; i >= 0; i-- { + if acc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = acc.hooks[i](mut) } if _, err := mut.Mutate(ctx, acc.mutation); err != nil { @@ -190,6 +196,19 @@ func (acc *AuthCodeCreate) SaveX(ctx context.Context) *AuthCode { return v } +// Exec executes the query. +func (acc *AuthCodeCreate) Exec(ctx context.Context) error { + _, err := acc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (acc *AuthCodeCreate) ExecX(ctx context.Context) { + if err := acc.Exec(ctx); err != nil { + panic(err) + } +} + // defaults sets the default values of the builder before save. func (acc *AuthCodeCreate) defaults() { if _, ok := acc.mutation.ClaimsPreferredUsername(); !ok { @@ -209,79 +228,79 @@ func (acc *AuthCodeCreate) defaults() { // check runs all checks and user-defined validators on the builder. func (acc *AuthCodeCreate) check() error { if _, ok := acc.mutation.ClientID(); !ok { - return &ValidationError{Name: "client_id", err: errors.New("db: missing required field \"client_id\"")} + return &ValidationError{Name: "client_id", err: errors.New(`db: missing required field "client_id"`)} } if v, ok := acc.mutation.ClientID(); ok { if err := authcode.ClientIDValidator(v); err != nil { - return &ValidationError{Name: "client_id", err: fmt.Errorf("db: validator failed for field \"client_id\": %w", err)} + return &ValidationError{Name: "client_id", err: fmt.Errorf(`db: validator failed for field "client_id": %w`, err)} } } if _, ok := acc.mutation.Nonce(); !ok { - return &ValidationError{Name: "nonce", err: errors.New("db: missing required field \"nonce\"")} + return &ValidationError{Name: "nonce", err: errors.New(`db: missing required field "nonce"`)} } if v, ok := acc.mutation.Nonce(); ok { if err := authcode.NonceValidator(v); err != nil { - return &ValidationError{Name: "nonce", err: fmt.Errorf("db: validator failed for field \"nonce\": %w", err)} + return &ValidationError{Name: "nonce", err: fmt.Errorf(`db: validator failed for field "nonce": %w`, err)} } } if _, ok := acc.mutation.RedirectURI(); !ok { - return &ValidationError{Name: "redirect_uri", err: errors.New("db: missing required field \"redirect_uri\"")} + return &ValidationError{Name: "redirect_uri", err: errors.New(`db: missing required field "redirect_uri"`)} } if v, ok := acc.mutation.RedirectURI(); ok { if err := authcode.RedirectURIValidator(v); err != nil { - return &ValidationError{Name: "redirect_uri", err: fmt.Errorf("db: validator failed for field \"redirect_uri\": %w", err)} + return &ValidationError{Name: "redirect_uri", err: fmt.Errorf(`db: validator failed for field "redirect_uri": %w`, err)} } } if _, ok := acc.mutation.ClaimsUserID(); !ok { - return &ValidationError{Name: "claims_user_id", err: errors.New("db: missing required field \"claims_user_id\"")} + return &ValidationError{Name: "claims_user_id", err: errors.New(`db: missing required field "claims_user_id"`)} } if v, ok := acc.mutation.ClaimsUserID(); ok { if err := authcode.ClaimsUserIDValidator(v); err != nil { - return &ValidationError{Name: "claims_user_id", err: fmt.Errorf("db: validator failed for field \"claims_user_id\": %w", err)} + return &ValidationError{Name: "claims_user_id", err: fmt.Errorf(`db: validator failed for field "claims_user_id": %w`, err)} } } if _, ok := acc.mutation.ClaimsUsername(); !ok { - return &ValidationError{Name: "claims_username", err: errors.New("db: missing required field \"claims_username\"")} + return &ValidationError{Name: "claims_username", err: errors.New(`db: missing required field "claims_username"`)} } if v, ok := acc.mutation.ClaimsUsername(); ok { if err := authcode.ClaimsUsernameValidator(v); err != nil { - return &ValidationError{Name: "claims_username", err: fmt.Errorf("db: validator failed for field \"claims_username\": %w", err)} + return &ValidationError{Name: "claims_username", err: fmt.Errorf(`db: validator failed for field "claims_username": %w`, err)} } } if _, ok := acc.mutation.ClaimsEmail(); !ok { - return &ValidationError{Name: "claims_email", err: errors.New("db: missing required field \"claims_email\"")} + return &ValidationError{Name: "claims_email", err: errors.New(`db: missing required field "claims_email"`)} } if v, ok := acc.mutation.ClaimsEmail(); ok { if err := authcode.ClaimsEmailValidator(v); err != nil { - return &ValidationError{Name: "claims_email", err: fmt.Errorf("db: validator failed for field \"claims_email\": %w", err)} + return &ValidationError{Name: "claims_email", err: fmt.Errorf(`db: validator failed for field "claims_email": %w`, err)} } } if _, ok := acc.mutation.ClaimsEmailVerified(); !ok { - return &ValidationError{Name: "claims_email_verified", err: errors.New("db: missing required field \"claims_email_verified\"")} + return &ValidationError{Name: "claims_email_verified", err: errors.New(`db: missing required field "claims_email_verified"`)} } if _, ok := acc.mutation.ClaimsPreferredUsername(); !ok { - return &ValidationError{Name: "claims_preferred_username", err: errors.New("db: missing required field \"claims_preferred_username\"")} + return &ValidationError{Name: "claims_preferred_username", err: errors.New(`db: missing required field "claims_preferred_username"`)} } if _, ok := acc.mutation.ConnectorID(); !ok { - return &ValidationError{Name: "connector_id", err: errors.New("db: missing required field \"connector_id\"")} + return &ValidationError{Name: "connector_id", err: errors.New(`db: missing required field "connector_id"`)} } if v, ok := acc.mutation.ConnectorID(); ok { if err := authcode.ConnectorIDValidator(v); err != nil { - return &ValidationError{Name: "connector_id", err: fmt.Errorf("db: validator failed for field \"connector_id\": %w", err)} + return &ValidationError{Name: "connector_id", err: fmt.Errorf(`db: validator failed for field "connector_id": %w`, err)} } } if _, ok := acc.mutation.Expiry(); !ok { - return &ValidationError{Name: "expiry", err: errors.New("db: missing required field \"expiry\"")} + return &ValidationError{Name: "expiry", err: errors.New(`db: missing required field "expiry"`)} } if _, ok := acc.mutation.CodeChallenge(); !ok { - return &ValidationError{Name: "code_challenge", err: errors.New("db: missing required field \"code_challenge\"")} + return &ValidationError{Name: "code_challenge", err: errors.New(`db: missing required field "code_challenge"`)} } if _, ok := acc.mutation.CodeChallengeMethod(); !ok { - return &ValidationError{Name: "code_challenge_method", err: errors.New("db: missing required field \"code_challenge_method\"")} + return &ValidationError{Name: "code_challenge_method", err: errors.New(`db: missing required field "code_challenge_method"`)} } if v, ok := acc.mutation.ID(); ok { if err := authcode.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -290,8 +309,8 @@ func (acc *AuthCodeCreate) check() error { func (acc *AuthCodeCreate) sqlSave(ctx context.Context) (*AuthCode, error) { _node, _spec := acc.createSpec() if err := sqlgraph.CreateNode(ctx, acc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -465,17 +484,19 @@ func (accb *AuthCodeCreateBulk) Save(ctx context.Context) ([]*AuthCode, error) { if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, accb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, accb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, accb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -500,3 +521,16 @@ func (accb *AuthCodeCreateBulk) SaveX(ctx context.Context) []*AuthCode { } return v } + +// Exec executes the query. +func (accb *AuthCodeCreateBulk) Exec(ctx context.Context) error { + _, err := accb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (accb *AuthCodeCreateBulk) ExecX(ctx context.Context) { + if err := accb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/authcode_delete.go b/storage/ent/db/authcode_delete.go index c76007b3aa..9b657236ab 100644 --- a/storage/ent/db/authcode_delete.go +++ b/storage/ent/db/authcode_delete.go @@ -20,9 +20,9 @@ type AuthCodeDelete struct { mutation *AuthCodeMutation } -// Where adds a new predicate to the AuthCodeDelete builder. +// Where appends a list predicates to the AuthCodeDelete builder. func (acd *AuthCodeDelete) Where(ps ...predicate.AuthCode) *AuthCodeDelete { - acd.mutation.predicates = append(acd.mutation.predicates, ps...) + acd.mutation.Where(ps...) return acd } @@ -46,6 +46,9 @@ func (acd *AuthCodeDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(acd.hooks) - 1; i >= 0; i-- { + if acd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = acd.hooks[i](mut) } if _, err := mut.Mutate(ctx, acd.mutation); err != nil { diff --git a/storage/ent/db/authcode_query.go b/storage/ent/db/authcode_query.go index 96b6a48504..89116dd99c 100644 --- a/storage/ent/db/authcode_query.go +++ b/storage/ent/db/authcode_query.go @@ -287,8 +287,8 @@ func (acq *AuthCodeQuery) GroupBy(field string, fields ...string) *AuthCodeGroup // Select(authcode.FieldClientID). // Scan(ctx, &v) // -func (acq *AuthCodeQuery) Select(field string, fields ...string) *AuthCodeSelect { - acq.fields = append([]string{field}, fields...) +func (acq *AuthCodeQuery) Select(fields ...string) *AuthCodeSelect { + acq.fields = append(acq.fields, fields...) return &AuthCodeSelect{AuthCodeQuery: acq} } @@ -398,10 +398,14 @@ func (acq *AuthCodeQuery) querySpec() *sqlgraph.QuerySpec { func (acq *AuthCodeQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(acq.driver.Dialect()) t1 := builder.Table(authcode.Table) - selector := builder.Select(t1.Columns(authcode.Columns...)...).From(t1) + columns := acq.fields + if len(columns) == 0 { + columns = authcode.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if acq.sql != nil { selector = acq.sql - selector.Select(selector.Columns(authcode.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range acq.predicates { p(selector) @@ -669,13 +673,24 @@ func (acgb *AuthCodeGroupBy) sqlScan(ctx context.Context, v interface{}) error { } func (acgb *AuthCodeGroupBy) sqlQuery() *sql.Selector { - selector := acgb.sql - columns := make([]string, 0, len(acgb.fields)+len(acgb.fns)) - columns = append(columns, acgb.fields...) + selector := acgb.sql.Select() + aggregation := make([]string, 0, len(acgb.fns)) for _, fn := range acgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(acgb.fields)+len(acgb.fns)) + for _, f := range acgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(acgb.fields...) + return selector.GroupBy(selector.Columns(acgb.fields...)...) } // AuthCodeSelect is the builder for selecting fields of AuthCode entities. @@ -891,16 +906,10 @@ func (acs *AuthCodeSelect) BoolX(ctx context.Context) bool { func (acs *AuthCodeSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := acs.sqlQuery().Query() + query, args := acs.sql.Query() if err := acs.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (acs *AuthCodeSelect) sqlQuery() sql.Querier { - selector := acs.sql - selector.Select(selector.Columns(acs.fields...)...) - return selector -} diff --git a/storage/ent/db/authcode_update.go b/storage/ent/db/authcode_update.go index 08374bd31d..f86d04c672 100644 --- a/storage/ent/db/authcode_update.go +++ b/storage/ent/db/authcode_update.go @@ -21,9 +21,9 @@ type AuthCodeUpdate struct { mutation *AuthCodeMutation } -// Where adds a new predicate for the AuthCodeUpdate builder. +// Where appends a list predicates to the AuthCodeUpdate builder. func (acu *AuthCodeUpdate) Where(ps ...predicate.AuthCode) *AuthCodeUpdate { - acu.mutation.predicates = append(acu.mutation.predicates, ps...) + acu.mutation.Where(ps...) return acu } @@ -190,6 +190,9 @@ func (acu *AuthCodeUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(acu.hooks) - 1; i >= 0; i-- { + if acu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = acu.hooks[i](mut) } if _, err := mut.Mutate(ctx, acu.mutation); err != nil { @@ -405,8 +408,8 @@ func (acu *AuthCodeUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, acu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{authcode.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -591,6 +594,9 @@ func (acuo *AuthCodeUpdateOne) Save(ctx context.Context) (*AuthCode, error) { return node, err }) for i := len(acuo.hooks) - 1; i >= 0; i-- { + if acuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = acuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, acuo.mutation); err != nil { @@ -826,8 +832,8 @@ func (acuo *AuthCodeUpdateOne) sqlSave(ctx context.Context) (_node *AuthCode, er if err = sqlgraph.UpdateNode(ctx, acuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{authcode.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/authrequest.go b/storage/ent/db/authrequest.go index ed64d9f679..ee3d0dd416 100644 --- a/storage/ent/db/authrequest.go +++ b/storage/ent/db/authrequest.go @@ -98,7 +98,6 @@ func (ar *AuthRequest) assignValues(columns []string, values []interface{}) erro ar.ClientID = value.String } case authrequest.FieldScopes: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field scopes", values[i]) } else if value != nil && len(*value) > 0 { @@ -107,7 +106,6 @@ func (ar *AuthRequest) assignValues(columns []string, values []interface{}) erro } } case authrequest.FieldResponseTypes: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field response_types", values[i]) } else if value != nil && len(*value) > 0 { @@ -170,7 +168,6 @@ func (ar *AuthRequest) assignValues(columns []string, values []interface{}) erro ar.ClaimsEmailVerified = value.Bool } case authrequest.FieldClaimsGroups: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field claims_groups", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/authrequest_create.go b/storage/ent/db/authrequest_create.go index e7a2c8cebe..3e96b28480 100644 --- a/storage/ent/db/authrequest_create.go +++ b/storage/ent/db/authrequest_create.go @@ -191,11 +191,17 @@ func (arc *AuthRequestCreate) Save(ctx context.Context) (*AuthRequest, error) { return nil, err } arc.mutation = mutation - node, err = arc.sqlSave(ctx) + if node, err = arc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(arc.hooks) - 1; i >= 0; i-- { + if arc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = arc.hooks[i](mut) } if _, err := mut.Mutate(ctx, arc.mutation); err != nil { @@ -214,6 +220,19 @@ func (arc *AuthRequestCreate) SaveX(ctx context.Context) *AuthRequest { return v } +// Exec executes the query. +func (arc *AuthRequestCreate) Exec(ctx context.Context) error { + _, err := arc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (arc *AuthRequestCreate) ExecX(ctx context.Context) { + if err := arc.Exec(ctx); err != nil { + panic(err) + } +} + // defaults sets the default values of the builder before save. func (arc *AuthRequestCreate) defaults() { if _, ok := arc.mutation.ClaimsPreferredUsername(); !ok { @@ -233,53 +252,53 @@ func (arc *AuthRequestCreate) defaults() { // check runs all checks and user-defined validators on the builder. func (arc *AuthRequestCreate) check() error { if _, ok := arc.mutation.ClientID(); !ok { - return &ValidationError{Name: "client_id", err: errors.New("db: missing required field \"client_id\"")} + return &ValidationError{Name: "client_id", err: errors.New(`db: missing required field "client_id"`)} } if _, ok := arc.mutation.RedirectURI(); !ok { - return &ValidationError{Name: "redirect_uri", err: errors.New("db: missing required field \"redirect_uri\"")} + return &ValidationError{Name: "redirect_uri", err: errors.New(`db: missing required field "redirect_uri"`)} } if _, ok := arc.mutation.Nonce(); !ok { - return &ValidationError{Name: "nonce", err: errors.New("db: missing required field \"nonce\"")} + return &ValidationError{Name: "nonce", err: errors.New(`db: missing required field "nonce"`)} } if _, ok := arc.mutation.State(); !ok { - return &ValidationError{Name: "state", err: errors.New("db: missing required field \"state\"")} + return &ValidationError{Name: "state", err: errors.New(`db: missing required field "state"`)} } if _, ok := arc.mutation.ForceApprovalPrompt(); !ok { - return &ValidationError{Name: "force_approval_prompt", err: errors.New("db: missing required field \"force_approval_prompt\"")} + return &ValidationError{Name: "force_approval_prompt", err: errors.New(`db: missing required field "force_approval_prompt"`)} } if _, ok := arc.mutation.LoggedIn(); !ok { - return &ValidationError{Name: "logged_in", err: errors.New("db: missing required field \"logged_in\"")} + return &ValidationError{Name: "logged_in", err: errors.New(`db: missing required field "logged_in"`)} } if _, ok := arc.mutation.ClaimsUserID(); !ok { - return &ValidationError{Name: "claims_user_id", err: errors.New("db: missing required field \"claims_user_id\"")} + return &ValidationError{Name: "claims_user_id", err: errors.New(`db: missing required field "claims_user_id"`)} } if _, ok := arc.mutation.ClaimsUsername(); !ok { - return &ValidationError{Name: "claims_username", err: errors.New("db: missing required field \"claims_username\"")} + return &ValidationError{Name: "claims_username", err: errors.New(`db: missing required field "claims_username"`)} } if _, ok := arc.mutation.ClaimsEmail(); !ok { - return &ValidationError{Name: "claims_email", err: errors.New("db: missing required field \"claims_email\"")} + return &ValidationError{Name: "claims_email", err: errors.New(`db: missing required field "claims_email"`)} } if _, ok := arc.mutation.ClaimsEmailVerified(); !ok { - return &ValidationError{Name: "claims_email_verified", err: errors.New("db: missing required field \"claims_email_verified\"")} + return &ValidationError{Name: "claims_email_verified", err: errors.New(`db: missing required field "claims_email_verified"`)} } if _, ok := arc.mutation.ClaimsPreferredUsername(); !ok { - return &ValidationError{Name: "claims_preferred_username", err: errors.New("db: missing required field \"claims_preferred_username\"")} + return &ValidationError{Name: "claims_preferred_username", err: errors.New(`db: missing required field "claims_preferred_username"`)} } if _, ok := arc.mutation.ConnectorID(); !ok { - return &ValidationError{Name: "connector_id", err: errors.New("db: missing required field \"connector_id\"")} + return &ValidationError{Name: "connector_id", err: errors.New(`db: missing required field "connector_id"`)} } if _, ok := arc.mutation.Expiry(); !ok { - return &ValidationError{Name: "expiry", err: errors.New("db: missing required field \"expiry\"")} + return &ValidationError{Name: "expiry", err: errors.New(`db: missing required field "expiry"`)} } if _, ok := arc.mutation.CodeChallenge(); !ok { - return &ValidationError{Name: "code_challenge", err: errors.New("db: missing required field \"code_challenge\"")} + return &ValidationError{Name: "code_challenge", err: errors.New(`db: missing required field "code_challenge"`)} } if _, ok := arc.mutation.CodeChallengeMethod(); !ok { - return &ValidationError{Name: "code_challenge_method", err: errors.New("db: missing required field \"code_challenge_method\"")} + return &ValidationError{Name: "code_challenge_method", err: errors.New(`db: missing required field "code_challenge_method"`)} } if v, ok := arc.mutation.ID(); ok { if err := authrequest.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -288,8 +307,8 @@ func (arc *AuthRequestCreate) check() error { func (arc *AuthRequestCreate) sqlSave(ctx context.Context) (*AuthRequest, error) { _node, _spec := arc.createSpec() if err := sqlgraph.CreateNode(ctx, arc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -495,17 +514,19 @@ func (arcb *AuthRequestCreateBulk) Save(ctx context.Context) ([]*AuthRequest, er if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, arcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, arcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, arcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -530,3 +551,16 @@ func (arcb *AuthRequestCreateBulk) SaveX(ctx context.Context) []*AuthRequest { } return v } + +// Exec executes the query. +func (arcb *AuthRequestCreateBulk) Exec(ctx context.Context) error { + _, err := arcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (arcb *AuthRequestCreateBulk) ExecX(ctx context.Context) { + if err := arcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/authrequest_delete.go b/storage/ent/db/authrequest_delete.go index e0d0ba6698..1e6ff754ad 100644 --- a/storage/ent/db/authrequest_delete.go +++ b/storage/ent/db/authrequest_delete.go @@ -20,9 +20,9 @@ type AuthRequestDelete struct { mutation *AuthRequestMutation } -// Where adds a new predicate to the AuthRequestDelete builder. +// Where appends a list predicates to the AuthRequestDelete builder. func (ard *AuthRequestDelete) Where(ps ...predicate.AuthRequest) *AuthRequestDelete { - ard.mutation.predicates = append(ard.mutation.predicates, ps...) + ard.mutation.Where(ps...) return ard } @@ -46,6 +46,9 @@ func (ard *AuthRequestDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(ard.hooks) - 1; i >= 0; i-- { + if ard.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = ard.hooks[i](mut) } if _, err := mut.Mutate(ctx, ard.mutation); err != nil { diff --git a/storage/ent/db/authrequest_query.go b/storage/ent/db/authrequest_query.go index b55861cf0c..e71f85461b 100644 --- a/storage/ent/db/authrequest_query.go +++ b/storage/ent/db/authrequest_query.go @@ -287,8 +287,8 @@ func (arq *AuthRequestQuery) GroupBy(field string, fields ...string) *AuthReques // Select(authrequest.FieldClientID). // Scan(ctx, &v) // -func (arq *AuthRequestQuery) Select(field string, fields ...string) *AuthRequestSelect { - arq.fields = append([]string{field}, fields...) +func (arq *AuthRequestQuery) Select(fields ...string) *AuthRequestSelect { + arq.fields = append(arq.fields, fields...) return &AuthRequestSelect{AuthRequestQuery: arq} } @@ -398,10 +398,14 @@ func (arq *AuthRequestQuery) querySpec() *sqlgraph.QuerySpec { func (arq *AuthRequestQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(arq.driver.Dialect()) t1 := builder.Table(authrequest.Table) - selector := builder.Select(t1.Columns(authrequest.Columns...)...).From(t1) + columns := arq.fields + if len(columns) == 0 { + columns = authrequest.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if arq.sql != nil { selector = arq.sql - selector.Select(selector.Columns(authrequest.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range arq.predicates { p(selector) @@ -669,13 +673,24 @@ func (argb *AuthRequestGroupBy) sqlScan(ctx context.Context, v interface{}) erro } func (argb *AuthRequestGroupBy) sqlQuery() *sql.Selector { - selector := argb.sql - columns := make([]string, 0, len(argb.fields)+len(argb.fns)) - columns = append(columns, argb.fields...) + selector := argb.sql.Select() + aggregation := make([]string, 0, len(argb.fns)) for _, fn := range argb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(argb.fields)+len(argb.fns)) + for _, f := range argb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(argb.fields...) + return selector.GroupBy(selector.Columns(argb.fields...)...) } // AuthRequestSelect is the builder for selecting fields of AuthRequest entities. @@ -891,16 +906,10 @@ func (ars *AuthRequestSelect) BoolX(ctx context.Context) bool { func (ars *AuthRequestSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := ars.sqlQuery().Query() + query, args := ars.sql.Query() if err := ars.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (ars *AuthRequestSelect) sqlQuery() sql.Querier { - selector := ars.sql - selector.Select(selector.Columns(ars.fields...)...) - return selector -} diff --git a/storage/ent/db/authrequest_update.go b/storage/ent/db/authrequest_update.go index 2d3f859443..2306d2e60c 100644 --- a/storage/ent/db/authrequest_update.go +++ b/storage/ent/db/authrequest_update.go @@ -21,9 +21,9 @@ type AuthRequestUpdate struct { mutation *AuthRequestMutation } -// Where adds a new predicate for the AuthRequestUpdate builder. +// Where appends a list predicates to the AuthRequestUpdate builder. func (aru *AuthRequestUpdate) Where(ps ...predicate.AuthRequest) *AuthRequestUpdate { - aru.mutation.predicates = append(aru.mutation.predicates, ps...) + aru.mutation.Where(ps...) return aru } @@ -214,6 +214,9 @@ func (aru *AuthRequestUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(aru.hooks) - 1; i >= 0; i-- { + if aru.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = aru.hooks[i](mut) } if _, err := mut.Mutate(ctx, aru.mutation); err != nil { @@ -423,8 +426,8 @@ func (aru *AuthRequestUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, aru.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{authrequest.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -633,6 +636,9 @@ func (aruo *AuthRequestUpdateOne) Save(ctx context.Context) (*AuthRequest, error return node, err }) for i := len(aruo.hooks) - 1; i >= 0; i-- { + if aruo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = aruo.hooks[i](mut) } if _, err := mut.Mutate(ctx, aruo.mutation); err != nil { @@ -862,8 +868,8 @@ func (aruo *AuthRequestUpdateOne) sqlSave(ctx context.Context) (_node *AuthReque if err = sqlgraph.UpdateNode(ctx, aruo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{authrequest.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/connector_create.go b/storage/ent/db/connector_create.go index eebe4d050d..387231b98e 100644 --- a/storage/ent/db/connector_create.go +++ b/storage/ent/db/connector_create.go @@ -75,11 +75,17 @@ func (cc *ConnectorCreate) Save(ctx context.Context) (*Connector, error) { return nil, err } cc.mutation = mutation - node, err = cc.sqlSave(ctx) + if node, err = cc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(cc.hooks) - 1; i >= 0; i-- { + if cc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = cc.hooks[i](mut) } if _, err := mut.Mutate(ctx, cc.mutation); err != nil { @@ -98,33 +104,46 @@ func (cc *ConnectorCreate) SaveX(ctx context.Context) *Connector { return v } +// Exec executes the query. +func (cc *ConnectorCreate) Exec(ctx context.Context) error { + _, err := cc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cc *ConnectorCreate) ExecX(ctx context.Context) { + if err := cc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (cc *ConnectorCreate) check() error { if _, ok := cc.mutation.GetType(); !ok { - return &ValidationError{Name: "type", err: errors.New("db: missing required field \"type\"")} + return &ValidationError{Name: "type", err: errors.New(`db: missing required field "type"`)} } if v, ok := cc.mutation.GetType(); ok { if err := connector.TypeValidator(v); err != nil { - return &ValidationError{Name: "type", err: fmt.Errorf("db: validator failed for field \"type\": %w", err)} + return &ValidationError{Name: "type", err: fmt.Errorf(`db: validator failed for field "type": %w`, err)} } } if _, ok := cc.mutation.Name(); !ok { - return &ValidationError{Name: "name", err: errors.New("db: missing required field \"name\"")} + return &ValidationError{Name: "name", err: errors.New(`db: missing required field "name"`)} } if v, ok := cc.mutation.Name(); ok { if err := connector.NameValidator(v); err != nil { - return &ValidationError{Name: "name", err: fmt.Errorf("db: validator failed for field \"name\": %w", err)} + return &ValidationError{Name: "name", err: fmt.Errorf(`db: validator failed for field "name": %w`, err)} } } if _, ok := cc.mutation.ResourceVersion(); !ok { - return &ValidationError{Name: "resource_version", err: errors.New("db: missing required field \"resource_version\"")} + return &ValidationError{Name: "resource_version", err: errors.New(`db: missing required field "resource_version"`)} } if _, ok := cc.mutation.Config(); !ok { - return &ValidationError{Name: "config", err: errors.New("db: missing required field \"config\"")} + return &ValidationError{Name: "config", err: errors.New(`db: missing required field "config"`)} } if v, ok := cc.mutation.ID(); ok { if err := connector.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -133,8 +152,8 @@ func (cc *ConnectorCreate) check() error { func (cc *ConnectorCreate) sqlSave(ctx context.Context) (*Connector, error) { _node, _spec := cc.createSpec() if err := sqlgraph.CreateNode(ctx, cc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -219,17 +238,19 @@ func (ccb *ConnectorCreateBulk) Save(ctx context.Context) ([]*Connector, error) if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, ccb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, ccb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, ccb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -254,3 +275,16 @@ func (ccb *ConnectorCreateBulk) SaveX(ctx context.Context) []*Connector { } return v } + +// Exec executes the query. +func (ccb *ConnectorCreateBulk) Exec(ctx context.Context) error { + _, err := ccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ccb *ConnectorCreateBulk) ExecX(ctx context.Context) { + if err := ccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/connector_delete.go b/storage/ent/db/connector_delete.go index 1368fcc1dc..1cad771fb1 100644 --- a/storage/ent/db/connector_delete.go +++ b/storage/ent/db/connector_delete.go @@ -20,9 +20,9 @@ type ConnectorDelete struct { mutation *ConnectorMutation } -// Where adds a new predicate to the ConnectorDelete builder. +// Where appends a list predicates to the ConnectorDelete builder. func (cd *ConnectorDelete) Where(ps ...predicate.Connector) *ConnectorDelete { - cd.mutation.predicates = append(cd.mutation.predicates, ps...) + cd.mutation.Where(ps...) return cd } @@ -46,6 +46,9 @@ func (cd *ConnectorDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(cd.hooks) - 1; i >= 0; i-- { + if cd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = cd.hooks[i](mut) } if _, err := mut.Mutate(ctx, cd.mutation); err != nil { diff --git a/storage/ent/db/connector_query.go b/storage/ent/db/connector_query.go index 2b4c787221..9bcf368a11 100644 --- a/storage/ent/db/connector_query.go +++ b/storage/ent/db/connector_query.go @@ -287,8 +287,8 @@ func (cq *ConnectorQuery) GroupBy(field string, fields ...string) *ConnectorGrou // Select(connector.FieldType). // Scan(ctx, &v) // -func (cq *ConnectorQuery) Select(field string, fields ...string) *ConnectorSelect { - cq.fields = append([]string{field}, fields...) +func (cq *ConnectorQuery) Select(fields ...string) *ConnectorSelect { + cq.fields = append(cq.fields, fields...) return &ConnectorSelect{ConnectorQuery: cq} } @@ -398,10 +398,14 @@ func (cq *ConnectorQuery) querySpec() *sqlgraph.QuerySpec { func (cq *ConnectorQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(cq.driver.Dialect()) t1 := builder.Table(connector.Table) - selector := builder.Select(t1.Columns(connector.Columns...)...).From(t1) + columns := cq.fields + if len(columns) == 0 { + columns = connector.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if cq.sql != nil { selector = cq.sql - selector.Select(selector.Columns(connector.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range cq.predicates { p(selector) @@ -669,13 +673,24 @@ func (cgb *ConnectorGroupBy) sqlScan(ctx context.Context, v interface{}) error { } func (cgb *ConnectorGroupBy) sqlQuery() *sql.Selector { - selector := cgb.sql - columns := make([]string, 0, len(cgb.fields)+len(cgb.fns)) - columns = append(columns, cgb.fields...) + selector := cgb.sql.Select() + aggregation := make([]string, 0, len(cgb.fns)) for _, fn := range cgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(cgb.fields)+len(cgb.fns)) + for _, f := range cgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(cgb.fields...) + return selector.GroupBy(selector.Columns(cgb.fields...)...) } // ConnectorSelect is the builder for selecting fields of Connector entities. @@ -891,16 +906,10 @@ func (cs *ConnectorSelect) BoolX(ctx context.Context) bool { func (cs *ConnectorSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := cs.sqlQuery().Query() + query, args := cs.sql.Query() if err := cs.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (cs *ConnectorSelect) sqlQuery() sql.Querier { - selector := cs.sql - selector.Select(selector.Columns(cs.fields...)...) - return selector -} diff --git a/storage/ent/db/connector_update.go b/storage/ent/db/connector_update.go index 90c972e4f2..1bc9ffb58c 100644 --- a/storage/ent/db/connector_update.go +++ b/storage/ent/db/connector_update.go @@ -20,9 +20,9 @@ type ConnectorUpdate struct { mutation *ConnectorMutation } -// Where adds a new predicate for the ConnectorUpdate builder. +// Where appends a list predicates to the ConnectorUpdate builder. func (cu *ConnectorUpdate) Where(ps ...predicate.Connector) *ConnectorUpdate { - cu.mutation.predicates = append(cu.mutation.predicates, ps...) + cu.mutation.Where(ps...) return cu } @@ -81,6 +81,9 @@ func (cu *ConnectorUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(cu.hooks) - 1; i >= 0; i-- { + if cu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = cu.hooks[i](mut) } if _, err := mut.Mutate(ctx, cu.mutation); err != nil { @@ -176,8 +179,8 @@ func (cu *ConnectorUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{connector.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -254,6 +257,9 @@ func (cuo *ConnectorUpdateOne) Save(ctx context.Context) (*Connector, error) { return node, err }) for i := len(cuo.hooks) - 1; i >= 0; i-- { + if cuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = cuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, cuo.mutation); err != nil { @@ -369,8 +375,8 @@ func (cuo *ConnectorUpdateOne) sqlSave(ctx context.Context) (_node *Connector, e if err = sqlgraph.UpdateNode(ctx, cuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{connector.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/devicerequest.go b/storage/ent/db/devicerequest.go index d50a7c836d..24da4a46f5 100644 --- a/storage/ent/db/devicerequest.go +++ b/storage/ent/db/devicerequest.go @@ -90,7 +90,6 @@ func (dr *DeviceRequest) assignValues(columns []string, values []interface{}) er dr.ClientSecret = value.String } case devicerequest.FieldScopes: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field scopes", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/devicerequest_create.go b/storage/ent/db/devicerequest_create.go index 70599fede2..102d028e6b 100644 --- a/storage/ent/db/devicerequest_create.go +++ b/storage/ent/db/devicerequest_create.go @@ -82,11 +82,17 @@ func (drc *DeviceRequestCreate) Save(ctx context.Context) (*DeviceRequest, error return nil, err } drc.mutation = mutation - node, err = drc.sqlSave(ctx) + if node, err = drc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(drc.hooks) - 1; i >= 0; i-- { + if drc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = drc.hooks[i](mut) } if _, err := mut.Mutate(ctx, drc.mutation); err != nil { @@ -105,42 +111,55 @@ func (drc *DeviceRequestCreate) SaveX(ctx context.Context) *DeviceRequest { return v } +// Exec executes the query. +func (drc *DeviceRequestCreate) Exec(ctx context.Context) error { + _, err := drc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (drc *DeviceRequestCreate) ExecX(ctx context.Context) { + if err := drc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (drc *DeviceRequestCreate) check() error { if _, ok := drc.mutation.UserCode(); !ok { - return &ValidationError{Name: "user_code", err: errors.New("db: missing required field \"user_code\"")} + return &ValidationError{Name: "user_code", err: errors.New(`db: missing required field "user_code"`)} } if v, ok := drc.mutation.UserCode(); ok { if err := devicerequest.UserCodeValidator(v); err != nil { - return &ValidationError{Name: "user_code", err: fmt.Errorf("db: validator failed for field \"user_code\": %w", err)} + return &ValidationError{Name: "user_code", err: fmt.Errorf(`db: validator failed for field "user_code": %w`, err)} } } if _, ok := drc.mutation.DeviceCode(); !ok { - return &ValidationError{Name: "device_code", err: errors.New("db: missing required field \"device_code\"")} + return &ValidationError{Name: "device_code", err: errors.New(`db: missing required field "device_code"`)} } if v, ok := drc.mutation.DeviceCode(); ok { if err := devicerequest.DeviceCodeValidator(v); err != nil { - return &ValidationError{Name: "device_code", err: fmt.Errorf("db: validator failed for field \"device_code\": %w", err)} + return &ValidationError{Name: "device_code", err: fmt.Errorf(`db: validator failed for field "device_code": %w`, err)} } } if _, ok := drc.mutation.ClientID(); !ok { - return &ValidationError{Name: "client_id", err: errors.New("db: missing required field \"client_id\"")} + return &ValidationError{Name: "client_id", err: errors.New(`db: missing required field "client_id"`)} } if v, ok := drc.mutation.ClientID(); ok { if err := devicerequest.ClientIDValidator(v); err != nil { - return &ValidationError{Name: "client_id", err: fmt.Errorf("db: validator failed for field \"client_id\": %w", err)} + return &ValidationError{Name: "client_id", err: fmt.Errorf(`db: validator failed for field "client_id": %w`, err)} } } if _, ok := drc.mutation.ClientSecret(); !ok { - return &ValidationError{Name: "client_secret", err: errors.New("db: missing required field \"client_secret\"")} + return &ValidationError{Name: "client_secret", err: errors.New(`db: missing required field "client_secret"`)} } if v, ok := drc.mutation.ClientSecret(); ok { if err := devicerequest.ClientSecretValidator(v); err != nil { - return &ValidationError{Name: "client_secret", err: fmt.Errorf("db: validator failed for field \"client_secret\": %w", err)} + return &ValidationError{Name: "client_secret", err: fmt.Errorf(`db: validator failed for field "client_secret": %w`, err)} } } if _, ok := drc.mutation.Expiry(); !ok { - return &ValidationError{Name: "expiry", err: errors.New("db: missing required field \"expiry\"")} + return &ValidationError{Name: "expiry", err: errors.New(`db: missing required field "expiry"`)} } return nil } @@ -148,8 +167,8 @@ func (drc *DeviceRequestCreate) check() error { func (drc *DeviceRequestCreate) sqlSave(ctx context.Context) (*DeviceRequest, error) { _node, _spec := drc.createSpec() if err := sqlgraph.CreateNode(ctx, drc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -248,19 +267,23 @@ func (drcb *DeviceRequestCreateBulk) Save(ctx context.Context) ([]*DeviceRequest if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, drcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, drcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, drcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } - id := specs[i].ID.Value.(int64) - nodes[i].ID = int(id) + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -285,3 +308,16 @@ func (drcb *DeviceRequestCreateBulk) SaveX(ctx context.Context) []*DeviceRequest } return v } + +// Exec executes the query. +func (drcb *DeviceRequestCreateBulk) Exec(ctx context.Context) error { + _, err := drcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (drcb *DeviceRequestCreateBulk) ExecX(ctx context.Context) { + if err := drcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/devicerequest_delete.go b/storage/ent/db/devicerequest_delete.go index 34c0b89044..1a64262228 100644 --- a/storage/ent/db/devicerequest_delete.go +++ b/storage/ent/db/devicerequest_delete.go @@ -20,9 +20,9 @@ type DeviceRequestDelete struct { mutation *DeviceRequestMutation } -// Where adds a new predicate to the DeviceRequestDelete builder. +// Where appends a list predicates to the DeviceRequestDelete builder. func (drd *DeviceRequestDelete) Where(ps ...predicate.DeviceRequest) *DeviceRequestDelete { - drd.mutation.predicates = append(drd.mutation.predicates, ps...) + drd.mutation.Where(ps...) return drd } @@ -46,6 +46,9 @@ func (drd *DeviceRequestDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(drd.hooks) - 1; i >= 0; i-- { + if drd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = drd.hooks[i](mut) } if _, err := mut.Mutate(ctx, drd.mutation); err != nil { diff --git a/storage/ent/db/devicerequest_query.go b/storage/ent/db/devicerequest_query.go index 08c76871bb..350b7ae6f1 100644 --- a/storage/ent/db/devicerequest_query.go +++ b/storage/ent/db/devicerequest_query.go @@ -287,8 +287,8 @@ func (drq *DeviceRequestQuery) GroupBy(field string, fields ...string) *DeviceRe // Select(devicerequest.FieldUserCode). // Scan(ctx, &v) // -func (drq *DeviceRequestQuery) Select(field string, fields ...string) *DeviceRequestSelect { - drq.fields = append([]string{field}, fields...) +func (drq *DeviceRequestQuery) Select(fields ...string) *DeviceRequestSelect { + drq.fields = append(drq.fields, fields...) return &DeviceRequestSelect{DeviceRequestQuery: drq} } @@ -398,10 +398,14 @@ func (drq *DeviceRequestQuery) querySpec() *sqlgraph.QuerySpec { func (drq *DeviceRequestQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(drq.driver.Dialect()) t1 := builder.Table(devicerequest.Table) - selector := builder.Select(t1.Columns(devicerequest.Columns...)...).From(t1) + columns := drq.fields + if len(columns) == 0 { + columns = devicerequest.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if drq.sql != nil { selector = drq.sql - selector.Select(selector.Columns(devicerequest.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range drq.predicates { p(selector) @@ -669,13 +673,24 @@ func (drgb *DeviceRequestGroupBy) sqlScan(ctx context.Context, v interface{}) er } func (drgb *DeviceRequestGroupBy) sqlQuery() *sql.Selector { - selector := drgb.sql - columns := make([]string, 0, len(drgb.fields)+len(drgb.fns)) - columns = append(columns, drgb.fields...) + selector := drgb.sql.Select() + aggregation := make([]string, 0, len(drgb.fns)) for _, fn := range drgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(drgb.fields)+len(drgb.fns)) + for _, f := range drgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(drgb.fields...) + return selector.GroupBy(selector.Columns(drgb.fields...)...) } // DeviceRequestSelect is the builder for selecting fields of DeviceRequest entities. @@ -891,16 +906,10 @@ func (drs *DeviceRequestSelect) BoolX(ctx context.Context) bool { func (drs *DeviceRequestSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := drs.sqlQuery().Query() + query, args := drs.sql.Query() if err := drs.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (drs *DeviceRequestSelect) sqlQuery() sql.Querier { - selector := drs.sql - selector.Select(selector.Columns(drs.fields...)...) - return selector -} diff --git a/storage/ent/db/devicerequest_update.go b/storage/ent/db/devicerequest_update.go index d71ca0edc0..21c2f3001a 100644 --- a/storage/ent/db/devicerequest_update.go +++ b/storage/ent/db/devicerequest_update.go @@ -21,9 +21,9 @@ type DeviceRequestUpdate struct { mutation *DeviceRequestMutation } -// Where adds a new predicate for the DeviceRequestUpdate builder. +// Where appends a list predicates to the DeviceRequestUpdate builder. func (dru *DeviceRequestUpdate) Where(ps ...predicate.DeviceRequest) *DeviceRequestUpdate { - dru.mutation.predicates = append(dru.mutation.predicates, ps...) + dru.mutation.Where(ps...) return dru } @@ -100,6 +100,9 @@ func (dru *DeviceRequestUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(dru.hooks) - 1; i >= 0; i-- { + if dru.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = dru.hooks[i](mut) } if _, err := mut.Mutate(ctx, dru.mutation); err != nil { @@ -225,8 +228,8 @@ func (dru *DeviceRequestUpdate) sqlSave(ctx context.Context) (n int, err error) if n, err = sqlgraph.UpdateNodes(ctx, dru.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{devicerequest.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -321,6 +324,9 @@ func (druo *DeviceRequestUpdateOne) Save(ctx context.Context) (*DeviceRequest, e return node, err }) for i := len(druo.hooks) - 1; i >= 0; i-- { + if druo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = druo.hooks[i](mut) } if _, err := mut.Mutate(ctx, druo.mutation); err != nil { @@ -466,8 +472,8 @@ func (druo *DeviceRequestUpdateOne) sqlSave(ctx context.Context) (_node *DeviceR if err = sqlgraph.UpdateNode(ctx, druo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{devicerequest.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/devicetoken_create.go b/storage/ent/db/devicetoken_create.go index 50ed1aad62..db73ad4d1c 100644 --- a/storage/ent/db/devicetoken_create.go +++ b/storage/ent/db/devicetoken_create.go @@ -82,11 +82,17 @@ func (dtc *DeviceTokenCreate) Save(ctx context.Context) (*DeviceToken, error) { return nil, err } dtc.mutation = mutation - node, err = dtc.sqlSave(ctx) + if node, err = dtc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(dtc.hooks) - 1; i >= 0; i-- { + if dtc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = dtc.hooks[i](mut) } if _, err := mut.Mutate(ctx, dtc.mutation); err != nil { @@ -105,32 +111,45 @@ func (dtc *DeviceTokenCreate) SaveX(ctx context.Context) *DeviceToken { return v } +// Exec executes the query. +func (dtc *DeviceTokenCreate) Exec(ctx context.Context) error { + _, err := dtc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (dtc *DeviceTokenCreate) ExecX(ctx context.Context) { + if err := dtc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (dtc *DeviceTokenCreate) check() error { if _, ok := dtc.mutation.DeviceCode(); !ok { - return &ValidationError{Name: "device_code", err: errors.New("db: missing required field \"device_code\"")} + return &ValidationError{Name: "device_code", err: errors.New(`db: missing required field "device_code"`)} } if v, ok := dtc.mutation.DeviceCode(); ok { if err := devicetoken.DeviceCodeValidator(v); err != nil { - return &ValidationError{Name: "device_code", err: fmt.Errorf("db: validator failed for field \"device_code\": %w", err)} + return &ValidationError{Name: "device_code", err: fmt.Errorf(`db: validator failed for field "device_code": %w`, err)} } } if _, ok := dtc.mutation.Status(); !ok { - return &ValidationError{Name: "status", err: errors.New("db: missing required field \"status\"")} + return &ValidationError{Name: "status", err: errors.New(`db: missing required field "status"`)} } if v, ok := dtc.mutation.Status(); ok { if err := devicetoken.StatusValidator(v); err != nil { - return &ValidationError{Name: "status", err: fmt.Errorf("db: validator failed for field \"status\": %w", err)} + return &ValidationError{Name: "status", err: fmt.Errorf(`db: validator failed for field "status": %w`, err)} } } if _, ok := dtc.mutation.Expiry(); !ok { - return &ValidationError{Name: "expiry", err: errors.New("db: missing required field \"expiry\"")} + return &ValidationError{Name: "expiry", err: errors.New(`db: missing required field "expiry"`)} } if _, ok := dtc.mutation.LastRequest(); !ok { - return &ValidationError{Name: "last_request", err: errors.New("db: missing required field \"last_request\"")} + return &ValidationError{Name: "last_request", err: errors.New(`db: missing required field "last_request"`)} } if _, ok := dtc.mutation.PollInterval(); !ok { - return &ValidationError{Name: "poll_interval", err: errors.New("db: missing required field \"poll_interval\"")} + return &ValidationError{Name: "poll_interval", err: errors.New(`db: missing required field "poll_interval"`)} } return nil } @@ -138,8 +157,8 @@ func (dtc *DeviceTokenCreate) check() error { func (dtc *DeviceTokenCreate) sqlSave(ctx context.Context) (*DeviceToken, error) { _node, _spec := dtc.createSpec() if err := sqlgraph.CreateNode(ctx, dtc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -238,19 +257,23 @@ func (dtcb *DeviceTokenCreateBulk) Save(ctx context.Context) ([]*DeviceToken, er if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, dtcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, dtcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, dtcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } - id := specs[i].ID.Value.(int64) - nodes[i].ID = int(id) + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -275,3 +298,16 @@ func (dtcb *DeviceTokenCreateBulk) SaveX(ctx context.Context) []*DeviceToken { } return v } + +// Exec executes the query. +func (dtcb *DeviceTokenCreateBulk) Exec(ctx context.Context) error { + _, err := dtcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (dtcb *DeviceTokenCreateBulk) ExecX(ctx context.Context) { + if err := dtcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/devicetoken_delete.go b/storage/ent/db/devicetoken_delete.go index 0ea9069d71..f23cc50ecc 100644 --- a/storage/ent/db/devicetoken_delete.go +++ b/storage/ent/db/devicetoken_delete.go @@ -20,9 +20,9 @@ type DeviceTokenDelete struct { mutation *DeviceTokenMutation } -// Where adds a new predicate to the DeviceTokenDelete builder. +// Where appends a list predicates to the DeviceTokenDelete builder. func (dtd *DeviceTokenDelete) Where(ps ...predicate.DeviceToken) *DeviceTokenDelete { - dtd.mutation.predicates = append(dtd.mutation.predicates, ps...) + dtd.mutation.Where(ps...) return dtd } @@ -46,6 +46,9 @@ func (dtd *DeviceTokenDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(dtd.hooks) - 1; i >= 0; i-- { + if dtd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = dtd.hooks[i](mut) } if _, err := mut.Mutate(ctx, dtd.mutation); err != nil { diff --git a/storage/ent/db/devicetoken_query.go b/storage/ent/db/devicetoken_query.go index e085440dbc..2fb2712fd8 100644 --- a/storage/ent/db/devicetoken_query.go +++ b/storage/ent/db/devicetoken_query.go @@ -287,8 +287,8 @@ func (dtq *DeviceTokenQuery) GroupBy(field string, fields ...string) *DeviceToke // Select(devicetoken.FieldDeviceCode). // Scan(ctx, &v) // -func (dtq *DeviceTokenQuery) Select(field string, fields ...string) *DeviceTokenSelect { - dtq.fields = append([]string{field}, fields...) +func (dtq *DeviceTokenQuery) Select(fields ...string) *DeviceTokenSelect { + dtq.fields = append(dtq.fields, fields...) return &DeviceTokenSelect{DeviceTokenQuery: dtq} } @@ -398,10 +398,14 @@ func (dtq *DeviceTokenQuery) querySpec() *sqlgraph.QuerySpec { func (dtq *DeviceTokenQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(dtq.driver.Dialect()) t1 := builder.Table(devicetoken.Table) - selector := builder.Select(t1.Columns(devicetoken.Columns...)...).From(t1) + columns := dtq.fields + if len(columns) == 0 { + columns = devicetoken.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if dtq.sql != nil { selector = dtq.sql - selector.Select(selector.Columns(devicetoken.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range dtq.predicates { p(selector) @@ -669,13 +673,24 @@ func (dtgb *DeviceTokenGroupBy) sqlScan(ctx context.Context, v interface{}) erro } func (dtgb *DeviceTokenGroupBy) sqlQuery() *sql.Selector { - selector := dtgb.sql - columns := make([]string, 0, len(dtgb.fields)+len(dtgb.fns)) - columns = append(columns, dtgb.fields...) + selector := dtgb.sql.Select() + aggregation := make([]string, 0, len(dtgb.fns)) for _, fn := range dtgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(dtgb.fields)+len(dtgb.fns)) + for _, f := range dtgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(dtgb.fields...) + return selector.GroupBy(selector.Columns(dtgb.fields...)...) } // DeviceTokenSelect is the builder for selecting fields of DeviceToken entities. @@ -891,16 +906,10 @@ func (dts *DeviceTokenSelect) BoolX(ctx context.Context) bool { func (dts *DeviceTokenSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := dts.sqlQuery().Query() + query, args := dts.sql.Query() if err := dts.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (dts *DeviceTokenSelect) sqlQuery() sql.Querier { - selector := dts.sql - selector.Select(selector.Columns(dts.fields...)...) - return selector -} diff --git a/storage/ent/db/devicetoken_update.go b/storage/ent/db/devicetoken_update.go index 51a4efe0e1..a61a8b0b14 100644 --- a/storage/ent/db/devicetoken_update.go +++ b/storage/ent/db/devicetoken_update.go @@ -21,9 +21,9 @@ type DeviceTokenUpdate struct { mutation *DeviceTokenMutation } -// Where adds a new predicate for the DeviceTokenUpdate builder. +// Where appends a list predicates to the DeviceTokenUpdate builder. func (dtu *DeviceTokenUpdate) Where(ps ...predicate.DeviceToken) *DeviceTokenUpdate { - dtu.mutation.predicates = append(dtu.mutation.predicates, ps...) + dtu.mutation.Where(ps...) return dtu } @@ -107,6 +107,9 @@ func (dtu *DeviceTokenUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(dtu.hooks) - 1; i >= 0; i-- { + if dtu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = dtu.hooks[i](mut) } if _, err := mut.Mutate(ctx, dtu.mutation); err != nil { @@ -229,8 +232,8 @@ func (dtu *DeviceTokenUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, dtu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{devicetoken.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -332,6 +335,9 @@ func (dtuo *DeviceTokenUpdateOne) Save(ctx context.Context) (*DeviceToken, error return node, err }) for i := len(dtuo.hooks) - 1; i >= 0; i-- { + if dtuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = dtuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, dtuo.mutation); err != nil { @@ -474,8 +480,8 @@ func (dtuo *DeviceTokenUpdateOne) sqlSave(ctx context.Context) (_node *DeviceTok if err = sqlgraph.UpdateNode(ctx, dtuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{devicetoken.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/ent.go b/storage/ent/db/ent.go index d84e721d06..42d7ad5205 100644 --- a/storage/ent/db/ent.go +++ b/storage/ent/db/ent.go @@ -7,9 +7,7 @@ import ( "fmt" "entgo.io/ent" - "entgo.io/ent/dialect" "entgo.io/ent/dialect/sql" - "entgo.io/ent/dialect/sql/sqlgraph" "github.com/dexidp/dex/storage/ent/db/authcode" "github.com/dexidp/dex/storage/ent/db/authrequest" "github.com/dexidp/dex/storage/ent/db/connector" @@ -177,7 +175,7 @@ func (e *ValidationError) Unwrap() error { return e.err } -// IsValidationError returns a boolean indicating whether the error is a validaton error. +// IsValidationError returns a boolean indicating whether the error is a validation error. func IsValidationError(err error) bool { if err == nil { return false @@ -277,21 +275,3 @@ func IsConstraintError(err error) bool { var e *ConstraintError return errors.As(err, &e) } - -func isSQLConstraintError(err error) (*ConstraintError, bool) { - if sqlgraph.IsConstraintError(err) { - return &ConstraintError{err.Error(), err}, true - } - return nil, false -} - -// rollback calls tx.Rollback and wraps the given error with the rollback error if present. -func rollback(tx dialect.Tx, err error) error { - if rerr := tx.Rollback(); rerr != nil { - err = fmt.Errorf("%w: %v", err, rerr) - } - if err, ok := isSQLConstraintError(err); ok { - return err - } - return err -} diff --git a/storage/ent/db/keys.go b/storage/ent/db/keys.go index d0312c92a9..acdd825773 100644 --- a/storage/ent/db/keys.go +++ b/storage/ent/db/keys.go @@ -62,7 +62,6 @@ func (k *Keys) assignValues(columns []string, values []interface{}) error { k.ID = value.String } case keys.FieldVerificationKeys: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field verification_keys", values[i]) } else if value != nil && len(*value) > 0 { @@ -71,7 +70,6 @@ func (k *Keys) assignValues(columns []string, values []interface{}) error { } } case keys.FieldSigningKey: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field signing_key", values[i]) } else if value != nil && len(*value) > 0 { @@ -80,7 +78,6 @@ func (k *Keys) assignValues(columns []string, values []interface{}) error { } } case keys.FieldSigningKeyPub: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field signing_key_pub", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/keys_create.go b/storage/ent/db/keys_create.go index 4dfae78bee..18e58f8b2f 100644 --- a/storage/ent/db/keys_create.go +++ b/storage/ent/db/keys_create.go @@ -78,11 +78,17 @@ func (kc *KeysCreate) Save(ctx context.Context) (*Keys, error) { return nil, err } kc.mutation = mutation - node, err = kc.sqlSave(ctx) + if node, err = kc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(kc.hooks) - 1; i >= 0; i-- { + if kc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = kc.hooks[i](mut) } if _, err := mut.Mutate(ctx, kc.mutation); err != nil { @@ -101,23 +107,36 @@ func (kc *KeysCreate) SaveX(ctx context.Context) *Keys { return v } +// Exec executes the query. +func (kc *KeysCreate) Exec(ctx context.Context) error { + _, err := kc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (kc *KeysCreate) ExecX(ctx context.Context) { + if err := kc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (kc *KeysCreate) check() error { if _, ok := kc.mutation.VerificationKeys(); !ok { - return &ValidationError{Name: "verification_keys", err: errors.New("db: missing required field \"verification_keys\"")} + return &ValidationError{Name: "verification_keys", err: errors.New(`db: missing required field "verification_keys"`)} } if _, ok := kc.mutation.SigningKey(); !ok { - return &ValidationError{Name: "signing_key", err: errors.New("db: missing required field \"signing_key\"")} + return &ValidationError{Name: "signing_key", err: errors.New(`db: missing required field "signing_key"`)} } if _, ok := kc.mutation.SigningKeyPub(); !ok { - return &ValidationError{Name: "signing_key_pub", err: errors.New("db: missing required field \"signing_key_pub\"")} + return &ValidationError{Name: "signing_key_pub", err: errors.New(`db: missing required field "signing_key_pub"`)} } if _, ok := kc.mutation.NextRotation(); !ok { - return &ValidationError{Name: "next_rotation", err: errors.New("db: missing required field \"next_rotation\"")} + return &ValidationError{Name: "next_rotation", err: errors.New(`db: missing required field "next_rotation"`)} } if v, ok := kc.mutation.ID(); ok { if err := keys.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -126,8 +145,8 @@ func (kc *KeysCreate) check() error { func (kc *KeysCreate) sqlSave(ctx context.Context) (*Keys, error) { _node, _spec := kc.createSpec() if err := sqlgraph.CreateNode(ctx, kc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -212,17 +231,19 @@ func (kcb *KeysCreateBulk) Save(ctx context.Context) ([]*Keys, error) { if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, kcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, kcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, kcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -247,3 +268,16 @@ func (kcb *KeysCreateBulk) SaveX(ctx context.Context) []*Keys { } return v } + +// Exec executes the query. +func (kcb *KeysCreateBulk) Exec(ctx context.Context) error { + _, err := kcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (kcb *KeysCreateBulk) ExecX(ctx context.Context) { + if err := kcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/keys_delete.go b/storage/ent/db/keys_delete.go index 620f8f106d..6950c2578a 100644 --- a/storage/ent/db/keys_delete.go +++ b/storage/ent/db/keys_delete.go @@ -20,9 +20,9 @@ type KeysDelete struct { mutation *KeysMutation } -// Where adds a new predicate to the KeysDelete builder. +// Where appends a list predicates to the KeysDelete builder. func (kd *KeysDelete) Where(ps ...predicate.Keys) *KeysDelete { - kd.mutation.predicates = append(kd.mutation.predicates, ps...) + kd.mutation.Where(ps...) return kd } @@ -46,6 +46,9 @@ func (kd *KeysDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(kd.hooks) - 1; i >= 0; i-- { + if kd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = kd.hooks[i](mut) } if _, err := mut.Mutate(ctx, kd.mutation); err != nil { diff --git a/storage/ent/db/keys_query.go b/storage/ent/db/keys_query.go index 6d6b00f925..ee102e270e 100644 --- a/storage/ent/db/keys_query.go +++ b/storage/ent/db/keys_query.go @@ -287,8 +287,8 @@ func (kq *KeysQuery) GroupBy(field string, fields ...string) *KeysGroupBy { // Select(keys.FieldVerificationKeys). // Scan(ctx, &v) // -func (kq *KeysQuery) Select(field string, fields ...string) *KeysSelect { - kq.fields = append([]string{field}, fields...) +func (kq *KeysQuery) Select(fields ...string) *KeysSelect { + kq.fields = append(kq.fields, fields...) return &KeysSelect{KeysQuery: kq} } @@ -398,10 +398,14 @@ func (kq *KeysQuery) querySpec() *sqlgraph.QuerySpec { func (kq *KeysQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(kq.driver.Dialect()) t1 := builder.Table(keys.Table) - selector := builder.Select(t1.Columns(keys.Columns...)...).From(t1) + columns := kq.fields + if len(columns) == 0 { + columns = keys.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if kq.sql != nil { selector = kq.sql - selector.Select(selector.Columns(keys.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range kq.predicates { p(selector) @@ -669,13 +673,24 @@ func (kgb *KeysGroupBy) sqlScan(ctx context.Context, v interface{}) error { } func (kgb *KeysGroupBy) sqlQuery() *sql.Selector { - selector := kgb.sql - columns := make([]string, 0, len(kgb.fields)+len(kgb.fns)) - columns = append(columns, kgb.fields...) + selector := kgb.sql.Select() + aggregation := make([]string, 0, len(kgb.fns)) for _, fn := range kgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(kgb.fields)+len(kgb.fns)) + for _, f := range kgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(kgb.fields...) + return selector.GroupBy(selector.Columns(kgb.fields...)...) } // KeysSelect is the builder for selecting fields of Keys entities. @@ -891,16 +906,10 @@ func (ks *KeysSelect) BoolX(ctx context.Context) bool { func (ks *KeysSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := ks.sqlQuery().Query() + query, args := ks.sql.Query() if err := ks.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (ks *KeysSelect) sqlQuery() sql.Querier { - selector := ks.sql - selector.Select(selector.Columns(ks.fields...)...) - return selector -} diff --git a/storage/ent/db/keys_update.go b/storage/ent/db/keys_update.go index 8bc0ed3edb..0e40565fa0 100644 --- a/storage/ent/db/keys_update.go +++ b/storage/ent/db/keys_update.go @@ -23,9 +23,9 @@ type KeysUpdate struct { mutation *KeysMutation } -// Where adds a new predicate for the KeysUpdate builder. +// Where appends a list predicates to the KeysUpdate builder. func (ku *KeysUpdate) Where(ps ...predicate.Keys) *KeysUpdate { - ku.mutation.predicates = append(ku.mutation.predicates, ps...) + ku.mutation.Where(ps...) return ku } @@ -78,6 +78,9 @@ func (ku *KeysUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(ku.hooks) - 1; i >= 0; i-- { + if ku.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = ku.hooks[i](mut) } if _, err := mut.Mutate(ctx, ku.mutation); err != nil { @@ -158,8 +161,8 @@ func (ku *KeysUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, ku.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{keys.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -230,6 +233,9 @@ func (kuo *KeysUpdateOne) Save(ctx context.Context) (*Keys, error) { return node, err }) for i := len(kuo.hooks) - 1; i >= 0; i-- { + if kuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = kuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, kuo.mutation); err != nil { @@ -330,8 +336,8 @@ func (kuo *KeysUpdateOne) sqlSave(ctx context.Context) (_node *Keys, err error) if err = sqlgraph.UpdateNode(ctx, kuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{keys.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/migrate/schema.go b/storage/ent/db/migrate/schema.go index d5b1f535d9..d8b8b62cb8 100644 --- a/storage/ent/db/migrate/schema.go +++ b/storage/ent/db/migrate/schema.go @@ -10,196 +10,186 @@ import ( var ( // AuthCodesColumns holds the columns for the "auth_codes" table. AuthCodesColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "scopes", Type: field.TypeJSON, Nullable: true}, - {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "redirect_uri", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "redirect_uri", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "claims_email_verified", Type: field.TypeBool}, {Name: "claims_groups", Type: field.TypeJSON, Nullable: true}, - {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "connector_data", Type: field.TypeBytes, Nullable: true}, - {Name: "expiry", Type: field.TypeTime}, - {Name: "code_challenge", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "code_challenge_method", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "expiry", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, + {Name: "code_challenge", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "code_challenge_method", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, } // AuthCodesTable holds the schema information for the "auth_codes" table. AuthCodesTable = &schema.Table{ - Name: "auth_codes", - Columns: AuthCodesColumns, - PrimaryKey: []*schema.Column{AuthCodesColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "auth_codes", + Columns: AuthCodesColumns, + PrimaryKey: []*schema.Column{AuthCodesColumns[0]}, } // AuthRequestsColumns holds the columns for the "auth_requests" table. AuthRequestsColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "scopes", Type: field.TypeJSON, Nullable: true}, {Name: "response_types", Type: field.TypeJSON, Nullable: true}, - {Name: "redirect_uri", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "state", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "redirect_uri", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "state", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "force_approval_prompt", Type: field.TypeBool}, {Name: "logged_in", Type: field.TypeBool}, - {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "claims_email_verified", Type: field.TypeBool}, {Name: "claims_groups", Type: field.TypeJSON, Nullable: true}, - {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "connector_data", Type: field.TypeBytes, Nullable: true}, - {Name: "expiry", Type: field.TypeTime}, - {Name: "code_challenge", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "code_challenge_method", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "expiry", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, + {Name: "code_challenge", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "code_challenge_method", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, } // AuthRequestsTable holds the schema information for the "auth_requests" table. AuthRequestsTable = &schema.Table{ - Name: "auth_requests", - Columns: AuthRequestsColumns, - PrimaryKey: []*schema.Column{AuthRequestsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "auth_requests", + Columns: AuthRequestsColumns, + PrimaryKey: []*schema.Column{AuthRequestsColumns[0]}, } // ConnectorsColumns holds the columns for the "connectors" table. ConnectorsColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "type", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "name", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "resource_version", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 100, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "type", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "name", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "resource_version", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "config", Type: field.TypeBytes}, } // ConnectorsTable holds the schema information for the "connectors" table. ConnectorsTable = &schema.Table{ - Name: "connectors", - Columns: ConnectorsColumns, - PrimaryKey: []*schema.Column{ConnectorsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "connectors", + Columns: ConnectorsColumns, + PrimaryKey: []*schema.Column{ConnectorsColumns[0]}, } // DeviceRequestsColumns holds the columns for the "device_requests" table. DeviceRequestsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, - {Name: "user_code", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "device_code", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "client_secret", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "user_code", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "device_code", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "client_secret", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "scopes", Type: field.TypeJSON, Nullable: true}, - {Name: "expiry", Type: field.TypeTime}, + {Name: "expiry", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, } // DeviceRequestsTable holds the schema information for the "device_requests" table. DeviceRequestsTable = &schema.Table{ - Name: "device_requests", - Columns: DeviceRequestsColumns, - PrimaryKey: []*schema.Column{DeviceRequestsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "device_requests", + Columns: DeviceRequestsColumns, + PrimaryKey: []*schema.Column{DeviceRequestsColumns[0]}, } // DeviceTokensColumns holds the columns for the "device_tokens" table. DeviceTokensColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, - {Name: "device_code", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "status", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "device_code", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "status", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "token", Type: field.TypeBytes, Nullable: true}, - {Name: "expiry", Type: field.TypeTime}, - {Name: "last_request", Type: field.TypeTime}, + {Name: "expiry", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, + {Name: "last_request", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, {Name: "poll_interval", Type: field.TypeInt}, } // DeviceTokensTable holds the schema information for the "device_tokens" table. DeviceTokensTable = &schema.Table{ - Name: "device_tokens", - Columns: DeviceTokensColumns, - PrimaryKey: []*schema.Column{DeviceTokensColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "device_tokens", + Columns: DeviceTokensColumns, + PrimaryKey: []*schema.Column{DeviceTokensColumns[0]}, } // KeysColumns holds the columns for the "keys" table. KeysColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "verification_keys", Type: field.TypeJSON}, {Name: "signing_key", Type: field.TypeJSON}, {Name: "signing_key_pub", Type: field.TypeJSON}, - {Name: "next_rotation", Type: field.TypeTime}, + {Name: "next_rotation", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, } // KeysTable holds the schema information for the "keys" table. KeysTable = &schema.Table{ - Name: "keys", - Columns: KeysColumns, - PrimaryKey: []*schema.Column{KeysColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "keys", + Columns: KeysColumns, + PrimaryKey: []*schema.Column{KeysColumns[0]}, } // Oauth2clientsColumns holds the columns for the "oauth2clients" table. Oauth2clientsColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "secret", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 100, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "secret", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "redirect_uris", Type: field.TypeJSON, Nullable: true}, {Name: "trusted_peers", Type: field.TypeJSON, Nullable: true}, {Name: "public", Type: field.TypeBool}, - {Name: "name", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "logo_url", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "name", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "logo_url", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, } // Oauth2clientsTable holds the schema information for the "oauth2clients" table. Oauth2clientsTable = &schema.Table{ - Name: "oauth2clients", - Columns: Oauth2clientsColumns, - PrimaryKey: []*schema.Column{Oauth2clientsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "oauth2clients", + Columns: Oauth2clientsColumns, + PrimaryKey: []*schema.Column{Oauth2clientsColumns[0]}, } // OfflineSessionsColumns holds the columns for the "offline_sessions" table. OfflineSessionsColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "conn_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "conn_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "refresh", Type: field.TypeBytes}, {Name: "connector_data", Type: field.TypeBytes, Nullable: true}, } // OfflineSessionsTable holds the schema information for the "offline_sessions" table. OfflineSessionsTable = &schema.Table{ - Name: "offline_sessions", - Columns: OfflineSessionsColumns, - PrimaryKey: []*schema.Column{OfflineSessionsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "offline_sessions", + Columns: OfflineSessionsColumns, + PrimaryKey: []*schema.Column{OfflineSessionsColumns[0]}, } // PasswordsColumns holds the columns for the "passwords" table. PasswordsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, - {Name: "email", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "email", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "hash", Type: field.TypeBytes}, - {Name: "username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, } // PasswordsTable holds the schema information for the "passwords" table. PasswordsTable = &schema.Table{ - Name: "passwords", - Columns: PasswordsColumns, - PrimaryKey: []*schema.Column{PasswordsColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "passwords", + Columns: PasswordsColumns, + PrimaryKey: []*schema.Column{PasswordsColumns[0]}, } // RefreshTokensColumns holds the columns for the "refresh_tokens" table. RefreshTokensColumns = []*schema.Column{ - {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "id", Type: field.TypeString, Unique: true, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "client_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "scopes", Type: field.TypeJSON, Nullable: true}, - {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "nonce", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_user_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_username", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "claims_email", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "claims_email_verified", Type: field.TypeBool}, {Name: "claims_groups", Type: field.TypeJSON, Nullable: true}, - {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"sqlite3": "text"}}, + {Name: "claims_preferred_username", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "connector_id", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "connector_data", Type: field.TypeBytes, Nullable: true}, - {Name: "token", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "obsolete_token", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"sqlite3": "text"}}, - {Name: "created_at", Type: field.TypeTime}, - {Name: "last_used", Type: field.TypeTime}, + {Name: "token", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "obsolete_token", Type: field.TypeString, Size: 2147483647, Default: "", SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, + {Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, + {Name: "last_used", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime(3)", "postgres": "timestamptz", "sqlite3": "timestamp"}}, } // RefreshTokensTable holds the schema information for the "refresh_tokens" table. RefreshTokensTable = &schema.Table{ - Name: "refresh_tokens", - Columns: RefreshTokensColumns, - PrimaryKey: []*schema.Column{RefreshTokensColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "refresh_tokens", + Columns: RefreshTokensColumns, + PrimaryKey: []*schema.Column{RefreshTokensColumns[0]}, } // Tables holds all the tables in the schema. Tables = []*schema.Table{ diff --git a/storage/ent/db/mutation.go b/storage/ent/db/mutation.go index 7ccab3f2b3..d6d1dbab81 100644 --- a/storage/ent/db/mutation.go +++ b/storage/ent/db/mutation.go @@ -149,8 +149,8 @@ func (m *AuthCodeMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *AuthCodeMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -737,6 +737,11 @@ func (m *AuthCodeMutation) ResetCodeChallengeMethod() { m.code_challenge_method = nil } +// Where appends a list predicates to the AuthCodeMutation builder. +func (m *AuthCodeMutation) Where(ps ...predicate.AuthCode) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *AuthCodeMutation) Op() Op { return m.op @@ -1262,8 +1267,8 @@ func (m *AuthRequestMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *AuthRequestMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -2007,6 +2012,11 @@ func (m *AuthRequestMutation) ResetCodeChallengeMethod() { m.code_challenge_method = nil } +// Where appends a list predicates to the AuthRequestMutation builder. +func (m *AuthRequestMutation) Where(ps ...predicate.AuthRequest) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *AuthRequestMutation) Op() Op { return m.op @@ -2591,8 +2601,8 @@ func (m *ConnectorMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *ConnectorMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -2744,6 +2754,11 @@ func (m *ConnectorMutation) ResetConfig() { m._config = nil } +// Where appends a list predicates to the ConnectorMutation builder. +func (m *ConnectorMutation) Where(ps ...predicate.Connector) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *ConnectorMutation) Op() Op { return m.op @@ -3042,8 +3057,8 @@ func (m DeviceRequestMutation) Tx() (*Tx, error) { return tx, nil } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *DeviceRequestMutation) ID() (id int, exists bool) { if m.id == nil { return @@ -3280,6 +3295,11 @@ func (m *DeviceRequestMutation) ResetExpiry() { m.expiry = nil } +// Where appends a list predicates to the DeviceRequestMutation builder. +func (m *DeviceRequestMutation) Where(ps ...predicate.DeviceRequest) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *DeviceRequestMutation) Op() Op { return m.op @@ -3622,8 +3642,8 @@ func (m DeviceTokenMutation) Tx() (*Tx, error) { return tx, nil } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *DeviceTokenMutation) ID() (id int, exists bool) { if m.id == nil { return @@ -3880,6 +3900,11 @@ func (m *DeviceTokenMutation) ResetPollInterval() { m.addpoll_interval = nil } +// Where appends a list predicates to the DeviceTokenMutation builder. +func (m *DeviceTokenMutation) Where(ps ...predicate.DeviceToken) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *DeviceTokenMutation) Op() Op { return m.op @@ -4240,8 +4265,8 @@ func (m *KeysMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *KeysMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -4393,6 +4418,11 @@ func (m *KeysMutation) ResetNextRotation() { m.next_rotation = nil } +// Where appends a list predicates to the KeysMutation builder. +func (m *KeysMutation) Where(ps ...predicate.Keys) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *KeysMutation) Op() Op { return m.op @@ -4697,8 +4727,8 @@ func (m *OAuth2ClientMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *OAuth2ClientMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -4948,6 +4978,11 @@ func (m *OAuth2ClientMutation) ResetLogoURL() { m.logo_url = nil } +// Where appends a list predicates to the OAuth2ClientMutation builder. +func (m *OAuth2ClientMutation) Where(ps ...predicate.OAuth2Client) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *OAuth2ClientMutation) Op() Op { return m.op @@ -5299,8 +5334,8 @@ func (m *OfflineSessionMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *OfflineSessionMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -5465,6 +5500,11 @@ func (m *OfflineSessionMutation) ResetConnectorData() { delete(m.clearedFields, offlinesession.FieldConnectorData) } +// Where appends a list predicates to the OfflineSessionMutation builder. +func (m *OfflineSessionMutation) Where(ps ...predicate.OfflineSession) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *OfflineSessionMutation) Op() Op { return m.op @@ -5770,8 +5810,8 @@ func (m PasswordMutation) Tx() (*Tx, error) { return tx, nil } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *PasswordMutation) ID() (id int, exists bool) { if m.id == nil { return @@ -5923,6 +5963,11 @@ func (m *PasswordMutation) ResetUserID() { m.user_id = nil } +// Where appends a list predicates to the PasswordMutation builder. +func (m *PasswordMutation) Where(ps ...predicate.Password) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *PasswordMutation) Op() Op { return m.op @@ -6236,8 +6281,8 @@ func (m *RefreshTokenMutation) SetID(id string) { m.id = &id } -// ID returns the ID value in the mutation. Note that the ID -// is only available if it was provided to the builder. +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. func (m *RefreshTokenMutation) ID() (id string, exists bool) { if m.id == nil { return @@ -6824,6 +6869,11 @@ func (m *RefreshTokenMutation) ResetLastUsed() { m.last_used = nil } +// Where appends a list predicates to the RefreshTokenMutation builder. +func (m *RefreshTokenMutation) Where(ps ...predicate.RefreshToken) { + m.predicates = append(m.predicates, ps...) +} + // Op returns the operation name. func (m *RefreshTokenMutation) Op() Op { return m.op diff --git a/storage/ent/db/oauth2client.go b/storage/ent/db/oauth2client.go index 687a6e692d..57d64a4979 100644 --- a/storage/ent/db/oauth2client.go +++ b/storage/ent/db/oauth2client.go @@ -69,7 +69,6 @@ func (o *OAuth2Client) assignValues(columns []string, values []interface{}) erro o.Secret = value.String } case oauth2client.FieldRedirectUris: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field redirect_uris", values[i]) } else if value != nil && len(*value) > 0 { @@ -78,7 +77,6 @@ func (o *OAuth2Client) assignValues(columns []string, values []interface{}) erro } } case oauth2client.FieldTrustedPeers: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field trusted_peers", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/oauth2client_create.go b/storage/ent/db/oauth2client_create.go index 259b9473dc..b141352b26 100644 --- a/storage/ent/db/oauth2client_create.go +++ b/storage/ent/db/oauth2client_create.go @@ -87,11 +87,17 @@ func (oc *OAuth2ClientCreate) Save(ctx context.Context) (*OAuth2Client, error) { return nil, err } oc.mutation = mutation - node, err = oc.sqlSave(ctx) + if node, err = oc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(oc.hooks) - 1; i >= 0; i-- { + if oc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = oc.hooks[i](mut) } if _, err := mut.Mutate(ctx, oc.mutation); err != nil { @@ -110,38 +116,51 @@ func (oc *OAuth2ClientCreate) SaveX(ctx context.Context) *OAuth2Client { return v } +// Exec executes the query. +func (oc *OAuth2ClientCreate) Exec(ctx context.Context) error { + _, err := oc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (oc *OAuth2ClientCreate) ExecX(ctx context.Context) { + if err := oc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (oc *OAuth2ClientCreate) check() error { if _, ok := oc.mutation.Secret(); !ok { - return &ValidationError{Name: "secret", err: errors.New("db: missing required field \"secret\"")} + return &ValidationError{Name: "secret", err: errors.New(`db: missing required field "secret"`)} } if v, ok := oc.mutation.Secret(); ok { if err := oauth2client.SecretValidator(v); err != nil { - return &ValidationError{Name: "secret", err: fmt.Errorf("db: validator failed for field \"secret\": %w", err)} + return &ValidationError{Name: "secret", err: fmt.Errorf(`db: validator failed for field "secret": %w`, err)} } } if _, ok := oc.mutation.Public(); !ok { - return &ValidationError{Name: "public", err: errors.New("db: missing required field \"public\"")} + return &ValidationError{Name: "public", err: errors.New(`db: missing required field "public"`)} } if _, ok := oc.mutation.Name(); !ok { - return &ValidationError{Name: "name", err: errors.New("db: missing required field \"name\"")} + return &ValidationError{Name: "name", err: errors.New(`db: missing required field "name"`)} } if v, ok := oc.mutation.Name(); ok { if err := oauth2client.NameValidator(v); err != nil { - return &ValidationError{Name: "name", err: fmt.Errorf("db: validator failed for field \"name\": %w", err)} + return &ValidationError{Name: "name", err: fmt.Errorf(`db: validator failed for field "name": %w`, err)} } } if _, ok := oc.mutation.LogoURL(); !ok { - return &ValidationError{Name: "logo_url", err: errors.New("db: missing required field \"logo_url\"")} + return &ValidationError{Name: "logo_url", err: errors.New(`db: missing required field "logo_url"`)} } if v, ok := oc.mutation.LogoURL(); ok { if err := oauth2client.LogoURLValidator(v); err != nil { - return &ValidationError{Name: "logo_url", err: fmt.Errorf("db: validator failed for field \"logo_url\": %w", err)} + return &ValidationError{Name: "logo_url", err: fmt.Errorf(`db: validator failed for field "logo_url": %w`, err)} } } if v, ok := oc.mutation.ID(); ok { if err := oauth2client.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -150,8 +169,8 @@ func (oc *OAuth2ClientCreate) check() error { func (oc *OAuth2ClientCreate) sqlSave(ctx context.Context) (*OAuth2Client, error) { _node, _spec := oc.createSpec() if err := sqlgraph.CreateNode(ctx, oc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -252,17 +271,19 @@ func (ocb *OAuth2ClientCreateBulk) Save(ctx context.Context) ([]*OAuth2Client, e if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, ocb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, ocb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, ocb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -287,3 +308,16 @@ func (ocb *OAuth2ClientCreateBulk) SaveX(ctx context.Context) []*OAuth2Client { } return v } + +// Exec executes the query. +func (ocb *OAuth2ClientCreateBulk) Exec(ctx context.Context) error { + _, err := ocb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ocb *OAuth2ClientCreateBulk) ExecX(ctx context.Context) { + if err := ocb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/oauth2client_delete.go b/storage/ent/db/oauth2client_delete.go index ab0a45f607..71a33c765e 100644 --- a/storage/ent/db/oauth2client_delete.go +++ b/storage/ent/db/oauth2client_delete.go @@ -20,9 +20,9 @@ type OAuth2ClientDelete struct { mutation *OAuth2ClientMutation } -// Where adds a new predicate to the OAuth2ClientDelete builder. +// Where appends a list predicates to the OAuth2ClientDelete builder. func (od *OAuth2ClientDelete) Where(ps ...predicate.OAuth2Client) *OAuth2ClientDelete { - od.mutation.predicates = append(od.mutation.predicates, ps...) + od.mutation.Where(ps...) return od } @@ -46,6 +46,9 @@ func (od *OAuth2ClientDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(od.hooks) - 1; i >= 0; i-- { + if od.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = od.hooks[i](mut) } if _, err := mut.Mutate(ctx, od.mutation); err != nil { diff --git a/storage/ent/db/oauth2client_query.go b/storage/ent/db/oauth2client_query.go index 558542f16f..d236328826 100644 --- a/storage/ent/db/oauth2client_query.go +++ b/storage/ent/db/oauth2client_query.go @@ -287,8 +287,8 @@ func (oq *OAuth2ClientQuery) GroupBy(field string, fields ...string) *OAuth2Clie // Select(oauth2client.FieldSecret). // Scan(ctx, &v) // -func (oq *OAuth2ClientQuery) Select(field string, fields ...string) *OAuth2ClientSelect { - oq.fields = append([]string{field}, fields...) +func (oq *OAuth2ClientQuery) Select(fields ...string) *OAuth2ClientSelect { + oq.fields = append(oq.fields, fields...) return &OAuth2ClientSelect{OAuth2ClientQuery: oq} } @@ -398,10 +398,14 @@ func (oq *OAuth2ClientQuery) querySpec() *sqlgraph.QuerySpec { func (oq *OAuth2ClientQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(oq.driver.Dialect()) t1 := builder.Table(oauth2client.Table) - selector := builder.Select(t1.Columns(oauth2client.Columns...)...).From(t1) + columns := oq.fields + if len(columns) == 0 { + columns = oauth2client.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if oq.sql != nil { selector = oq.sql - selector.Select(selector.Columns(oauth2client.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range oq.predicates { p(selector) @@ -669,13 +673,24 @@ func (ogb *OAuth2ClientGroupBy) sqlScan(ctx context.Context, v interface{}) erro } func (ogb *OAuth2ClientGroupBy) sqlQuery() *sql.Selector { - selector := ogb.sql - columns := make([]string, 0, len(ogb.fields)+len(ogb.fns)) - columns = append(columns, ogb.fields...) + selector := ogb.sql.Select() + aggregation := make([]string, 0, len(ogb.fns)) for _, fn := range ogb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(ogb.fields)+len(ogb.fns)) + for _, f := range ogb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(ogb.fields...) + return selector.GroupBy(selector.Columns(ogb.fields...)...) } // OAuth2ClientSelect is the builder for selecting fields of OAuth2Client entities. @@ -891,16 +906,10 @@ func (os *OAuth2ClientSelect) BoolX(ctx context.Context) bool { func (os *OAuth2ClientSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := os.sqlQuery().Query() + query, args := os.sql.Query() if err := os.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (os *OAuth2ClientSelect) sqlQuery() sql.Querier { - selector := os.sql - selector.Select(selector.Columns(os.fields...)...) - return selector -} diff --git a/storage/ent/db/oauth2client_update.go b/storage/ent/db/oauth2client_update.go index 329824183d..29b7f090f5 100644 --- a/storage/ent/db/oauth2client_update.go +++ b/storage/ent/db/oauth2client_update.go @@ -20,9 +20,9 @@ type OAuth2ClientUpdate struct { mutation *OAuth2ClientMutation } -// Where adds a new predicate for the OAuth2ClientUpdate builder. +// Where appends a list predicates to the OAuth2ClientUpdate builder. func (ou *OAuth2ClientUpdate) Where(ps ...predicate.OAuth2Client) *OAuth2ClientUpdate { - ou.mutation.predicates = append(ou.mutation.predicates, ps...) + ou.mutation.Where(ps...) return ou } @@ -105,6 +105,9 @@ func (ou *OAuth2ClientUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(ou.hooks) - 1; i >= 0; i-- { + if ou.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = ou.hooks[i](mut) } if _, err := mut.Mutate(ctx, ou.mutation); err != nil { @@ -231,8 +234,8 @@ func (ou *OAuth2ClientUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, ou.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{oauth2client.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -333,6 +336,9 @@ func (ouo *OAuth2ClientUpdateOne) Save(ctx context.Context) (*OAuth2Client, erro return node, err }) for i := len(ouo.hooks) - 1; i >= 0; i-- { + if ouo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = ouo.hooks[i](mut) } if _, err := mut.Mutate(ctx, ouo.mutation); err != nil { @@ -479,8 +485,8 @@ func (ouo *OAuth2ClientUpdateOne) sqlSave(ctx context.Context) (_node *OAuth2Cli if err = sqlgraph.UpdateNode(ctx, ouo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{oauth2client.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/offlinesession_create.go b/storage/ent/db/offlinesession_create.go index 1103e8eeab..add3912a5b 100644 --- a/storage/ent/db/offlinesession_create.go +++ b/storage/ent/db/offlinesession_create.go @@ -75,11 +75,17 @@ func (osc *OfflineSessionCreate) Save(ctx context.Context) (*OfflineSession, err return nil, err } osc.mutation = mutation - node, err = osc.sqlSave(ctx) + if node, err = osc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(osc.hooks) - 1; i >= 0; i-- { + if osc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = osc.hooks[i](mut) } if _, err := mut.Mutate(ctx, osc.mutation); err != nil { @@ -98,30 +104,43 @@ func (osc *OfflineSessionCreate) SaveX(ctx context.Context) *OfflineSession { return v } +// Exec executes the query. +func (osc *OfflineSessionCreate) Exec(ctx context.Context) error { + _, err := osc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (osc *OfflineSessionCreate) ExecX(ctx context.Context) { + if err := osc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (osc *OfflineSessionCreate) check() error { if _, ok := osc.mutation.UserID(); !ok { - return &ValidationError{Name: "user_id", err: errors.New("db: missing required field \"user_id\"")} + return &ValidationError{Name: "user_id", err: errors.New(`db: missing required field "user_id"`)} } if v, ok := osc.mutation.UserID(); ok { if err := offlinesession.UserIDValidator(v); err != nil { - return &ValidationError{Name: "user_id", err: fmt.Errorf("db: validator failed for field \"user_id\": %w", err)} + return &ValidationError{Name: "user_id", err: fmt.Errorf(`db: validator failed for field "user_id": %w`, err)} } } if _, ok := osc.mutation.ConnID(); !ok { - return &ValidationError{Name: "conn_id", err: errors.New("db: missing required field \"conn_id\"")} + return &ValidationError{Name: "conn_id", err: errors.New(`db: missing required field "conn_id"`)} } if v, ok := osc.mutation.ConnID(); ok { if err := offlinesession.ConnIDValidator(v); err != nil { - return &ValidationError{Name: "conn_id", err: fmt.Errorf("db: validator failed for field \"conn_id\": %w", err)} + return &ValidationError{Name: "conn_id", err: fmt.Errorf(`db: validator failed for field "conn_id": %w`, err)} } } if _, ok := osc.mutation.Refresh(); !ok { - return &ValidationError{Name: "refresh", err: errors.New("db: missing required field \"refresh\"")} + return &ValidationError{Name: "refresh", err: errors.New(`db: missing required field "refresh"`)} } if v, ok := osc.mutation.ID(); ok { if err := offlinesession.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -130,8 +149,8 @@ func (osc *OfflineSessionCreate) check() error { func (osc *OfflineSessionCreate) sqlSave(ctx context.Context) (*OfflineSession, error) { _node, _spec := osc.createSpec() if err := sqlgraph.CreateNode(ctx, osc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -216,17 +235,19 @@ func (oscb *OfflineSessionCreateBulk) Save(ctx context.Context) ([]*OfflineSessi if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, oscb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, oscb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, oscb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -251,3 +272,16 @@ func (oscb *OfflineSessionCreateBulk) SaveX(ctx context.Context) []*OfflineSessi } return v } + +// Exec executes the query. +func (oscb *OfflineSessionCreateBulk) Exec(ctx context.Context) error { + _, err := oscb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (oscb *OfflineSessionCreateBulk) ExecX(ctx context.Context) { + if err := oscb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/offlinesession_delete.go b/storage/ent/db/offlinesession_delete.go index 8ca8337837..3b2e914358 100644 --- a/storage/ent/db/offlinesession_delete.go +++ b/storage/ent/db/offlinesession_delete.go @@ -20,9 +20,9 @@ type OfflineSessionDelete struct { mutation *OfflineSessionMutation } -// Where adds a new predicate to the OfflineSessionDelete builder. +// Where appends a list predicates to the OfflineSessionDelete builder. func (osd *OfflineSessionDelete) Where(ps ...predicate.OfflineSession) *OfflineSessionDelete { - osd.mutation.predicates = append(osd.mutation.predicates, ps...) + osd.mutation.Where(ps...) return osd } @@ -46,6 +46,9 @@ func (osd *OfflineSessionDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(osd.hooks) - 1; i >= 0; i-- { + if osd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = osd.hooks[i](mut) } if _, err := mut.Mutate(ctx, osd.mutation); err != nil { diff --git a/storage/ent/db/offlinesession_query.go b/storage/ent/db/offlinesession_query.go index a4fbe1fda9..4306deaa87 100644 --- a/storage/ent/db/offlinesession_query.go +++ b/storage/ent/db/offlinesession_query.go @@ -287,8 +287,8 @@ func (osq *OfflineSessionQuery) GroupBy(field string, fields ...string) *Offline // Select(offlinesession.FieldUserID). // Scan(ctx, &v) // -func (osq *OfflineSessionQuery) Select(field string, fields ...string) *OfflineSessionSelect { - osq.fields = append([]string{field}, fields...) +func (osq *OfflineSessionQuery) Select(fields ...string) *OfflineSessionSelect { + osq.fields = append(osq.fields, fields...) return &OfflineSessionSelect{OfflineSessionQuery: osq} } @@ -398,10 +398,14 @@ func (osq *OfflineSessionQuery) querySpec() *sqlgraph.QuerySpec { func (osq *OfflineSessionQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(osq.driver.Dialect()) t1 := builder.Table(offlinesession.Table) - selector := builder.Select(t1.Columns(offlinesession.Columns...)...).From(t1) + columns := osq.fields + if len(columns) == 0 { + columns = offlinesession.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if osq.sql != nil { selector = osq.sql - selector.Select(selector.Columns(offlinesession.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range osq.predicates { p(selector) @@ -669,13 +673,24 @@ func (osgb *OfflineSessionGroupBy) sqlScan(ctx context.Context, v interface{}) e } func (osgb *OfflineSessionGroupBy) sqlQuery() *sql.Selector { - selector := osgb.sql - columns := make([]string, 0, len(osgb.fields)+len(osgb.fns)) - columns = append(columns, osgb.fields...) + selector := osgb.sql.Select() + aggregation := make([]string, 0, len(osgb.fns)) for _, fn := range osgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(osgb.fields)+len(osgb.fns)) + for _, f := range osgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(osgb.fields...) + return selector.GroupBy(selector.Columns(osgb.fields...)...) } // OfflineSessionSelect is the builder for selecting fields of OfflineSession entities. @@ -891,16 +906,10 @@ func (oss *OfflineSessionSelect) BoolX(ctx context.Context) bool { func (oss *OfflineSessionSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := oss.sqlQuery().Query() + query, args := oss.sql.Query() if err := oss.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (oss *OfflineSessionSelect) sqlQuery() sql.Querier { - selector := oss.sql - selector.Select(selector.Columns(oss.fields...)...) - return selector -} diff --git a/storage/ent/db/offlinesession_update.go b/storage/ent/db/offlinesession_update.go index d6edd52221..20c9faf336 100644 --- a/storage/ent/db/offlinesession_update.go +++ b/storage/ent/db/offlinesession_update.go @@ -20,9 +20,9 @@ type OfflineSessionUpdate struct { mutation *OfflineSessionMutation } -// Where adds a new predicate for the OfflineSessionUpdate builder. +// Where appends a list predicates to the OfflineSessionUpdate builder. func (osu *OfflineSessionUpdate) Where(ps ...predicate.OfflineSession) *OfflineSessionUpdate { - osu.mutation.predicates = append(osu.mutation.predicates, ps...) + osu.mutation.Where(ps...) return osu } @@ -87,6 +87,9 @@ func (osu *OfflineSessionUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(osu.hooks) - 1; i >= 0; i-- { + if osu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = osu.hooks[i](mut) } if _, err := mut.Mutate(ctx, osu.mutation); err != nil { @@ -188,8 +191,8 @@ func (osu *OfflineSessionUpdate) sqlSave(ctx context.Context) (n int, err error) if n, err = sqlgraph.UpdateNodes(ctx, osu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{offlinesession.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -272,6 +275,9 @@ func (osuo *OfflineSessionUpdateOne) Save(ctx context.Context) (*OfflineSession, return node, err }) for i := len(osuo.hooks) - 1; i >= 0; i-- { + if osuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = osuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, osuo.mutation); err != nil { @@ -393,8 +399,8 @@ func (osuo *OfflineSessionUpdateOne) sqlSave(ctx context.Context) (_node *Offlin if err = sqlgraph.UpdateNode(ctx, osuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{offlinesession.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/password_create.go b/storage/ent/db/password_create.go index 2e01f4a227..af902ea387 100644 --- a/storage/ent/db/password_create.go +++ b/storage/ent/db/password_create.go @@ -69,11 +69,17 @@ func (pc *PasswordCreate) Save(ctx context.Context) (*Password, error) { return nil, err } pc.mutation = mutation - node, err = pc.sqlSave(ctx) + if node, err = pc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(pc.hooks) - 1; i >= 0; i-- { + if pc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = pc.hooks[i](mut) } if _, err := mut.Mutate(ctx, pc.mutation); err != nil { @@ -92,33 +98,46 @@ func (pc *PasswordCreate) SaveX(ctx context.Context) *Password { return v } +// Exec executes the query. +func (pc *PasswordCreate) Exec(ctx context.Context) error { + _, err := pc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pc *PasswordCreate) ExecX(ctx context.Context) { + if err := pc.Exec(ctx); err != nil { + panic(err) + } +} + // check runs all checks and user-defined validators on the builder. func (pc *PasswordCreate) check() error { if _, ok := pc.mutation.Email(); !ok { - return &ValidationError{Name: "email", err: errors.New("db: missing required field \"email\"")} + return &ValidationError{Name: "email", err: errors.New(`db: missing required field "email"`)} } if v, ok := pc.mutation.Email(); ok { if err := password.EmailValidator(v); err != nil { - return &ValidationError{Name: "email", err: fmt.Errorf("db: validator failed for field \"email\": %w", err)} + return &ValidationError{Name: "email", err: fmt.Errorf(`db: validator failed for field "email": %w`, err)} } } if _, ok := pc.mutation.Hash(); !ok { - return &ValidationError{Name: "hash", err: errors.New("db: missing required field \"hash\"")} + return &ValidationError{Name: "hash", err: errors.New(`db: missing required field "hash"`)} } if _, ok := pc.mutation.Username(); !ok { - return &ValidationError{Name: "username", err: errors.New("db: missing required field \"username\"")} + return &ValidationError{Name: "username", err: errors.New(`db: missing required field "username"`)} } if v, ok := pc.mutation.Username(); ok { if err := password.UsernameValidator(v); err != nil { - return &ValidationError{Name: "username", err: fmt.Errorf("db: validator failed for field \"username\": %w", err)} + return &ValidationError{Name: "username", err: fmt.Errorf(`db: validator failed for field "username": %w`, err)} } } if _, ok := pc.mutation.UserID(); !ok { - return &ValidationError{Name: "user_id", err: errors.New("db: missing required field \"user_id\"")} + return &ValidationError{Name: "user_id", err: errors.New(`db: missing required field "user_id"`)} } if v, ok := pc.mutation.UserID(); ok { if err := password.UserIDValidator(v); err != nil { - return &ValidationError{Name: "user_id", err: fmt.Errorf("db: validator failed for field \"user_id\": %w", err)} + return &ValidationError{Name: "user_id", err: fmt.Errorf(`db: validator failed for field "user_id": %w`, err)} } } return nil @@ -127,8 +146,8 @@ func (pc *PasswordCreate) check() error { func (pc *PasswordCreate) sqlSave(ctx context.Context) (*Password, error) { _node, _spec := pc.createSpec() if err := sqlgraph.CreateNode(ctx, pc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -211,19 +230,23 @@ func (pcb *PasswordCreateBulk) Save(ctx context.Context) ([]*Password, error) { if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, pcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, pcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, pcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } - id := specs[i].ID.Value.(int64) - nodes[i].ID = int(id) + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -248,3 +271,16 @@ func (pcb *PasswordCreateBulk) SaveX(ctx context.Context) []*Password { } return v } + +// Exec executes the query. +func (pcb *PasswordCreateBulk) Exec(ctx context.Context) error { + _, err := pcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pcb *PasswordCreateBulk) ExecX(ctx context.Context) { + if err := pcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/password_delete.go b/storage/ent/db/password_delete.go index 87d018fc16..d1c59870d9 100644 --- a/storage/ent/db/password_delete.go +++ b/storage/ent/db/password_delete.go @@ -20,9 +20,9 @@ type PasswordDelete struct { mutation *PasswordMutation } -// Where adds a new predicate to the PasswordDelete builder. +// Where appends a list predicates to the PasswordDelete builder. func (pd *PasswordDelete) Where(ps ...predicate.Password) *PasswordDelete { - pd.mutation.predicates = append(pd.mutation.predicates, ps...) + pd.mutation.Where(ps...) return pd } @@ -46,6 +46,9 @@ func (pd *PasswordDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(pd.hooks) - 1; i >= 0; i-- { + if pd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = pd.hooks[i](mut) } if _, err := mut.Mutate(ctx, pd.mutation); err != nil { diff --git a/storage/ent/db/password_query.go b/storage/ent/db/password_query.go index 8bfe9a83c3..50e493fd2d 100644 --- a/storage/ent/db/password_query.go +++ b/storage/ent/db/password_query.go @@ -287,8 +287,8 @@ func (pq *PasswordQuery) GroupBy(field string, fields ...string) *PasswordGroupB // Select(password.FieldEmail). // Scan(ctx, &v) // -func (pq *PasswordQuery) Select(field string, fields ...string) *PasswordSelect { - pq.fields = append([]string{field}, fields...) +func (pq *PasswordQuery) Select(fields ...string) *PasswordSelect { + pq.fields = append(pq.fields, fields...) return &PasswordSelect{PasswordQuery: pq} } @@ -398,10 +398,14 @@ func (pq *PasswordQuery) querySpec() *sqlgraph.QuerySpec { func (pq *PasswordQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(pq.driver.Dialect()) t1 := builder.Table(password.Table) - selector := builder.Select(t1.Columns(password.Columns...)...).From(t1) + columns := pq.fields + if len(columns) == 0 { + columns = password.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if pq.sql != nil { selector = pq.sql - selector.Select(selector.Columns(password.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range pq.predicates { p(selector) @@ -669,13 +673,24 @@ func (pgb *PasswordGroupBy) sqlScan(ctx context.Context, v interface{}) error { } func (pgb *PasswordGroupBy) sqlQuery() *sql.Selector { - selector := pgb.sql - columns := make([]string, 0, len(pgb.fields)+len(pgb.fns)) - columns = append(columns, pgb.fields...) + selector := pgb.sql.Select() + aggregation := make([]string, 0, len(pgb.fns)) for _, fn := range pgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(pgb.fields)+len(pgb.fns)) + for _, f := range pgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(pgb.fields...) + return selector.GroupBy(selector.Columns(pgb.fields...)...) } // PasswordSelect is the builder for selecting fields of Password entities. @@ -891,16 +906,10 @@ func (ps *PasswordSelect) BoolX(ctx context.Context) bool { func (ps *PasswordSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := ps.sqlQuery().Query() + query, args := ps.sql.Query() if err := ps.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (ps *PasswordSelect) sqlQuery() sql.Querier { - selector := ps.sql - selector.Select(selector.Columns(ps.fields...)...) - return selector -} diff --git a/storage/ent/db/password_update.go b/storage/ent/db/password_update.go index 0eb1cb61c8..f15fb01710 100644 --- a/storage/ent/db/password_update.go +++ b/storage/ent/db/password_update.go @@ -20,9 +20,9 @@ type PasswordUpdate struct { mutation *PasswordMutation } -// Where adds a new predicate for the PasswordUpdate builder. +// Where appends a list predicates to the PasswordUpdate builder. func (pu *PasswordUpdate) Where(ps ...predicate.Password) *PasswordUpdate { - pu.mutation.predicates = append(pu.mutation.predicates, ps...) + pu.mutation.Where(ps...) return pu } @@ -81,6 +81,9 @@ func (pu *PasswordUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(pu.hooks) - 1; i >= 0; i-- { + if pu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = pu.hooks[i](mut) } if _, err := mut.Mutate(ctx, pu.mutation); err != nil { @@ -181,8 +184,8 @@ func (pu *PasswordUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{password.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -259,6 +262,9 @@ func (puo *PasswordUpdateOne) Save(ctx context.Context) (*Password, error) { return node, err }) for i := len(puo.hooks) - 1; i >= 0; i-- { + if puo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = puo.hooks[i](mut) } if _, err := mut.Mutate(ctx, puo.mutation); err != nil { @@ -379,8 +385,8 @@ func (puo *PasswordUpdateOne) sqlSave(ctx context.Context) (_node *Password, err if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{password.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/refreshtoken.go b/storage/ent/db/refreshtoken.go index 7e5270791b..3c59120654 100644 --- a/storage/ent/db/refreshtoken.go +++ b/storage/ent/db/refreshtoken.go @@ -90,7 +90,6 @@ func (rt *RefreshToken) assignValues(columns []string, values []interface{}) err rt.ClientID = value.String } case refreshtoken.FieldScopes: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field scopes", values[i]) } else if value != nil && len(*value) > 0 { @@ -129,7 +128,6 @@ func (rt *RefreshToken) assignValues(columns []string, values []interface{}) err rt.ClaimsEmailVerified = value.Bool } case refreshtoken.FieldClaimsGroups: - if value, ok := values[i].(*[]byte); !ok { return fmt.Errorf("unexpected type %T for field claims_groups", values[i]) } else if value != nil && len(*value) > 0 { diff --git a/storage/ent/db/refreshtoken_create.go b/storage/ent/db/refreshtoken_create.go index e73f276a59..00d29775d5 100644 --- a/storage/ent/db/refreshtoken_create.go +++ b/storage/ent/db/refreshtoken_create.go @@ -183,11 +183,17 @@ func (rtc *RefreshTokenCreate) Save(ctx context.Context) (*RefreshToken, error) return nil, err } rtc.mutation = mutation - node, err = rtc.sqlSave(ctx) + if node, err = rtc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID mutation.done = true return node, err }) for i := len(rtc.hooks) - 1; i >= 0; i-- { + if rtc.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = rtc.hooks[i](mut) } if _, err := mut.Mutate(ctx, rtc.mutation); err != nil { @@ -206,6 +212,19 @@ func (rtc *RefreshTokenCreate) SaveX(ctx context.Context) *RefreshToken { return v } +// Exec executes the query. +func (rtc *RefreshTokenCreate) Exec(ctx context.Context) error { + _, err := rtc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (rtc *RefreshTokenCreate) ExecX(ctx context.Context) { + if err := rtc.Exec(ctx); err != nil { + panic(err) + } +} + // defaults sets the default values of the builder before save. func (rtc *RefreshTokenCreate) defaults() { if _, ok := rtc.mutation.ClaimsPreferredUsername(); !ok { @@ -233,74 +252,74 @@ func (rtc *RefreshTokenCreate) defaults() { // check runs all checks and user-defined validators on the builder. func (rtc *RefreshTokenCreate) check() error { if _, ok := rtc.mutation.ClientID(); !ok { - return &ValidationError{Name: "client_id", err: errors.New("db: missing required field \"client_id\"")} + return &ValidationError{Name: "client_id", err: errors.New(`db: missing required field "client_id"`)} } if v, ok := rtc.mutation.ClientID(); ok { if err := refreshtoken.ClientIDValidator(v); err != nil { - return &ValidationError{Name: "client_id", err: fmt.Errorf("db: validator failed for field \"client_id\": %w", err)} + return &ValidationError{Name: "client_id", err: fmt.Errorf(`db: validator failed for field "client_id": %w`, err)} } } if _, ok := rtc.mutation.Nonce(); !ok { - return &ValidationError{Name: "nonce", err: errors.New("db: missing required field \"nonce\"")} + return &ValidationError{Name: "nonce", err: errors.New(`db: missing required field "nonce"`)} } if v, ok := rtc.mutation.Nonce(); ok { if err := refreshtoken.NonceValidator(v); err != nil { - return &ValidationError{Name: "nonce", err: fmt.Errorf("db: validator failed for field \"nonce\": %w", err)} + return &ValidationError{Name: "nonce", err: fmt.Errorf(`db: validator failed for field "nonce": %w`, err)} } } if _, ok := rtc.mutation.ClaimsUserID(); !ok { - return &ValidationError{Name: "claims_user_id", err: errors.New("db: missing required field \"claims_user_id\"")} + return &ValidationError{Name: "claims_user_id", err: errors.New(`db: missing required field "claims_user_id"`)} } if v, ok := rtc.mutation.ClaimsUserID(); ok { if err := refreshtoken.ClaimsUserIDValidator(v); err != nil { - return &ValidationError{Name: "claims_user_id", err: fmt.Errorf("db: validator failed for field \"claims_user_id\": %w", err)} + return &ValidationError{Name: "claims_user_id", err: fmt.Errorf(`db: validator failed for field "claims_user_id": %w`, err)} } } if _, ok := rtc.mutation.ClaimsUsername(); !ok { - return &ValidationError{Name: "claims_username", err: errors.New("db: missing required field \"claims_username\"")} + return &ValidationError{Name: "claims_username", err: errors.New(`db: missing required field "claims_username"`)} } if v, ok := rtc.mutation.ClaimsUsername(); ok { if err := refreshtoken.ClaimsUsernameValidator(v); err != nil { - return &ValidationError{Name: "claims_username", err: fmt.Errorf("db: validator failed for field \"claims_username\": %w", err)} + return &ValidationError{Name: "claims_username", err: fmt.Errorf(`db: validator failed for field "claims_username": %w`, err)} } } if _, ok := rtc.mutation.ClaimsEmail(); !ok { - return &ValidationError{Name: "claims_email", err: errors.New("db: missing required field \"claims_email\"")} + return &ValidationError{Name: "claims_email", err: errors.New(`db: missing required field "claims_email"`)} } if v, ok := rtc.mutation.ClaimsEmail(); ok { if err := refreshtoken.ClaimsEmailValidator(v); err != nil { - return &ValidationError{Name: "claims_email", err: fmt.Errorf("db: validator failed for field \"claims_email\": %w", err)} + return &ValidationError{Name: "claims_email", err: fmt.Errorf(`db: validator failed for field "claims_email": %w`, err)} } } if _, ok := rtc.mutation.ClaimsEmailVerified(); !ok { - return &ValidationError{Name: "claims_email_verified", err: errors.New("db: missing required field \"claims_email_verified\"")} + return &ValidationError{Name: "claims_email_verified", err: errors.New(`db: missing required field "claims_email_verified"`)} } if _, ok := rtc.mutation.ClaimsPreferredUsername(); !ok { - return &ValidationError{Name: "claims_preferred_username", err: errors.New("db: missing required field \"claims_preferred_username\"")} + return &ValidationError{Name: "claims_preferred_username", err: errors.New(`db: missing required field "claims_preferred_username"`)} } if _, ok := rtc.mutation.ConnectorID(); !ok { - return &ValidationError{Name: "connector_id", err: errors.New("db: missing required field \"connector_id\"")} + return &ValidationError{Name: "connector_id", err: errors.New(`db: missing required field "connector_id"`)} } if v, ok := rtc.mutation.ConnectorID(); ok { if err := refreshtoken.ConnectorIDValidator(v); err != nil { - return &ValidationError{Name: "connector_id", err: fmt.Errorf("db: validator failed for field \"connector_id\": %w", err)} + return &ValidationError{Name: "connector_id", err: fmt.Errorf(`db: validator failed for field "connector_id": %w`, err)} } } if _, ok := rtc.mutation.Token(); !ok { - return &ValidationError{Name: "token", err: errors.New("db: missing required field \"token\"")} + return &ValidationError{Name: "token", err: errors.New(`db: missing required field "token"`)} } if _, ok := rtc.mutation.ObsoleteToken(); !ok { - return &ValidationError{Name: "obsolete_token", err: errors.New("db: missing required field \"obsolete_token\"")} + return &ValidationError{Name: "obsolete_token", err: errors.New(`db: missing required field "obsolete_token"`)} } if _, ok := rtc.mutation.CreatedAt(); !ok { - return &ValidationError{Name: "created_at", err: errors.New("db: missing required field \"created_at\"")} + return &ValidationError{Name: "created_at", err: errors.New(`db: missing required field "created_at"`)} } if _, ok := rtc.mutation.LastUsed(); !ok { - return &ValidationError{Name: "last_used", err: errors.New("db: missing required field \"last_used\"")} + return &ValidationError{Name: "last_used", err: errors.New(`db: missing required field "last_used"`)} } if v, ok := rtc.mutation.ID(); ok { if err := refreshtoken.IDValidator(v); err != nil { - return &ValidationError{Name: "id", err: fmt.Errorf("db: validator failed for field \"id\": %w", err)} + return &ValidationError{Name: "id", err: fmt.Errorf(`db: validator failed for field "id": %w`, err)} } } return nil @@ -309,8 +328,8 @@ func (rtc *RefreshTokenCreate) check() error { func (rtc *RefreshTokenCreate) sqlSave(ctx context.Context) (*RefreshToken, error) { _node, _spec := rtc.createSpec() if err := sqlgraph.CreateNode(ctx, rtc.driver, _spec); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } @@ -484,17 +503,19 @@ func (rtcb *RefreshTokenCreateBulk) Save(ctx context.Context) ([]*RefreshToken, if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, rtcb.builders[i+1].mutation) } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} // Invoke the actual operation on the latest mutation in the chain. - if err = sqlgraph.BatchCreate(ctx, rtcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil { - if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + if err = sqlgraph.BatchCreate(ctx, rtcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } } } - mutation.done = true if err != nil { return nil, err } + mutation.id = &nodes[i].ID + mutation.done = true return nodes[i], nil }) for i := len(builder.hooks) - 1; i >= 0; i-- { @@ -519,3 +540,16 @@ func (rtcb *RefreshTokenCreateBulk) SaveX(ctx context.Context) []*RefreshToken { } return v } + +// Exec executes the query. +func (rtcb *RefreshTokenCreateBulk) Exec(ctx context.Context) error { + _, err := rtcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (rtcb *RefreshTokenCreateBulk) ExecX(ctx context.Context) { + if err := rtcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/storage/ent/db/refreshtoken_delete.go b/storage/ent/db/refreshtoken_delete.go index 34671548be..e5c882bb33 100644 --- a/storage/ent/db/refreshtoken_delete.go +++ b/storage/ent/db/refreshtoken_delete.go @@ -20,9 +20,9 @@ type RefreshTokenDelete struct { mutation *RefreshTokenMutation } -// Where adds a new predicate to the RefreshTokenDelete builder. +// Where appends a list predicates to the RefreshTokenDelete builder. func (rtd *RefreshTokenDelete) Where(ps ...predicate.RefreshToken) *RefreshTokenDelete { - rtd.mutation.predicates = append(rtd.mutation.predicates, ps...) + rtd.mutation.Where(ps...) return rtd } @@ -46,6 +46,9 @@ func (rtd *RefreshTokenDelete) Exec(ctx context.Context) (int, error) { return affected, err }) for i := len(rtd.hooks) - 1; i >= 0; i-- { + if rtd.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = rtd.hooks[i](mut) } if _, err := mut.Mutate(ctx, rtd.mutation); err != nil { diff --git a/storage/ent/db/refreshtoken_query.go b/storage/ent/db/refreshtoken_query.go index 503e606f3d..2ee4d4f972 100644 --- a/storage/ent/db/refreshtoken_query.go +++ b/storage/ent/db/refreshtoken_query.go @@ -287,8 +287,8 @@ func (rtq *RefreshTokenQuery) GroupBy(field string, fields ...string) *RefreshTo // Select(refreshtoken.FieldClientID). // Scan(ctx, &v) // -func (rtq *RefreshTokenQuery) Select(field string, fields ...string) *RefreshTokenSelect { - rtq.fields = append([]string{field}, fields...) +func (rtq *RefreshTokenQuery) Select(fields ...string) *RefreshTokenSelect { + rtq.fields = append(rtq.fields, fields...) return &RefreshTokenSelect{RefreshTokenQuery: rtq} } @@ -398,10 +398,14 @@ func (rtq *RefreshTokenQuery) querySpec() *sqlgraph.QuerySpec { func (rtq *RefreshTokenQuery) sqlQuery(ctx context.Context) *sql.Selector { builder := sql.Dialect(rtq.driver.Dialect()) t1 := builder.Table(refreshtoken.Table) - selector := builder.Select(t1.Columns(refreshtoken.Columns...)...).From(t1) + columns := rtq.fields + if len(columns) == 0 { + columns = refreshtoken.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) if rtq.sql != nil { selector = rtq.sql - selector.Select(selector.Columns(refreshtoken.Columns...)...) + selector.Select(selector.Columns(columns...)...) } for _, p := range rtq.predicates { p(selector) @@ -669,13 +673,24 @@ func (rtgb *RefreshTokenGroupBy) sqlScan(ctx context.Context, v interface{}) err } func (rtgb *RefreshTokenGroupBy) sqlQuery() *sql.Selector { - selector := rtgb.sql - columns := make([]string, 0, len(rtgb.fields)+len(rtgb.fns)) - columns = append(columns, rtgb.fields...) + selector := rtgb.sql.Select() + aggregation := make([]string, 0, len(rtgb.fns)) for _, fn := range rtgb.fns { - columns = append(columns, fn(selector)) + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(rtgb.fields)+len(rtgb.fns)) + for _, f := range rtgb.fields { + columns = append(columns, selector.C(f)) + } + for _, c := range aggregation { + columns = append(columns, c) + } + selector.Select(columns...) } - return selector.Select(columns...).GroupBy(rtgb.fields...) + return selector.GroupBy(selector.Columns(rtgb.fields...)...) } // RefreshTokenSelect is the builder for selecting fields of RefreshToken entities. @@ -891,16 +906,10 @@ func (rts *RefreshTokenSelect) BoolX(ctx context.Context) bool { func (rts *RefreshTokenSelect) sqlScan(ctx context.Context, v interface{}) error { rows := &sql.Rows{} - query, args := rts.sqlQuery().Query() + query, args := rts.sql.Query() if err := rts.driver.Query(ctx, query, args, rows); err != nil { return err } defer rows.Close() return sql.ScanSlice(rows, v) } - -func (rts *RefreshTokenSelect) sqlQuery() sql.Querier { - selector := rts.sql - selector.Select(selector.Columns(rts.fields...)...) - return selector -} diff --git a/storage/ent/db/refreshtoken_update.go b/storage/ent/db/refreshtoken_update.go index 87ccfcd059..913666bb55 100644 --- a/storage/ent/db/refreshtoken_update.go +++ b/storage/ent/db/refreshtoken_update.go @@ -21,9 +21,9 @@ type RefreshTokenUpdate struct { mutation *RefreshTokenMutation } -// Where adds a new predicate for the RefreshTokenUpdate builder. +// Where appends a list predicates to the RefreshTokenUpdate builder. func (rtu *RefreshTokenUpdate) Where(ps ...predicate.RefreshToken) *RefreshTokenUpdate { - rtu.mutation.predicates = append(rtu.mutation.predicates, ps...) + rtu.mutation.Where(ps...) return rtu } @@ -206,6 +206,9 @@ func (rtu *RefreshTokenUpdate) Save(ctx context.Context) (int, error) { return affected, err }) for i := len(rtu.hooks) - 1; i >= 0; i-- { + if rtu.hooks[i] == nil { + return 0, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = rtu.hooks[i](mut) } if _, err := mut.Mutate(ctx, rtu.mutation); err != nil { @@ -416,8 +419,8 @@ func (rtu *RefreshTokenUpdate) sqlSave(ctx context.Context) (n int, err error) { if n, err = sqlgraph.UpdateNodes(ctx, rtu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{refreshtoken.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return 0, err } @@ -618,6 +621,9 @@ func (rtuo *RefreshTokenUpdateOne) Save(ctx context.Context) (*RefreshToken, err return node, err }) for i := len(rtuo.hooks) - 1; i >= 0; i-- { + if rtuo.hooks[i] == nil { + return nil, fmt.Errorf("db: uninitialized hook (forgotten import db/runtime?)") + } mut = rtuo.hooks[i](mut) } if _, err := mut.Mutate(ctx, rtuo.mutation); err != nil { @@ -848,8 +854,8 @@ func (rtuo *RefreshTokenUpdateOne) sqlSave(ctx context.Context) (_node *RefreshT if err = sqlgraph.UpdateNode(ctx, rtuo.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{refreshtoken.Label} - } else if cerr, ok := isSQLConstraintError(err); ok { - err = cerr + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} } return nil, err } diff --git a/storage/ent/db/runtime.go b/storage/ent/db/runtime.go index 49f4157ac0..d3123b3fe9 100644 --- a/storage/ent/db/runtime.go +++ b/storage/ent/db/runtime.go @@ -99,7 +99,21 @@ func init() { // connectorDescID is the schema descriptor for id field. connectorDescID := connectorFields[0].Descriptor() // connector.IDValidator is a validator for the "id" field. It is called by the builders before save. - connector.IDValidator = connectorDescID.Validators[0].(func(string) error) + connector.IDValidator = func() func(string) error { + validators := connectorDescID.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(id string) error { + for _, fn := range fns { + if err := fn(id); err != nil { + return err + } + } + return nil + } + }() devicerequestFields := schema.DeviceRequest{}.Fields() _ = devicerequestFields // devicerequestDescUserCode is the schema descriptor for user_code field. @@ -151,7 +165,21 @@ func init() { // oauth2clientDescID is the schema descriptor for id field. oauth2clientDescID := oauth2clientFields[0].Descriptor() // oauth2client.IDValidator is a validator for the "id" field. It is called by the builders before save. - oauth2client.IDValidator = oauth2clientDescID.Validators[0].(func(string) error) + oauth2client.IDValidator = func() func(string) error { + validators := oauth2clientDescID.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(id string) error { + for _, fn := range fns { + if err := fn(id); err != nil { + return err + } + } + return nil + } + }() offlinesessionFields := schema.OfflineSession{}.Fields() _ = offlinesessionFields // offlinesessionDescUserID is the schema descriptor for user_id field. diff --git a/storage/ent/db/runtime/runtime.go b/storage/ent/db/runtime/runtime.go index 6f056d2df9..b52d54b64a 100644 --- a/storage/ent/db/runtime/runtime.go +++ b/storage/ent/db/runtime/runtime.go @@ -5,6 +5,6 @@ package runtime // The schema-stitching logic is generated in github.com/dexidp/dex/storage/ent/db/runtime.go const ( - Version = "v0.8.0" // Version of ent codegen. - Sum = "h1:xirrW//1oda7pp0bz+XssSOv4/C3nmgYQOxjIfljFt8=" // Sum of ent codegen. + Version = "v0.9.0" // Version of ent codegen. + Sum = "h1:2S1zfpMMW6p+wctj6kcYUprNPNjLWFW06T5MdyAfmWc=" // Sum of ent codegen. ) diff --git a/storage/ent/mysql.go b/storage/ent/mysql.go new file mode 100644 index 0000000000..f7c4909e46 --- /dev/null +++ b/storage/ent/mysql.go @@ -0,0 +1,161 @@ +package ent + +import ( + "context" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "database/sql" + "fmt" + "net" + "os" + "strconv" + "time" + + entSQL "entgo.io/ent/dialect/sql" + "github.com/go-sql-driver/mysql" + + // Register postgres driver. + _ "github.com/lib/pq" + + "github.com/dexidp/dex/pkg/log" + "github.com/dexidp/dex/storage" + "github.com/dexidp/dex/storage/ent/client" + "github.com/dexidp/dex/storage/ent/db" +) + +const ( + // MySQL SSL modes + mysqlSSLTrue = "true" + mysqlSSLFalse = "false" + mysqlSSLSkipVerify = "skip-verify" + mysqlSSLCustom = "custom" +) + +// MySQL options for creating an SQL db. +type MySQL struct { + NetworkDB + + SSL SSL `json:"ssl"` + + params map[string]string +} + +// Open always returns a new in sqlite3 storage. +func (m *MySQL) Open(logger log.Logger) (storage.Storage, error) { + logger.Debug("experimental ent-based storage driver is enabled") + drv, err := m.driver() + if err != nil { + return nil, err + } + + databaseClient := client.NewDatabase( + client.WithClient(db.NewClient(db.Driver(drv))), + client.WithHasher(sha256.New), + // Set tx isolation leve for each transaction as dex does for postgres + client.WithTxIsolationLevel(sql.LevelSerializable), + ) + + if err := databaseClient.Schema().Create(context.TODO()); err != nil { + return nil, err + } + + return databaseClient, nil +} + +func (m *MySQL) driver() (*entSQL.Driver, error) { + var tlsConfig string + + switch { + case m.SSL.CAFile != "" || m.SSL.CertFile != "" || m.SSL.KeyFile != "": + if err := m.makeTLSConfig(); err != nil { + return nil, fmt.Errorf("failed to make TLS config: %v", err) + } + tlsConfig = mysqlSSLCustom + case m.SSL.Mode == "": + tlsConfig = mysqlSSLTrue + default: + tlsConfig = m.SSL.Mode + } + + drv, err := entSQL.Open("mysql", m.dsn(tlsConfig)) + if err != nil { + return nil, err + } + + if m.MaxIdleConns == 0 { + /* Override default behaviour to fix https://github.com/dexidp/dex/issues/1608 */ + drv.DB().SetMaxIdleConns(0) + } else { + drv.DB().SetMaxIdleConns(m.MaxIdleConns) + } + + return drv, nil +} + +func (m *MySQL) dsn(tlsConfig string) string { + cfg := mysql.Config{ + User: m.User, + Passwd: m.Password, + DBName: m.Database, + AllowNativePasswords: true, + + Timeout: time.Second * time.Duration(m.ConnectionTimeout), + + TLSConfig: tlsConfig, + + ParseTime: true, + Params: make(map[string]string), + } + + if m.Host != "" { + if m.Host[0] != '/' { + cfg.Net = "tcp" + cfg.Addr = m.Host + + if m.Port != 0 { + cfg.Addr = net.JoinHostPort(m.Host, strconv.Itoa(int(m.Port))) + } + } else { + cfg.Net = "unix" + cfg.Addr = m.Host + } + } + + for k, v := range m.params { + cfg.Params[k] = v + } + + return cfg.FormatDSN() +} + +func (m *MySQL) makeTLSConfig() error { + cfg := &tls.Config{} + + if m.SSL.CAFile != "" { + rootCertPool := x509.NewCertPool() + + pem, err := os.ReadFile(m.SSL.CAFile) + if err != nil { + return err + } + + if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { + return fmt.Errorf("failed to append PEM") + } + cfg.RootCAs = rootCertPool + } + + if m.SSL.CertFile != "" && m.SSL.KeyFile != "" { + clientCert := make([]tls.Certificate, 0, 1) + certs, err := tls.LoadX509KeyPair(m.SSL.CertFile, m.SSL.KeyFile) + if err != nil { + return err + } + clientCert = append(clientCert, certs) + cfg.Certificates = clientCert + } + + mysql.RegisterTLSConfig(mysqlSSLCustom, cfg) + return nil +} diff --git a/storage/ent/mysql_test.go b/storage/ent/mysql_test.go new file mode 100644 index 0000000000..6c2dfa1ddf --- /dev/null +++ b/storage/ent/mysql_test.go @@ -0,0 +1,150 @@ +package ent + +import ( + "os" + "strconv" + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + + "github.com/dexidp/dex/storage" + "github.com/dexidp/dex/storage/conformance" +) + +const ( + MySQLEntHostEnv = "DEX_MYSQL_ENT_HOST" + MySQLEntPortEnv = "DEX_MYSQL_ENT_PORT" + MySQLEntDatabaseEnv = "DEX_MYSQL_ENT_DATABASE" + MySQLEntUserEnv = "DEX_MYSQL_ENT_USER" + MySQLEntPasswordEnv = "DEX_MYSQL_ENT_PASSWORD" +) + +func mysqlTestConfig(host string, port uint64) *MySQL { + return &MySQL{ + NetworkDB: NetworkDB{ + Database: getenv(MySQLEntDatabaseEnv, "mysql"), + User: getenv(MySQLEntUserEnv, "mysql"), + Password: getenv(MySQLEntPasswordEnv, "mysql"), + Host: host, + Port: uint16(port), + }, + SSL: SSL{ + Mode: mysqlSSLSkipVerify, + }, + params: map[string]string{ + "innodb_lock_wait_timeout": "1", + }, + } +} + +func newMySQLStorage(host string, port uint64) storage.Storage { + logger := &logrus.Logger{ + Out: os.Stderr, + Formatter: &logrus.TextFormatter{DisableColors: true}, + Level: logrus.DebugLevel, + } + + cfg := mysqlTestConfig(host, port) + s, err := cfg.Open(logger) + if err != nil { + panic(err) + } + return s +} + +func TestMySQL(t *testing.T) { + host := os.Getenv(MySQLEntHostEnv) + if host == "" { + t.Skipf("test environment variable %s not set, skipping", MySQLEntHostEnv) + } + + port := uint64(3306) + if rawPort := os.Getenv(MySQLEntPortEnv); rawPort != "" { + var err error + + port, err = strconv.ParseUint(rawPort, 10, 32) + require.NoError(t, err, "invalid mysql port %q: %s", rawPort, err) + } + + newStorage := func() storage.Storage { + return newMySQLStorage(host, port) + } + conformance.RunTests(t, newStorage) + conformance.RunTransactionTests(t, newStorage) +} + +func TestMySQLDSN(t *testing.T) { + tests := []struct { + name string + cfg *MySQL + desiredDSN string + }{ + { + name: "Host port", + cfg: &MySQL{ + NetworkDB: NetworkDB{ + Host: "localhost", + Port: uint16(3306), + }, + }, + desiredDSN: "tcp(localhost:3306)/?checkConnLiveness=false&parseTime=true&tls=false&maxAllowedPacket=0", + }, + { + name: "Host with port", + cfg: &MySQL{ + NetworkDB: NetworkDB{ + Host: "localhost:3306", + }, + }, + desiredDSN: "tcp(localhost:3306)/?checkConnLiveness=false&parseTime=true&tls=false&maxAllowedPacket=0", + }, + { + name: "Host ipv6 with port", + cfg: &MySQL{ + NetworkDB: NetworkDB{ + Host: "[a:b:c:d]:3306", + }, + }, + desiredDSN: "tcp([a:b:c:d]:3306)/?checkConnLiveness=false&parseTime=true&tls=false&maxAllowedPacket=0", + }, + { + name: "Credentials and timeout", + cfg: &MySQL{ + NetworkDB: NetworkDB{ + Database: "test", + User: "test", + Password: "test", + ConnectionTimeout: 5, + }, + }, + desiredDSN: "test:test@/test?checkConnLiveness=false&parseTime=true&timeout=5s&tls=false&maxAllowedPacket=0", + }, + { + name: "SSL", + cfg: &MySQL{ + SSL: SSL{ + CAFile: "/ca.crt", + KeyFile: "/cert.crt", + CertFile: "/cert.key", + }, + }, + desiredDSN: "/?checkConnLiveness=false&parseTime=true&tls=false&maxAllowedPacket=0", + }, + { + name: "With Params", + cfg: &MySQL{ + params: map[string]string{ + "innodb_lock_wait_timeout": "1", + }, + }, + desiredDSN: "/?checkConnLiveness=false&parseTime=true&tls=false&maxAllowedPacket=0&innodb_lock_wait_timeout=1", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.desiredDSN, tt.cfg.dsn(mysqlSSLFalse)) + }) + } +} diff --git a/storage/ent/postgres_test.go b/storage/ent/postgres_test.go index 8021e3a13d..c8e3a54df2 100644 --- a/storage/ent/postgres_test.go +++ b/storage/ent/postgres_test.go @@ -20,13 +20,6 @@ const ( PostgresEntPasswordEnv = "DEX_POSTGRES_ENT_PASSWORD" ) -func getenv(key, defaultVal string) string { - if val := os.Getenv(key); val != "" { - return val - } - return defaultVal -} - func postgresTestConfig(host string, port uint64) *Postgres { return &Postgres{ NetworkDB: NetworkDB{ diff --git a/storage/ent/schema/authcode.go b/storage/ent/schema/authcode.go index 1c7cdf5905..1574347b30 100644 --- a/storage/ent/schema/authcode.go +++ b/storage/ent/schema/authcode.go @@ -73,7 +73,8 @@ func (AuthCode) Fields() []ent.Field { field.Bytes("connector_data"). Nillable(). Optional(), - field.Time("expiry"), + field.Time("expiry"). + SchemaType(timeSchema), field.Text("code_challenge"). SchemaType(textSchema). Default(""), diff --git a/storage/ent/schema/authrequest.go b/storage/ent/schema/authrequest.go index a16fe55180..7d41e83082 100644 --- a/storage/ent/schema/authrequest.go +++ b/storage/ent/schema/authrequest.go @@ -77,7 +77,8 @@ func (AuthRequest) Fields() []ent.Field { field.Bytes("connector_data"). Nillable(). Optional(), - field.Time("expiry"), + field.Time("expiry"). + SchemaType(timeSchema), field.Text("code_challenge"). SchemaType(textSchema). diff --git a/storage/ent/schema/client.go b/storage/ent/schema/client.go index f00e84e5e7..b897c52a2e 100644 --- a/storage/ent/schema/client.go +++ b/storage/ent/schema/client.go @@ -28,6 +28,7 @@ func (OAuth2Client) Fields() []ent.Field { return []ent.Field{ field.Text("id"). SchemaType(textSchema). + MaxLen(100). NotEmpty(). Unique(), field.Text("secret"). diff --git a/storage/ent/schema/connector.go b/storage/ent/schema/connector.go index 436762e2ad..41b65eb4fb 100644 --- a/storage/ent/schema/connector.go +++ b/storage/ent/schema/connector.go @@ -26,6 +26,7 @@ func (Connector) Fields() []ent.Field { return []ent.Field{ field.Text("id"). SchemaType(textSchema). + MaxLen(100). NotEmpty(). Unique(), field.Text("type"). diff --git a/storage/ent/schema/devicerequest.go b/storage/ent/schema/devicerequest.go index 99931d5bc7..00a6138693 100644 --- a/storage/ent/schema/devicerequest.go +++ b/storage/ent/schema/devicerequest.go @@ -40,7 +40,8 @@ func (DeviceRequest) Fields() []ent.Field { NotEmpty(), field.JSON("scopes", []string{}). Optional(), - field.Time("expiry"), + field.Time("expiry"). + SchemaType(timeSchema), } } diff --git a/storage/ent/schema/devicetoken.go b/storage/ent/schema/devicetoken.go index f944051faf..29927e2b19 100644 --- a/storage/ent/schema/devicetoken.go +++ b/storage/ent/schema/devicetoken.go @@ -33,8 +33,10 @@ func (DeviceToken) Fields() []ent.Field { SchemaType(textSchema). NotEmpty(), field.Bytes("token").Nillable().Optional(), - field.Time("expiry"), - field.Time("last_request"), + field.Time("expiry"). + SchemaType(timeSchema), + field.Time("last_request"). + SchemaType(timeSchema), field.Int("poll_interval"), } } diff --git a/storage/ent/schema/dialects.go b/storage/ent/schema/dialects.go new file mode 100644 index 0000000000..2e5be8fb10 --- /dev/null +++ b/storage/ent/schema/dialects.go @@ -0,0 +1,21 @@ +package schema + +import ( + "entgo.io/ent/dialect" +) + +var textSchema = map[string]string{ + dialect.Postgres: "text", + dialect.SQLite: "text", + // MySQL doesn't support indices on text fields w/o + // specifying key length. Use varchar instead (767 byte + // is the max key length for InnoDB with 4k pages). + // For compound indexes (with two keys) even less. + dialect.MySQL: "varchar(384)", +} + +var timeSchema = map[string]string{ + dialect.Postgres: "timestamptz", + dialect.SQLite: "timestamp", + dialect.MySQL: "datetime(3)", +} diff --git a/storage/ent/schema/keys.go b/storage/ent/schema/keys.go index 58481edb2d..ec5cd3f6bb 100644 --- a/storage/ent/schema/keys.go +++ b/storage/ent/schema/keys.go @@ -34,7 +34,8 @@ func (Keys) Fields() []ent.Field { field.JSON("verification_keys", []storage.VerificationKey{}), field.JSON("signing_key", jose.JSONWebKey{}), field.JSON("signing_key_pub", jose.JSONWebKey{}), - field.Time("next_rotation"), + field.Time("next_rotation"). + SchemaType(timeSchema), } } diff --git a/storage/ent/schema/refreshtoken.go b/storage/ent/schema/refreshtoken.go index 00c640d44e..86e61d5276 100644 --- a/storage/ent/schema/refreshtoken.go +++ b/storage/ent/schema/refreshtoken.go @@ -81,8 +81,10 @@ func (RefreshToken) Fields() []ent.Field { Default(""), field.Time("created_at"). + SchemaType(timeSchema). Default(time.Now), field.Time("last_used"). + SchemaType(timeSchema). Default(time.Now), } } diff --git a/storage/ent/schema/types.go b/storage/ent/schema/types.go deleted file mode 100644 index f22b71d103..0000000000 --- a/storage/ent/schema/types.go +++ /dev/null @@ -1,9 +0,0 @@ -package schema - -import ( - "entgo.io/ent/dialect" -) - -var textSchema = map[string]string{ - dialect.SQLite: "text", -} diff --git a/storage/ent/sqlite.go b/storage/ent/sqlite.go index e6c43cd922..22866b6f0b 100644 --- a/storage/ent/sqlite.go +++ b/storage/ent/sqlite.go @@ -33,12 +33,10 @@ func (s *SQLite3) Open(logger log.Logger) (storage.Storage, error) { return nil, err } + // always allow only one connection to sqlite3, any other thread/go-routine + // attempting concurrent access will have to wait pool := drv.DB() - if s.File == ":memory:" { - // sqlite3 uses file locks to coordinate concurrent access. In memory - // doesn't support this, so limit the number of connections to 1. - pool.SetMaxOpenConns(1) - } + pool.SetMaxOpenConns(1) databaseClient := client.NewDatabase( client.WithClient(db.NewClient(db.Driver(drv))), diff --git a/storage/ent/sqlite_test.go b/storage/ent/sqlite_test.go index 10047b7fd6..301d769b4a 100644 --- a/storage/ent/sqlite_test.go +++ b/storage/ent/sqlite_test.go @@ -27,5 +27,4 @@ func newSQLiteStorage() storage.Storage { func TestSQLite3(t *testing.T) { conformance.RunTests(t, newSQLiteStorage) - conformance.RunTransactionTests(t, newSQLiteStorage) } diff --git a/storage/ent/utils.go b/storage/ent/utils.go new file mode 100644 index 0000000000..6f51e065c4 --- /dev/null +++ b/storage/ent/utils.go @@ -0,0 +1,10 @@ +package ent + +import "os" + +func getenv(key, defaultVal string) string { + if val := os.Getenv(key); val != "" { + return val + } + return defaultVal +} diff --git a/storage/kubernetes/client.go b/storage/kubernetes/client.go index 1769bf49f5..a5a72afa98 100644 --- a/storage/kubernetes/client.go +++ b/storage/kubernetes/client.go @@ -13,7 +13,6 @@ import ( "hash" "hash/fnv" "io" - "io/ioutil" "net" "net/http" "os" @@ -132,7 +131,7 @@ func checkHTTPErr(r *http.Response, validStatusCodes ...int) error { } } - body, err := ioutil.ReadAll(io.LimitReader(r.Body, 2<<15)) // 64 KiB + body, err := io.ReadAll(io.LimitReader(r.Body, 2<<15)) // 64 KiB if err != nil { return fmt.Errorf("read response body: %v", err) } @@ -156,7 +155,7 @@ func checkHTTPErr(r *http.Response, validStatusCodes ...int) error { // Close the response body. The initial request is drained so the connection can // be reused. func closeResp(r *http.Response) { - io.Copy(ioutil.Discard, r.Body) + io.Copy(io.Discard, r.Body) r.Body.Close() } @@ -312,7 +311,7 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, l if file == "" { return nil, nil } - return ioutil.ReadFile(file) + return os.ReadFile(file) } if caData, err := data(cluster.CertificateAuthorityData, cluster.CertificateAuthority); err != nil { @@ -379,7 +378,7 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, l } func loadKubeConfig(kubeConfigPath string) (cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, err error) { - data, err := ioutil.ReadFile(kubeConfigPath) + data, err := os.ReadFile(kubeConfigPath) if err != nil { err = fmt.Errorf("read %s: %v", kubeConfigPath, err) return @@ -425,7 +424,7 @@ func namespaceFromServiceAccountJWT(s string) (string, error) { } func namespaceFromFile(path string) (string, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return "", err } @@ -481,7 +480,7 @@ func inClusterConfig() (k8sapi.Cluster, k8sapi.AuthInfo, string, error) { CertificateAuthority: serviceAccountCAPath, } - token, err := ioutil.ReadFile(serviceAccountTokenPath) + token, err := os.ReadFile(serviceAccountTokenPath) if err != nil { return cluster, k8sapi.AuthInfo{}, "", err } diff --git a/storage/kubernetes/client_test.go b/storage/kubernetes/client_test.go index 5fee577423..cfd04857b6 100644 --- a/storage/kubernetes/client_test.go +++ b/storage/kubernetes/client_test.go @@ -3,7 +3,6 @@ package kubernetes import ( "hash" "hash/fnv" - "io/ioutil" "net/http" "os" "path/filepath" @@ -72,7 +71,7 @@ func TestInClusterTransport(t *testing.T) { fpath := filepath.Join(os.TempDir(), "test.in_cluster") defer os.RemoveAll(fpath) - err = ioutil.WriteFile(fpath, []byte("def"), 0644) + err = os.WriteFile(fpath, []byte("def"), 0o644) require.NoError(t, err) tests := []struct { @@ -136,7 +135,7 @@ func TestGetClusterConfigNamespace(t *testing.T) { var namespaceFile string { - tmpfile, err := ioutil.TempFile(os.TempDir(), "test-get-cluster-config-namespace") + tmpfile, err := os.CreateTemp(os.TempDir(), "test-get-cluster-config-namespace") require.NoError(t, err) _, err = tmpfile.Write([]byte("namespace-from-file")) diff --git a/storage/kubernetes/storage.go b/storage/kubernetes/storage.go index 13549ef5ff..ca505859bc 100644 --- a/storage/kubernetes/storage.go +++ b/storage/kubernetes/storage.go @@ -740,13 +740,14 @@ func retryOnConflict(ctx context.Context, action func() error) error { for { select { case <-time.After(getNextStep()): - if err := action(); err == nil || !isKubernetesAPIConflictError(err) { + err := action() + if err == nil || !isKubernetesAPIConflictError(err) { return err } attempts++ if attempts >= 4 { - return errors.New("maximum timeout reached while retrying a conflicted request") + return fmt.Errorf("maximum timeout reached while retrying a conflicted request: %w", err) } case <-ctx.Done(): return errors.New("canceled") diff --git a/storage/kubernetes/storage_test.go b/storage/kubernetes/storage_test.go index 5033ad06f8..4571327a15 100644 --- a/storage/kubernetes/storage_test.go +++ b/storage/kubernetes/storage_test.go @@ -262,7 +262,7 @@ func TestRetryOnConflict(t *testing.T) { { "Timeout reached", func() error { err := httpErr{status: 409}; return error(&err) }, - "maximum timeout reached while retrying a conflicted request", + "maximum timeout reached while retrying a conflicted request: Conflict: response from server \"\"", }, { "HTTP Error", diff --git a/storage/kubernetes/transport.go b/storage/kubernetes/transport.go index 984184c7ab..5d39c27fba 100644 --- a/storage/kubernetes/transport.go +++ b/storage/kubernetes/transport.go @@ -1,8 +1,8 @@ package kubernetes import ( - "io/ioutil" "net/http" + "os" "sync" "time" @@ -103,7 +103,7 @@ func (c *inClusterTransportHelper) UpdateToken() { return } - token, err := ioutil.ReadFile(c.tokenLocation) + token, err := os.ReadFile(c.tokenLocation) if err != nil { return } diff --git a/storage/sql/config.go b/storage/sql/config.go index 97ec6cb9b5..1aedf04cae 100644 --- a/storage/sql/config.go +++ b/storage/sql/config.go @@ -5,8 +5,8 @@ import ( "crypto/x509" "database/sql" "fmt" - "io/ioutil" "net" + "os" "regexp" "strconv" "strings" @@ -320,7 +320,7 @@ func (s *MySQL) makeTLSConfig() error { cfg := &tls.Config{} if s.SSL.CAFile != "" { rootCertPool := x509.NewCertPool() - pem, err := ioutil.ReadFile(s.SSL.CAFile) + pem, err := os.ReadFile(s.SSL.CAFile) if err != nil { return err }