diff --git a/.fleet/settings.json b/.fleet/settings.json new file mode 100644 index 0000000..af27bc6 --- /dev/null +++ b/.fleet/settings.json @@ -0,0 +1,21 @@ +{ + "editor.formatOnSave": true, + "plugins": [ + { + "type": "add", + "pluginName": "fleet.ai" + }, + { + "type": "add", + "pluginName": "fleet.go.ai" + }, + { + "type": "add", + "pluginName": "fleet.python.ai" + }, + { + "type": "add", + "pluginName": "fleet.rust.ai" + } + ] +} diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml new file mode 100644 index 0000000..c216d4a --- /dev/null +++ b/.github/workflows/build_and_test.yml @@ -0,0 +1,134 @@ +name: Go CI/CD + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.22" + - name: Verify workspace + run: go work sync + - name: Check formatting + run: | + all_formatted=true + for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + echo "Checking formatting in $dir" + if [ -n "$(gofmt -s -l $dir)" ]; then + echo "Formatting issues in $dir:" + gofmt -s -l $dir + all_formatted=false + else + echo "No formatting issues in $dir" + fi + done + if [ "$all_formatted" = false ]; then + echo "Formatting errors found. Please run 'go fmt ./...' in each module to fix." + exit 1 + fi + - name: Run go vet + run: | + for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + echo "Running go vet in $dir" + go vet ./$dir/... + done + + # - name: Run goimports + # run: | + # for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + # echo "Running goimports in $dir" + # goimports -l $dir + # done + + # - name: Run gocyclo + # run: | + # for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + # echo "Running gocyclo in $dir" + # gocyclo -over 15 $dir + # done + + # - name: Static check + # run: | + # for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + # echo "Running staticcheck in $dir" + # staticcheck $dir + # done + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.22" + - name: Run tests + run: | + go work use . + for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + echo "Running tests in $dir" + go test -v -race -coverprofile=$dir/coverage.txt -covermode=atomic ./$dir/... + done + - name: Combine coverage + run: | + echo "mode: atomic" > coverage.txt + for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + if [ -f $dir/coverage.txt ]; then + tail -n +2 $dir/coverage.txt >> coverage.txt + fi + done + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./coverage.txt + - name: Upload coverage artifact + uses: actions/upload-artifact@v2 + with: + name: coverage + path: coverage.txt + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.22" + - name: Build + run: | + for dir in $(go work edit -json | jq -r '.Use[].DiskPath'); do + echo "Building in $dir" + go build -v ./$dir/... + done + + deploy-coverage: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Download coverage artifact + uses: actions/download-artifact@v2 + with: + name: coverage + - name: Generate coverage HTML + run: | + go tool cover -html=coverage.txt -o coverage.html + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.TOKEN }} + publish_dir: . + publish_branch: gh-pages + keep_files: true + user_name: "github-actions[bot]" + user_email: "github-actions[bot]@users.noreply.github.com" + commit_message: "Deploy coverage report to GitHub Pages" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 76ebefe..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: CI/CD - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: 1.18 - - name: Test - run: go test ./... - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - - build: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build Docker image - run: docker build -t datavinci:${{ github.sha }} . - - name: Push to Docker Hub - run: | - echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin - docker push datavinci:${{ github.sha }} - - deploy: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Deploy to Kubernetes - run: | - # Add your Kubernetes deployment commands here - # kubectl apply -f k8s/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 507d2bf..badbb40 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,31 @@ # vendor/ # Go workspace file -go.work -go.work.sum +# go.work +# go.work.sum -.env \ No newline at end of file +.env +.fleet +.idea +.vscode +*.log +*.log.* +*.log-* +.DS_Store + + +node_modules + +web/node_modules +datavinci +ai +report +realtime + +/internal/auth/coverage.txt +/internal/datasource/coverage.txt +/internal/visualization/coverage.txt +/internal/realtime/coverage.txt +/internal/report/coverage.txt +/internal/ai/coverage.txt +/pkg/coverage.txt diff --git a/.idea/datavinci.iml b/.idea/datavinci.iml index 5d81a31..a524500 100644 --- a/.idea/datavinci.iml +++ b/.idea/datavinci.iml @@ -8,4 +8,4 @@ - \ No newline at end of file + diff --git a/.idea/modules.xml b/.idea/modules.xml index 61c7313..680c05c 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 35eb1dd..dcb6b8c 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,4 +3,4 @@ - \ No newline at end of file + diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..3b48062 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,52 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + args: [--allow-multiple-documents] + # - id: check-added-large-files + # args: [--maxkb=1000] + + # - repo: https://github.com/golangci/golangci-lint + # rev: v1.54.2 + # hooks: + # - id: golangci-lint + + - repo: https://github.com/dnephin/pre-commit-golang + rev: v0.5.1 + hooks: + - id: go-fmt + # - id: go-vet + # files: \.go$ + # exclude: ^datavinci/ + - id: go-imports + - id: go-cyclo + # args: [-over=15] + - id: validate-toml + - id: no-go-testing + # - id: go-critic + # args: [--disable=sloppyTypeAssert] + - id: go-unit-tests + - id: go-build + - id: go-mod-tidy + + # - repo: https://github.com/pre-commit/mirrors-prettier + # rev: v3.0.3 + # hooks: + # - id: prettier + # types_or: [javascript, jsx, ts, tsx, json] + # files: ^web/ + + # - repo: https://github.com/pre-commit/mirrors-eslint + # rev: v8.49.0 + # hooks: + # - id: eslint + # files: ^web/.*\.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx in web folder + # types: [file] + # additional_dependencies: + # - eslint@9.6.0 + # - typescript@5.2.2 + # - "@typescript-eslint/parser@6.7.0" + # - "@typescript-eslint/eslint-plugin@6.7.0" diff --git a/Dockerfile b/Dockerfile index a831bf4..bdbe614 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,4 +10,4 @@ FROM alpine:latest WORKDIR /root/ COPY --from=builder /app/datavinci . EXPOSE 8080 -CMD ["./datavinci"] \ No newline at end of file +CMD ["./datavinci"] diff --git a/README.md b/README.md index 8c362a0..3510fd4 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,16 @@ Run the tests with: ```bash go test ./... cd web && yarn test && cd .. + +// or + +go test -v -race -coverprofile=pkg/coverage.txt -covermode=atomic ./internal/auth/... +``` + +To ensure that the code meets our standards, run the pre-commit hooks: + +```bash +pre-commit run --all-files ``` ### Linting @@ -216,10 +226,95 @@ helm install datavinci deployments/helm Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) before submitting a pull request. -## License +## Pre-commit Hooks -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. +We use pre-commit hooks to ensure code quality and consistency. These hooks run automatically before each commit, checking your changes against our coding standards and running various linters. + +### Setup + +1. Install pre-commit: + ```bash + pip install pre-commit + ``` + +2. Install the git hook scripts: + ```bash + pre-commit install + ``` + +### Running pre-commit + +The hooks will run automatically on `git commit`. If you want to run the hooks manually (for example, to test them or run them on all files), you can use: + +```bash +pre-commit run --all-files ``` +### Our pre-commit hooks + +We use the following hooks: + +- **For Go:** + + - `go-fmt`: Formats Go code + - `go-vet`: Reports suspicious constructs + - `go-imports`: Updates import lines + - `go-cyclo`: Checks function complexity + - `golangci-lint`: Runs multiple Go linters + - `go-critic`: Provides extensive code analysis + - `go-unit-tests`: Runs Go unit tests + - `go-build`: Checks if the code builds + - `go-mod-tidy`: Runs `go mod tidy` + +- ** ensure that you have the following tools installed:** + + - `golangci-lint` + - `go-critic` + - `go-cyclo` + - `go-unit-tests` + - `go-build` + - `go-mod-tidy` + + ```bash + go install github.com/fzipp/gocyclo/cmd/gocyclo@latest + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + go install github.com/go-critic/go-critic/cmd/gocritic@latest + go install github.com/hexdigest/gounit/cmd/gounit@latest + go install github.com/securego/gosec/v2/cmd/gosec@latest + ``` + +- **For TypeScript/JavaScript:** + + - `prettier`: Formats code + - `eslint`: Lints JavaScript and TypeScript code + +- **General:** + - `trailing-whitespace`: Trims trailing whitespace + - `end-of-file-fixer`: Ensures files end with a newline + - `check-yaml`: Checks yaml files for parseable syntax + - `check-added-large-files`: Prevents giant files from being committed + +### Skipping hooks + +If you need to bypass the pre-commit hooks (not recommended), you can use: + +```bash +git commit -m "Your commit message" --no-verify ``` + +However, please use this sparingly and ensure your code still meets our standards. + +### Updating hooks + +To update the pre-commit hooks to the latest versions, run: + +```bash +pre-commit autoupdate +``` + +Then commit the changes to `.pre-commit-config.yaml`. + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/certs/postgresql.cnf b/certs/postgresql.cnf index 888d379..fa8ffc4 100644 --- a/certs/postgresql.cnf +++ b/certs/postgresql.cnf @@ -7,4 +7,4 @@ C = US ST = Nevada L = Las Vegas O = github.com/lib/pq -CN = pqgosslcert \ No newline at end of file +CN = pqgosslcert diff --git a/certs/root.cnf b/certs/root.cnf index 2e0d611..ea6def2 100644 --- a/certs/root.cnf +++ b/certs/root.cnf @@ -7,4 +7,4 @@ C = US ST = Nevada L = Las Vegas O = github.com/lib/pq -CN = pq CA \ No newline at end of file +CN = pq CA diff --git a/certs/server.cnf b/certs/server.cnf index 0c7f3a9..ba4b557 100644 --- a/certs/server.cnf +++ b/certs/server.cnf @@ -26,4 +26,4 @@ subjectKeyIdentifier = hash basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment subjectAltName = DNS:postgres -nsComment = "OpenSSL Generated Certificate" \ No newline at end of file +nsComment = "OpenSSL Generated Certificate" diff --git a/cmd/datavinci/main.go b/cmd/datavinci/main.go index a7b0c17..8139c1e 100644 --- a/cmd/datavinci/main.go +++ b/cmd/datavinci/main.go @@ -15,7 +15,7 @@ import ( func main() { // Set up a connection to the server. - conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("did not connect: %v", err) } @@ -30,7 +30,7 @@ func main() { // Connect to the data source connResp, err := c.Connect(ctx, &pb.ConnectRequest{ConnectorName: "mongo"}) if err != nil { - log.Fatalf("Could not connect: %v", err) + fmt.Printf("Could not connect: %v", err) } log.Printf("Connect Response: %t", connResp.GetSuccess()) @@ -54,7 +54,7 @@ func main() { Command: string(insertQueryJSON), }) if err != nil { - log.Fatalf("Could not insert data: %v", err) + fmt.Printf("Could not insert data: %v", err) } fmt.Println("Inserted test data successfully") @@ -70,7 +70,7 @@ func main() { Query: string(selectQueryJSON), }) if err != nil { - log.Fatalf("Could not query data: %v", err) + fmt.Printf("Could not query data: %v", err) } fmt.Println("Query results:") @@ -95,7 +95,7 @@ func main() { Command: string(updateQueryJSON), }) if err != nil { - log.Fatalf("Could not update data: %v", err) + fmt.Printf("Could not update data: %v", err) } fmt.Println("Updated data successfully") @@ -105,7 +105,7 @@ func main() { Query: string(selectQueryJSON), }) if err != nil { - log.Fatalf("Could not query updated data: %v", err) + fmt.Printf("Could not query updated data: %v", err) } fmt.Println("Updated query results:") for _, row := range queryResp.GetRows() { @@ -126,7 +126,7 @@ func main() { Command: string(deleteQueryJSON), }) if err != nil { - log.Fatalf("Could not delete data: %v", err) + fmt.Printf("Could not delete data: %v", err) } fmt.Println("Deleted data successfully") @@ -136,14 +136,14 @@ func main() { Query: string(selectQueryJSON), }) if err != nil { - log.Fatalf("Could not query after deletion: %v", err) + fmt.Printf("Could not query data after deletion: %v", err) } fmt.Printf("Number of results after deletion: %d\n", len(queryResp.GetRows())) // Disconnect from the data source disconnResp, err := c.Disconnect(ctx, &pb.DisconnectRequest{ConnectorName: "example_mongo"}) if err != nil { - log.Fatalf("Could not disconnect: %v", err) + fmt.Printf("Could not disconnect: %v", err) } log.Printf("Disconnect Response: %t", disconnResp.GetSuccess()) } diff --git a/deployments/k8s/deployment.yml b/deployments/k8s/deployment.yml index 571beb9..a542dd7 100644 --- a/deployments/k8s/deployment.yml +++ b/deployments/k8s/deployment.yml @@ -44,4 +44,4 @@ spec: - protocol: TCP port: 80 targetPort: 8080 - type: LoadBalancer \ No newline at end of file + type: LoadBalancer diff --git a/docker-compose.yml b/docker-compose.yml index 6e36c16..24651cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,4 +22,4 @@ services: - postgres_data:/var/lib/postgresql/data volumes: - postgres_data: \ No newline at end of file + postgres_data: diff --git a/go.mod b/go.mod index 5a699e5..0d25aa8 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ module datavinci -go 1.21 +go 1.22 -require google.golang.org/grpc v1.64.0 +toolchain go1.22.5 + +require google.golang.org/grpc v1.65.0 require ( - golang.org/x/net v0.22.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/protobuf v1.34.2 // indirect ) diff --git a/go.sum b/go.sum index 4808442..2a4541c 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,14 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/go.work b/go.work new file mode 100644 index 0000000..630b1a0 --- /dev/null +++ b/go.work @@ -0,0 +1,14 @@ +go 1.22 + +toolchain go1.22.5 + +use ( + . + ./internal/ai + ./internal/auth + ./internal/datasource + ./internal/realtime + ./internal/report + ./internal/visualization + ./pkg +) diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000..c8d0223 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,202 @@ +cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= +cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= +cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/brianvoe/gofakeit/v7 v7.0.4/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/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/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ= +github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= +github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= +github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lyft/protoc-gen-star/v2 v2.0.3 h1:/3+/2sWyXeMLzKd1bX+ixWKgEMsULrIivpDsuaF441o= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nats-io/nats.go v1.34.0 h1:fnxnPCNiwIG5w08rlMcEKTUw4AV/nKyGCOJE8TdhSPk= +github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= +github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/sagikazarmark/crypt v0.19.0 h1:WMyLTjHBo64UvNcWqpzY3pbZTYgnemZU8FBZigKc42E= +github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= +github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= +go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= +go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A= +go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= +go.etcd.io/etcd/client/v2 v2.305.12 h1:0m4ovXYo1CHaA/Mp3X/Fak5sRNIWf01wk/X1/G3sGKI= +go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E= +go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= +go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g= +golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU= +google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/img_1.png b/img_1.png deleted file mode 100644 index bdb8e5f..0000000 Binary files a/img_1.png and /dev/null differ diff --git a/internal/ai/main.go b/internal/ai/main.go new file mode 100644 index 0000000..24963e5 --- /dev/null +++ b/internal/ai/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("Hello, world!") +} diff --git a/internal/auth/api/proto/auth.proto b/internal/auth/api/proto/auth.proto index e22f539..7723446 100644 --- a/internal/auth/api/proto/auth.proto +++ b/internal/auth/api/proto/auth.proto @@ -97,4 +97,4 @@ message GetUserRequest { message GetUserResponse { User user = 1; -} \ No newline at end of file +} diff --git a/internal/auth/api/proto/authorization.proto b/internal/auth/api/proto/authorization.proto index 74800fe..6be0efd 100644 --- a/internal/auth/api/proto/authorization.proto +++ b/internal/auth/api/proto/authorization.proto @@ -118,4 +118,4 @@ message AddPermissionToRoleRequest { message RemovePermissionFromRoleRequest { string role_id = 1; Permission permission = 2; -} \ No newline at end of file +} diff --git a/internal/auth/api/proto/common.proto b/internal/auth/api/proto/common.proto index edeb398..37538aa 100644 --- a/internal/auth/api/proto/common.proto +++ b/internal/auth/api/proto/common.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package datavinci.auth; -option go_package = "datavinci/internal/auth/grpc"; +option go_package = "datavinci/internal/auth/grpc"; import "google/protobuf/timestamp.proto"; @@ -35,4 +35,4 @@ message Permission { message Error { string code = 1; string message = 2; -} \ No newline at end of file +} diff --git a/internal/auth/ent/client.go b/internal/auth/ent/client.go index 9e7e5a6..524af2a 100644 --- a/internal/auth/ent/client.go +++ b/internal/auth/ent/client.go @@ -658,7 +658,8 @@ func (c *UserClient) QueryTokens(u *User) *TokenQuery { // Hooks returns the client hooks. func (c *UserClient) Hooks() []Hook { - return c.hooks.User + hooks := c.hooks.User + return append(hooks[:len(hooks):len(hooks)], user.Hooks[:]...) } // Interceptors returns the client interceptors. diff --git a/internal/auth/ent/enttest/enttest.go b/internal/auth/ent/enttest/enttest.go index d05faea..bb0f943 100644 --- a/internal/auth/ent/enttest/enttest.go +++ b/internal/auth/ent/enttest/enttest.go @@ -5,6 +5,7 @@ package enttest import ( "auth/ent" "context" + // required by schema hooks. _ "auth/ent/runtime" diff --git a/internal/auth/ent/runtime.go b/internal/auth/ent/runtime.go index 081e005..a1528af 100644 --- a/internal/auth/ent/runtime.go +++ b/internal/auth/ent/runtime.go @@ -2,68 +2,4 @@ package ent -import ( - "auth/ent/role" - "auth/ent/schema" - "auth/ent/token" - "auth/ent/user" - "time" -) - -// The init function reads all schema descriptors with runtime code -// (default values, validators, hooks and policies) and stitches it -// to their package variables. -func init() { - roleFields := schema.Role{}.Fields() - _ = roleFields - // roleDescCreatedAt is the schema descriptor for created_at field. - roleDescCreatedAt := roleFields[3].Descriptor() - // role.DefaultCreatedAt holds the default value on creation for the created_at field. - role.DefaultCreatedAt = roleDescCreatedAt.Default.(func() time.Time) - // roleDescUpdatedAt is the schema descriptor for updated_at field. - roleDescUpdatedAt := roleFields[4].Descriptor() - // role.DefaultUpdatedAt holds the default value on creation for the updated_at field. - role.DefaultUpdatedAt = roleDescUpdatedAt.Default.(func() time.Time) - // role.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. - role.UpdateDefaultUpdatedAt = roleDescUpdatedAt.UpdateDefault.(func() time.Time) - // roleDescID is the schema descriptor for id field. - roleDescID := roleFields[0].Descriptor() - // role.DefaultID holds the default value on creation for the id field. - role.DefaultID = roleDescID.Default.(func() string) - tokenFields := schema.Token{}.Fields() - _ = tokenFields - // tokenDescRevoked is the schema descriptor for revoked field. - tokenDescRevoked := tokenFields[4].Descriptor() - // token.DefaultRevoked holds the default value on creation for the revoked field. - token.DefaultRevoked = tokenDescRevoked.Default.(bool) - // tokenDescCreatedAt is the schema descriptor for created_at field. - tokenDescCreatedAt := tokenFields[5].Descriptor() - // token.DefaultCreatedAt holds the default value on creation for the created_at field. - token.DefaultCreatedAt = tokenDescCreatedAt.Default.(func() time.Time) - // tokenDescUpdatedAt is the schema descriptor for updated_at field. - tokenDescUpdatedAt := tokenFields[6].Descriptor() - // token.DefaultUpdatedAt holds the default value on creation for the updated_at field. - token.DefaultUpdatedAt = tokenDescUpdatedAt.Default.(func() time.Time) - // token.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. - token.UpdateDefaultUpdatedAt = tokenDescUpdatedAt.UpdateDefault.(func() time.Time) - // tokenDescID is the schema descriptor for id field. - tokenDescID := tokenFields[0].Descriptor() - // token.DefaultID holds the default value on creation for the id field. - token.DefaultID = tokenDescID.Default.(func() string) - userFields := schema.User{}.Fields() - _ = userFields - // userDescCreatedAt is the schema descriptor for created_at field. - userDescCreatedAt := userFields[4].Descriptor() - // user.DefaultCreatedAt holds the default value on creation for the created_at field. - user.DefaultCreatedAt = userDescCreatedAt.Default.(func() time.Time) - // userDescUpdatedAt is the schema descriptor for updated_at field. - userDescUpdatedAt := userFields[5].Descriptor() - // user.DefaultUpdatedAt holds the default value on creation for the updated_at field. - user.DefaultUpdatedAt = userDescUpdatedAt.Default.(func() time.Time) - // user.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. - user.UpdateDefaultUpdatedAt = userDescUpdatedAt.UpdateDefault.(func() time.Time) - // userDescID is the schema descriptor for id field. - userDescID := userFields[0].Descriptor() - // user.DefaultID holds the default value on creation for the id field. - user.DefaultID = userDescID.Default.(func() string) -} +// The schema-stitching logic is generated in auth/ent/runtime/runtime.go diff --git a/internal/auth/ent/runtime/runtime.go b/internal/auth/ent/runtime/runtime.go index 36a66f9..954e583 100644 --- a/internal/auth/ent/runtime/runtime.go +++ b/internal/auth/ent/runtime/runtime.go @@ -2,7 +2,73 @@ package runtime -// The schema-stitching logic is generated in auth/ent/runtime.go +import ( + "auth/ent/role" + "auth/ent/schema" + "auth/ent/token" + "auth/ent/user" + "time" +) + +// The init function reads all schema descriptors with runtime code +// (default values, validators, hooks and policies) and stitches it +// to their package variables. +func init() { + roleFields := schema.Role{}.Fields() + _ = roleFields + // roleDescCreatedAt is the schema descriptor for created_at field. + roleDescCreatedAt := roleFields[3].Descriptor() + // role.DefaultCreatedAt holds the default value on creation for the created_at field. + role.DefaultCreatedAt = roleDescCreatedAt.Default.(func() time.Time) + // roleDescUpdatedAt is the schema descriptor for updated_at field. + roleDescUpdatedAt := roleFields[4].Descriptor() + // role.DefaultUpdatedAt holds the default value on creation for the updated_at field. + role.DefaultUpdatedAt = roleDescUpdatedAt.Default.(func() time.Time) + // role.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + role.UpdateDefaultUpdatedAt = roleDescUpdatedAt.UpdateDefault.(func() time.Time) + // roleDescID is the schema descriptor for id field. + roleDescID := roleFields[0].Descriptor() + // role.DefaultID holds the default value on creation for the id field. + role.DefaultID = roleDescID.Default.(func() string) + tokenFields := schema.Token{}.Fields() + _ = tokenFields + // tokenDescRevoked is the schema descriptor for revoked field. + tokenDescRevoked := tokenFields[4].Descriptor() + // token.DefaultRevoked holds the default value on creation for the revoked field. + token.DefaultRevoked = tokenDescRevoked.Default.(bool) + // tokenDescCreatedAt is the schema descriptor for created_at field. + tokenDescCreatedAt := tokenFields[5].Descriptor() + // token.DefaultCreatedAt holds the default value on creation for the created_at field. + token.DefaultCreatedAt = tokenDescCreatedAt.Default.(func() time.Time) + // tokenDescUpdatedAt is the schema descriptor for updated_at field. + tokenDescUpdatedAt := tokenFields[6].Descriptor() + // token.DefaultUpdatedAt holds the default value on creation for the updated_at field. + token.DefaultUpdatedAt = tokenDescUpdatedAt.Default.(func() time.Time) + // token.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + token.UpdateDefaultUpdatedAt = tokenDescUpdatedAt.UpdateDefault.(func() time.Time) + // tokenDescID is the schema descriptor for id field. + tokenDescID := tokenFields[0].Descriptor() + // token.DefaultID holds the default value on creation for the id field. + token.DefaultID = tokenDescID.Default.(func() string) + userHooks := schema.User{}.Hooks() + user.Hooks[0] = userHooks[0] + userFields := schema.User{}.Fields() + _ = userFields + // userDescCreatedAt is the schema descriptor for created_at field. + userDescCreatedAt := userFields[4].Descriptor() + // user.DefaultCreatedAt holds the default value on creation for the created_at field. + user.DefaultCreatedAt = userDescCreatedAt.Default.(func() time.Time) + // userDescUpdatedAt is the schema descriptor for updated_at field. + userDescUpdatedAt := userFields[5].Descriptor() + // user.DefaultUpdatedAt holds the default value on creation for the updated_at field. + user.DefaultUpdatedAt = userDescUpdatedAt.Default.(func() time.Time) + // user.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + user.UpdateDefaultUpdatedAt = userDescUpdatedAt.UpdateDefault.(func() time.Time) + // userDescID is the schema descriptor for id field. + userDescID := userFields[0].Descriptor() + // user.DefaultID holds the default value on creation for the id field. + user.DefaultID = userDescID.Default.(func() string) +} const ( Version = "v0.13.1" // Version of ent codegen. diff --git a/internal/auth/ent/schema/user.go b/internal/auth/ent/schema/user.go index be25caa..c6043eb 100644 --- a/internal/auth/ent/schema/user.go +++ b/internal/auth/ent/schema/user.go @@ -1,6 +1,7 @@ package schema import ( + "auth/pkg" "context" "time" @@ -8,7 +9,6 @@ import ( "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" "github.com/google/uuid" - "golang.org/x/crypto/bcrypt" ) // User holds the schema definition for the User entity. @@ -54,7 +54,7 @@ func HashPassword() ent.Hook { return func(next ent.Mutator) ent.Mutator { return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { if password, ok := m.Field("password"); ok { - hash, err := bcrypt.GenerateFromPassword([]byte(password.(string)), bcrypt.DefaultCost) + hash, err := pkg.NewPasswordHasher(12).HashPassword(password.(string)) // HLc if err != nil { return nil, err } diff --git a/internal/auth/ent/user/user.go b/internal/auth/ent/user/user.go index b153dfe..0838533 100644 --- a/internal/auth/ent/user/user.go +++ b/internal/auth/ent/user/user.go @@ -5,6 +5,7 @@ package user import ( "time" + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" ) @@ -70,7 +71,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "auth/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultCreatedAt holds the default value on creation for the "created_at" field. DefaultCreatedAt func() time.Time // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. diff --git a/internal/auth/ent/user_create.go b/internal/auth/ent/user_create.go index 8d6d56f..a408439 100644 --- a/internal/auth/ent/user_create.go +++ b/internal/auth/ent/user_create.go @@ -119,7 +119,9 @@ func (uc *UserCreate) Mutation() *UserMutation { // Save creates the User in the database. func (uc *UserCreate) Save(ctx context.Context) (*User, error) { - uc.defaults() + if err := uc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, uc.sqlSave, uc.mutation, uc.hooks) } @@ -146,19 +148,29 @@ func (uc *UserCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (uc *UserCreate) defaults() { +func (uc *UserCreate) defaults() error { if _, ok := uc.mutation.CreatedAt(); !ok { + if user.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized user.DefaultCreatedAt (forgotten import ent/runtime?)") + } v := user.DefaultCreatedAt() uc.mutation.SetCreatedAt(v) } if _, ok := uc.mutation.UpdatedAt(); !ok { + if user.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized user.DefaultUpdatedAt (forgotten import ent/runtime?)") + } v := user.DefaultUpdatedAt() uc.mutation.SetUpdatedAt(v) } if _, ok := uc.mutation.ID(); !ok { + if user.DefaultID == nil { + return fmt.Errorf("ent: uninitialized user.DefaultID (forgotten import ent/runtime?)") + } v := user.DefaultID() uc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/auth/ent/user_update.go b/internal/auth/ent/user_update.go index 72a1920..866d6be 100644 --- a/internal/auth/ent/user_update.go +++ b/internal/auth/ent/user_update.go @@ -171,7 +171,9 @@ func (uu *UserUpdate) RemoveTokens(t ...*Token) *UserUpdate { // Save executes the query and returns the number of nodes affected by the update operation. func (uu *UserUpdate) Save(ctx context.Context) (int, error) { - uu.defaults() + if err := uu.defaults(); err != nil { + return 0, err + } return withHooks(ctx, uu.sqlSave, uu.mutation, uu.hooks) } @@ -198,11 +200,15 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (uu *UserUpdate) defaults() { +func (uu *UserUpdate) defaults() error { if _, ok := uu.mutation.UpdatedAt(); !ok { + if user.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized user.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } v := user.UpdateDefaultUpdatedAt() uu.mutation.SetUpdatedAt(v) } + return nil } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { @@ -493,7 +499,9 @@ func (uuo *UserUpdateOne) Select(field string, fields ...string) *UserUpdateOne // Save executes the query and returns the updated User entity. func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { - uuo.defaults() + if err := uuo.defaults(); err != nil { + return nil, err + } return withHooks(ctx, uuo.sqlSave, uuo.mutation, uuo.hooks) } @@ -520,11 +528,15 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (uuo *UserUpdateOne) defaults() { +func (uuo *UserUpdateOne) defaults() error { if _, ok := uuo.mutation.UpdatedAt(); !ok { + if user.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized user.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } v := user.UpdateDefaultUpdatedAt() uuo.mutation.SetUpdatedAt(v) } + return nil } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) { diff --git a/internal/auth/go.mod b/internal/auth/go.mod index a7d7914..14da49e 100644 --- a/internal/auth/go.mod +++ b/internal/auth/go.mod @@ -1,25 +1,37 @@ module auth -go 1.21 +go 1.22 + +toolchain go1.22.5 require ( + github.com/brianvoe/gofakeit/v7 v7.0.4 github.com/go-redis/redis/v8 v8.11.5 github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/mattn/go-sqlite3 v1.14.16 + github.com/stretchr/testify v1.9.0 + go.uber.org/zap v1.21.0 golang.org/x/crypto v0.23.0 + golang.org/x/time v0.5.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 ) require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.21.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.20.0 // indirect - golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( diff --git a/internal/auth/go.sum b/internal/auth/go.sum index 81d9d35..8962c3d 100644 --- a/internal/auth/go.sum +++ b/internal/auth/go.sum @@ -8,18 +8,20 @@ github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tj github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/brianvoe/gofakeit/v7 v7.0.4 h1:Mkxwz9jYg8Ad8NvT9HA27pCMZGFQo08MK6jD0QTKEww= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/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= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= @@ -39,8 +41,9 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc= github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= -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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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= @@ -59,26 +62,29 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -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/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -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.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= 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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -131,6 +137,7 @@ google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6h google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/auth/internal/auth/service/auth_service.go b/internal/auth/internal/auth/service/auth_service.go index 3952433..f9ae89b 100644 --- a/internal/auth/internal/auth/service/auth_service.go +++ b/internal/auth/internal/auth/service/auth_service.go @@ -155,7 +155,7 @@ func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (*pb.Logi return nil, status.Errorf(codes.Internal, "Failed to fetch user: %v", err) } - if user == nil || !s.userRepo.CheckPassword(ctx, req.Password) { + if user == nil || !s.userRepo.CheckPassword(ctx, user.Username, req.Password) { return nil, status.Errorf(codes.Unauthenticated, "Invalid username or password") } diff --git a/internal/auth/internal/db/db.go b/internal/auth/internal/db/db.go index 0e92502..c68bfca 100644 --- a/internal/auth/internal/db/db.go +++ b/internal/auth/internal/db/db.go @@ -116,4 +116,4 @@ func ConnectRedis(redisURL string) (*redis.Client, error) { } return client, nil -} \ No newline at end of file +} diff --git a/internal/auth/internal/interceptor/interceptor.go b/internal/auth/internal/interceptor/interceptor.go index 9b2500f..105e8b3 100644 --- a/internal/auth/internal/interceptor/interceptor.go +++ b/internal/auth/internal/interceptor/interceptor.go @@ -8,24 +8,13 @@ package interceptor import ( "context" - "encoding/base64" - "fmt" - "strings" - "sync" "time" "github.com/dgrijalva/jwt-go" "github.com/patrickmn/go-cache" "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" "golang.org/x/time/rate" "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/peer" - "google.golang.org/grpc/status" - - "pkg/config" ) // contextKey is a custom type for context keys to avoid collisions. @@ -41,7 +30,7 @@ const ( // JWT authentication scheme. JWT AuthScheme = "Bearer" // APIKey authentication scheme. - APIKey AuthScheme = "ApiKey" + APIKey AuthScheme = "APIKey" ) // AuthInterceptorConfig holds the configuration for the AuthInterceptor. @@ -116,6 +105,13 @@ func WithTokenRefreshWindow(window time.Duration) AuthInterceptorOption { } } +// WithAPIKeyCache sets the cache for API key validation. +func WithAPIKeyCache(cache *cache.Cache) AuthInterceptorOption { + return func(config *AuthInterceptorConfig) { + config.APIKeyCache = cache + } +} + // NewAuthInterceptor creates a new AuthInterceptor with the given options. // // Usage: @@ -150,386 +146,26 @@ func NewAuthInterceptor(opts ...AuthInterceptorOption) grpc.UnaryServerIntercept // authInterceptor is the core function that performs the authentication. func authInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, config *AuthInterceptorConfig) (interface{}, error) { - // Apply rate limiting - if err := config.RateLimiter.Wait(ctx); err != nil { - config.Logger.Warn("Rate limit exceeded", zap.Error(err)) - return nil, status.Errorf(codes.ResourceExhausted, "Rate limit exceeded") - } - - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - config.Logger.Warn("Missing metadata") - return nil, status.Errorf(codes.Unauthenticated, "Missing metadata") - } - - authHeader, ok := md[config.MetadataKey] - if !ok || len(authHeader) == 0 { - config.Logger.Warn("Missing authorization header") - return nil, status.Errorf(codes.Unauthenticated, "Missing authorization header") - } - - authParts := strings.SplitN(authHeader[0], " ", 2) - if len(authParts) != 2 { - config.Logger.Warn("Invalid authorization header format") - return nil, status.Errorf(codes.Unauthenticated, "Invalid authorization header format") - } - - authScheme := AuthScheme(authParts[0]) - authToken := authParts[1] - - var claims jwt.MapClaims - var err error - - switch authScheme { - case JWT: - claims, err = config.TokenValidator(authToken) - if err != nil { - config.Logger.Warn("Invalid JWT token", zap.Error(err)) - return nil, status.Errorf(codes.Unauthenticated, "Invalid token: %v", err) - } - - // Check if token needs refresh - if exp, ok := claims["exp"].(float64); ok { - expTime := time.Unix(int64(exp), 0) - if time.Until(expTime) < config.TokenRefreshWindow { - newToken, err := config.RefreshTokenFunc(authToken) - if err != nil { - config.Logger.Warn("Failed to refresh token", zap.Error(err)) - } else { - // Add the new token to the outgoing context - md.Set("new-token", newToken) - ctx = metadata.NewOutgoingContext(ctx, md) - } - } - } - - case APIKey: - valid, err := validateAPIKey(authToken, config) - if err != nil || !valid { - config.Logger.Warn("Invalid API key", zap.Error(err)) - return nil, status.Errorf(codes.Unauthenticated, "Invalid API key") - } - claims = jwt.MapClaims{"api_key": authToken} - - default: - config.Logger.Warn("Unsupported authentication scheme", zap.String("scheme", string(authScheme))) - return nil, status.Errorf(codes.Unauthenticated, "Unsupported authentication scheme") - } - - newCtx := context.WithValue(ctx, userClaimsKey, claims) - - // Log the authenticated request - peer, _ := peer.FromContext(ctx) - config.Logger.Info("Authenticated request", - zap.String("method", info.FullMethod), - zap.String("peer", peer.Addr.String()), - zap.Any("claims", claims), - ) - - return handler(newCtx, req) -} - -// defaultTokenValidator is the default implementation of JWT token validation. -// -// This function parses and validates a JWT token using a secret key. -// In a production environment, you should replace this with your own -// implementation that uses your secret key and includes any additional -// validation logic specific to your application. -func defaultTokenValidator(tokenString string) (jwt.MapClaims, error) { - conf, err := config.Load() - if err != nil { + if err := validateConfig(config); err != nil { return nil, err } - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(conf.JWTSecret), nil - }) - if err != nil { + if err := applyRateLimiting(ctx, config); err != nil { return nil, err } - if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - return claims, nil - } - - return nil, fmt.Errorf("invalid token") -} - -// defaultAPIKeyValidator is the default implementation of API key validation. -func defaultAPIKeyValidator(apiKey string) (bool, error) { - validKeys := map[string]bool{ - // we will read from our database - } - - isValid, exists := validKeys[apiKey] - if !exists { - return false, nil - } - return isValid, nil -} - -// validateAPIKey checks the validity of an API key, using caching for performance. -func validateAPIKey(apiKey string, config *AuthInterceptorConfig) (bool, error) { - // Check cache first - if valid, found := config.APIKeyCache.Get(apiKey); found { - return valid.(bool), nil - } - - // If not in cache, validate using the provided validator - valid, err := config.APIKeyValidator(apiKey) + authToken, authScheme, err := extractAuthInfo(ctx, config) if err != nil { - return false, err - } - - // Cache the result - config.APIKeyCache.Set(apiKey, valid, cache.DefaultExpiration) - - return valid, nil -} - -// defaultRefreshTokenFunc is the default implementation of token refresh. -func defaultRefreshTokenFunc(oldToken string) (string, error) { - return "new-refreshed-token-" + oldToken[len(oldToken)-5:], nil -} - -// GetUserClaims retrieves the user claims from the context. -// -// This function can be used in your gRPC handlers to access the -// authenticated user's claims. -// -// Usage: -// -// func (s *server) SomeMethod(ctx context.Context, req *pb.Request) (*pb.Response, error) { -// claims, ok := interceptor.GetUserClaims(ctx) -// if !ok { -// return nil, status.Errorf(codes.Unauthenticated, "No user claims found") -// } -// // Use claims... -// } -func GetUserClaims(ctx context.Context) (jwt.MapClaims, bool) { - claims, ok := ctx.Value(userClaimsKey).(jwt.MapClaims) - return claims, ok -} - -// TokenGenerator is a helper struct for generating JWT tokens. -type TokenGenerator struct { - secretKey []byte - issuer string - duration time.Duration -} - -// NewTokenGenerator creates a new TokenGenerator. -func NewTokenGenerator(secretKey []byte, issuer string, duration time.Duration) *TokenGenerator { - return &TokenGenerator{ - secretKey: secretKey, - issuer: issuer, - duration: duration, - } -} - -// GenerateToken generates a new JWT token with the given claims. -func (g *TokenGenerator) GenerateToken(claims jwt.MapClaims) (string, error) { - now := time.Now() - claims["iss"] = g.issuer - claims["iat"] = now.Unix() - claims["exp"] = now.Add(g.duration).Unix() - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString(g.secretKey) -} - -// PerIPRateLimiter is a helper struct for per-IP rate limiting. -type PerIPRateLimiter struct { - ips map[string]*rate.Limiter - mu *sync.RWMutex - r rate.Limit - b int -} - -// NewPerIPRateLimiter creates a new PerIPRateLimiter. -func NewPerIPRateLimiter(r rate.Limit, b int) *PerIPRateLimiter { - return &PerIPRateLimiter{ - ips: make(map[string]*rate.Limiter), - mu: &sync.RWMutex{}, - r: r, - b: b, - } -} - -// AddIP adds an IP address to the rate limiter. -func (l *PerIPRateLimiter) AddIP(ip string) *rate.Limiter { - l.mu.Lock() - defer l.mu.Unlock() - - limiter := rate.NewLimiter(l.r, l.b) - l.ips[ip] = limiter - return limiter -} - -// GetLimiter returns the rate limiter for the given IP address. -func (l *PerIPRateLimiter) GetLimiter(ip string) *rate.Limiter { - l.mu.Lock() - limiter, exists := l.ips[ip] - - if !exists { - l.mu.Unlock() - return l.AddIP(ip) - } - - l.mu.Unlock() - return limiter -} - -// PasswordHasher is a helper struct for hashing and verifying passwords. -type PasswordHasher struct { - cost int -} - -// NewPasswordHasher creates a new PasswordHasher. -// -// Parameters: -// - cost: The cost of the bcrypt algorithm (default is 10). -// -// Usage: -// -// hasher := NewPasswordHasher(12) -func NewPasswordHasher(cost int) *PasswordHasher { - if cost == 0 { - cost = 10 + return nil, err } - return &PasswordHasher{cost: cost} -} - -// HashPassword hashes a password using bcrypt. -// -// Parameters: -// - password: The password to hash. -// -// Returns: -// - The hashed password and an error if hashing fails. -// -// Usage: -// -// hashedPassword, err := hasher.HashPassword("myPassword123") -func (ph *PasswordHasher) HashPassword(password string) (string, error) { - bytes, err := bcrypt.GenerateFromPassword([]byte(password), ph.cost) - return string(bytes), err -} -// CheckPassword checks if a password matches the hashed version. -// -// Parameters: -// - password: The password to check. -// - hashedPassword: The hashed password to compare against. -// -// Returns: -// - true if the password matches, false otherwise. -// -// Usage: -// -// if hasher.CheckPassword("myPassword123", hashedPassword) { -// // Password is correct -// } -func (ph *PasswordHasher) CheckPassword(password, hashedPassword string) bool { - err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) - return err == nil -} - -// Base64Encoder is a helper struct for encoding and decoding Base64 strings. -type Base64Encoder struct{} - -// NewBase64Encoder creates a new Base64Encoder. -// -// Usage: -// -// encoder := NewBase64Encoder() -func NewBase64Encoder() *Base64Encoder { - return &Base64Encoder{} -} - -// Encode encodes a string to Base64. -// -// Parameters: -// - data: The string to encode. -// -// Returns: -// - The Base64 encoded string. -// -// Usage: -// -// encoded := encoder.Encode("Hello, World!") -func (b *Base64Encoder) Encode(data string) string { - return base64.StdEncoding.EncodeToString([]byte(data)) -} - -// Decode decodes a Base64 string. -// -// Parameters: -// - encodedData: The Base64 encoded string to decode. -// -// Returns: -// - The decoded string and an error if decoding fails. -// -// Usage: -// -// decoded, err := encoder.Decode(encodedString) -func (b *Base64Encoder) Decode(encodedData string) (string, error) { - data, err := base64.StdEncoding.DecodeString(encodedData) + claims, err := authenticateRequest(ctx, authToken, authScheme, config) if err != nil { - return "", err - } - return string(data), nil -} - -// AuthMetadataKey is a helper function to get the metadata key for authentication. -// -// Parameters: -// - ctx: The context from which to extract the metadata. -// -// Returns: -// - The authentication metadata key and a boolean indicating if it was found. -// -// Usage: -// -// key, ok := AuthMetadataKey(ctx) -// if !ok { -// return status.Errorf(codes.Unauthenticated, "Missing authentication metadata") -// } -func AuthMetadataKey(ctx context.Context) (string, bool) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return "", false - } - - values := md.Get("authorization") - if len(values) == 0 { - return "", false + return nil, err } - return values[0], true -} + newCtx := context.WithValue(ctx, userClaimsKey, claims) + logAuthenticatedRequest(newCtx, info, config, claims) -// ExtractBearerToken is a helper function to extract the Bearer token from an authorization header. -// -// Parameters: -// - authHeader: The full authorization header. -// -// Returns: -// - The Bearer token and an error if extraction fails. -// -// Usage: -// -// token, err := ExtractBearerToken(authHeader) -// if err != nil { -// return status.Errorf(codes.Unauthenticated, "Invalid authorization header") -// } -func ExtractBearerToken(authHeader string) (string, error) { - parts := strings.SplitN(authHeader, " ", 2) - if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { - return "", fmt.Errorf("invalid authorization header format") - } - return parts[1], nil + return handler(newCtx, req) } diff --git a/internal/auth/internal/interceptor/interceptor_test.go b/internal/auth/internal/interceptor/interceptor_test.go index b998447..17e1ca1 100644 --- a/internal/auth/internal/interceptor/interceptor_test.go +++ b/internal/auth/internal/interceptor/interceptor_test.go @@ -1,366 +1,91 @@ -package interceptor_test +package interceptor import ( - "auth/internal/interceptor" "context" - "fmt" - "log" - "net" "testing" "time" "github.com/dgrijalva/jwt-go" + "github.com/patrickmn/go-cache" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "go.uber.org/zap" + "golang.org/x/time/rate" "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/grpc/test/bufconn" - - pb "auth/pb" ) - -func (s *mockService) SayHello(ctx context.Context, req *HelloRequest) (*HelloResponse, error) { - claims, ok := interceptor.GetUserClaims(ctx) - if !ok { - return nil, status.Errorf(codes.Unauthenticated, "No user claims found") - } - return &HelloResponse{Message: fmt.Sprintf("Hello, %v!", claims["sub"])}, nil +func TestNewAuthInterceptor(t *testing.T) { + interceptor := NewAuthInterceptor() + assert.NotNil(t, interceptor) } -type HelloRequest struct{} -type HelloResponse struct { - Message string -} +func TestWithOptions(t *testing.T) { + logger := zap.NewExample() + tokenValidator := func(string) (jwt.MapClaims, error) { return nil, nil } + apiKeyValidator := func(string) (bool, error) { return true, nil } + refreshFunc := func(string) (string, error) { return "", nil } + cache := cache.New(5*time.Minute, 10*time.Minute) -const bufSize = 1024 * 1024 - -var lis *bufconn.Listener - -func init() { - lis = bufconn.Listen(bufSize) -} + interceptor := NewAuthInterceptor( + WithLogger(logger), + WithTokenValidator(tokenValidator), + WithAPIKeyValidator(apiKeyValidator), + WithMetadataKey("custom-auth"), + WithRateLimiter(rate.NewLimiter(rate.Every(time.Second), 5)), + WithRefreshTokenFunc(refreshFunc), + WithSupportedSchemes(JWT, APIKey), + WithTokenRefreshWindow(10*time.Minute), + WithAPIKeyCache(cache), + ) -type mockService struct { - pb.UnimplementedAuthServiceServer + assert.NotNil(t, interceptor) } -func (s *mockService) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { - claims, ok := interceptor.GetUserClaims(ctx) - if !ok { - return nil, status.Errorf(codes.Unauthenticated, "No user claims found") +func TestAuthInterceptor(t *testing.T) { + config := &AuthInterceptorConfig{ + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123"}, nil + }, + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "valid-api-key", nil + }, + MetadataKey: "authorization", + Logger: zap.NewNop(), + SupportedSchemes: []AuthScheme{JWT, APIKey}, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), // Add this line } - return &pb.LoginResponse{AccessToken: claims["sub"].(string)}, nil -} - -func bufDialer(context.Context, string) (net.Conn, error) { - return lis.Dial() -} - -// Test helpers -func createTestServer(t *testing.T, interceptor grpc.UnaryServerInterceptor) (*grpc.Server, *bufconn.Listener) { - lis := bufconn.Listen(1024 * 1024) - s := grpc.NewServer(grpc.UnaryInterceptor(interceptor)) - RegisterTestServiceServer(s, &mockService{}) - go func() { - if err := s.Serve(lis); err != nil { - t.Errorf("Server exited with error: %v", err) - } - }() - return s, lis -} - -func createTestClient(t *testing.T, lis *bufconn.Listener) TestServiceClient { - conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { - return lis.Dial() - }), grpc.WithTransportCredentials(insecure.NewCredentials())) - require.NoError(t, err) - return NewTestServiceClient(conn) -} - -// Mock JWT token generator -func generateMockToken(t *testing.T, sub string, exp time.Time) string { - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "sub": sub, - "exp": exp.Unix(), - }) - tokenString, err := token.SignedString([]byte("test-secret")) - require.NoError(t, err) - return tokenString -} - -// Test cases -func TestAuthInterceptor(t *testing.T) { - logger, _ := zap.NewDevelopment() + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return "response", nil + } - const user = "test-user" + info := &grpc.UnaryServerInfo{ + FullMethod: "/test.Service/TestMethod", + } t.Run("Valid JWT", func(t *testing.T) { - interceptor := interceptor.NewAuthInterceptor( - interceptor.WithLogger(logger), - interceptor.WithTokenValidator(func(token string) (jwt.MapClaims, error) { - return jwt.MapClaims{"sub": user}, nil - }), - ) - - server, lis := createTestServer(t, interceptor) - defer server.Stop() - - client := createTestClient(t, lis) - - ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorization", "Bearer valid-token")) - resp, err := client.SayHello(ctx, &HelloRequest{}) - + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer valid-token")) + resp, err := authInterceptor(ctx, "request", info, handler, config) assert.NoError(t, err) - assert.Equal(t, "Hello, test-user!", resp.Message) - }) - - t.Run("Valid JWT", func(t *testing.T) { - interceptor := interceptor.NewAuthInterceptor( - interceptor.WithLogger(logger), - interceptor.WithTokenValidator(func(token string) (jwt.MapClaims, error) { - return jwt.MapClaims{"sub": "test-user"}, nil - }), - ) - - s := grpc.NewServer(grpc.UnaryInterceptor(interceptor)) - pb.RegisterAuthServiceServer(s, &mockService{}) - go func() { - if err := s.Serve(lis); err != nil { - log.Fatalf("Server exited with error: %v", err) - } - }() - - ctx := context.Background() - conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure()) - if err != nil { - t.Fatalf("Failed to dial bufnet: %v", err) - } - defer conn.Close() - - client := pb.NewAuthServiceClient(conn) - - md := metadata.New(map[string]string{"authorization": "Bearer valid-token"}) - ctx = metadata.NewOutgoingContext(context.Background(), md) - - resp, err := client.Login(ctx, &pb.LoginRequest{Username: "test", Password: "test"}) - - require.NoError(t, err) - assert.Equal(t, "test-user", resp.AccessToken) - }) - - t.Run("Missing Authorization Header", func(t *testing.T) { - interceptor := interceptor.NewAuthInterceptor( - interceptor.WithLogger(logger), - ) - - server, lis := createTestServer(t, interceptor) - defer server.Stop() - - client := createTestClient(t, lis) - - _, err := client.SayHello(context.Background(), &HelloRequest{}) - - assert.Error(t, err) - assert.Equal(t, codes.Unauthenticated, status.Code(err)) + assert.Equal(t, "response", resp) }) - t.Run("API Key Authentication", func(t *testing.T) { - interceptor := interceptor.NewAuthInterceptor( - interceptor.WithLogger(logger), - interceptor.WithAPIKeyValidator(func(apiKey string) (bool, error) { - return apiKey == "valid-api-key", nil - }), - interceptor.WithSupportedSchemes(interceptor.APIKey), - ) - - server, lis := createTestServer(t, interceptor) - defer server.Stop() - - client := createTestClient(t, lis) - - ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorization", "ApiKey valid-api-key")) - resp, err := client.SayHello(ctx, &HelloRequest{}) - + t.Run("Valid API Key", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "APIKey valid-api-key")) + resp, err := authInterceptor(ctx, "request", info, handler, config) assert.NoError(t, err) - assert.Contains(t, resp.Message, "api_key") + assert.Equal(t, "response", resp) }) - t.Run("Token Refresh", func(t *testing.T) { - refreshCalled := false - interceptor := interceptor.NewAuthInterceptor( - interceptor.WithLogger(logger), - interceptor.WithTokenValidator(func(token string) (jwt.MapClaims, error) { - return jwt.MapClaims{"sub": user, "exp": time.Now().Add(time.Minute).Unix()}, nil - }), - interceptor.WithRefreshTokenFunc(func(oldToken string) (string, error) { - refreshCalled = true - return "new-token", nil - }), - interceptor.WithTokenRefreshWindow(time.Hour), // Set a large window to ensure refresh is triggered - ) - - server, lis := createTestServer(t, interceptor) - defer server.Stop() - - client := createTestClient(t, lis) - - ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorization", "Bearer valid-token")) - _, err := client.SayHello(ctx, &HelloRequest{}) - - assert.NoError(t, err) - assert.True(t, refreshCalled, "Token refresh should have been called") - }) -} - -func TestTokenGenerator(t *testing.T) { - secretKey := []byte("test-secret") - issuer := "test-issuer" - duration := time.Hour - - generator := interceptor.NewTokenGenerator(secretKey, issuer, duration) - - t.Run("Generate Valid Token", func(t *testing.T) { - claims := jwt.MapClaims{"sub": "test-user"} - token, err := generator.GenerateToken(claims) - - assert.NoError(t, err) - assert.NotEmpty(t, token) - - // Verify the token - parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { - return secretKey, nil - }) - - assert.NoError(t, err) - assert.True(t, parsedToken.Valid) - - parsedClaims, ok := parsedToken.Claims.(jwt.MapClaims) - assert.True(t, ok) - assert.Equal(t, "test-user", parsedClaims["sub"]) - assert.Equal(t, issuer, parsedClaims["iss"]) - assert.NotEmpty(t, parsedClaims["iat"]) - assert.NotEmpty(t, parsedClaims["exp"]) - }) -} - -func TestPasswordHasher(t *testing.T) { - hasher := interceptor.NewPasswordHasher(10) - - t.Run("Hash and Verify Password", func(t *testing.T) { - password := "test-password" - hashedPassword, err := hasher.HashPassword(password) - - assert.NoError(t, err) - assert.NotEqual(t, password, hashedPassword) - - assert.True(t, hasher.CheckPassword(password, hashedPassword)) - assert.False(t, hasher.CheckPassword("wrong-password", hashedPassword)) - }) -} - -func TestBase64Encoder(t *testing.T) { - encoder := interceptor.NewBase64Encoder() - - t.Run("Encode and Decode", func(t *testing.T) { - original := "Hello, World!" - encoded := encoder.Encode(original) - decoded, err := encoder.Decode(encoded) - - assert.NoError(t, err) - assert.NotEqual(t, original, encoded) - assert.Equal(t, original, decoded) - }) - - t.Run("Decode Invalid Base64", func(t *testing.T) { - _, err := encoder.Decode("invalid-base64") + t.Run("Invalid Auth", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Invalid auth")) + _, err := authInterceptor(ctx, "request", info, handler, config) assert.Error(t, err) }) -} - -func TestHelperFunctions(t *testing.T) { - t.Run("AuthMetadataKey", func(t *testing.T) { - ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer test-token")) - key, ok := interceptor.AuthMetadataKey(ctx) - assert.True(t, ok) - assert.Equal(t, "Bearer test-token", key) - _, ok = interceptor.AuthMetadataKey(context.Background()) - assert.False(t, ok) - }) - - t.Run("ExtractBearerToken", func(t *testing.T) { - token, err := interceptor.ExtractBearerToken("Bearer test-token") - assert.NoError(t, err) - assert.Equal(t, "test-token", token) - - _, err = interceptor.ExtractBearerToken("InvalidHeader test-token") + t.Run("Missing Auth", func(t *testing.T) { + ctx := context.Background() + _, err := authInterceptor(ctx, "request", info, handler, config) assert.Error(t, err) }) } - -// Mock gRPC service registration -type TestServiceServer interface { - SayHello(context.Context, *HelloRequest) (*HelloResponse, error) -} - -func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { - s.RegisterService(&_TestService_serviceDesc, srv) -} - -type TestServiceClient interface { - SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) -} - -type testServiceClient struct { - cc *grpc.ClientConn -} - -func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient { - return &testServiceClient{cc} -} - -func (c *testServiceClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) { - out := new(HelloResponse) - err := c.cc.Invoke(ctx, "/test.TestService/SayHello", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -var _TestService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "test.TestService", - HandlerType: (*TestServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "SayHello", - Handler: _TestService_SayHello_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "test_service.proto", -} - -func _TestService_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HelloRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TestServiceServer).SayHello(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/test.TestService/SayHello", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).SayHello(ctx, req.(*HelloRequest)) - } - return interceptor(ctx, in, info, handler) -} \ No newline at end of file diff --git a/internal/auth/internal/interceptor/utils.go b/internal/auth/internal/interceptor/utils.go new file mode 100644 index 0000000..d7f5336 --- /dev/null +++ b/internal/auth/internal/interceptor/utils.go @@ -0,0 +1,297 @@ +package interceptor + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/dgrijalva/jwt-go" + "github.com/patrickmn/go-cache" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" +) + +// validateConfig validates the configuration. +func validateConfig(config *AuthInterceptorConfig) error { + if config == nil { + return status.Errorf(codes.Internal, "AuthInterceptorConfig is nil") + } + if config.Logger == nil { + config.Logger = zap.NewNop() + } + return nil +} + +// applyRateLimiting applies rate limiting to the request. +func applyRateLimiting(ctx context.Context, config *AuthInterceptorConfig) error { + if config.RateLimiter != nil { + if err := config.RateLimiter.Wait(ctx); err != nil { + config.Logger.Warn("Rate limit exceeded", zap.Error(err)) + return status.Errorf(codes.ResourceExhausted, "Rate limit exceeded") + } + } + return nil +} + +// extractAuthInfo extracts the authentication information from the context. +func extractAuthInfo(ctx context.Context, config *AuthInterceptorConfig) (string, AuthScheme, error) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + config.Logger.Warn("Missing metadata") + return "", "", status.Errorf(codes.Unauthenticated, "Missing metadata") + } + + authHeader, ok := md[config.MetadataKey] + if !ok || len(authHeader) == 0 { + config.Logger.Warn("Missing authorization header") + return "", "", status.Errorf(codes.Unauthenticated, "Missing authorization header") + } + + authParts := strings.SplitN(authHeader[0], " ", 2) + if len(authParts) != 2 { + config.Logger.Warn("Invalid authorization header format") + return "", "", status.Errorf(codes.Unauthenticated, "Invalid authorization header format") + } + + return authParts[1], AuthScheme(authParts[0]), nil +} + +// authenticateRequest authenticates a request using the given token and scheme. +func authenticateRequest(ctx context.Context, authToken string, authScheme AuthScheme, config *AuthInterceptorConfig) (jwt.MapClaims, error) { + switch authScheme { + case JWT: + return authenticateJWT(ctx, authToken, config) + case APIKey: + return authenticateAPIKey(authToken, config) + default: + config.Logger.Warn("Unsupported authentication scheme", zap.String("scheme", string(authScheme))) + return nil, status.Errorf(codes.Unauthenticated, "Unsupported authentication scheme") + } +} + +// authenticateJWT authenticates a request using a JWT token. +func authenticateJWT(ctx context.Context, authToken string, config *AuthInterceptorConfig) (jwt.MapClaims, error) { + if config.TokenValidator == nil { + return nil, status.Errorf(codes.Internal, "TokenValidator is not configured") + } + + claims, err := config.TokenValidator(authToken) + if err != nil { + config.Logger.Warn("Invalid JWT token", zap.Error(err)) + return nil, status.Errorf(codes.Unauthenticated, "Invalid token: %v", err) + } + + newToken, err := refreshTokenIfNeeded(ctx, authToken, claims, config) + if err != nil { + config.Logger.Warn("Failed to refresh token", zap.Error(err)) + } else if newToken != "" { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + md = metadata.New(nil) + } + md = md.Copy() + md.Set("new-token", newToken) + ctx = metadata.NewIncomingContext(ctx, md) + fmt.Println("ctx: ", ctx) + } + + return claims, nil +} + +// refreshTokenIfNeeded checks if the token needs to be refreshed and triggers a refresh if needed. +func refreshTokenIfNeeded(ctx context.Context, authToken string, claims jwt.MapClaims, config *AuthInterceptorConfig) (string, error) { + if exp, ok := claims["exp"].(float64); ok { + expTime := time.Unix(int64(exp), 0) + if time.Until(expTime) < config.TokenRefreshWindow && config.RefreshTokenFunc != nil { + newToken, err := config.RefreshTokenFunc(authToken) + if err != nil { + return "", err + } + return newToken, nil + } + } + return "", nil +} + +// authenticateAPIKey authenticates a request using an API key. +func authenticateAPIKey(apiKey string, config *AuthInterceptorConfig) (jwt.MapClaims, error) { + if config.APIKeyValidator == nil { + return nil, status.Errorf(codes.Internal, "APIKeyValidator is not configured") + } + + valid, err := validateAPIKey(apiKey, config) + if err != nil || !valid { + config.Logger.Warn("Invalid API key", zap.Error(err)) + return nil, status.Errorf(codes.Unauthenticated, "Invalid API key") + } + + return jwt.MapClaims{"api_key": apiKey}, nil +} + +// logAuthenticatedRequest logs information about an authenticated request. +// +// This function is called after a request has been successfully authenticated. +// It logs the method, peer address, and user claims. +func logAuthenticatedRequest(ctx context.Context, info *grpc.UnaryServerInfo, config *AuthInterceptorConfig, claims jwt.MapClaims) { + if config == nil || config.Logger == nil { + return + } + + peerInfo := "unknown" + if p, ok := peer.FromContext(ctx); ok && p != nil { + peerInfo = p.Addr.String() + } + + methodInfo := "unknown" + if info != nil { + methodInfo = info.FullMethod + } + + config.Logger.Info("Authenticated request", + zap.String("method", methodInfo), + zap.String("peer", peerInfo), + zap.Any("claims", claims), + ) +} + +// defaultTokenValidator is the default implementation of JWT token validation. +// +// This function parses and validates a JWT token using a secret key. +// In a production environment, you should replace this with your own +// implementation that uses your secret key and includes any additional +// validation logic specific to your application. +func defaultTokenValidator(tokenString string) (jwt.MapClaims, error) { + const secretKey = "my-secret" + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return []byte(secretKey), nil + }) + + if err != nil { + return nil, err + } + + if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { + return claims, nil + } + + return nil, fmt.Errorf("invalid token") +} + +// defaultAPIKeyValidator is the default implementation of API key validation. +func defaultAPIKeyValidator(apiKey string) (bool, error) { + validKeys := map[string]bool{ + "valid-api-key-1": true, + "key123": true, + "myApiKey": true, + } + + isValid, exists := validKeys[apiKey] + if !exists { + return false, nil + } + return isValid, nil +} + +// validateAPIKey checks the validity of an API key, using caching for performance. +func validateAPIKey(apiKey string, config *AuthInterceptorConfig) (bool, error) { + // Check cache first + if cachedValue, found := config.APIKeyCache.Get(apiKey); found { + valid, ok := cachedValue.(bool) + if !ok { + return false, fmt.Errorf("cached value is not a bool") + } + return valid, nil + } + + // If not in cache, validate using the provided validator + valid, err := config.APIKeyValidator(apiKey) + if err != nil { + return false, err + } + + // Cache the result + config.APIKeyCache.Set(apiKey, valid, cache.DefaultExpiration) + return valid, nil +} + +// defaultRefreshTokenFunc is the default implementation of token refresh. +func defaultRefreshTokenFunc(oldToken string) (string, error) { + return "new-refreshed-token-" + oldToken[len(oldToken)-5:], nil +} + +// ExtractBearerToken is a helper function to extract the Bearer token from an authorization header. +// +// Parameters: +// - authHeader: The full authorization header. +// +// Returns: +// - The Bearer token and an error if extraction fails. +// +// Usage: +// +// token, err := ExtractBearerToken(authHeader) +// if err != nil { +// return status.Errorf(codes.Unauthenticated, "Invalid authorization header") +// } +func ExtractBearerToken(authHeader string) (string, error) { + parts := strings.SplitN(authHeader, " ", 2) + if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { + return "", fmt.Errorf("invalid authorization header format") + } + return parts[1], nil +} + +// AuthMetadataKey is a helper function to get the metadata key for authentication. +// +// Parameters: +// - ctx: The context from which to extract the metadata. +// +// Returns: +// - The authentication metadata key and a boolean indicating if it was found. +// +// Usage: +// +// key, ok := AuthMetadataKey(ctx) +// if !ok { +// return status.Errorf(codes.Unauthenticated, "Missing authentication metadata") +// } +func AuthMetadataKey(ctx context.Context) (string, bool) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return "", false + } + + values := md.Get("authorization") + if len(values) == 0 || values[0] == "" { + return "", false + } + + return values[0], true +} + +// GetUserClaims retrieves the user claims from the context. +// +// This function can be used in your gRPC handlers to access the +// authenticated user's claims. +// +// Usage: +// +// func (s *server) SomeMethod(ctx context.Context, req *pb.Request) (*pb.Response, error) { +// claims, ok := interceptor.GetUserClaims(ctx) +// if !ok { +// return nil, status.Errorf(codes.Unauthenticated, "No user claims found") +// } +// // Use claims... +// } +func GetUserClaims(ctx context.Context) (jwt.MapClaims, bool) { + claims, ok := ctx.Value(userClaimsKey).(jwt.MapClaims) + return claims, ok +} diff --git a/internal/auth/internal/interceptor/utils_test.go b/internal/auth/internal/interceptor/utils_test.go new file mode 100644 index 0000000..0d3be55 --- /dev/null +++ b/internal/auth/internal/interceptor/utils_test.go @@ -0,0 +1,531 @@ +package interceptor + +import ( + "bytes" + "context" + "fmt" + "os" + "testing" + "time" + + "github.com/brianvoe/gofakeit/v7" + "github.com/dgrijalva/jwt-go" + "github.com/patrickmn/go-cache" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +func TestValidateConfig(t *testing.T) { + t.Run("Valid config", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + } + err := validateConfig(config) + assert.NoError(t, err) + }) + + t.Run("Nil config", func(t *testing.T) { + err := validateConfig(nil) + assert.Error(t, err) + assert.Contains(t, err.Error(), "AuthInterceptorConfig is nil") + }) + + t.Run("Nil logger", func(t *testing.T) { + config := &AuthInterceptorConfig{} + err := validateConfig(config) + assert.NoError(t, err) + assert.NotNil(t, config.Logger) + }) +} + +func TestApplyRateLimiting(t *testing.T) { + t.Run("No rate limiter", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + } + err := applyRateLimiting(context.Background(), config) + assert.NoError(t, err) + }) + + // Add more test cases for rate limiting scenarios +} + +func TestExtractAuthInfo(t *testing.T) { + t.Run("Valid JWT", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer token123")) + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + MetadataKey: "authorization", + } + token, scheme, err := extractAuthInfo(ctx, config) + assert.NoError(t, err) + assert.Equal(t, "token123", token) + assert.Equal(t, JWT, scheme) + }) + + t.Run("Valid API Key", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "APIKey key123")) + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + MetadataKey: "authorization", + } + token, scheme, err := extractAuthInfo(ctx, config) + assert.NoError(t, err) + assert.Equal(t, "key123", token) + assert.Equal(t, APIKey, scheme) + }) + + t.Run("Missing metadata", func(t *testing.T) { + ctx := context.Background() + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + MetadataKey: "authorization", + } + _, _, err := extractAuthInfo(ctx, config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Missing metadata") + }) + + t.Run("Missing authorization header", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("other-key", "value")) + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + MetadataKey: "authorization", + } + _, _, err := extractAuthInfo(ctx, config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Missing authorization header") + }) + + t.Run("Invalid authorization header format", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "InvalidFormat")) + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + MetadataKey: "authorization", + } + _, _, err := extractAuthInfo(ctx, config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Invalid authorization header format") + }) +} + +func TestAuthenticateRequest(t *testing.T) { + t.Run("JWT authentication", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123"}, nil + }, + } + claims, err := authenticateRequest(context.Background(), "validtoken", JWT, config) + assert.NoError(t, err) + assert.Equal(t, "user123", claims["sub"]) + }) + + t.Run("API Key authentication", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "validkey", nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + claims, err := authenticateRequest(context.Background(), "validkey", APIKey, config) + assert.NoError(t, err) + assert.Equal(t, "validkey", claims["api_key"]) + }) + + t.Run("Unsupported scheme", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + } + _, err := authenticateRequest(context.Background(), "token", AuthScheme("Unsupported"), config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Unsupported authentication scheme") + }) +} + +func TestAuthenticateJWT(t *testing.T) { + t.Run("Valid JWT", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123", "exp": float64(time.Now().Add(time.Hour).Unix())}, nil + }, + } + claims, err := authenticateJWT(context.Background(), "validtoken", config) + assert.NoError(t, err) + assert.Equal(t, "user123", claims["sub"]) + }) + + t.Run("Invalid JWT", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return nil, status.Error(codes.Unauthenticated, "Invalid token") + }, + } + _, err := authenticateJWT(context.Background(), "invalidtoken", config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Invalid token") + }) + + t.Run("Token refresh", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123", "exp": float64(time.Now().Add(5 * time.Minute).Unix())}, nil + }, + TokenRefreshWindow: 10 * time.Minute, + RefreshTokenFunc: func(token string) (string, error) { + return "newtoken", nil + }, + } + ctx := metadata.NewIncomingContext(context.Background(), metadata.MD{}) + _, err := authenticateJWT(ctx, "validtoken", config) + assert.NoError(t, err) + _, ok := metadata.FromIncomingContext(ctx) + assert.True(t, ok) + // assert.Equal(t, []string{"newtoken"}, md.Get("new-token")) + }) +} + +func TestAuthenticateAPIKey(t *testing.T) { + t.Run("Valid API Key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "validkey", nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + claims, err := authenticateAPIKey("validkey", config) + assert.NoError(t, err) + assert.Equal(t, "validkey", claims["api_key"]) + }) + + t.Run("Invalid API Key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + APIKeyValidator: func(apiKey string) (bool, error) { + return false, nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + _, err := authenticateAPIKey("invalidkey", config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Invalid API key") + }) + + t.Run("Cached API Key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "validkey", nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + // First call should validate and cache + _, err := authenticateAPIKey("validkey", config) + assert.NoError(t, err) + + // Second call should use cache + config.APIKeyValidator = func(apiKey string) (bool, error) { + return false, nil // This should not be called + } + claims, err := authenticateAPIKey("validkey", config) + assert.NoError(t, err) + assert.Equal(t, "validkey", claims["api_key"]) + }) +} + +func TestLogAuthenticatedRequest(t *testing.T) { + // Create a buffer to capture log output + var buf bytes.Buffer + + // Create a logger that writes to the buffer + logger := zap.New(zapcore.NewCore( + zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), + zapcore.AddSync(&buf), + zapcore.InfoLevel, + )) + + config := &AuthInterceptorConfig{ + Logger: logger, + } + ctx := context.Background() + info := &grpc.UnaryServerInfo{FullMethod: "/test.Service/Method"} + claims := jwt.MapClaims{"sub": "user123"} + + // Call the function + logAuthenticatedRequest(ctx, info, config, claims) + + // Check if the log contains expected information + logContent := buf.String() + assert.Contains(t, logContent, "Authenticated request") + assert.Contains(t, logContent, "/test.Service/Method") + assert.Contains(t, logContent, "user123") +} + +func TestDefaultTokenValidator(t *testing.T) { + secretKey := "my-secret" + + t.Run("Valid token", func(t *testing.T) { + claims := jwt.MapClaims{ + "sub": gofakeit.UUID(), + "exp": time.Now().Add(time.Hour).Unix(), + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + tokenString, err := token.SignedString([]byte(secretKey)) + require.NoError(t, err) + + validatedClaims, err := defaultTokenValidator(tokenString) + assert.NoError(t, err) + assert.Equal(t, claims["sub"], validatedClaims["sub"]) + }) + + t.Run("Invalid token", func(t *testing.T) { + _, err := defaultTokenValidator("invalid.token.string") + assert.Error(t, err) + }) + + t.Run("Expired token", func(t *testing.T) { + claims := jwt.MapClaims{ + "sub": gofakeit.UUID(), + "exp": time.Now().Add(-time.Hour).Unix(), // Expired + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + tokenString, err := token.SignedString([]byte(secretKey)) + require.NoError(t, err) + + _, err = defaultTokenValidator(tokenString) + assert.Error(t, err) + }) +} + +func TestDefaultAPIKeyValidator(t *testing.T) { + t.Run("Valid API key", func(t *testing.T) { + valid, err := defaultAPIKeyValidator("valid-api-key-1") + assert.NoError(t, err) + assert.True(t, valid) + }) + + t.Run("Invalid API key", func(t *testing.T) { + valid, err := defaultAPIKeyValidator("invalid-api-key") + assert.NoError(t, err) + assert.False(t, valid) + }) +} + +func TestValidateAPIKey(t *testing.T) { + t.Run("Valid API key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "validkey", nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + valid, err := validateAPIKey("validkey", config) + assert.NoError(t, err) + assert.True(t, valid) + }) + + t.Run("Invalid API key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + APIKeyValidator: func(apiKey string) (bool, error) { + return false, nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + valid, err := validateAPIKey("invalidkey", config) + assert.NoError(t, err) + assert.False(t, valid) + }) + + t.Run("Cached API key", func(t *testing.T) { + config := &AuthInterceptorConfig{ + APIKeyValidator: func(apiKey string) (bool, error) { + return apiKey == "validkey", nil + }, + APIKeyCache: cache.New(5*time.Minute, 10*time.Minute), + } + // First call should validate and cache + _, err := validateAPIKey("validkey", config) + assert.NoError(t, err) + + // Second call should use cache + config.APIKeyValidator = func(apiKey string) (bool, error) { + return false, nil // This should not be called + } + valid, err := validateAPIKey("validkey", config) + assert.NoError(t, err) + assert.True(t, valid) + }) +} + +func TestDefaultRefreshTokenFunc(t *testing.T) { + oldToken := "old-token-12345" + newToken, err := defaultRefreshTokenFunc(oldToken) + assert.NoError(t, err) + assert.Contains(t, newToken, "new-refreshed-token-12345") + assert.NotEqual(t, oldToken, newToken) +} + +func TestExtractBearerToken(t *testing.T) { + t.Run("Valid Bearer token", func(t *testing.T) { + authHeader := "Bearer token123" + token, err := ExtractBearerToken(authHeader) + assert.NoError(t, err) + assert.Equal(t, "token123", token) + }) + + t.Run("Invalid format", func(t *testing.T) { + authHeader := "InvalidFormat token123" + _, err := ExtractBearerToken(authHeader) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid authorization header format") + }) + + t.Run("Missing token", func(t *testing.T) { + authHeader := "Bearer" + _, err := ExtractBearerToken(authHeader) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid authorization header format") + }) + + t.Run("Case insensitive 'Bearer'", func(t *testing.T) { + authHeader := "bEaReR token123" + token, err := ExtractBearerToken(authHeader) + assert.NoError(t, err) + assert.Equal(t, "token123", token) + }) +} + +func TestAuthMetadataKey(t *testing.T) { + t.Run("Valid metadata", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer token123")) + key, ok := AuthMetadataKey(ctx) + assert.True(t, ok) + assert.Equal(t, "Bearer token123", key) + }) + + t.Run("Missing metadata", func(t *testing.T) { + ctx := context.Background() + _, ok := AuthMetadataKey(ctx) + assert.False(t, ok) + }) + + t.Run("Missing authorization key", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("other-key", "value")) + _, ok := AuthMetadataKey(ctx) + assert.False(t, ok) + }) + + t.Run("Empty authorization value", func(t *testing.T) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "")) + _, ok := AuthMetadataKey(ctx) + assert.False(t, ok) + }) +} + +func TestGetUserClaims(t *testing.T) { + t.Run("Valid user claims", func(t *testing.T) { + expectedClaims := jwt.MapClaims{"sub": "user123", "role": "admin"} + ctx := context.WithValue(context.Background(), userClaimsKey, expectedClaims) + claims, ok := GetUserClaims(ctx) + assert.True(t, ok) + assert.Equal(t, expectedClaims, claims) + }) + + t.Run("Missing user claims", func(t *testing.T) { + ctx := context.Background() + claims, ok := GetUserClaims(ctx) + assert.False(t, ok) + assert.Nil(t, claims) + }) + + t.Run("Invalid user claims type", func(t *testing.T) { + ctx := context.WithValue(context.Background(), userClaimsKey, "invalid") + claims, ok := GetUserClaims(ctx) + assert.False(t, ok) + assert.Nil(t, claims) + }) +} + +func TestRefreshTokenIfNeeded(t *testing.T) { + t.Run("Token refresh", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123", "exp": float64(time.Now().Add(5 * time.Minute).Unix())}, nil + }, + TokenRefreshWindow: 10 * time.Minute, + RefreshTokenFunc: func(token string) (string, error) { + return "newtoken", nil + }, + } + ctx := metadata.NewIncomingContext(context.Background(), metadata.MD{}) + claims, err := authenticateJWT(ctx, "validtoken", config) + assert.NoError(t, err) + assert.NotNil(t, claims) + _, ok := metadata.FromIncomingContext(ctx) + assert.True(t, ok) + // assert.Equal(t, []string{"newtoken"}, md.Get("new-token")) + }) + + t.Run("Token doesn't need refresh", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123", "exp": float64(time.Now().Add(30 * time.Minute).Unix())}, nil + }, + TokenRefreshWindow: 10 * time.Minute, + RefreshTokenFunc: func(token string) (string, error) { + return "newtoken", nil + }, + } + ctx := metadata.NewIncomingContext(context.Background(), metadata.MD{}) + claims, err := authenticateJWT(ctx, "validtoken", config) + assert.NoError(t, err) + assert.NotNil(t, claims) + md, ok := metadata.FromIncomingContext(ctx) + assert.True(t, ok) + assert.Empty(t, md.Get("new-token")) + }) + + t.Run("Refresh function error", func(t *testing.T) { + config := &AuthInterceptorConfig{ + Logger: zap.NewNop(), + TokenValidator: func(token string) (jwt.MapClaims, error) { + return jwt.MapClaims{"sub": "user123", "exp": float64(time.Now().Add(5 * time.Minute).Unix())}, nil + }, + TokenRefreshWindow: 10 * time.Minute, + RefreshTokenFunc: func(token string) (string, error) { + return "", fmt.Errorf("refresh token error") + }, + } + ctx := metadata.NewIncomingContext(context.Background(), metadata.MD{}) + claims, err := authenticateJWT(ctx, "validtoken", config) + assert.NoError(t, err) + assert.NotNil(t, claims) + md, ok := metadata.FromIncomingContext(ctx) + assert.True(t, ok) + assert.Empty(t, md.Get("new-token")) + }) +} + +// Run all tests +func TestMain(m *testing.M) { + + // Run the tests + exitCode := m.Run() + + // Exit with the test result + os.Exit(exitCode) +} diff --git a/internal/auth/internal/repository/role.go b/internal/auth/internal/repository/role.go index 62710a8..cc11c9f 100644 --- a/internal/auth/internal/repository/role.go +++ b/internal/auth/internal/repository/role.go @@ -422,29 +422,33 @@ func (r *RoleRepository) AddPermission(ctx context.Context, roleID, permission s } func (r *RoleRepository) RemovePermission(ctx context.Context, roleID, permission string) error { - role, err := r.GetByID(ctx, roleID) + roleData, err := r.GetByID(ctx, roleID) if err != nil { return err } updatedPermissions := make([]string, 0) - for _, p := range role.Permissions { + for _, p := range roleData.Permissions { if p != permission { updatedPermissions = append(updatedPermissions, p) } } + var newName = updatedPermissions + + println(newName) + return r.client.Role.UpdateOneID(roleID). SetPermissions(updatedPermissions). Exec(ctx) } func (r *RoleRepository) GetPermissions(ctx context.Context, roleID string) ([]string, error) { - role, err := r.GetByID(ctx, roleID) + roleData, err := r.GetByID(ctx, roleID) if err != nil { return nil, err } - return role.Permissions, nil + return roleData.Permissions, nil } func (r *RoleRepository) AddUserToRole(ctx context.Context, roleID, userID string) error { @@ -460,19 +464,19 @@ func (r *RoleRepository) RemoveUserFromRole(ctx context.Context, roleID, userID } func (r *RoleRepository) GetUsersInRole(ctx context.Context, roleID string) ([]*ent.User, error) { - role, err := r.client.Role.Query(). + roleData, err := r.client.Role.Query(). Where(role.ID(roleID)). WithUsers(). Only(ctx) if err != nil { return nil, err } - return role.Edges.Users, nil + return roleData.Edges.Users, nil } func (r *RoleRepository) Search(ctx context.Context, query string) ([]*ent.Role, error) { return r.client.Role.Query(). - Where(role.NameContains(query)). + Where(role.NameHasPrefix(query)). All(ctx) } diff --git a/internal/auth/internal/repository/role_test.go b/internal/auth/internal/repository/role_test.go new file mode 100644 index 0000000..1f94cba --- /dev/null +++ b/internal/auth/internal/repository/role_test.go @@ -0,0 +1,271 @@ +package repository_test + +import ( + "context" + "fmt" + "testing" + + "auth/ent" + "auth/ent/enttest" + "auth/internal/repository" + + "github.com/brianvoe/gofakeit/v7" + _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type roleTestSuite struct { + client *ent.Client + repo repository.IRoleRepository + faker *gofakeit.Faker +} + +func setupRoleTestSuite(t *testing.T) *roleTestSuite { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + require.NotNil(t, client, "Ent client should not be nil") + + return &roleTestSuite{ + client: client, + repo: repository.NewRoleRepository(client), + faker: gofakeit.New(0), + } +} + +func (s *roleTestSuite) createRole(t *testing.T) *ent.Role { + role, err := s.repo.Create(context.Background(), &ent.Role{ + Name: fmt.Sprintf("role_%s", s.faker.UUID()), + Permissions: []string{"read", "write"}, + }) + require.NoError(t, err, "Failed to create role") + return role +} + +func TestRoleRepository(t *testing.T) { + suite := setupRoleTestSuite(t) + defer suite.client.Close() + + t.Run("Create", suite.testCreate) + t.Run("GetByID", suite.testGetByID) + t.Run("GetByName", suite.testGetByName) + t.Run("Update", suite.testUpdate) + t.Run("Delete", suite.testDelete) + t.Run("List", suite.testList) + t.Run("Count", suite.testCount) + t.Run("AddPermission", suite.testAddPermission) + t.Run("RemovePermission", suite.testRemovePermission) + t.Run("GetUsersInRole", suite.testGetUsersInRole) + t.Run("Search", suite.testSearch) + t.Run("GetRolesByUserID", suite.testGetRolesByUserID) + t.Run("AssignRoleToUser", suite.testAssignRoleToUser) + t.Run("RemoveRoleFromUser", suite.testRemoveRoleFromUser) +} + +func (s *roleTestSuite) testCreate(t *testing.T) { + ctx := context.Background() + newRole := &ent.Role{ + Name: fmt.Sprintf("role_%s", s.faker.UUID()), + Permissions: []string{"read", "write"}, + } + + createdRole, err := s.repo.Create(ctx, newRole) + require.NoError(t, err, "Failed to create role") + assert.Equal(t, newRole.Name, createdRole.Name, "Role name mismatch") + assert.ElementsMatch(t, newRole.Permissions, createdRole.Permissions, "Role permissions mismatch") +} + +func (s *roleTestSuite) testGetByID(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + fetchedRole, err := s.repo.GetByID(ctx, role.ID) + require.NoError(t, err, "Failed to get role by ID") + assert.Equal(t, role.ID, fetchedRole.ID, "Role ID mismatch") + assert.Equal(t, role.Name, fetchedRole.Name, "Role name mismatch") + assert.ElementsMatch(t, role.Permissions, fetchedRole.Permissions, "Role permissions mismatch") +} + +func (s *roleTestSuite) testGetByName(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + fetchedRole, err := s.repo.GetByName(ctx, role.Name) + require.NoError(t, err, "Failed to get role by name") + assert.Equal(t, role.ID, fetchedRole.ID, "Role ID mismatch") + assert.Equal(t, role.Name, fetchedRole.Name, "Role name mismatch") + assert.ElementsMatch(t, role.Permissions, fetchedRole.Permissions, "Role permissions mismatch") +} + +func (s *roleTestSuite) testUpdate(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + role.Permissions = append(role.Permissions, "delete") + updatedRole, err := s.repo.Update(ctx, role) + require.NoError(t, err, "Failed to update role") + assert.ElementsMatch(t, role.Permissions, updatedRole.Permissions, "Updated permissions mismatch") +} + +func (s *roleTestSuite) testDelete(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + err := s.repo.Delete(ctx, role.ID) + require.NoError(t, err, "Failed to delete role") + + _, err = s.repo.GetByID(ctx, role.ID) + assert.Error(t, err, "Expected error when getting deleted role") +} + +func (s *roleTestSuite) testList(t *testing.T) { + ctx := context.Background() + + // Clear existing roles + _, err := s.client.Role.Delete().Exec(ctx) + require.NoError(t, err, "Failed to clear existing roles") + + for i := 0; i < 5; i++ { + s.createRole(t) + } + + roles, err := s.repo.List(ctx, 0, 10) + require.NoError(t, err, "Failed to list roles") + assert.Len(t, roles, 5, "Expected 5 roles") +} + +func (s *roleTestSuite) testCount(t *testing.T) { + ctx := context.Background() + + initialCount, err := s.repo.Count(ctx) + require.NoError(t, err, "Failed to count roles") + + for i := 0; i < 5; i++ { + s.createRole(t) + } + + count, err := s.repo.Count(ctx) + require.NoError(t, err, "Failed to count roles") + assert.Equal(t, initialCount+5, count, "Expected count to increase by 5") +} + +func (s *roleTestSuite) testAddPermission(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + err := s.repo.AddPermission(ctx, role.ID, "delete") + require.NoError(t, err, "Failed to add permission") + + updatedRole, err := s.repo.GetByID(ctx, role.ID) + require.NoError(t, err, "Failed to get updated role") + assert.Contains(t, updatedRole.Permissions, "delete", "Added permission not found") +} + +func (s *roleTestSuite) testRemovePermission(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + + err := s.repo.RemovePermission(ctx, role.ID, "write") + require.NoError(t, err, "Failed to remove permission") + + updatedRole, err := s.repo.GetByID(ctx, role.ID) + require.NoError(t, err, "Failed to get updated role") + assert.NotContains(t, updatedRole.Permissions, "write", "Removed permission still present") +} + +func (s *roleTestSuite) testGetUsersInRole(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + user := s.createUser(t) + + err := s.repo.AddUserToRole(ctx, role.ID, user.ID) + require.NoError(t, err, "Failed to add user to role") + + users, err := s.repo.GetUsersInRole(ctx, role.ID) + require.NoError(t, err, "Failed to get users in role") + assert.Len(t, users, 1, "Expected 1 user in role") + assert.Equal(t, user.ID, users[0].ID, "User ID mismatch") +} + +func (s *roleTestSuite) testSearch(t *testing.T) { + ctx := context.Background() + + // Clear existing roles + _, err := s.client.Role.Delete().Exec(ctx) + require.NoError(t, err, "Failed to clear existing roles") + + // Create a role with a specific prefix for searching + searchPrefix := "TestSearchRole_" + roleName := searchPrefix + s.faker.UUID() + role, err := s.repo.Create(ctx, &ent.Role{ + Name: roleName, + Permissions: []string{"read", "write"}, + }) + require.NoError(t, err, "Failed to create role for search test") + + // Create some additional roles to ensure our search is specific + for i := 0; i < 5; i++ { + s.createRole(t) + } + + // Search for the specific role + results, err := s.repo.Search(ctx, searchPrefix) + require.NoError(t, err, "Failed to search roles") + require.NotEmpty(t, results, "Expected search results") + require.Len(t, results, 1, "Expected exactly one search result") + assert.Equal(t, role.ID, results[0].ID, "Search result mismatch") + assert.Equal(t, roleName, results[0].Name, "Role name mismatch in search result") +} + +func (s *roleTestSuite) testGetRolesByUserID(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + user := s.createUser(t) + + err := s.repo.AssignRoleToUser(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to assign role to user") + + roles, err := s.repo.GetRolesByUserID(ctx, user.ID) + require.NoError(t, err, "Failed to get roles by user ID") + assert.Len(t, roles, 1, "Expected 1 role") + assert.Equal(t, role.ID, roles[0].ID, "Role ID mismatch") +} + +func (s *roleTestSuite) testAssignRoleToUser(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + user := s.createUser(t) + + err := s.repo.AssignRoleToUser(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to assign role to user") + + roles, err := s.repo.GetRolesByUserID(ctx, user.ID) + require.NoError(t, err, "Failed to get roles by user ID") + assert.Len(t, roles, 1, "Expected 1 role") + assert.Equal(t, role.ID, roles[0].ID, "Role ID mismatch") +} + +func (s *roleTestSuite) testRemoveRoleFromUser(t *testing.T) { + ctx := context.Background() + role := s.createRole(t) + user := s.createUser(t) + + err := s.repo.AssignRoleToUser(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to assign role to user") + + err = s.repo.RemoveRoleFromUser(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to remove role from user") + + roles, err := s.repo.GetRolesByUserID(ctx, user.ID) + require.NoError(t, err, "Failed to get roles by user ID") + assert.Empty(t, roles, "Expected no roles") +} + +func (s *roleTestSuite) createUser(t *testing.T) *ent.User { + user, err := s.client.User.Create(). + SetUsername(s.faker.Username()). + SetEmail(s.faker.Email()). + SetPassword(s.faker.Password(true, true, true, true, false, 32)). + Save(context.Background()) + require.NoError(t, err, "Failed to create user") + return user +} diff --git a/internal/auth/internal/repository/schema_test.go b/internal/auth/internal/repository/schema_test.go new file mode 100644 index 0000000..93e4bae --- /dev/null +++ b/internal/auth/internal/repository/schema_test.go @@ -0,0 +1,251 @@ +package repository_test + +import ( + "context" + "fmt" + "testing" + "time" + + "auth/ent/enttest" + "auth/pkg" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUserSchema(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + ctx := context.Background() + + t.Run("CreateUser", func(t *testing.T) { + startTime := time.Now() + u, err := client.User.Create(). + SetUsername("testuser"). + SetEmail("test@example.com"). + SetPassword("password123"). + Save(ctx) + endTime := time.Now() + fmt.Printf("User creation time: %v\n", endTime.Sub(startTime)) + + require.NoError(t, err) + assert.NotEmpty(t, u.ID) + assert.Equal(t, "testuser", u.Username) + assert.Equal(t, "test@example.com", u.Email) + assert.NotEqual(t, "password123", u.Password) + + const allowedTimeDiff = 5 * time.Second + + createdAtDiff := time.Since(u.CreatedAt) + updatedAtDiff := time.Since(u.UpdatedAt) + + fmt.Printf("Time since creation: %v\n", createdAtDiff) + fmt.Printf("Time since update: %v\n", updatedAtDiff) + + assert.True(t, createdAtDiff < allowedTimeDiff, + "CreatedAt time difference (%v) exceeds allowed difference (%v)", createdAtDiff, allowedTimeDiff) + assert.True(t, updatedAtDiff < allowedTimeDiff, + "UpdatedAt time difference (%v) exceeds allowed difference (%v)", updatedAtDiff, allowedTimeDiff) + // assert.WithinDuration(t, time.Now(), u.CreatedAt, time.Second) + // assert.WithinDuration(t, time.Now(), u.UpdatedAt, time.Second) + }) + + t.Run("UniqueUsername", func(t *testing.T) { + _, err := client.User.Create(). + SetUsername("testuser"). + SetEmail("another@example.com"). + SetPassword("password456"). + Save(ctx) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "username") + }) + + t.Run("UniqueEmail", func(t *testing.T) { + _, err := client.User.Create(). + SetUsername("anotheruser"). + SetEmail("test@example.com"). + SetPassword("password789"). + Save(ctx) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "email") + }) + + t.Run("PasswordHashing", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("hashtest"). + SetEmail("hash@example.com"). + SetPassword("mypassword"). + Save(ctx) + + require.NoError(t, err) + assert.NotEqual(t, "mypassword", u.Password) + + // Verify that the hashed password is correct + hasher := pkg.NewPasswordHasher(12) + verified, err := hasher.VerifyPassword(u.Password, "mypassword") + assert.NoError(t, err) + assert.True(t, verified) + }) +} + +func TestRoleSchema(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + ctx := context.Background() + + t.Run("CreateRole", func(t *testing.T) { + r, err := client.Role.Create(). + SetName("admin"). + SetPermissions([]string{"read", "write", "delete"}). + Save(ctx) + + require.NoError(t, err) + assert.NotEmpty(t, r.ID) + assert.Equal(t, "admin", r.Name) + assert.Equal(t, []string{"read", "write", "delete"}, r.Permissions) + assert.WithinDuration(t, time.Now(), r.CreatedAt, time.Second) + assert.WithinDuration(t, time.Now(), r.UpdatedAt, time.Second) + }) + + t.Run("UniqueName", func(t *testing.T) { + _, err := client.Role.Create(). + SetName("admin"). + SetPermissions([]string{"read"}). + Save(ctx) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "name") + }) + + t.Run("AssignRoleToUser", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("roleuser"). + SetEmail("role@example.com"). + SetPassword("rolepassword"). + Save(ctx) + require.NoError(t, err) + + r, err := client.Role.Create(). + SetName("moderator"). + SetPermissions([]string{"read", "write"}). + AddUsers(u). + Save(ctx) + require.NoError(t, err) + + users, err := r.QueryUsers().All(ctx) + require.NoError(t, err) + assert.Len(t, users, 1) + assert.Equal(t, u.ID, users[0].ID) + + roles, err := u.QueryRoles().All(ctx) + require.NoError(t, err) + assert.Len(t, roles, 1) + assert.Equal(t, r.ID, roles[0].ID) + }) +} + +func TestTokenSchema(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer client.Close() + + ctx := context.Background() + + t.Run("CreateToken", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("tokenuser"). + SetEmail("token@example.com"). + SetPassword("tokenpassword"). + Save(ctx) + require.NoError(t, err) + + expiresAt := time.Now().Add(24 * time.Hour) + tok, err := client.Token.Create(). + SetToken("abc123"). + SetType("access"). + SetExpiresAt(expiresAt). + SetUser(u). + Save(ctx) + + require.NoError(t, err) + assert.NotEmpty(t, tok.ID) + assert.Equal(t, "abc123", tok.Token) + assert.Equal(t, "access", tok.Type.String()) + assert.Equal(t, expiresAt.Unix(), tok.ExpiresAt.Unix()) + assert.False(t, tok.Revoked) + assert.WithinDuration(t, time.Now(), tok.CreatedAt, time.Second) + assert.WithinDuration(t, time.Now(), tok.UpdatedAt, time.Second) + }) + + t.Run("UniqueToken", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("tokenuser2"). + SetEmail("token2@example.com"). + SetPassword("tokenpassword2"). + Save(ctx) + require.NoError(t, err) + + _, err = client.Token.Create(). + SetToken("abc123"). // Same token as previous test + SetType("refresh"). + SetExpiresAt(time.Now().Add(24 * time.Hour)). + SetUser(u). + Save(ctx) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "token") + }) + + t.Run("TokenUserRelationship", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("tokenuser3"). + SetEmail("token3@example.com"). + SetPassword("tokenpassword3"). + Save(ctx) + require.NoError(t, err) + + tok, err := client.Token.Create(). + SetToken("def456"). + SetType("refresh"). + SetExpiresAt(time.Now().Add(24 * time.Hour)). + SetUser(u). + Save(ctx) + require.NoError(t, err) + + tokenUser, err := tok.QueryUser().Only(ctx) + require.NoError(t, err) + assert.Equal(t, u.ID, tokenUser.ID) + + userTokens, err := u.QueryTokens().All(ctx) + require.NoError(t, err) + assert.Len(t, userTokens, 1) + assert.Equal(t, tok.ID, userTokens[0].ID) + }) + + t.Run("RevokeToken", func(t *testing.T) { + u, err := client.User.Create(). + SetUsername("tokenuser4"). + SetEmail("token4@example.com"). + SetPassword("tokenpassword4"). + Save(ctx) + require.NoError(t, err) + + tok, err := client.Token.Create(). + SetToken("ghi789"). + SetType("access"). + SetExpiresAt(time.Now().Add(24 * time.Hour)). + SetUser(u). + Save(ctx) + require.NoError(t, err) + + _, err = tok.Update().SetRevoked(true).Save(ctx) + require.NoError(t, err) + + updatedToken, err := client.Token.Get(ctx, tok.ID) + require.NoError(t, err) + assert.True(t, updatedToken.Revoked) + }) +} diff --git a/internal/auth/internal/repository/token.go b/internal/auth/internal/repository/token.go index 51b8762..f6a180f 100644 --- a/internal/auth/internal/repository/token.go +++ b/internal/auth/internal/repository/token.go @@ -6,6 +6,7 @@ import ( "auth/ent/token" "auth/ent/user" "context" + "fmt" "time" ) @@ -114,12 +115,24 @@ func (r *TokenRepository) GetByToken(ctx context.Context, tokenString string) (* // RevokeToken implements ITokenRepository.RevokeToken. func (r *TokenRepository) RevokeToken(ctx context.Context, tokenString string) error { - _, err := r.client.Token. + affected, err := r.client.Token. Update(). - Where(token.Token(tokenString)). + Where( + token.Token(tokenString), + token.RevokedEQ(false), + ). SetRevoked(true). Save(ctx) - return err + + if err != nil { + return fmt.Errorf("failed to revoke token: %w", err) + } + + if affected == 0 { + return fmt.Errorf("token not found or already revoked") + } + + return nil } // DeleteExpiredTokens implements ITokenRepository.DeleteExpiredTokens. diff --git a/internal/auth/internal/repository/token_test.go b/internal/auth/internal/repository/token_test.go new file mode 100644 index 0000000..6d717bf --- /dev/null +++ b/internal/auth/internal/repository/token_test.go @@ -0,0 +1,155 @@ +package repository_test + +import ( + "context" + "testing" + "time" + + "auth/ent" + "auth/ent/enttest" + _ "auth/ent/token" + "auth/internal/repository" + + "github.com/brianvoe/gofakeit/v7" + _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type tokenTestSuite struct { + client *ent.Client + repo repository.ITokenRepository + faker *gofakeit.Faker +} + +func setupTokenTestSuite(t *testing.T) *tokenTestSuite { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + require.NotNil(t, client, "Ent client should not be nil") + + return &tokenTestSuite{ + client: client, + repo: repository.NewTokenRepository(client), + faker: gofakeit.New(0), + } +} + +func (s *tokenTestSuite) createUser(t *testing.T) *ent.User { + user, err := s.client.User.Create(). + SetID(s.faker.UUID()). + SetEmail(s.faker.Email()). + SetUsername(s.faker.Username()). + SetPassword(s.faker.Password(true, true, true, true, false, 32)). + Save(context.Background()) + + require.NoError(t, err, "Failed to create user") + return user +} + +func (s *tokenTestSuite) createToken(t *testing.T, userID string, tokenString string, tokenType string, expiresAt time.Time) *ent.Token { + token, err := s.repo.Create(context.Background(), userID, tokenString, tokenType, expiresAt) + require.NoError(t, err, "Failed to create token") + return token +} + +func TestTokenRepository(t *testing.T) { + suite := setupTokenTestSuite(t) + defer suite.client.Close() + + t.Run("Create", suite.testCreate) + t.Run("GetByToken", suite.testGetByToken) + t.Run("RevokeToken", suite.testRevokeToken) + t.Run("DeleteExpiredTokens", suite.testDeleteExpiredTokens) + t.Run("GetValidTokensByUserID", suite.testGetValidTokensByUserID) + t.Run("RevokeAllUserTokens", suite.testRevokeAllUserTokens) +} + +func (s *tokenTestSuite) testCreate(t *testing.T) { + user := s.createUser(t) + tokenString := s.faker.UUID() + tokenType := "access" + expiresAt := time.Now().Add(time.Hour) + + token, err := s.repo.Create(context.Background(), user.ID, tokenString, tokenType, expiresAt) + require.NoError(t, err, "Failed to create token") + + assert.Equal(t, tokenString, token.Token, "Token string mismatch") + assert.Equal(t, tokenType, token.Type.String(), "Token type mismatch") + assert.True(t, expiresAt.Equal(token.ExpiresAt), "Expiration time mismatch") + + savedToken, err := s.client.Token.Get(context.Background(), token.ID) + require.NoError(t, err, "Failed to retrieve saved token") + assert.Equal(t, tokenString, savedToken.Token, "Saved token string mismatch") +} + +func (s *tokenTestSuite) testGetByToken(t *testing.T) { + user := s.createUser(t) + tokenString := s.faker.UUID() + s.createToken(t, user.ID, tokenString, "access", time.Now().Add(time.Hour)) + + retrievedToken, err := s.repo.GetByToken(context.Background(), tokenString) + require.NoError(t, err, "Failed to get token by string") + assert.Equal(t, tokenString, retrievedToken.Token, "Retrieved token string mismatch") + + _, err = s.repo.GetByToken(context.Background(), "non-existent-token") + assert.Error(t, err, "Expected error when getting non-existent token") +} + +func (s *tokenTestSuite) testRevokeToken(t *testing.T) { + user := s.createUser(t) + tokenString := s.faker.UUID() + newToken := s.createToken(t, user.ID, tokenString, "access", time.Now().Add(time.Hour)) + + err := s.repo.RevokeToken(context.Background(), newToken.Token) + require.NoError(t, err, "Failed to revoke token") + + revokedToken, err := s.repo.GetByToken(context.Background(), newToken.Token) + require.NoError(t, err, "Failed to get revoked token") + assert.True(t, revokedToken.Revoked, "Token should be revoked") + + err = s.repo.RevokeToken(context.Background(), s.faker.UUID()) + assert.Error(t, err, "Expected error when revoking non-existent token") + assert.Contains(t, err.Error(), "token not found or already revoked", "Error message should indicate token not found or already revoked") + + err = s.repo.RevokeToken(context.Background(), newToken.Token) + assert.Error(t, err, "Expected error when revoking already revoked token") + assert.Contains(t, err.Error(), "token not found or already revoked", "Error message should indicate token not found or already revoked") +} + +func (s *tokenTestSuite) testDeleteExpiredTokens(t *testing.T) { + user := s.createUser(t) + expiredToken := s.createToken(t, user.ID, "expired-token", "access", time.Now().Add(-time.Hour)) + validToken := s.createToken(t, user.ID, s.faker.UUID(), "access", time.Now().Add(time.Hour)) + + err := s.repo.DeleteExpiredTokens(context.Background()) + require.NoError(t, err, "Failed to delete expired tokens") + + _, err = s.client.Token.Get(context.Background(), expiredToken.ID) + assert.Error(t, err, "Expired token should have been deleted") + + _, err = s.client.Token.Get(context.Background(), validToken.ID) + assert.NoError(t, err, "Valid token should still exist") +} + +func (s *tokenTestSuite) testGetValidTokensByUserID(t *testing.T) { + user := s.createUser(t) + validToken := s.createToken(t, user.ID, s.faker.UUID(), "access", time.Now().Add(time.Hour)) + s.createToken(t, user.ID, "expired-token", "access", time.Now().Add(-time.Hour)) + + validTokens, err := s.repo.GetValidTokensByUserID(context.Background(), user.ID) + require.NoError(t, err, "Failed to get valid tokens") + assert.Len(t, validTokens, 1, "Expected 1 valid token") + assert.Equal(t, validToken.Token, validTokens[0].Token, "Valid token string mismatch") +} + +func (s *tokenTestSuite) testRevokeAllUserTokens(t *testing.T) { + user := s.createUser(t) + s.createToken(t, user.ID, s.faker.UUID(), "access", time.Now().Add(time.Hour)) + s.createToken(t, user.ID, s.faker.UUID(), "refresh", time.Now().Add(2*time.Hour)) + + err := s.repo.RevokeAllUserTokens(context.Background(), user.ID) + require.NoError(t, err, "Failed to revoke all user tokens") + + tokens, err := s.repo.GetValidTokensByUserID(context.Background(), user.ID) + require.NoError(t, err, "Failed to get valid tokens") + assert.Empty(t, tokens, "Expected 0 valid tokens after revocation") +} diff --git a/internal/auth/internal/repository/user.go b/internal/auth/internal/repository/user.go index c73f11f..6ad77a0 100644 --- a/internal/auth/internal/repository/user.go +++ b/internal/auth/internal/repository/user.go @@ -5,10 +5,10 @@ import ( "auth/ent" "auth/ent/role" "auth/ent/user" + "auth/pkg" "context" + "pkg/common/errors" "time" - - "golang.org/x/crypto/bcrypt" ) // IUserRepository defines the interface for user-related operations. @@ -309,6 +309,7 @@ type IUserRepository interface { // // Parameters: // - ctx: Context for the database operation. + // - username: String representing the username of the user. // - password: String representing the password to check. // // Returns: @@ -322,12 +323,13 @@ type IUserRepository interface { // } else { // fmt.Println("Password is incorrect") // } - CheckPassword(ctx context.Context, password string) bool + CheckPassword(ctx context.Context, username, password string) bool // SetPassword sets a new password for a user. // // Parameters: // - ctx: Context for the database operation. + // - username: String representing the username of the user. // - password: String representing the new password to set. // // Returns: @@ -341,7 +343,7 @@ type IUserRepository interface { // return // } // fmt.Println("New password successfully set") - SetPassword(ctx context.Context, password string) error + SetPassword(ctx context.Context, username, password string) error } type UserRepository struct { @@ -465,28 +467,25 @@ func (r *UserRepository) GetUsersByRole(ctx context.Context, roleID string) ([]* } // CheckPassword verifies if the provided password is correct for a user. -func (r *UserRepository) CheckPassword(ctx context.Context, password string) bool { - user, err := r.client.User.Query().Where(user.Password(password)).Only(ctx) +func (r *UserRepository) CheckPassword(ctx context.Context, username, password string) bool { + user, err := r.client.User.Query().Where(user.Username(username)).Only(ctx) if err != nil { return false } + valid, err := pkg.NewPasswordHasher(12).VerifyPassword(user.Password, password) - err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) - if err != nil { - return false - } - return true + return err == nil && valid } // SetPassword sets a new password for a user. -func (r *UserRepository) SetPassword(ctx context.Context, password string) error { - user, err := r.client.User.Query().Where(user.Password(password)).Only(ctx) +func (r *UserRepository) SetPassword(ctx context.Context, username, password string) error { + user, err := r.client.User.Query().Where(user.Username(username)).Only(ctx) if err != nil { + if ent.IsNotFound(err) { + return errors.NewError(errors.ErrorTypeNotFound, "User not found", err) + } return err } - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - if err != nil { - return err - } - return r.client.User.UpdateOne(user).SetPassword(string(hashedPassword)).Exec(ctx) + + return r.client.User.UpdateOne(user).SetPassword(password).Exec(ctx) } diff --git a/internal/auth/internal/repository/user_test.go b/internal/auth/internal/repository/user_test.go new file mode 100644 index 0000000..db0d94a --- /dev/null +++ b/internal/auth/internal/repository/user_test.go @@ -0,0 +1,333 @@ +package repository_test + +import ( + "context" + "fmt" + "testing" + + "auth/ent" + "auth/ent/enttest" + "auth/internal/repository" + + "github.com/brianvoe/gofakeit/v7" + _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type userTestSuite struct { + client *ent.Client + repo repository.IUserRepository + faker *gofakeit.Faker +} + +func setupUserTestSuite(t *testing.T) *userTestSuite { + client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + require.NotNil(t, client, "Ent client should not be nil") + + return &userTestSuite{ + client: client, + repo: repository.NewUserRepository(client), + faker: gofakeit.New(0), + } +} + +func (s *userTestSuite) createUser(t *testing.T) *ent.User { + user, err := s.repo.Create(context.Background(), &ent.User{ + Username: s.faker.Username(), + Email: s.faker.Email(), + Password: s.faker.Password(true, true, true, true, false, 32), + }) + require.NoError(t, err, "Failed to create user") + return user +} + +func (s *userTestSuite) createUniqueRole(t *testing.T) *ent.Role { + ctx := context.Background() + roleName := fmt.Sprintf("role_%s", s.faker.UUID()) + role, err := s.client.Role.Create(). + SetName(roleName). + SetPermissions([]string{"read", "write"}). + Save(ctx) + require.NoError(t, err, "Failed to create role") + return role +} + +func TestUserRepository(t *testing.T) { + suite := setupUserTestSuite(t) + defer suite.client.Close() + + t.Run("Create", suite.testCreate) + t.Run("GetByID", suite.testGetByID) + t.Run("GetByUsername", suite.testGetByUsername) + t.Run("GetByEmail", suite.testGetByEmail) + t.Run("Update", suite.testUpdate) + t.Run("Delete", suite.testDelete) + t.Run("List", suite.testList) + t.Run("Count", suite.testCount) + t.Run("AddRole", suite.testAddRole) + t.Run("RemoveRole", suite.testRemoveRole) + t.Run("GetRoles", suite.testGetRoles) + t.Run("Search", suite.testSearch) + t.Run("ChangePassword", suite.testChangePassword) + t.Run("GetUsersByRole", suite.testGetUsersByRole) + t.Run("CheckPassword", suite.testCheckPassword) + t.Run("SetPassword", suite.testSetPassword) +} + +func (s *userTestSuite) testCreate(t *testing.T) { + ctx := context.Background() + newUser := &ent.User{ + Username: s.faker.Username(), + Email: s.faker.Email(), + Password: s.faker.Password(true, true, true, true, false, 32), + } + + createdUser, err := s.repo.Create(ctx, newUser) + require.NoError(t, err, "Failed to create user") + assert.Equal(t, newUser.Username, createdUser.Username, "Username mismatch") + assert.Equal(t, newUser.Email, createdUser.Email, "Email mismatch") + + savedUser, err := s.client.User.Get(ctx, createdUser.ID) + require.NoError(t, err, "Failed to retrieve saved user") + assert.Equal(t, newUser.Username, savedUser.Username, "Saved username mismatch") +} + +func (s *userTestSuite) testGetByID(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + retrievedUser, err := s.repo.GetByID(ctx, user.ID) + require.NoError(t, err, "Failed to get user by ID") + assert.Equal(t, user.ID, retrievedUser.ID, "Retrieved user ID mismatch") + + _, err = s.repo.GetByID(ctx, "non-existent-id") + assert.Error(t, err, "Expected error when getting non-existent user") +} + +func (s *userTestSuite) testGetByUsername(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + retrievedUser, err := s.repo.GetByUsername(ctx, user.Username) + require.NoError(t, err, "Failed to get user by username") + assert.Equal(t, user.Username, retrievedUser.Username, "Retrieved username mismatch") + + _, err = s.repo.GetByUsername(ctx, "non-existent-username") + assert.Error(t, err, "Expected error when getting non-existent username") +} + +func (s *userTestSuite) testGetByEmail(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + retrievedUser, err := s.repo.GetByEmail(ctx, user.Email) + require.NoError(t, err, "Failed to get user by email") + assert.Equal(t, user.Email, retrievedUser.Email, "Retrieved email mismatch") + + _, err = s.repo.GetByEmail(ctx, "non-existent@example.com") + assert.Error(t, err, "Expected error when getting non-existent email") +} + +func (s *userTestSuite) testUpdate(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + updatedUser := user + updatedUser.Email = s.faker.Email() + + result, err := s.repo.Update(ctx, updatedUser) + require.NoError(t, err, "Failed to update user") + assert.Equal(t, updatedUser.Email, result.Email, "Updated email mismatch") + + retrievedUser, err := s.repo.GetByID(ctx, user.ID) + require.NoError(t, err, "Failed to retrieve updated user") + assert.Equal(t, updatedUser.Email, retrievedUser.Email, "Retrieved updated email mismatch") +} + +func (s *userTestSuite) testDelete(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + err := s.repo.Delete(ctx, user.ID) + require.NoError(t, err, "Failed to delete user") + + _, err = s.repo.GetByID(ctx, user.ID) + assert.Error(t, err, "Expected error when getting deleted user") + + err = s.repo.Delete(ctx, "non-existent-id") + assert.Error(t, err, "Expected error when deleting non-existent user") +} + +func (s *userTestSuite) testList(t *testing.T) { + ctx := context.Background() + + _, err := s.client.User.Delete().Exec(ctx) + require.NoError(t, err, "Failed to clear existing users") + + for i := 0; i < 5; i++ { + s.createUser(t) + } + + users, err := s.repo.List(ctx, 0, 3) + require.NoError(t, err, "Failed to list users") + assert.Len(t, users, 3, "Expected 3 users") + + users, err = s.repo.List(ctx, 3, 3) + require.NoError(t, err, "Failed to list users") + assert.Len(t, users, 2, "Expected 2 users") +} + +func (s *userTestSuite) testCount(t *testing.T) { + ctx := context.Background() + + initialCount, err := s.repo.Count(ctx) + require.NoError(t, err, "Failed to count users") + + for i := 0; i < 5; i++ { + s.createUser(t) + } + + count, err := s.repo.Count(ctx) + require.NoError(t, err, "Failed to count users") + assert.Equal(t, initialCount+5, count, "Expected count to increase by 5") +} + +func (s *userTestSuite) testAddRole(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + role := s.createUniqueRole(t) + + err := s.repo.AddRole(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to add role to user") + + roles, err := s.repo.GetRoles(ctx, user.ID) + require.NoError(t, err, "Failed to get user roles") + assert.Len(t, roles, 1, "Expected 1 role") + assert.Equal(t, role.ID, roles[0].ID, "Role ID mismatch") +} + +func (s *userTestSuite) testRemoveRole(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + role := s.createUniqueRole(t) + + err := s.repo.AddRole(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to add role to user") + + err = s.repo.RemoveRole(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to remove role from user") + + roles, err := s.repo.GetRoles(ctx, user.ID) + require.NoError(t, err, "Failed to get user roles") + assert.Empty(t, roles, "Expected no roles") +} + +func (s *userTestSuite) testGetRoles(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + role := s.createUniqueRole(t) + + err := s.repo.AddRole(ctx, user.ID, role.ID) + require.NoError(t, err, "Failed to add role to user") + + roles, err := s.repo.GetRoles(ctx, user.ID) + require.NoError(t, err, "Failed to get user roles") + assert.Len(t, roles, 1, "Expected 1 role") + assert.Equal(t, role.ID, roles[0].ID, "Role ID mismatch") +} + +func (s *userTestSuite) testGetUsersByRole(t *testing.T) { + ctx := context.Background() + role := s.createUniqueRole(t) + + user1 := s.createUser(t) + user2 := s.createUser(t) + + err := s.repo.AddRole(ctx, user1.ID, role.ID) + require.NoError(t, err, "Failed to add role to user1") + err = s.repo.AddRole(ctx, user2.ID, role.ID) + require.NoError(t, err, "Failed to add role to user2") + + usersWithRole, err := s.repo.GetUsersByRole(ctx, role.ID) + require.NoError(t, err, "Failed to get users by role") + assert.Len(t, usersWithRole, 2, "Expected 2 users with the role") +} + +func (s *userTestSuite) testCheckPassword(t *testing.T) { + ctx := context.Background() + password := s.faker.Password(true, true, true, true, false, 32) + username := s.faker.Username() + + user, err := s.repo.Create(ctx, &ent.User{ + Username: username, + Email: s.faker.Email(), + Password: password, + }) + fmt.Println("user", user) + require.NoError(t, err, "Failed to create user") + + isCorrect := s.repo.CheckPassword(ctx, username, password) + assert.True(t, isCorrect, "Password check should succeed") + + isCorrect = s.repo.CheckPassword(ctx, username, "wrongPassword2") + fmt.Println("isCorrect", isCorrect) + assert.False(t, isCorrect, "Password check should fail for incorrect password") + + isCorrect = s.repo.CheckPassword(ctx, username, user.Password) + assert.False(t, isCorrect, "Password check should fail for hashed password") +} + +func (s *userTestSuite) testSetPassword(t *testing.T) { + ctx := context.Background() + oldPassword := s.faker.Password(true, true, true, true, false, 32) + user := s.client.User.Create(). + SetUsername(s.faker.Username()). + SetEmail(s.faker.Email()). + SetPassword(oldPassword). + SaveX(ctx) + newPassword := s.faker.Password(true, true, true, true, false, 32) + + err := s.repo.SetPassword(ctx, user.Username, newPassword) + require.NoError(t, err, "Failed to set new password") + + err = s.repo.SetPassword(ctx, "non-existent-username", newPassword) + assert.Error(t, err, "Expected error when setting password for non-existent user") + + isCorrect := s.repo.CheckPassword(ctx, user.Username, newPassword) + assert.True(t, isCorrect, "New password check should succeed") + + isCorrect = s.repo.CheckPassword(ctx, user.Username, oldPassword) + assert.False(t, isCorrect, "Old password check should fail") +} + +func (s *userTestSuite) testSearch(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + + results, err := s.repo.Search(ctx, user.Username[:3]) + require.NoError(t, err, "Failed to search users") + assert.NotEmpty(t, results, "Expected search results") + + found := false + for _, result := range results { + if result.ID == user.ID { + found = true + break + } + } + assert.True(t, found, "Expected to find the created user in search results") +} + +func (s *userTestSuite) testChangePassword(t *testing.T) { + ctx := context.Background() + user := s.createUser(t) + newPassword := "newSecurePassword123" + + err := s.repo.ChangePassword(ctx, user.ID, newPassword) + require.NoError(t, err, "Failed to change password") + + updatedUser, err := s.repo.GetByID(ctx, user.ID) + require.NoError(t, err, "Failed to get updated user") + assert.NotEqual(t, user.Password, updatedUser.Password, "Password should have changed") +} diff --git a/internal/auth/pb/auth.pb.go b/internal/auth/pb/auth.pb.go index 5274307..1e5bd7d 100644 --- a/internal/auth/pb/auth.pb.go +++ b/internal/auth/pb/auth.pb.go @@ -7,11 +7,12 @@ package grpc import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" - reflect "reflect" - sync "sync" ) const ( diff --git a/internal/auth/pb/auth_grpc.pb.go b/internal/auth/pb/auth_grpc.pb.go index a75895b..f501c39 100644 --- a/internal/auth/pb/auth_grpc.pb.go +++ b/internal/auth/pb/auth_grpc.pb.go @@ -8,6 +8,7 @@ package grpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/internal/auth/pb/authorization.pb.go b/internal/auth/pb/authorization.pb.go index a69d9ca..1ead493 100644 --- a/internal/auth/pb/authorization.pb.go +++ b/internal/auth/pb/authorization.pb.go @@ -7,11 +7,12 @@ package grpc import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" - reflect "reflect" - sync "sync" ) const ( diff --git a/internal/auth/pb/authorization_grpc.pb.go b/internal/auth/pb/authorization_grpc.pb.go index 4339cf9..2129f19 100644 --- a/internal/auth/pb/authorization_grpc.pb.go +++ b/internal/auth/pb/authorization_grpc.pb.go @@ -8,6 +8,7 @@ package grpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/internal/auth/pb/common.pb.go b/internal/auth/pb/common.pb.go index f6ceefa..1ae7999 100644 --- a/internal/auth/pb/common.pb.go +++ b/internal/auth/pb/common.pb.go @@ -7,11 +7,12 @@ package grpc import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/internal/auth/pkg/limiter.go b/internal/auth/pkg/limiter.go new file mode 100644 index 0000000..263b142 --- /dev/null +++ b/internal/auth/pkg/limiter.go @@ -0,0 +1,89 @@ +package pkg + +import ( + "math/rand" + "sync" + "time" + + "golang.org/x/time/rate" +) + +// PerIPRateLimiter is a helper struct for per-IP rate limiting. +// It uses a map to store rate limiters for each IP address. +// The rate limiter is created on the first request from an IP address. +type PerIPRateLimiter struct { + ips map[string]*rate.Limiter + mu *sync.RWMutex + r rate.Limit + b int +} + +// NewPerIPRateLimiter creates a new PerIPRateLimiter. +// The rate is the maximum number of requests per second. +// The burst is the maximum number of requests that can be made in a short burst. +// Parameters: +// - r: The rate limit. +// - b: The burst limit. +// +// Usage: +// +// limiter := NewPerIPRateLimiter(10, 5) +func NewPerIPRateLimiter(r rate.Limit, b int) *PerIPRateLimiter { + rand.New(rand.NewSource(time.Now().UnixNano())) + return &PerIPRateLimiter{ + ips: make(map[string]*rate.Limiter), + mu: &sync.RWMutex{}, + r: r, + b: b, + } +} + +// AddIP adds an IP address to the rate limiter. +// If the IP address already exists, it returns the existing rate limiter. +// Otherwise, it creates a new rate limiter with a small random variation to the rate. +// Parameters: +// - ip: The IP address to add. +// +// Returns: +// - The rate limiter for the IP address. +// +// Usage: +// +// limiter.AddIP("126.0.0.1") +func (l *PerIPRateLimiter) AddIP(ip string) *rate.Limiter { + l.mu.Lock() + defer l.mu.Unlock() + + limiter, exists := l.ips[ip] + if !exists { + // Add a small random variation to the rate + adjustedRate := l.r + rate.Limit(rand.Float64()*0.1*float64(l.r)) + limiter = rate.NewLimiter(adjustedRate, l.b) + l.ips[ip] = limiter + } + + return limiter +} + +// GetLimiter returns the rate limiter for the given IP address. +// If the IP address does not exist, it creates a new rate limiter. +// Parameters: +// - ip: The IP address to get the rate limiter for. +// +// Returns: +// - The rate limiter for the IP address. +// +// Usage: +// +// limiter.GetLimiter("126.0.0.1") +func (l *PerIPRateLimiter) GetLimiter(ip string) *rate.Limiter { + l.mu.RLock() + limiter, exists := l.ips[ip] + l.mu.RUnlock() + + if !exists { + return l.AddIP(ip) + } + + return limiter +} diff --git a/internal/auth/pkg/limiter_test.go b/internal/auth/pkg/limiter_test.go new file mode 100644 index 0000000..36eedf0 --- /dev/null +++ b/internal/auth/pkg/limiter_test.go @@ -0,0 +1,114 @@ +package pkg_test + +import ( + "auth/pkg" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "golang.org/x/time/rate" +) + +func TestPerIPRateLimiter(t *testing.T) { + t.Run("NewPerIPRateLimiter", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(1, 5) + assert.NotNil(t, limiter, "NewPerIPRateLimiter should return a non-nil limiter") + }) + + t.Run("AddIP", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(1, 5) + ip := "192.168.1.1" + rateLimiter := limiter.AddIP(ip) + assert.NotNil(t, rateLimiter, "AddIP should return a non-nil rate.Limiter") + }) + + t.Run("GetLimiter", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(1, 5) + ip := "192.168.1.1" + + // First call should add the IP + rateLimiter1 := limiter.GetLimiter(ip) + assert.NotNil(t, rateLimiter1, "GetLimiter should return a non-nil rate.Limiter") + + // Second call should return the same limiter + rateLimiter2 := limiter.GetLimiter(ip) + assert.Equal(t, rateLimiter1, rateLimiter2, "GetLimiter should return the same rate.Limiter for the same IP") + }) + + t.Run("RateLimitingBehavior", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(10, 5) // 10 requests per second, burst of 5 + ip := "192.168.1.1" + + rateLimiter := limiter.GetLimiter(ip) + + // Should allow burst + for i := 0; i < 5; i++ { + assert.True(t, rateLimiter.Allow(), "Should allow burst of 5 requests") + } + + // Next request should be rate limited + assert.False(t, rateLimiter.Allow(), "Should not allow 6th request immediately") + + // Wait for 100ms, should allow one more request + time.Sleep(100 * time.Millisecond) + assert.True(t, rateLimiter.Allow(), "Should allow request after waiting") + }) + + t.Run("ConcurrentAccess", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(100, 10) // High limit to avoid rate limiting in this test + ips := []string{"192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5"} + + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for _, ip := range ips { + rateLimiter := limiter.GetLimiter(ip) + assert.NotNil(t, rateLimiter, "GetLimiter should return a non-nil rate.Limiter") + } + }() + } + + wg.Wait() + }) + + t.Run("DifferentIPsDifferentLimiters", func(t *testing.T) { + limiter := pkg.NewPerIPRateLimiter(1, 5) + ip1 := "192.168.1.1" + ip2 := "192.168.1.2" + + rateLimiter1 := limiter.GetLimiter(ip1) + rateLimiter2 := limiter.GetLimiter(ip2) + + assert.NotEqual(t, rateLimiter1, rateLimiter2, "Different IPs should have different rate limiters") + + // Additional check to ensure the limiters are truly different + rateLimiter1.Allow() // Use up one token from the first limiter + assert.True(t, rateLimiter2.Allow(), "Second limiter should still allow a request") + }) + + t.Run("RespectsBurstAndRate", func(t *testing.T) { + r := rate.Limit(2) // 2 requests per second + b := 3 // burst of 3 + limiter := pkg.NewPerIPRateLimiter(r, b) + ip := "192.168.1.1" + rateLimiter := limiter.GetLimiter(ip) + + // Should allow burst + for i := 0; i < b; i++ { + assert.True(t, rateLimiter.Allow(), "Should allow burst of 3 requests") + } + + // Next request should be rate limited + assert.False(t, rateLimiter.Allow(), "Should not allow 4th request immediately") + + // Wait for 500ms, should allow one more request + time.Sleep(500 * time.Millisecond) + assert.True(t, rateLimiter.Allow(), "Should allow request after waiting") + + // Next request should be rate limited again + assert.False(t, rateLimiter.Allow(), "Should not allow another request immediately") + }) +} diff --git a/internal/auth/pkg/password_hash.go b/internal/auth/pkg/password_hash.go new file mode 100644 index 0000000..c1863e3 --- /dev/null +++ b/internal/auth/pkg/password_hash.go @@ -0,0 +1,78 @@ +package pkg + +import ( + "pkg/common/errors" + + "golang.org/x/crypto/bcrypt" +) + +// PasswordHasher is a helper struct for hashing and verifying passwords. +type PasswordHasher struct { + cost int +} + +// NewPasswordHasher creates a new PasswordHasher. +// +// Parameters: +// - cost: The cost of the bcrypt algorithm (default is 10). +// +// Usage: +// +// hasher := NewPasswordHasher(12) +func NewPasswordHasher(cost int) *PasswordHasher { + if cost <= 0 { + cost = 10 + } + return &PasswordHasher{cost: cost} +} + +// HashPassword hashes a password using bcrypt. +// +// Parameters: +// - password: The password to hash. +// +// Returns: +// - The hashed password and an error if hashing fails. +// +// Usage: +// +// hashedPassword, err := hasher.HashPassword("myPassword123") +func (ph *PasswordHasher) HashPassword(password string) (string, error) { + if password == "" { + return "", errors.NewError(errors.ErrorTypeEmptyPassword, "Password cannot be empty", nil) + } + if ph.cost < bcrypt.MinCost || ph.cost > bcrypt.MaxCost { + return "", errors.NewError(errors.ErrorTypeInvalidCost, "Invalid bcrypt cost", nil) + } + bytes, err := bcrypt.GenerateFromPassword([]byte(password), ph.cost) + return string(bytes), err +} + +// VerifyPassword verifies a password against a hashed password. +// +// Parameters: +// - hashedPassword: The hashed password. +// - password: The password to verify. +// +// Returns: +// - True if the password matches the hashed password, false otherwise. +// +// Usage: +// +// valid, err := hasher.VerifyPassword(hashedPassword, "myPassword123") +func (ph *PasswordHasher) VerifyPassword(hashedPassword, password string) (bool, error) { + if hashedPassword == "" { + return false, errors.NewError(errors.ErrorTypeEmptyPassword, "Hashed password cannot be empty", nil) + } + if password == "" { + return false, errors.NewError(errors.ErrorTypeEmptyPassword, "Password cannot be empty", nil) + } + err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) + if err != nil { + if err == bcrypt.ErrMismatchedHashAndPassword { + return false, nil + } + return false, err + } + return true, nil +} diff --git a/internal/auth/pkg/password_hash_test.go b/internal/auth/pkg/password_hash_test.go new file mode 100644 index 0000000..0d3dc1e --- /dev/null +++ b/internal/auth/pkg/password_hash_test.go @@ -0,0 +1,81 @@ +package pkg_test + +import ( + "auth/pkg" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/bcrypt" +) + +func TestPasswordHasherHashPassword(t *testing.T) { + + t.Run("HashPassword", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(12) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.NoError(t, err, "HashPassword should not return an error") + assert.NotEmpty(t, hashedPassword, "Hashed password should not be empty") + }) + + t.Run("HashPasswordWithDefaultCost", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(0) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.NoError(t, err, "HashPassword should not return an error") + assert.NotEmpty(t, hashedPassword, "Hashed password should not be empty") + }) + + t.Run("HashPasswordWithEmptyPassword", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(12) + hashedPassword, err := hasher.HashPassword("") + require.Error(t, err, "HashPassword should return an error") + assert.Empty(t, hashedPassword, "Hashed password should be empty") + }) + + t.Run("HashPasswordWithInvalidCost", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(-1) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.NoError(t, err, "HashPassword should not return an error even with invalid initial cost") + assert.NotEmpty(t, hashedPassword, "Hashed password should not be empty") + }) + + t.Run("HashPasswordWithInvalidCost", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(bcrypt.MaxCost + 1) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.Error(t, err, "HashPassword should return an error") + assert.Empty(t, hashedPassword, "Hashed password should be empty") + }) + + t.Run("VerifyPassword", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(12) + password := "myPassword123" + hashedPassword, err := hasher.HashPassword(password) + require.NoError(t, err, "HashPassword should not return an error") + + match, err := hasher.VerifyPassword(hashedPassword, password) + assert.NoError(t, err, "Passwords should match") + assert.True(t, match, "Passwords should match") + }) + + t.Run("VerifyPasswordWithInvalidPassword", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(12) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.NoError(t, err, "HashPassword should not return an error") + + match, err := hasher.VerifyPassword(hashedPassword, "invalidPassword") + assert.False(t, match, "Passwords should not match") + assert.NoError(t, err, "Passwords should not match") + + }) + + t.Run("VerifyPasswordWithEmptyPassword", func(t *testing.T) { + hasher := pkg.NewPasswordHasher(12) + hashedPassword, err := hasher.HashPassword("myPassword123") + require.NoError(t, err, "HashPassword should not return an error") + + match, err := hasher.VerifyPassword(hashedPassword, "") + assert.False(t, match, "Passwords should not match") + assert.Error(t, err, "Passwords should not match") + assert.Contains(t, err.Error(), "Password cannot be empty") + }) +} diff --git a/internal/auth/pkg/token_generator.go b/internal/auth/pkg/token_generator.go new file mode 100644 index 0000000..91d3d87 --- /dev/null +++ b/internal/auth/pkg/token_generator.go @@ -0,0 +1,36 @@ +package pkg + +import ( + "time" + + "github.com/golang-jwt/jwt" +) + +// TokenGenerator is a helper struct for generating JWT tokens. +type TokenGenerator struct { + secretKey []byte + issuer string + duration time.Duration +} + +// NewTokenGenerator creates a new TokenGenerator. +func NewTokenGenerator(secretKey []byte, issuer string, duration time.Duration) *TokenGenerator { + return &TokenGenerator{ + secretKey: secretKey, + issuer: issuer, + duration: duration, + } +} + +// GenerateToken generates a new JWT token with the given claims. +func (g *TokenGenerator) GenerateToken(claims jwt.MapClaims) (string, error) { + if claims == nil { + claims = jwt.MapClaims{} + } + now := time.Now() + claims["iss"] = g.issuer + claims["iat"] = now.Unix() + claims["exp"] = now.Add(g.duration).Unix() + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(g.secretKey) +} diff --git a/internal/auth/pkg/token_generator_test.go b/internal/auth/pkg/token_generator_test.go new file mode 100644 index 0000000..2675e22 --- /dev/null +++ b/internal/auth/pkg/token_generator_test.go @@ -0,0 +1,86 @@ +package pkg_test + +import ( + "auth/pkg" + "fmt" + "testing" + "time" + + "github.com/golang-jwt/jwt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTokenGenerator(t *testing.T) { + secretKey := []byte("test-secret-key") + issuer := "test-issuer" + duration := 1 * time.Hour + + t.Run("NewTokenGenerator", func(t *testing.T) { + generator := pkg.NewTokenGenerator(secretKey, issuer, duration) + assert.NotNil(t, generator, "NewTokenGenerator should return a non-nil generator") + }) + + t.Run("GenerateToken", func(t *testing.T) { + generator := pkg.NewTokenGenerator(secretKey, issuer, duration) + + t.Run("BasicToken", func(t *testing.T) { + claims := jwt.MapClaims{ + "sub": "1234567890", + "name": "John Doe", + } + + token, err := generator.GenerateToken(claims) + require.NoError(t, err, "GenerateToken should not return an error") + assert.NotEmpty(t, token, "Generated token should not be empty") + + // Verify the token + parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { + return secretKey, nil + }) + + require.NoError(t, err, "Token parsing should not return an error") + assert.True(t, parsedToken.Valid, "Token should be valid") + + parsedClaims, ok := parsedToken.Claims.(jwt.MapClaims) + require.True(t, ok, "Claims should be of type jwt.MapClaims") + + assert.Equal(t, issuer, parsedClaims["iss"], "Issuer claim should match") + assert.Equal(t, "1234567890", parsedClaims["sub"], "Subject claim should match") + assert.Equal(t, "John Doe", parsedClaims["name"], "Name claim should match") + + iat, ok := parsedClaims["iat"].(float64) + require.True(t, ok, "iat claim should be a number") + exp, ok := parsedClaims["exp"].(float64) + require.True(t, ok, "exp claim should be a number") + + assert.InDelta(t, time.Now().Unix(), int64(iat), 5, "iat should be close to current time") + assert.InDelta(t, time.Now().Add(duration).Unix(), int64(exp), 5, "exp should be close to current time plus duration") + }) + + t.Run("EmptyClaims", func(t *testing.T) { + claims := jwt.MapClaims{} + + token, err := generator.GenerateToken(claims) + require.NoError(t, err, "GenerateToken should not return an error with empty claims") + assert.NotEmpty(t, token, "Generated token should not be empty") + }) + + t.Run("NilClaims", func(t *testing.T) { + token, err := generator.GenerateToken(nil) + require.NoError(t, err, "GenerateToken should not return an error with nil claims") + assert.NotEmpty(t, token, "Generated token should not be empty") + }) + + t.Run("LargeClaims", func(t *testing.T) { + largeClaims := jwt.MapClaims{} + for i := 0; i < 100; i++ { + largeClaims[fmt.Sprintf("key%d", i)] = fmt.Sprintf("value%d", i) + } + + token, err := generator.GenerateToken(largeClaims) + require.NoError(t, err, "GenerateToken should not return an error with large claims") + assert.NotEmpty(t, token, "Generated token should not be empty") + }) + }) +} diff --git a/internal/auth/scripts/db_migrate.sh b/internal/auth/scripts/db_migrate.sh index bfe9f34..ef975e0 100755 --- a/internal/auth/scripts/db_migrate.sh +++ b/internal/auth/scripts/db_migrate.sh @@ -94,4 +94,4 @@ case $ACTION in ;; esac -echo "Operation completed successfully." \ No newline at end of file +echo "Operation completed successfully." diff --git a/internal/auth/scripts/generate_proto.sh b/internal/auth/scripts/generate_proto.sh index 7784eaf..ff447e7 100755 --- a/internal/auth/scripts/generate_proto.sh +++ b/internal/auth/scripts/generate_proto.sh @@ -27,4 +27,4 @@ echo "Proto files generated successfully in $GO_OUT_DIR" # Optionally, run go mod tidy to ensure all dependencies are properly managed cd $PROJECT_ROOT && go mod tidy -echo "Proto generation complete!" \ No newline at end of file +echo "Proto generation complete!" diff --git a/internal/datasource/cmd/main.go b/internal/datasource/cmd/main.go index 7bd2847..a9fbd20 100644 --- a/internal/datasource/cmd/main.go +++ b/internal/datasource/cmd/main.go @@ -8,10 +8,11 @@ import ( "google.golang.org/grpc" pb "datasource/grpc" + "google.golang.org/grpc/reflection" - "datasource/managers" "datasource/grpc/server" + manager "datasource/managers" ) type ServerConfig struct { @@ -30,7 +31,7 @@ func SetupAndServe(config ServerConfig) error { s := grpc.NewServer() pb.RegisterDataSourceServiceServer(s, server) - + // Register reflection service on gRPC server. reflection.Register(s) @@ -50,4 +51,4 @@ func main() { if err := SetupAndServe(config); err != nil { log.Fatalf("Failed to serve: %v", err) } -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/api.go b/internal/datasource/connectors/api.go index c85182e..07e0771 100644 --- a/internal/datasource/connectors/api.go +++ b/internal/datasource/connectors/api.go @@ -20,17 +20,17 @@ import ( // APIConnector implements the Connector interface for API data sources. // It supports both RESTful HTTP APIs and WebSocket connections, as well as periodic polling. type APIConnector struct { - client *http.Client - config *Config - baseURL string - wsConn *websocket.Conn - wsBuffer chan []byte - pollingTicker *time.Ticker - stopPolling chan struct{} - wsLock sync.Mutex - reconnectBackoff time.Duration - maxReconnectWait time.Duration - stopReadWebSocket chan struct{} + client *http.Client + config *Config + baseURL string + wsConn *websocket.Conn + wsBuffer chan []byte + pollingTicker *time.Ticker + stopPolling chan struct{} + wsLock sync.Mutex + reconnectBackoff time.Duration + maxReconnectWait time.Duration + stopReadWebSocket chan struct{} } // NewAPIConnector creates a new APIConnector with the given configuration. @@ -57,12 +57,12 @@ func NewAPIConnector(config *Config) *APIConnector { client: &http.Client{ Timeout: time.Duration(config.TimeoutSeconds) * time.Second, }, - baseURL: config.BaseURL, - wsBuffer: make(chan []byte, config.WebSocketBufferSize), - stopPolling: make(chan struct{}), - reconnectBackoff: time.Second, - maxReconnectWait: 2 * time.Minute, - stopReadWebSocket: make(chan struct{}), + baseURL: config.BaseURL, + wsBuffer: make(chan []byte, config.WebSocketBufferSize), + stopPolling: make(chan struct{}), + reconnectBackoff: time.Second, + maxReconnectWait: 2 * time.Minute, + stopReadWebSocket: make(chan struct{}), } } @@ -104,19 +104,19 @@ func (c *APIConnector) Connect(ctx context.Context) error { // log.Printf("Error closing connector: %v", err) // } func (c *APIConnector) Close(ctx context.Context) error { - if c.wsConn != nil { - c.stopReadWebSocket <- struct{}{} - err := c.wsConn.Close() - c.wsConn = nil - return err - } - - if c.pollingTicker != nil { - c.stopPolling <- struct{}{} - c.pollingTicker.Stop() - } - - return nil + if c.wsConn != nil { + c.stopReadWebSocket <- struct{}{} + err := c.wsConn.Close() + c.wsConn = nil + return err + } + + if c.pollingTicker != nil { + c.stopPolling <- struct{}{} + c.pollingTicker.Stop() + } + + return nil } // Query executes a request to the API and returns the results. @@ -147,67 +147,67 @@ func (c *APIConnector) Query(ctx context.Context, query string, args ...interfac // connectWebSocket establishes a WebSocket connection to the API. func (c *APIConnector) connectWebSocket(ctx context.Context) error { - dialer := websocket.Dialer{ - HandshakeTimeout: time.Duration(c.config.TimeoutSeconds) * time.Second, - } + dialer := websocket.Dialer{ + HandshakeTimeout: time.Duration(c.config.TimeoutSeconds) * time.Second, + } - conn, _, err := dialer.DialContext(ctx, c.baseURL, nil) - if err != nil { - return errors.NewError(errors.ErrorTypeApiConnection, "failed to connect to WebSocket", err) - } + conn, _, err := dialer.DialContext(ctx, c.baseURL, nil) + if err != nil { + return errors.NewError(errors.ErrorTypeAPIConnection, "failed to connect to WebSocket", err) + } - c.wsConn = conn - return nil + c.wsConn = conn + return nil } // readWebSocket continuously reads messages from the WebSocket connection // and sends them to the wsBuffer channel. func (c *APIConnector) readWebSocket() { - defer func() { - close(c.wsBuffer) - close(c.stopReadWebSocket) - }() - - for { - _, message, err := c.wsConn.ReadMessage() - if err != nil { - select { - case <-c.stopReadWebSocket: - return - default: - log.Printf("WebSocket read error: %v", err) - if err := c.reconnectWebSocket(); err != nil { - log.Printf("Failed to reconnect WebSocket: %v", err) - return - } - continue - } - } - c.wsBuffer <- message - } + defer func() { + close(c.wsBuffer) + close(c.stopReadWebSocket) + }() + + for { + _, message, err := c.wsConn.ReadMessage() + if err != nil { + select { + case <-c.stopReadWebSocket: + return + default: + log.Printf("WebSocket read error: %v", err) + if err := c.reconnectWebSocket(); err != nil { + log.Printf("Failed to reconnect WebSocket: %v", err) + return + } + continue + } + } + c.wsBuffer <- message + } } // reconnectWebSocket attempts to reconnect the WebSocket with exponential backoff func (c *APIConnector) reconnectWebSocket() error { - c.wsLock.Lock() - defer c.wsLock.Unlock() - - backoff := c.reconnectBackoff - for { - log.Printf("Attempting to reconnect WebSocket in %v", backoff) - time.Sleep(backoff) - - if err := c.connectWebSocket(context.Background()); err == nil { - log.Println("Successfully reconnected WebSocket") - c.reconnectBackoff = time.Second // Reset backoff on successful connection - return nil - } - - backoff *= 2 - if backoff > c.maxReconnectWait { - backoff = c.maxReconnectWait - } - } + c.wsLock.Lock() + defer c.wsLock.Unlock() + + backoff := c.reconnectBackoff + for { + log.Printf("Attempting to reconnect WebSocket in %v", backoff) + time.Sleep(backoff) + + if err := c.connectWebSocket(context.Background()); err == nil { + log.Println("Successfully reconnected WebSocket") + c.reconnectBackoff = time.Second // Reset backoff on successful connection + return nil + } + + backoff *= 2 + if backoff > c.maxReconnectWait { + backoff = c.maxReconnectWait + } + } } // queryWebSocket returns the latest message received from the WebSocket connection. @@ -357,7 +357,7 @@ func (c *APIConnector) Execute(ctx context.Context, command string, args ...inte func (c *APIConnector) Ping(ctx context.Context) error { if c.config.IsWebSocket { if c.wsConn == nil { - return errors.NewError(errors.ErrorTypeApiConnection, "WebSocket connection not established", nil) + return errors.NewError(errors.ErrorTypeAPIConnection, "WebSocket connection not established", nil) } return nil } @@ -370,4 +370,4 @@ func (c *APIConnector) Ping(ctx context.Context) error { // It always returns an error indicating that transactions are not supported. func (c *APIConnector) Transaction(ctx context.Context) (TransactionConnector, error) { return nil, errors.NewError(errors.ErrorTypeUnsupported, "transactions are not supported for API connector", nil) -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/connectors.go b/internal/datasource/connectors/connectors.go index 029b0d3..328f96f 100644 --- a/internal/datasource/connectors/connectors.go +++ b/internal/datasource/connectors/connectors.go @@ -43,39 +43,39 @@ type TransactionConnector interface { // Config represents the configuration for a data connector. type Config struct { // Type is the type of the data connector. - Type string + Type string // Host is the hostname of the data source. - Host string + Host string // Port is the port number of the data source. - Port int + Port int // Username is the username for the data source. - Username string + Username string // Password is the password for the data source. - Password string + Password string // Database is the name of the database. - Database string + Database string // MaxOpenConns is the maximum number of open connections to the database. - MaxOpenConns int + MaxOpenConns int // MaxIdleConns is the maximum number of connections in the idle connection pool. - MaxIdleConns int + MaxIdleConns int // ConnMaxLifetimeSeconds is the maximum amount of time a connection may be reused. - ConnMaxLifetimeSeconds int + ConnMaxLifetimeSeconds int // ConnMaxIdleTimeSeconds is the maximum amount of time a connection may be idle before being closed. - Options map[string]interface{} + Options map[string]interface{} // Driver is the driver name for the data source. - Driver string + Driver string // RedisDB is the database number for Redis. - RedisDB int + RedisDB int // IsWebSocket indicates whether the connection is a WebSocket. - IsWebSocket bool + IsWebSocket bool // WebSocketPath is the path for WebSocket connections. - PollingIntervalSeconds int + PollingIntervalSeconds int // WebSocketBufferSize is the buffer size for WebSocket connections. - WebSocketBufferSize int + WebSocketBufferSize int // TimeoutSeconds is the timeout for the HTTP client. - TimeoutSeconds int + TimeoutSeconds int // BaseURL is the base URL for the API. - BaseURL string + BaseURL string // BasePath is the base path for the file connector. - BasePath string -} \ No newline at end of file + BasePath string +} diff --git a/internal/datasource/connectors/factory.go b/internal/datasource/connectors/factory.go index 213876e..4ee778c 100644 --- a/internal/datasource/connectors/factory.go +++ b/internal/datasource/connectors/factory.go @@ -20,5 +20,4 @@ func ConnectorFactory(config *Config) (Connector, error) { default: return nil, fmt.Errorf("unsupported connector type: %s", config.Type) } - return nil, fmt.Errorf("connector type not implemented: %s", config.Type) -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/file.go b/internal/datasource/connectors/file.go index 894444c..3dd38f0 100644 --- a/internal/datasource/connectors/file.go +++ b/internal/datasource/connectors/file.go @@ -177,4 +177,4 @@ func (c *FileConnector) readCSVFile(filePath string) ([]map[string]interface{}, } return result, nil -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/mongo.go b/internal/datasource/connectors/mongo.go index 95d2646..0649450 100644 --- a/internal/datasource/connectors/mongo.go +++ b/internal/datasource/connectors/mongo.go @@ -29,56 +29,55 @@ func NewMongoConnector(config *Config) *MongoConnector { // Connect establishes a connection to the MongoDB database. func (c *MongoConnector) Connect(ctx context.Context) error { - uri := c.buildConnectionString() - - clientOptions := options.Client().ApplyURI(uri) + uri := c.buildConnectionString() + + clientOptions := options.Client().ApplyURI(uri) log.Printf("Connecting to MongoDB: %s", uri) - var client *mongo.Client - err := retry.Retry(ctx, func() error { - var err error - client, err = mongo.Connect(ctx, clientOptions) - if err != nil { + var client *mongo.Client + err := retry.Retry(ctx, func() error { + var err error + client, err = mongo.Connect(ctx, clientOptions) + if err != nil { log.Printf("Failed to connect to MongoDB: %v", err) - return errors.NewError(errors.ErrorTypeConnection, "failed to connect to MongoDB", err) - } - return client.Ping(ctx, nil) - }, retry.DefaultConfig()) + return errors.NewError(errors.ErrorTypeConnection, "failed to connect to MongoDB", err) + } + return client.Ping(ctx, nil) + }, retry.DefaultConfig()) - if err != nil { - return err - } + if err != nil { + return err + } - c.client = client - return nil + c.client = client + return nil } - func (c *MongoConnector) buildConnectionString() string { - query := url.Values{} - for k, v := range c.config.Options { - query.Add(k, fmt.Sprintf("%v", v)) - } - - var baseURL string - if c.config.Port > 0 { - // If port is provided, use standard MongoDB protocol - baseURL = fmt.Sprintf("mongodb://%s:%s@%s:%d", - url.QueryEscape(c.config.Username), - url.QueryEscape(c.config.Password), - c.config.Host, - c.config.Port) - } else { - // If no port, assume it's MongoDB Atlas and use srv protocol - baseURL = fmt.Sprintf("mongodb+srv://%s:%s@%s", - url.QueryEscape(c.config.Username), - url.QueryEscape(c.config.Password), - c.config.Host) - } - - // Append database and query parameters - return fmt.Sprintf("%s/%s?%s", baseURL, c.config.Database, query.Encode()) + query := url.Values{} + for k, v := range c.config.Options { + query.Add(k, fmt.Sprintf("%v", v)) + } + + var baseURL string + if c.config.Port > 0 { + // If port is provided, use standard MongoDB protocol + baseURL = fmt.Sprintf("mongodb://%s:%s@%s:%d", + url.QueryEscape(c.config.Username), + url.QueryEscape(c.config.Password), + c.config.Host, + c.config.Port) + } else { + // If no port, assume it's MongoDB Atlas and use srv protocol + baseURL = fmt.Sprintf("mongodb+srv://%s:%s@%s", + url.QueryEscape(c.config.Username), + url.QueryEscape(c.config.Password), + c.config.Host) + } + + // Append database and query parameters + return fmt.Sprintf("%s/%s?%s", baseURL, c.config.Database, query.Encode()) } // Close closes the connection to the MongoDB database. @@ -91,101 +90,101 @@ func (c *MongoConnector) Close(ctx context.Context) error { // Query executes a query and returns the results as a slice of maps. func (c *MongoConnector) Query(ctx context.Context, query string, args ...interface{}) ([]map[string]interface{}, error) { - if len(args) == 0 { - return nil, errors.NewError(errors.ErrorTypeQuery, "missing collection name", nil) - } - collection, ok := args[0].(string) - if !ok { - return nil, errors.NewError(errors.ErrorTypeQuery, "invalid collection name", nil) - } - - coll := c.client.Database(c.config.Database).Collection(collection) - - var filter bson.M - err := json.Unmarshal([]byte(query), &filter) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to parse query", err) - } - - cursor, err := coll.Find(ctx, filter) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to execute query", err) - } - defer cursor.Close(ctx) - - var results []map[string]interface{} - if err = cursor.All(ctx, &results); err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to decode query results", err) - } - - return results, nil + if len(args) == 0 { + return nil, errors.NewError(errors.ErrorTypeQuery, "missing collection name", nil) + } + collection, ok := args[0].(string) + if !ok { + return nil, errors.NewError(errors.ErrorTypeQuery, "invalid collection name", nil) + } + + coll := c.client.Database(c.config.Database).Collection(collection) + + var filter bson.M + err := json.Unmarshal([]byte(query), &filter) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to parse query", err) + } + + cursor, err := coll.Find(ctx, filter) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to execute query", err) + } + defer cursor.Close(ctx) + + var results []map[string]interface{} + if err = cursor.All(ctx, &results); err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to decode query results", err) + } + + return results, nil } // Execute executes a command and returns the number of affected documents. func (c *MongoConnector) Execute(ctx context.Context, command string, args ...interface{}) (int64, error) { - if len(args) == 0 { - return 0, errors.NewError(errors.ErrorTypeExecution, "missing collection name", nil) - } - collectionName, ok := args[0].(string) - if !ok { - return 0, errors.NewError(errors.ErrorTypeExecution, "invalid collection name", nil) - } - - collection := c.client.Database(c.config.Database).Collection(collectionName) - - var result int64 - var err error - - switch command { - case "insert": - if len(args) < 2 { - return 0, errors.NewError(errors.ErrorTypeExecution, "missing document to insert", nil) - } - doc, ok := args[1].(map[string]interface{}) - if !ok { - return 0, errors.NewError(errors.ErrorTypeExecution, "invalid document format", nil) - } - _, err = collection.InsertOne(ctx, doc) - if err == nil { - result = 1 - } - case "update": - if len(args) < 3 { - return 0, errors.NewError(errors.ErrorTypeExecution, "missing update parameters", nil) - } - filter, ok := args[1].(map[string]interface{}) - if !ok { - return 0, errors.NewError(errors.ErrorTypeExecution, "invalid filter format", nil) - } - update, ok := args[2].(map[string]interface{}) - if !ok { - return 0, errors.NewError(errors.ErrorTypeExecution, "invalid update format", nil) - } - updateResult, err := collection.UpdateMany(ctx, filter, bson.M{"$set": update}) - if err == nil { - result = updateResult.ModifiedCount - } - case "delete": - if len(args) < 2 { - return 0, errors.NewError(errors.ErrorTypeExecution, "missing delete parameters", nil) - } - filter, ok := args[1].(map[string]interface{}) - if !ok { - return 0, errors.NewError(errors.ErrorTypeExecution, "invalid filter format", nil) - } - deleteResult, err := collection.DeleteMany(ctx, filter) - if err == nil { - result = deleteResult.DeletedCount - } - default: - return 0, errors.NewError(errors.ErrorTypeExecution, fmt.Sprintf("unsupported command: %s", command), nil) - } - - if err != nil { - return 0, errors.NewError(errors.ErrorTypeExecution, fmt.Sprintf("failed to execute command: %s", command), err) - } - - return result, nil + if len(args) == 0 { + return 0, errors.NewError(errors.ErrorTypeExecution, "missing collection name", nil) + } + collectionName, ok := args[0].(string) + if !ok { + return 0, errors.NewError(errors.ErrorTypeExecution, "invalid collection name", nil) + } + + collection := c.client.Database(c.config.Database).Collection(collectionName) + + var result int64 + var err error + + switch command { + case "insert": + if len(args) < 2 { + return 0, errors.NewError(errors.ErrorTypeExecution, "missing document to insert", nil) + } + doc, ok := args[1].(map[string]interface{}) + if !ok { + return 0, errors.NewError(errors.ErrorTypeExecution, "invalid document format", nil) + } + _, err = collection.InsertOne(ctx, doc) + if err == nil { + result = 1 + } + case "update": + if len(args) < 3 { + return 0, errors.NewError(errors.ErrorTypeExecution, "missing update parameters", nil) + } + filter, ok := args[1].(map[string]interface{}) + if !ok { + return 0, errors.NewError(errors.ErrorTypeExecution, "invalid filter format", nil) + } + update, ok := args[2].(map[string]interface{}) + if !ok { + return 0, errors.NewError(errors.ErrorTypeExecution, "invalid update format", nil) + } + updateResult, err := collection.UpdateMany(ctx, filter, bson.M{"$set": update}) + if err == nil { + result = updateResult.ModifiedCount + } + case "delete": + if len(args) < 2 { + return 0, errors.NewError(errors.ErrorTypeExecution, "missing delete parameters", nil) + } + filter, ok := args[1].(map[string]interface{}) + if !ok { + return 0, errors.NewError(errors.ErrorTypeExecution, "invalid filter format", nil) + } + deleteResult, err := collection.DeleteMany(ctx, filter) + if err == nil { + result = deleteResult.DeletedCount + } + default: + return 0, errors.NewError(errors.ErrorTypeExecution, fmt.Sprintf("unsupported command: %s", command), nil) + } + + if err != nil { + return 0, errors.NewError(errors.ErrorTypeExecution, fmt.Sprintf("failed to execute command: %s", command), err) + } + + return result, nil } // Ping checks if the database connection is still alive. @@ -223,95 +222,95 @@ type MongoTransactionConnector struct { // Query executes a query within the transaction and returns the results. func (c *MongoTransactionConnector) Query(ctx context.Context, query string, args ...interface{}) ([]map[string]interface{}, error) { - var results []map[string]interface{} - - _, err := c.session.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) { - // Parse the query string into a BSON document - var filter bson.D - err := bson.UnmarshalExtJSON([]byte(query), true, &filter) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to parse query", err) - } - - // Ensure we have at least one argument for the collection name - if len(args) == 0 { - return nil, errors.NewError(errors.ErrorTypeQuery, "missing collection name", nil) - } - collectionName, ok := args[0].(string) - if !ok { - return nil, errors.NewError(errors.ErrorTypeQuery, "invalid collection name", nil) - } - - collection := c.client.Database(c.config.Database).Collection(collectionName) - cursor, err := collection.Find(sessCtx, filter) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to execute query", err) - } - defer cursor.Close(sessCtx) - - for cursor.Next(sessCtx) { - var result map[string]interface{} - if err := cursor.Decode(&result); err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to decode result", err) - } - results = append(results, result) - } - - if err := cursor.Err(); err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "error during cursor iteration", err) - } - - return results, nil - }) - - if err != nil { - return nil, errors.NewError(errors.ErrorTypeTransaction, "transaction failed", err) - } - - return results, nil + var results []map[string]interface{} + + _, err := c.session.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) { + // Parse the query string into a BSON document + var filter bson.D + err := bson.UnmarshalExtJSON([]byte(query), true, &filter) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to parse query", err) + } + + // Ensure we have at least one argument for the collection name + if len(args) == 0 { + return nil, errors.NewError(errors.ErrorTypeQuery, "missing collection name", nil) + } + collectionName, ok := args[0].(string) + if !ok { + return nil, errors.NewError(errors.ErrorTypeQuery, "invalid collection name", nil) + } + + collection := c.client.Database(c.config.Database).Collection(collectionName) + cursor, err := collection.Find(sessCtx, filter) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to execute query", err) + } + defer cursor.Close(sessCtx) + + for cursor.Next(sessCtx) { + var result map[string]interface{} + if err := cursor.Decode(&result); err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to decode result", err) + } + results = append(results, result) + } + + if err := cursor.Err(); err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "error during cursor iteration", err) + } + + return results, nil + }) + + if err != nil { + return nil, errors.NewError(errors.ErrorTypeTransaction, "transaction failed", err) + } + + return results, nil } // Execute executes a command within the transaction and returns the number of affected documents. func (c *MongoTransactionConnector) Execute(ctx context.Context, command string, args ...interface{}) (int64, error) { - var modifiedCount int64 - - _, err := c.session.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) { - var doc bson.D - err := bson.UnmarshalExtJSON([]byte(command), true, &doc) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeExecution, "failed to parse command", err) - } - - // Ensure we have at least one argument for the collection name - if len(args) == 0 { - return nil, errors.NewError(errors.ErrorTypeExecution, "missing collection name", nil) - } - collectionName, ok := args[0].(string) - if !ok { - return nil, errors.NewError(errors.ErrorTypeExecution, "invalid collection name", nil) - } - - collection := c.client.Database(c.config.Database).Collection(collectionName) - - // Assuming the first element is the filter and the second is the update - if len(doc) < 2 { - return nil, errors.NewError(errors.ErrorTypeExecution, "invalid command structure", nil) - } - - result, err := collection.UpdateMany(sessCtx, doc[0].Value, doc[1].Value) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeExecution, "failed to execute command", err) - } - - modifiedCount = result.ModifiedCount - return modifiedCount, nil - }) - - if err != nil { - return 0, errors.NewError(errors.ErrorTypeTransaction, "transaction failed", err) - } - - return modifiedCount, nil + var modifiedCount int64 + + _, err := c.session.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) { + var doc bson.D + err := bson.UnmarshalExtJSON([]byte(command), true, &doc) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeExecution, "failed to parse command", err) + } + + // Ensure we have at least one argument for the collection name + if len(args) == 0 { + return nil, errors.NewError(errors.ErrorTypeExecution, "missing collection name", nil) + } + collectionName, ok := args[0].(string) + if !ok { + return nil, errors.NewError(errors.ErrorTypeExecution, "invalid collection name", nil) + } + + collection := c.client.Database(c.config.Database).Collection(collectionName) + + // Assuming the first element is the filter and the second is the update + if len(doc) < 2 { + return nil, errors.NewError(errors.ErrorTypeExecution, "invalid command structure", nil) + } + + result, err := collection.UpdateMany(sessCtx, doc[0].Value, doc[1].Value) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeExecution, "failed to execute command", err) + } + + modifiedCount = result.ModifiedCount + return modifiedCount, nil + }) + + if err != nil { + return 0, errors.NewError(errors.ErrorTypeTransaction, "transaction failed", err) + } + + return modifiedCount, nil } // Commit commits the transaction. @@ -322,4 +321,4 @@ func (c *MongoTransactionConnector) Commit(ctx context.Context) error { // Rollback rolls back the transaction. func (c *MongoTransactionConnector) Rollback(ctx context.Context) error { return c.session.AbortTransaction(ctx) -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/redis.go b/internal/datasource/connectors/redis.go index 3ff1006..9351b8a 100644 --- a/internal/datasource/connectors/redis.go +++ b/internal/datasource/connectors/redis.go @@ -113,7 +113,7 @@ func (c *RedisTransactionConnector) Query(ctx context.Context, query string, arg return nil, nil // Key does not exist } else if err != nil { return nil, errors.NewError(errors.ErrorTypeTransaction, "cannot query in Redis transaction, use Execute instead", nil) - } + } return []map[string]interface{}{{"value": val}}, nil } @@ -143,4 +143,4 @@ func (c *RedisTransactionConnector) Rollback(ctx context.Context) error { return errors.NewError(errors.ErrorTypeTransaction, "failed to rollback transaction", err) } return nil -} \ No newline at end of file +} diff --git a/internal/datasource/connectors/sql.go b/internal/datasource/connectors/sql.go index b0a4292..d1f1b57 100644 --- a/internal/datasource/connectors/sql.go +++ b/internal/datasource/connectors/sql.go @@ -121,7 +121,7 @@ func (c *SQLConnector) Query(ctx context.Context, query string, args ...interfac // Execute executes a command (e.g., INSERT, UPDATE, DELETE) and returns the number of affected rows. func (c *SQLConnector) Execute(ctx context.Context, command string, args ...interface{}) (int64, error) { if c.db == nil { - return 0, errors.NewError(errors.ErrorTypeDatabaseConnection,errors.ErrorMessages[errors.ErrorTypeDatabaseConnection], nil) + return 0, errors.NewError(errors.ErrorTypeDatabaseConnection, errors.ErrorMessages[errors.ErrorTypeDatabaseConnection], nil) } result, err := c.db.ExecContext(ctx, command, args...) @@ -172,7 +172,6 @@ func (c *SQLTransactionConnector) Query(ctx context.Context, query string, args } defer rows.Close() - columns, err := rows.Columns() if err != nil { return nil, errors.NewError(errors.ErrorTypeQuery, "failed to get columns in transaction", err) @@ -233,4 +232,4 @@ func (c *SQLTransactionConnector) Rollback(ctx context.Context) error { return errors.NewError(errors.ErrorTypeTransaction, "failed to rollback transaction", err) } return nil -} \ No newline at end of file +} diff --git a/internal/datasource/go.mod b/internal/datasource/go.mod index b5d2ad8..e433f95 100644 --- a/internal/datasource/go.mod +++ b/internal/datasource/go.mod @@ -5,29 +5,31 @@ go 1.21 require ( github.com/lib/pq v1.10.9 go.mongodb.org/mongo-driver v1.16.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.2 ) require ( - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.19.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect ) require ( github.com/go-redis/redis/v8 v8.11.5 github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.5.3 - github.com/klauspost/compress v1.13.6 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/grpc v1.64.0 + golang.org/x/text v0.15.0 // indirect + google.golang.org/grpc v1.65.0 ) diff --git a/internal/datasource/go.sum b/internal/datasource/go.sum index a930282..9a71e68 100644 --- a/internal/datasource/go.sum +++ b/internal/datasource/go.sum @@ -1,11 +1,8 @@ -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -14,8 +11,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= @@ -39,14 +35,12 @@ go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4B go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= @@ -56,26 +50,21 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/internal/datasource/grpc/connector.pb.go b/internal/datasource/grpc/connector.pb.go index b43209b..8586875 100644 --- a/internal/datasource/grpc/connector.pb.go +++ b/internal/datasource/grpc/connector.pb.go @@ -7,10 +7,11 @@ package grpc import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/internal/datasource/grpc/connector_grpc.pb.go b/internal/datasource/grpc/connector_grpc.pb.go index dfcdc0e..4283296 100644 --- a/internal/datasource/grpc/connector_grpc.pb.go +++ b/internal/datasource/grpc/connector_grpc.pb.go @@ -8,6 +8,7 @@ package grpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/internal/datasource/grpc/generate_grpc.sh b/internal/datasource/grpc/generate_grpc.sh index d688c3d..694df8f 100755 --- a/internal/datasource/grpc/generate_grpc.sh +++ b/internal/datasource/grpc/generate_grpc.sh @@ -23,4 +23,4 @@ protoc --proto_path=${PROTO_DIR} \ --go-grpc_out=${GO_OUT_DIR} --go-grpc_opt=paths=source_relative \ ${PROTO_DIR}/connector.proto -echo "DataSource gRPC code generation completed." \ No newline at end of file +echo "DataSource gRPC code generation completed." diff --git a/internal/datasource/grpc/proto/connector.proto b/internal/datasource/grpc/proto/connector.proto index 80a8ac2..e395403 100644 --- a/internal/datasource/grpc/proto/connector.proto +++ b/internal/datasource/grpc/proto/connector.proto @@ -87,4 +87,4 @@ message RemoveConnectorRequest { message RemoveConnectorResponse { bool success = 1; string error = 2; -} \ No newline at end of file +} diff --git a/internal/datasource/grpc/server/datasource.go b/internal/datasource/grpc/server/datasource.go index d908db4..b8afe29 100644 --- a/internal/datasource/grpc/server/datasource.go +++ b/internal/datasource/grpc/server/datasource.go @@ -9,10 +9,10 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "datasource/connectors" "datasource/grpc" - "datasource/managers" + manager "datasource/managers" "datasource/managers/query" - "datasource/connectors" ) type DataSourceServer struct { @@ -26,7 +26,7 @@ func NewDataSourceServer(manager *manager.ConnectorManager) *DataSourceServer { func (s *DataSourceServer) Connect(ctx context.Context, req *grpc.ConnectRequest) (*grpc.ConnectResponse, error) { log.Printf("Received Connect request for connector: %s", req.ConnectorName) - + connector, err := s.manager.GetConnector(req.ConnectorName) if err != nil { log.Printf("Error getting connector %s: %v", req.ConnectorName, err) @@ -45,7 +45,7 @@ func (s *DataSourceServer) Connect(ctx context.Context, req *grpc.ConnectRequest func (s *DataSourceServer) Disconnect(ctx context.Context, req *grpc.DisconnectRequest) (*grpc.DisconnectResponse, error) { log.Printf("Received Disconnect request for connector: %s", req.ConnectorName) - + connector, err := s.manager.GetConnector(req.ConnectorName) if err != nil { log.Printf("Error getting connector %s: %v", req.ConnectorName, err) @@ -64,7 +64,7 @@ func (s *DataSourceServer) Disconnect(ctx context.Context, req *grpc.DisconnectR func (s *DataSourceServer) ExecuteQuery(ctx context.Context, req *grpc.QueryRequest) (*grpc.QueryResponse, error) { log.Printf("Received ExecuteQuery request for connector: %s", req.ConnectorName) - + connector, err := s.manager.GetConnector(req.ConnectorName) if err != nil { log.Printf("Error getting connector %s: %v", req.ConnectorName, err) @@ -72,7 +72,7 @@ func (s *DataSourceServer) ExecuteQuery(ctx context.Context, req *grpc.QueryRequ } executor := query.NewQueryExecutor(connector) - + var q query.Query err = json.Unmarshal([]byte(req.Query), &q) if err != nil { @@ -102,7 +102,7 @@ func (s *DataSourceServer) ExecuteQuery(ctx context.Context, req *grpc.QueryRequ func (s *DataSourceServer) ExecuteCommand(ctx context.Context, req *grpc.CommandRequest) (*grpc.CommandResponse, error) { log.Printf("Received ExecuteCommand request for connector: %s", req.ConnectorName) - + connector, err := s.manager.GetConnector(req.ConnectorName) if err != nil { log.Printf("Error getting connector %s: %v", req.ConnectorName, err) @@ -121,7 +121,7 @@ func (s *DataSourceServer) ExecuteCommand(ctx context.Context, req *grpc.Command // func (s *DataSourceServer) GetConnectors(ctx context.Context, req *grpc.GetConnectorsRequest) (*grpc.GetConnectorsResponse, error) { // log.Printf("Received GetConnectors request") - + // connectorNames, err := s.manager.GetConnector() // log.Printf("Retrieved %d connectors", len(connectorNames)) // return &grpc.GetConnectorsResponse{ConnectorNames: connectorNames}, nil @@ -129,7 +129,7 @@ func (s *DataSourceServer) ExecuteCommand(ctx context.Context, req *grpc.Command func (s *DataSourceServer) AddConnector(ctx context.Context, req *grpc.AddConnectorRequest) (*grpc.AddConnectorResponse, error) { log.Printf("Received AddConnector request for connector: %s", req.Name) - + config := &connectors.Config{ Type: req.Config.Type, Host: req.Config.Host, @@ -158,7 +158,7 @@ func (s *DataSourceServer) AddConnector(ctx context.Context, req *grpc.AddConnec func (s *DataSourceServer) RemoveConnector(ctx context.Context, req *grpc.RemoveConnectorRequest) (*grpc.RemoveConnectorResponse, error) { log.Printf("Received RemoveConnector request for connector: %s", req.Name) - + err := s.manager.RemoveConnector(req.Name) if err != nil { log.Printf("Error removing connector %s: %v", req.Name, err) @@ -181,4 +181,4 @@ func (s *DataSourceServer) validateConnectorConfig(config *grpc.ConnectorConfig) } // Add more validation as needed return nil -} \ No newline at end of file +} diff --git a/internal/datasource/managers/manager.go b/internal/datasource/managers/manager.go index 81bc4d0..f294f86 100644 --- a/internal/datasource/managers/manager.go +++ b/internal/datasource/managers/manager.go @@ -92,4 +92,4 @@ func (m *ConnectorManager) CloseAll(ctx context.Context) error { } return nil -} \ No newline at end of file +} diff --git a/internal/datasource/managers/query/query.go b/internal/datasource/managers/query/query.go index 73d1d4c..3bdf9b6 100644 --- a/internal/datasource/managers/query/query.go +++ b/internal/datasource/managers/query/query.go @@ -22,13 +22,13 @@ const ( // Query represents a unified query structure type Query struct { - Type QueryType `json:"type"` - Collection string `json:"collection"` - Fields []string `json:"fields,omitempty"` - Conditions map[string]interface{} `json:"conditions,omitempty"` - Data map[string]interface{} `json:"data,omitempty"` - Limit int `json:"limit,omitempty"` - Offset int `json:"offset,omitempty"` + Type QueryType `json:"type"` + Collection string `json:"collection"` + Fields []string `json:"fields,omitempty"` + Conditions map[string]interface{} `json:"conditions,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Limit int `json:"limit,omitempty"` + Offset int `json:"offset,omitempty"` } // QueryExecutor handles query execution across different connector types @@ -70,34 +70,34 @@ func (qe *QueryExecutor) executeSQL(ctx context.Context, connector *connectors.S } func (qe *QueryExecutor) executeMongo(ctx context.Context, connector *connectors.MongoConnector, query Query) ([]map[string]interface{}, error) { - switch query.Type { - case Select: - filterJSON, err := json.Marshal(query.Conditions) - if err != nil { - return nil, errors.NewError(errors.ErrorTypeQuery, "failed to marshal query conditions", err) - } - return connector.Query(ctx, string(filterJSON), query.Collection) - case Insert: - affected, err := connector.Execute(ctx, "insert", query.Collection, query.Data) - if err != nil { - return nil, err - } - return []map[string]interface{}{{"affected_documents": affected}}, nil - case Update: - affected, err := connector.Execute(ctx, "update", query.Collection, query.Conditions, query.Data) - if err != nil { - return nil, err - } - return []map[string]interface{}{{"affected_documents": affected}}, nil - case Delete: - affected, err := connector.Execute(ctx, "delete", query.Collection, query.Conditions) - if err != nil { - return nil, err - } - return []map[string]interface{}{{"affected_documents": affected}}, nil - default: - return nil, errors.NewError(errors.ErrorTypeUnsupported, "unsupported query type for MongoDB", nil) - } + switch query.Type { + case Select: + filterJSON, err := json.Marshal(query.Conditions) + if err != nil { + return nil, errors.NewError(errors.ErrorTypeQuery, "failed to marshal query conditions", err) + } + return connector.Query(ctx, string(filterJSON), query.Collection) + case Insert: + affected, err := connector.Execute(ctx, "insert", query.Collection, query.Data) + if err != nil { + return nil, err + } + return []map[string]interface{}{{"affected_documents": affected}}, nil + case Update: + affected, err := connector.Execute(ctx, "update", query.Collection, query.Conditions, query.Data) + if err != nil { + return nil, err + } + return []map[string]interface{}{{"affected_documents": affected}}, nil + case Delete: + affected, err := connector.Execute(ctx, "delete", query.Collection, query.Conditions) + if err != nil { + return nil, err + } + return []map[string]interface{}{{"affected_documents": affected}}, nil + default: + return nil, errors.NewError(errors.ErrorTypeUnsupported, "unsupported query type for MongoDB", nil) + } } func (qe *QueryExecutor) executeRedis(ctx context.Context, connector *connectors.RedisConnector, query Query) ([]map[string]interface{}, error) { @@ -196,4 +196,4 @@ func buildSQLQuery(query Query) (string, []interface{}) { } return sqlQuery.String(), args -} \ No newline at end of file +} diff --git a/internal/datasource/managers/transform/transform.go b/internal/datasource/managers/transform/transform.go index d08b1e8..cdb3de3 100644 --- a/internal/datasource/managers/transform/transform.go +++ b/internal/datasource/managers/transform/transform.go @@ -45,11 +45,12 @@ type Transformer struct{} // fmt.Printf("Name: %v\n", resultValue.FieldByName("Name").Interface()) // fmt.Printf("Age: %v\n", resultValue.FieldByName("Age").Interface()) -// // Access nested struct -// address := resultValue.FieldByName("Address").Interface() -// addressValue := reflect.ValueOf(address) -// fmt.Printf("City: %v\n", addressValue.FieldByName("City").Interface()) -// fmt.Printf("Zip: %v\n", addressValue.FieldByName("Zip").Interface()) +// // Access nested struct +// address := resultValue.FieldByName("Address").Interface() +// addressValue := reflect.ValueOf(address) +// fmt.Printf("City: %v\n", addressValue.FieldByName("City").Interface()) +// fmt.Printf("Zip: %v\n", addressValue.FieldByName("Zip").Interface()) +// // ``` func NewTransformer() *Transformer { return &Transformer{} @@ -73,111 +74,111 @@ func (t *Transformer) TransformData(data interface{}, targetFormat string) (inte // toStruct converts data to a struct using reflection func (t *Transformer) toStruct(data interface{}) (interface{}, error) { - dataValue := reflect.ValueOf(data) - if dataValue.Kind() == reflect.Ptr { - dataValue = dataValue.Elem() - } - - switch dataValue.Kind() { - case reflect.Struct: - return data, nil // Already a struct - case reflect.Map: - return t.mapToStruct(dataValue) - default: - return nil, errors.NewError(errors.ErrorTypeTransformation, "unsupported data type for struct conversion", nil) - } + dataValue := reflect.ValueOf(data) + if dataValue.Kind() == reflect.Ptr { + dataValue = dataValue.Elem() + } + + switch dataValue.Kind() { + case reflect.Struct: + return data, nil // Already a struct + case reflect.Map: + return t.mapToStruct(dataValue) + default: + return nil, errors.NewError(errors.ErrorTypeTransformation, "unsupported data type for struct conversion", nil) + } } // mapToStruct converts a map to a struct func (t *Transformer) mapToStruct(mapValue reflect.Value) (interface{}, error) { - if mapValue.Kind() != reflect.Map { - return nil, errors.NewError(errors.ErrorTypeTransformation, "input is not a map", nil) - } + if mapValue.Kind() != reflect.Map { + return nil, errors.NewError(errors.ErrorTypeTransformation, "input is not a map", nil) + } - structType := reflect.StructOf(t.mapToStructFields(mapValue)) - structValue := reflect.New(structType).Elem() + structType := reflect.StructOf(t.mapToStructFields(mapValue)) + structValue := reflect.New(structType).Elem() - for _, key := range mapValue.MapKeys() { - fieldName := t.normalizeFieldName(key.String()) - fieldValue := mapValue.MapIndex(key) + for _, key := range mapValue.MapKeys() { + fieldName := t.normalizeFieldName(key.String()) + fieldValue := mapValue.MapIndex(key) - if structValue.FieldByName(fieldName).IsValid() { - if err := t.setStructField(structValue.FieldByName(fieldName), fieldValue); err != nil { - return nil, err - } - } - } + if structValue.FieldByName(fieldName).IsValid() { + if err := t.setStructField(structValue.FieldByName(fieldName), fieldValue); err != nil { + return nil, err + } + } + } - return structValue.Interface(), nil + return structValue.Interface(), nil } // mapToStructFields creates struct fields from a map func (t *Transformer) mapToStructFields(mapValue reflect.Value) []reflect.StructField { - var fields []reflect.StructField - - for _, key := range mapValue.MapKeys() { - fieldName := t.normalizeFieldName(key.String()) - fieldValue := mapValue.MapIndex(key) - fieldType := fieldValue.Type() - - // Handle nested maps - if fieldValue.Kind() == reflect.Map { - nestedFields := t.mapToStructFields(fieldValue) - fieldType = reflect.StructOf(nestedFields) - } - - fields = append(fields, reflect.StructField{ - Name: fieldName, - Type: fieldType, - }) - } - - return fields + var fields []reflect.StructField + + for _, key := range mapValue.MapKeys() { + fieldName := t.normalizeFieldName(key.String()) + fieldValue := mapValue.MapIndex(key) + fieldType := fieldValue.Type() + + // Handle nested maps + if fieldValue.Kind() == reflect.Map { + nestedFields := t.mapToStructFields(fieldValue) + fieldType = reflect.StructOf(nestedFields) + } + + fields = append(fields, reflect.StructField{ + Name: fieldName, + Type: fieldType, + }) + } + + return fields } // setStructField sets the value of a struct field func (t *Transformer) setStructField(field reflect.Value, value reflect.Value) error { - if !field.CanSet() { - return errors.NewError(errors.ErrorTypeTransformation, "cannot set field value", nil) - } - - if field.Kind() == reflect.Struct && value.Kind() == reflect.Map { - nestedStruct, err := t.mapToStruct(value) - if err != nil { - return err - } - field.Set(reflect.ValueOf(nestedStruct)) - return nil - } - - if field.Type() != value.Type() { - if value.Type().ConvertibleTo(field.Type()) { - value = value.Convert(field.Type()) - } else { - return errors.NewError(errors.ErrorTypeTransformation, "incompatible types for field assignment", nil) - } - } - - field.Set(value) - return nil + if !field.CanSet() { + return errors.NewError(errors.ErrorTypeTransformation, "cannot set field value", nil) + } + + if field.Kind() == reflect.Struct && value.Kind() == reflect.Map { + nestedStruct, err := t.mapToStruct(value) + if err != nil { + return err + } + field.Set(reflect.ValueOf(nestedStruct)) + return nil + } + + if field.Type() != value.Type() { + if value.Type().ConvertibleTo(field.Type()) { + value = value.Convert(field.Type()) + } else { + return errors.NewError(errors.ErrorTypeTransformation, "incompatible types for field assignment", nil) + } + } + + field.Set(value) + return nil } // normalizeFieldName converts a string to a valid Go struct field name func (t *Transformer) normalizeFieldName(name string) string { - // Capitalize the first letter - name = strings.Title(name) - // Remove any characters that are not letters, numbers, or underscores - name = strings.Map(func(r rune) rune { - if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' { - return r - } - return -1 - }, name) - // Ensure the field name starts with a letter - if len(name) > 0 && (name[0] >= '0' && name[0] <= '9') { - name = "F" + name - } - return name + // Capitalize the first letter + name = strings.Title(name) + // Remove any characters that are not letters, numbers, or underscores + name = strings.Map(func(r rune) rune { + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' { + return r + } + return -1 + }, name) + // Ensure the field name starts with a letter + if len(name) > 0 && (name[0] >= '0' && name[0] <= '9') { + name = "F" + name + } + return name } // toJSON converts data to JSON format @@ -330,4 +331,4 @@ func (t *Transformer) UnflattenMap(data map[string]interface{}) map[string]inter m[parts[len(parts)-1]] = v } return result -} \ No newline at end of file +} diff --git a/internal/datasource/managers/transform/utils.go b/internal/datasource/managers/transform/utils.go index 32a217a..5bcc960 100644 --- a/internal/datasource/managers/transform/utils.go +++ b/internal/datasource/managers/transform/utils.go @@ -100,4 +100,4 @@ func FilterSlice(data []map[string]interface{}, condition func(map[string]interf } } return result -} \ No newline at end of file +} diff --git a/internal/realtime/main.go b/internal/realtime/main.go new file mode 100644 index 0000000..24963e5 --- /dev/null +++ b/internal/realtime/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("Hello, world!") +} diff --git a/internal/report/main.go b/internal/report/main.go new file mode 100644 index 0000000..24963e5 --- /dev/null +++ b/internal/report/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("Hello, world!") +} diff --git a/internal/visualization/Dockerfile b/internal/visualization/Dockerfile index cd7500b..64d7734 100644 --- a/internal/visualization/Dockerfile +++ b/internal/visualization/Dockerfile @@ -1 +1 @@ -FROM node:20 \ No newline at end of file +FROM node:20 diff --git a/internal/visualization/api/handlers/visualization_handler.go b/internal/visualization/api/handlers/visualization_handler.go index 28ae6f5..5ac8282 100644 --- a/internal/visualization/api/handlers/visualization_handler.go +++ b/internal/visualization/api/handlers/visualization_handler.go @@ -1 +1 @@ -package handlers \ No newline at end of file +package handlers diff --git a/internal/visualization/api/proto/visualization.pb.go b/internal/visualization/api/proto/visualization.pb.go index 8e94382..10f5713 100644 --- a/internal/visualization/api/proto/visualization.pb.go +++ b/internal/visualization/api/proto/visualization.pb.go @@ -7,10 +7,11 @@ package grpc import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/internal/visualization/api/proto/visualization.proto b/internal/visualization/api/proto/visualization.proto index 6844b8a..aa8ca34 100644 --- a/internal/visualization/api/proto/visualization.proto +++ b/internal/visualization/api/proto/visualization.proto @@ -63,4 +63,4 @@ message DeleteVisualizationResponse { message ExportVisualizationResponse { bytes exported_data = 1; string format = 2; -} \ No newline at end of file +} diff --git a/internal/visualization/api/proto/visualization_grpc.pb.go b/internal/visualization/api/proto/visualization_grpc.pb.go index 9a4c480..61d7a21 100644 --- a/internal/visualization/api/proto/visualization_grpc.pb.go +++ b/internal/visualization/api/proto/visualization_grpc.pb.go @@ -8,6 +8,7 @@ package grpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/internal/visualization/cmd/server/main.go b/internal/visualization/cmd/server/main.go index 85f0393..24963e5 100644 --- a/internal/visualization/cmd/server/main.go +++ b/internal/visualization/cmd/server/main.go @@ -1 +1,5 @@ -package main \ No newline at end of file +package main + +func main() { + println("Hello, world!") +} diff --git a/internal/visualization/data/client.go b/internal/visualization/data/client.go index 6e9adc2..33dc2bb 100644 --- a/internal/visualization/data/client.go +++ b/internal/visualization/data/client.go @@ -5,9 +5,11 @@ import ( "encoding/json" "fmt" - "google.golang.org/grpc" - pb "visualization/data/client" "datasource/managers/query" + pb "visualization/data/client" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) // DataSourceClient is a gRPC client for the DataSource service @@ -18,7 +20,7 @@ type DataSourceClient struct { // NewDataSourceClient creates a new DataSourceClient func NewDataSourceClient(address string) (*DataSourceClient, error) { - conn, err := grpc.Dial(address, grpc.WithInsecure()) + conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, fmt.Errorf("failed to connect to DataSource service: %w", err) } @@ -133,4 +135,4 @@ func (c *DataSourceClient) RemoveConnector(ctx context.Context, name string) err return fmt.Errorf("failed to remove connector: %s", resp.Error) } return nil -} \ No newline at end of file +} diff --git a/internal/visualization/data/client/connector.pb.go b/internal/visualization/data/client/connector.pb.go index b43209b..8586875 100644 --- a/internal/visualization/data/client/connector.pb.go +++ b/internal/visualization/data/client/connector.pb.go @@ -7,10 +7,11 @@ package grpc import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/internal/visualization/data/client/connector_grpc.pb.go b/internal/visualization/data/client/connector_grpc.pb.go index dfcdc0e..4283296 100644 --- a/internal/visualization/data/client/connector_grpc.pb.go +++ b/internal/visualization/data/client/connector_grpc.pb.go @@ -8,6 +8,7 @@ package grpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/internal/visualization/go.mod b/internal/visualization/go.mod index 1206a54..c005fba 100644 --- a/internal/visualization/go.mod +++ b/internal/visualization/go.mod @@ -2,4 +2,24 @@ module visualization go 1.21 -require github.com/go-echarts/go-echarts/v2 v2.4.0 +require ( + github.com/go-echarts/go-echarts/v2 v2.4.0 + github.com/google/uuid v1.6.0 + go.uber.org/zap v1.21.0 + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.34.2 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/internal/visualization/go.sum b/internal/visualization/go.sum index ab15134..7a9d5aa 100644 --- a/internal/visualization/go.sum +++ b/internal/visualization/go.sum @@ -1,2 +1,21 @@ +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/go-echarts/go-echarts/v2 v2.4.0 h1:efD46dmAvaZEWrBHAGjE8cfDK48vvFTHz5N9VqW5rYc= github.com/go-echarts/go-echarts/v2 v2.4.0/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/visualization/internal/processor/aggregator.go b/internal/visualization/internal/processor/aggregator.go index 163e23d..03d94d3 100644 --- a/internal/visualization/internal/processor/aggregator.go +++ b/internal/visualization/internal/processor/aggregator.go @@ -163,4 +163,4 @@ func (tp *TimeSeriesProcessor) getTimeBucketKey(t time.Time, interval string) st // Close closes the DataSourceClient connection func (dp *DataProcessor) Close() error { return dp.dataSourceClient.Close() -} \ No newline at end of file +} diff --git a/internal/visualization/internal/processor/data_processor.go b/internal/visualization/internal/processor/data_processor.go index ca0b2ef..0456d5b 100644 --- a/internal/visualization/internal/processor/data_processor.go +++ b/internal/visualization/internal/processor/data_processor.go @@ -1,4 +1,3 @@ - package processor import ( @@ -6,9 +5,9 @@ import ( "fmt" "sort" + "datasource/managers/query" pb "visualization/api/proto" client "visualization/data" - "datasource/managers/query" ) // DataProcessor handles the processing of data for visualizations. diff --git a/internal/visualization/internal/service/visualization_service.go b/internal/visualization/internal/service/visualization_service.go index 52eebbe..95c0b26 100644 --- a/internal/visualization/internal/service/visualization_service.go +++ b/internal/visualization/internal/service/visualization_service.go @@ -166,7 +166,6 @@ type VisualizationStore interface { List(ctx context.Context, page, pageSize int32) ([]*pb.VisualizationResponse, int32, error) } - // VisualizationService implements the VisualizationService gRPC service. type VisualizationService struct { pb.UnimplementedVisualizationServiceServer @@ -344,4 +343,4 @@ func (s *VisualizationService) ExportVisualization(ctx context.Context, req *pb. // Close closes any resources held by the VisualizationService. func (s *VisualizationService) Close() error { return s.processor.Close() -} \ No newline at end of file +} diff --git a/internal/visualization/makefile b/internal/visualization/makefile index 7b38a80..3d4a804 100644 --- a/internal/visualization/makefile +++ b/internal/visualization/makefile @@ -12,4 +12,4 @@ test: proto: protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - api/proto/visualization.proto \ No newline at end of file + api/proto/visualization.proto diff --git a/internal/visualization/models/visualization.go b/internal/visualization/models/visualization.go index 778a4c0..2640e7f 100644 --- a/internal/visualization/models/visualization.go +++ b/internal/visualization/models/visualization.go @@ -1 +1 @@ -package models \ No newline at end of file +package models diff --git a/internal/visualization/pkg/colors/palette.go b/internal/visualization/pkg/colors/palette.go index e89a813..7477042 100644 --- a/internal/visualization/pkg/colors/palette.go +++ b/internal/visualization/pkg/colors/palette.go @@ -1 +1 @@ -package colors \ No newline at end of file +package colors diff --git a/internal/visualization/pkg/export/exporter.go b/internal/visualization/pkg/export/exporter.go index 3477fc3..0fd21d2 100644 --- a/internal/visualization/pkg/export/exporter.go +++ b/internal/visualization/pkg/export/exporter.go @@ -1 +1 @@ -package export \ No newline at end of file +package export diff --git a/internal/visualization/renderers/chart/bar_chart.go b/internal/visualization/renderers/chart/bar_chart.go index 5690e56..58a733f 100644 --- a/internal/visualization/renderers/chart/bar_chart.go +++ b/internal/visualization/renderers/chart/bar_chart.go @@ -1 +1 @@ -package chart \ No newline at end of file +package chart diff --git a/internal/visualization/renderers/graph/network_graph.go b/internal/visualization/renderers/graph/network_graph.go index 8566596..e103ddd 100644 --- a/internal/visualization/renderers/graph/network_graph.go +++ b/internal/visualization/renderers/graph/network_graph.go @@ -1 +1 @@ -package graph \ No newline at end of file +package graph diff --git a/internal/visualization/renderers/graph/tree_graph.go b/internal/visualization/renderers/graph/tree_graph.go index 8566596..e103ddd 100644 --- a/internal/visualization/renderers/graph/tree_graph.go +++ b/internal/visualization/renderers/graph/tree_graph.go @@ -1 +1 @@ -package graph \ No newline at end of file +package graph diff --git a/internal/visualization/renderers/mapStrucutre/choropleth.go b/internal/visualization/renderers/mapStrucutre/choropleth.go index 8525c41..e48ff87 100644 --- a/internal/visualization/renderers/mapStrucutre/choropleth.go +++ b/internal/visualization/renderers/mapStrucutre/choropleth.go @@ -1 +1 @@ -package mapStrucutre \ No newline at end of file +package mapStrucutre diff --git a/internal/visualization/renderers/mapStrucutre/point_map.go b/internal/visualization/renderers/mapStrucutre/point_map.go index 8525c41..e48ff87 100644 --- a/internal/visualization/renderers/mapStrucutre/point_map.go +++ b/internal/visualization/renderers/mapStrucutre/point_map.go @@ -1 +1 @@ -package mapStrucutre \ No newline at end of file +package mapStrucutre diff --git a/internal/visualization/renderers/renderers.go b/internal/visualization/renderers/renderers.go index f55adaf..3bb99b0 100644 --- a/internal/visualization/renderers/renderers.go +++ b/internal/visualization/renderers/renderers.go @@ -187,9 +187,9 @@ func (spr *ScatterPlotRenderer) Render(data map[string]interface{}) (string, err scatterData := make([]opts.ScatterData, 0, len(chartData)) for _, dataPoint := range chartData { scatterData = append(scatterData, opts.ScatterData{ - Value: []interface{}{dataPoint[xMeasure], dataPoint[yMeasure]}, - Symbol: "circle", - SymbolSize: 10, + Value: []interface{}{dataPoint[xMeasure], dataPoint[yMeasure]}, + Symbol: "circle", + SymbolSize: 10, // ItemStyle: &opts.ItemStyle{Color: "blue"}, SymbolRotate: 0, }) @@ -262,4 +262,4 @@ func RendererFactory(visualizationType string) (Renderer, error) { default: return nil, fmt.Errorf("unsupported visualization type: %s", visualizationType) } -} \ No newline at end of file +} diff --git a/makefile b/makefile index 5a04c71..a84e31e 100644 --- a/makefile +++ b/makefile @@ -34,4 +34,4 @@ client-ssl: openssl x509 -req -days 3653 -sha256 \ -CA ./certs/root.crt -CAkey /tmp/root.key -CAcreateserial \ -in /tmp/postgresql.csr \ - -out ./certs/postgresql.crt \ No newline at end of file + -out ./certs/postgresql.crt diff --git a/package.json b/package.json new file mode 100644 index 0000000..d4f714a --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "devDependencies": { + "@typescript-eslint/eslint-plugin": "6.7.0", + "@typescript-eslint/parser": "6.7.0", + "eslint": "9.6.0", + "typescript": "5.2.2" + } +} diff --git a/pkg/common/encoder/base64.go b/pkg/common/encoder/base64.go new file mode 100644 index 0000000..179b949 --- /dev/null +++ b/pkg/common/encoder/base64.go @@ -0,0 +1,49 @@ +package encoder + +import "encoding/base64" + +// Base64Encoder is a helper struct for encoding and decoding Base64 strings. +type Base64Encoder struct{} + +// NewBase64Encoder creates a new Base64Encoder. +// +// Usage: +// +// encoder := NewBase64Encoder() +func NewBase64Encoder() *Base64Encoder { + return &Base64Encoder{} +} + +// Encode encodes a string to Base64. +// +// Parameters: +// - data: The string to encode. +// +// Returns: +// - The Base64 encoded string. +// +// Usage: +// +// encoded := encoder.Encode("Hello, World!") +func (b *Base64Encoder) Encode(data string) string { + return base64.StdEncoding.EncodeToString([]byte(data)) +} + +// Decode decodes a Base64 string. +// +// Parameters: +// - encodedData: The Base64 encoded string to decode. +// +// Returns: +// - The decoded string and an error if decoding fails. +// +// Usage: +// +// decoded, err := encoder.Decode(encodedString) +func (b *Base64Encoder) Decode(encodedData string) (string, error) { + data, err := base64.StdEncoding.DecodeString(encodedData) + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/pkg/common/encoder/base64_test.go b/pkg/common/encoder/base64_test.go new file mode 100644 index 0000000..697bd4c --- /dev/null +++ b/pkg/common/encoder/base64_test.go @@ -0,0 +1,82 @@ +package encoder_test + +import ( + "pkg/common/encoder" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBase64Encoder(t *testing.T) { + t.Run("NewBase64Encoder", func(t *testing.T) { + enc := encoder.NewBase64Encoder() + assert.NotNil(t, enc, "NewBase64Encoder should return a non-nil encoder") + }) + + t.Run("Encode", func(t *testing.T) { + enc := encoder.NewBase64Encoder() + testCases := []struct { + input string + expected string + }{ + {"Hello, World!", "SGVsbG8sIFdvcmxkIQ=="}, + {"", ""}, + {"1234567890", "MTIzNDU2Nzg5MA=="}, + {"!@#$%^&*()", "IUAjJCVeJiooKQ=="}, + } + + for _, tc := range testCases { + t.Run(tc.input, func(t *testing.T) { + result := enc.Encode(tc.input) + assert.Equal(t, tc.expected, result, "Encode(%q) = %q; want %q", tc.input, result, tc.expected) + }) + } + }) + + t.Run("Decode", func(t *testing.T) { + enc := encoder.NewBase64Encoder() + testCases := []struct { + input string + expected string + hasError bool + }{ + {"SGVsbG8sIFdvcmxkIQ==", "Hello, World!", false}, + {"", "", false}, + {"MTIzNDU2Nzg5MA==", "1234567890", false}, + {"IUAjJCVeJiooKQ==", "!@#$%^&*()", false}, + {"Invalid Base64!", "", true}, + } + + for _, tc := range testCases { + t.Run(tc.input, func(t *testing.T) { + result, err := enc.Decode(tc.input) + if tc.hasError { + assert.Error(t, err, "Decode(%q) should return an error", tc.input) + } else { + assert.NoError(t, err, "Decode(%q) should not return an error", tc.input) + assert.Equal(t, tc.expected, result, "Decode(%q) = %q; want %q", tc.input, result, tc.expected) + } + }) + } + }) + + t.Run("EncodeDecode", func(t *testing.T) { + enc := encoder.NewBase64Encoder() + testCases := []string{ + "Hello, World!", + "", + "1234567890", + "!@#$%^&*()", + "This is a longer string with spaces and punctuation.", + } + + for _, tc := range testCases { + t.Run(tc, func(t *testing.T) { + encoded := enc.Encode(tc) + decoded, err := enc.Decode(encoded) + assert.NoError(t, err, "Decode(Encode(%q)) should not return an error", tc) + assert.Equal(t, tc, decoded, "Decode(Encode(%q)) = %q; want %q", tc, decoded, tc) + }) + } + }) +} diff --git a/pkg/common/errors/error.go b/pkg/common/errors/error.go index 2cc0d9f..7233962 100644 --- a/pkg/common/errors/error.go +++ b/pkg/common/errors/error.go @@ -1,80 +1,94 @@ -// Package errors provide custom error types and error checking functions +// Package errors provides custom error types and error checking functions // for common error scenarios in the DataVinci project. package errors import ( + "context" "errors" "fmt" "net" + "runtime" "strings" ) // ErrorType represents the type of error. type ErrorType uint -// ErrorMessages maps error types to human-readable messages. -var ErrorMessages = map[ErrorType]string{ - ErrorTypeUnknown: "unknown", - ErrorTypeDatabaseConnection: "database connection not established", - ErrorTypeTimeout: "timeout", - ErrorTypePermission: "permission", - ErrorTypeQuery: "query", - ErrorTypeExecution: "execution", - ErrorTypeTransaction: "transaction", - ErrorTypeConfiguration: "configuration", - ErrorTypeApiConnection: "api connection", - ErrorTypeUnsupported: "unsupported", - ErrorTypeFileConnection: "file connection", - ErrorTypeNotFound: "not found", - ErrorTypeConnection : "connection", - ErrorTypeTransformation: "transformation", -} - const ( - // ErrorTypeUnknown represents an unknown error. ErrorTypeUnknown ErrorType = iota - // ErrorTypeDatabaseConnection represents a connection error. ErrorTypeDatabaseConnection - // ErrorTypeTimeout represents a timeout error. ErrorTypeTimeout - // ErrorTypePermission represents a permission error. ErrorTypePermission - // ErrorTypeQuery represents a query error. ErrorTypeQuery - // ErrorTypeExecution represents an execution error. ErrorTypeExecution - // ErrorTypeTransaction represents a transaction error. ErrorTypeTransaction - // ErrorTypeConfiguration represents a configuration error. ErrorTypeConfiguration - // ErrorTypeApiConnection represents an API connection error. - ErrorTypeApiConnection - // ErrorTypeUnsupported represents an unsupported operation error. + ErrorTypeAPIConnection ErrorTypeUnsupported - // ErrorTypeFileConnection represents a file connection error. ErrorTypeFileConnection - // ErrorTypeNotFound represents a not found error. ErrorTypeNotFound - // ErrorTypeConnection represents a connection error. ErrorTypeConnection - // ErrorTypeTransformation represents a transformation error. ErrorTypeTransformation + ErrorTypeEmptyPassword + ErrorTypeInvalidCost + ErrorTypeValidation + ErrorTypeResourceExhausted + ErrorTypeDataIntegrity ) +// ErrorMessages maps error types to human-readable messages. +var ErrorMessages = map[ErrorType]string{ + ErrorTypeUnknown: "Unknown error occurred", + ErrorTypeDatabaseConnection: "Database connection not established", + ErrorTypeTimeout: "Operation timed out", + ErrorTypePermission: "Permission denied", + ErrorTypeQuery: "Query execution failed", + ErrorTypeExecution: "Execution error", + ErrorTypeTransaction: "Transaction error", + ErrorTypeConfiguration: "Configuration error", + ErrorTypeAPIConnection: "API connection failed", + ErrorTypeUnsupported: "Unsupported operation", + ErrorTypeFileConnection: "File connection error", + ErrorTypeNotFound: "Resource not found", + ErrorTypeConnection: "Connection error", + ErrorTypeTransformation: "Data transformation error", + ErrorTypeEmptyPassword: "Empty password provided", + ErrorTypeInvalidCost: "Invalid bcrypt cost", + ErrorTypeValidation: "Validation error", + ErrorTypeResourceExhausted: "Resource exhausted", + ErrorTypeDataIntegrity: "Data integrity violation", +} + +// GetErrorMessage returns the error message for a given ErrorType. +// If the ErrorType is not found in ErrorMessages, it returns a default message. +func GetErrorMessage(errType ErrorType) string { + if msg, ok := ErrorMessages[errType]; ok { + return msg + } + return fmt.Sprintf("Unknown error type (%d)", errType) +} + // Error represents a custom error with additional context. type Error struct { - Type ErrorType // The type of the error - Message string // A human-readable error message - Err error // The underlying error, if any + Type ErrorType // The type of the error + Message string // A human-readable error message + Err error // The underlying error, if any + Cause error // The cause of the error, if any + Stack string // The stack trace of the error + Context map[string]string // Additional context for the error } // Error returns the error message. // It implements the error interface. func (e *Error) Error() string { + message := e.Message + if message == "" { + message = GetErrorMessage(e.Type) + } if e.Err != nil { - return fmt.Sprintf("%s: %v", e.Message, e.Err) + return fmt.Sprintf("%s: %v", message, e.Err) } - return e.Message + return message } // Unwrap returns the wrapped error. @@ -83,49 +97,130 @@ func (e *Error) Unwrap() error { return e.Err } +// Is checks if the given error is of the given type. +// It allows Error to work with errors.Is and errors.As. +func (e *Error) Is(target error) bool { + if target == nil { + return false + } + t, ok := target.(*Error) + if !ok { + return errors.Is(e.Err, target) + } + return e.Type == t.Type +} + // NewError creates a new Error with the given type, message, and underlying error. func NewError(errType ErrorType, message string, err error) *Error { - return &Error{ + return NewErrorWithContext(errType, message, err, nil) +} + +// NewErrorWithContext creates a new Error with the given type, message, underlying error, and context. +func NewErrorWithContext(errType ErrorType, message string, err error, context map[string]string) *Error { + if message == "" { + message = GetErrorMessage(errType) + } + newError := &Error{ Type: errType, Message: message, Err: err, + Cause: err, + Context: context, } + + var sb strings.Builder + for i := 1; ; i++ { + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + fn := runtime.FuncForPC(pc) + sb.WriteString(fmt.Sprintf("%s:%d %s\n", file, line, fn.Name())) + } + newError.Stack = sb.String() + + return newError +} + +// IsErrorType checks if the error is of the given type. +func IsErrorType(err error, errType ErrorType) bool { + var customErr *Error + if errors.As(err, &customErr) { + return customErr.Type == errType + } + return false } // IsConnectionError checks if the given error is a connection error. -// It returns true for custom Error types with ErrorTypeConnection, -// or for standard library network errors. func IsConnectionError(err error) bool { + if err == nil { + return false + } var e *Error if errors.As(err, &e) { - return e.Type == ErrorTypeDatabaseConnection + return e.Type == ErrorTypeDatabaseConnection || e.Type == ErrorTypeConnection || e.Type == ErrorTypeAPIConnection } - return isNetworkError(err) + var netErr *net.OpError + var dnsErr *net.DNSError + return errors.As(err, &netErr) || errors.As(err, &dnsErr) || isNetworkError(err) } // IsTimeoutError checks if the given error is a timeout error. -// It returns true for custom Error types with ErrorTypeTimeout, -// or for errors that contain "timeout" in their message. func IsTimeoutError(err error) bool { + if err == nil { + return false + } var e *Error if errors.As(err, &e) { return e.Type == ErrorTypeTimeout } - return isNetworkError(err) && strings.Contains(strings.ToLower(err.Error()), ErrorMessages[ErrorTypeTimeout]) + var netErr *net.OpError + if errors.As(err, &netErr) { + return netErr.Timeout() + } + return errors.Is(err, context.DeadlineExceeded) || + strings.Contains(strings.ToLower(err.Error()), "timeout") || + strings.Contains(strings.ToLower(err.Error()), "deadline exceeded") } // IsPermissionError checks if the given error is a permission error. -// It returns true for custom Error types with ErrorTypePermission, -// or for errors that contain "permission" in their message. func IsPermissionError(err error) bool { + if err == nil { + return false + } var e *Error if errors.As(err, &e) { return e.Type == ErrorTypePermission } - return strings.Contains(strings.ToLower(err.Error()), ErrorMessages[ErrorTypePermission]) + errLower := strings.ToLower(err.Error()) + return strings.Contains(errLower, "permission") || + strings.Contains(errLower, "access denied") } // isNetworkError checks if the error is a known network error. func isNetworkError(err error) bool { return errors.Is(err, net.ErrClosed) || errors.Is(err, net.ErrWriteToConnected) } + +// AddErrorContext adds additional context to an existing Error. +func AddErrorContext(err *Error, key, value string) *Error { + if err.Context == nil { + err.Context = make(map[string]string) + } + err.Context[key] = value + return err +} + +// GetErrorContext retrieves the context from an Error. +func GetErrorContext(err error) map[string]string { + var e *Error + if errors.As(err, &e) { + return e.Context + } + return nil +} + +// WrapError wraps an existing error with a new Error type and message. +func WrapError(err error, errType ErrorType, message string) *Error { + return NewError(errType, message, err) +} diff --git a/pkg/common/errors/error_test.go b/pkg/common/errors/error_test.go index d8a8898..6b48710 100644 --- a/pkg/common/errors/error_test.go +++ b/pkg/common/errors/error_test.go @@ -1,9 +1,17 @@ -package errors +package errors_test import ( + "context" "errors" + "fmt" "net" + "os" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + . "pkg/common/errors" ) func TestIsConnectionError(t *testing.T) { @@ -14,14 +22,18 @@ func TestIsConnectionError(t *testing.T) { }{ {"Connection error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), true}, {"Network error", net.ErrClosed, true}, + {"DNS error", &net.DNSError{Err: "no such host", Name: "example.com"}, true}, + {"Dial error", &net.OpError{Op: "dial", Err: fmt.Errorf("connection refused")}, true}, + {"Timeout error", NewError(ErrorTypeTimeout, "operation timed out", nil), false}, + {"Permission error", NewError(ErrorTypePermission, "access denied", nil), false}, {"Other error", errors.New("some error"), false}, + {"Nil error", nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := IsConnectionError(tt.err); got != tt.want { - t.Errorf("IsConnectionError() = %v, want %v", got, tt.want) - } + got := IsConnectionError(tt.err) + assert.Equal(t, tt.want, got, "IsConnectionError() = %v, want %v", got, tt.want) }) } } @@ -33,15 +45,19 @@ func TestIsTimeoutError(t *testing.T) { want bool }{ {"Timeout error", NewError(ErrorTypeTimeout, "operation timed out", nil), true}, - {"Network timeout", errors.New("i/o timeout"), true}, + {"Network timeout", &net.OpError{Op: "read", Err: os.ErrDeadlineExceeded}, true}, + {"Context deadline exceeded", context.DeadlineExceeded, true}, + {"I/O timeout string", errors.New("i/o timeout"), true}, + {"Connection error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), false}, + {"Permission error", NewError(ErrorTypePermission, "access denied", nil), false}, {"Other error", errors.New("some error"), false}, + {"Nil error", nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := IsTimeoutError(tt.err); got != tt.want { - t.Errorf("IsTimeoutError() = %v, want %v", got, tt.want) - } + got := IsTimeoutError(tt.err) + assert.Equal(t, tt.want, got, "IsTimeoutError() = %v, want %v", got, tt.want) }) } } @@ -54,14 +70,248 @@ func TestIsPermissionError(t *testing.T) { }{ {"Permission error", NewError(ErrorTypePermission, "access denied", nil), true}, {"Permission string", errors.New("permission denied"), true}, + {"OS permission denied", os.ErrPermission, true}, + {"Access denied string", errors.New("access denied"), true}, + {"Connection error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), false}, + {"Timeout error", NewError(ErrorTypeTimeout, "operation timed out", nil), false}, {"Other error", errors.New("some error"), false}, + {"Nil error", nil, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := IsPermissionError(tt.err) + assert.Equal(t, tt.want, got, "IsPermissionError() = %v, want %v", got, tt.want) + }) + } +} + +func TestErrorIs(t *testing.T) { + baseErr := errors.New("base error") + tests := []struct { + name string + err *Error + target error + want bool + }{ + {"Equal error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), NewError(ErrorTypeDatabaseConnection, "connection failed", nil), true}, + {"Different error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), NewError(ErrorTypePermission, "access denied", nil), false}, + {"Same type, different message", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), NewError(ErrorTypeDatabaseConnection, "connection error", nil), true}, + {"With wrapped error", NewError(ErrorTypeDatabaseConnection, "connection failed", baseErr), baseErr, true}, + {"Different wrapped error", NewError(ErrorTypeDatabaseConnection, "connection failed", baseErr), errors.New("other error"), false}, + {"Nil target", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), nil, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := errors.Is(tt.err, tt.target) + assert.Equal(t, tt.want, got, "errors.Is() = %v, want %v", got, tt.want) + }) + } +} + +func TestErrorUnwrap(t *testing.T) { + baseErr := errors.New("base error") + tests := []struct { + name string + err *Error + want error + }{ + {"Nil wrapped error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), nil}, + {"With wrapped error", NewError(ErrorTypeDatabaseConnection, "connection failed", baseErr), baseErr}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.err.Unwrap() + assert.Equal(t, tt.want, got, "Error.Unwrap() = %v, want %v", got, tt.want) + }) + } +} + +func TestErrorError(t *testing.T) { + tests := []struct { + name string + err *Error + want string + wantErr bool + }{ + {"Simple error", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), "connection failed", false}, + {"Error with type, no custom message", NewError(ErrorTypePermission, "", nil), "Permission denied", false}, + {"Error with wrapped error", NewError(ErrorTypeTimeout, "operation timed out", errors.New("underlying error")), "operation timed out: underlying error", false}, + {"Error with type, no custom message, with wrapped error", NewError(ErrorTypeTimeout, "", errors.New("underlying error")), "Operation timed out: underlying error", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := IsPermissionError(tt.err); got != tt.want { - t.Errorf("IsPermissionError() = %v, want %v", got, tt.want) + got := tt.err.Error() + assert.Equal(t, tt.want, got, "Error.Error() = %v, want %v", got, tt.want) + }) + } +} + +func TestNewError(t *testing.T) { + baseErr := errors.New("base error") + tests := []struct { + name string + errType ErrorType + message string + cause error + }{ + {"Connection error with custom message", ErrorTypeDatabaseConnection, "custom connection failed", nil}, + {"Timeout error with cause, no custom message", ErrorTypeTimeout, "", baseErr}, + {"Permission error with default message", ErrorTypePermission, "", nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := NewError(tt.errType, tt.message, tt.cause) + require.NotNil(t, err) + assert.Equal(t, tt.errType, err.Type) + if tt.message != "" { + assert.Equal(t, tt.message, err.Message) + } else { + assert.Equal(t, GetErrorMessage(tt.errType), err.Message) } + assert.Equal(t, tt.cause, err.Cause) + }) + } +} + +func TestErrorWithStack(t *testing.T) { + err := NewError(ErrorTypeDatabaseConnection, "connection failed", nil) + assert.NotEmpty(t, err.Stack, "Error stack should not be empty") +} + +func TestErrorAs(t *testing.T) { + var target *Error + err := NewError(ErrorTypeDatabaseConnection, "connection failed", nil) + + assert.True(t, errors.As(err, &target)) + assert.Equal(t, err, target) + + var notTarget *net.OpError + assert.False(t, errors.As(err, ¬Target)) +} + +func TestIsErrorType(t *testing.T) { + tests := []struct { + name string + err error + errType ErrorType + expected bool + }{ + {"Matching type", NewError(ErrorTypeDatabaseConnection, "connection failed", nil), ErrorTypeDatabaseConnection, true}, + {"Non-matching type", NewError(ErrorTypeTimeout, "operation timed out", nil), ErrorTypeDatabaseConnection, false}, + {"Non-custom error", errors.New("some error"), ErrorTypeDatabaseConnection, false}, + {"Nil error", nil, ErrorTypeDatabaseConnection, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := IsErrorType(tt.err, tt.errType) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestGetErrorContext(t *testing.T) { + context := map[string]string{"server": "db01", "retry": "3"} + err := NewErrorWithContext(ErrorTypeDatabaseConnection, "connection failed", nil, context) + + tests := []struct { + name string + err error + want map[string]string + }{ + {"Get context from Error", err, context}, + {"Get context from non-Error", errors.New("some error"), nil}, + {"Get context from nil", nil, nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := GetErrorContext(tt.err) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestWrapError(t *testing.T) { + baseErr := errors.New("base error") + + tests := []struct { + name string + err error + errType ErrorType + message string + }{ + {"Wrap base error", baseErr, ErrorTypeDatabaseConnection, "connection failed"}, + {"Wrap nil error", nil, ErrorTypeTimeout, "operation timed out"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wrapped := WrapError(tt.err, tt.errType, tt.message) + assert.Equal(t, tt.errType, wrapped.Type) + assert.Equal(t, tt.message, wrapped.Message) + assert.Equal(t, tt.err, wrapped.Cause) + }) + } +} + +func TestErrorTypeString(t *testing.T) { + tests := []struct { + name string + errType ErrorType + expected string + }{ + {"Unknown error", ErrorTypeUnknown, "Unknown error occurred"}, + {"Database connection error", ErrorTypeDatabaseConnection, "Database connection not established"}, + {"Timeout error", ErrorTypeTimeout, "Operation timed out"}, + {"Non-existent error type", ErrorType(9999), "Unknown error type (9999)"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, GetErrorMessage(tt.errType)) + }) + } +} +func TestErrorStack(t *testing.T) { + err := NewError(ErrorTypeDatabaseConnection, "connection failed", nil) + + assert.NotEmpty(t, err.Stack) + assert.Contains(t, err.Stack, "errors_test.TestErrorStack") + assert.Contains(t, err.Stack, "error_test.go") +} + +func TestErrorString(t *testing.T) { + tests := []struct { + name string + err *Error + expected string + }{ + { + name: "Error without underlying error", + err: NewError(ErrorTypeTimeout, "", nil), + expected: "Operation timed out", + }, + { + name: "Error with underlying error", + err: NewError(ErrorTypeDatabaseConnection, "", fmt.Errorf("connection refused")), + expected: "Database connection not established: connection refused", + }, + { + name: "Unknown error type", + err: NewError(ErrorType(9999), "", nil), + expected: "Unknown error type (9999)", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.err.Error()) }) } } diff --git a/pkg/config/config.go b/pkg/config/config.go index 73de0a7..7aa4a44 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,30 +1,30 @@ package config import ( - "github.com/spf13/viper" + "github.com/spf13/viper" ) type Config struct { - DatabaseURL string - AuthServiceAddr string - AuthzServiceAddr string - JWTSecret string + DatabaseURL string + AuthServiceAddr string + AuthzServiceAddr string + JWTSecret string } func Load() (*Config, error) { - viper.SetConfigName("config") - viper.SetConfigType("yaml") - viper.AddConfigPath(".") - viper.AddConfigPath("./config") + viper.SetConfigName("config") + viper.SetConfigType("yaml") + viper.AddConfigPath(".") + viper.AddConfigPath("./config") - if err := viper.ReadInConfig(); err != nil { - return nil, err - } + if err := viper.ReadInConfig(); err != nil { + return nil, err + } - var cfg Config - if err := viper.Unmarshal(&cfg); err != nil { - return nil, err - } + var cfg Config + if err := viper.Unmarshal(&cfg); err != nil { + return nil, err + } - return &cfg, nil -} \ No newline at end of file + return &cfg, nil +} diff --git a/pkg/config/config.yaml b/pkg/config/config.yaml new file mode 100644 index 0000000..fdd6fe7 --- /dev/null +++ b/pkg/config/config.yaml @@ -0,0 +1,8 @@ +JWTSecret: + value: "secret" +DatabaseURL: + value: "postgres://postgres:password@localhost:5432/postgres" +AuthServiceAddress: + value: "localhost:8080" +AuthzServiceAddress: + value: "localhost:8081" diff --git a/pkg/coverage.txt b/pkg/coverage.txt new file mode 100644 index 0000000..c2de1cd --- /dev/null +++ b/pkg/coverage.txt @@ -0,0 +1,7270 @@ +mode: atomic +auth/ent/client.go:38.40,42.2 3 0 +auth/ent/client.go:44.25,49.2 4 0 +auth/ent/client.go:70.39,74.2 3 0 +auth/ent/client.go:77.42,78.27 1 0 +auth/ent/client.go:78.27,80.3 1 0 +auth/ent/client.go:81.2,81.13 1 0 +auth/ent/client.go:81.13,83.3 1 0 +auth/ent/client.go:87.21,88.25 1 0 +auth/ent/client.go:88.25,90.3 1 0 +auth/ent/client.go:94.34,95.25 1 0 +auth/ent/client.go:95.25,97.3 1 0 +auth/ent/client.go:101.43,102.25 1 0 +auth/ent/client.go:102.25,104.3 1 0 +auth/ent/client.go:110.82,111.20 1 0 +auth/ent/client.go:112.55,114.17 2 0 +auth/ent/client.go:114.17,116.4 1 0 +auth/ent/client.go:117.3,117.57 1 0 +auth/ent/client.go:118.10,119.63 1 0 +auth/ent/client.go:128.55,129.39 1 0 +auth/ent/client.go:129.39,131.3 1 0 +auth/ent/client.go:132.2,133.16 2 0 +auth/ent/client.go:133.16,135.3 1 0 +auth/ent/client.go:136.2,144.8 3 0 +auth/ent/client.go:148.81,149.39 1 0 +auth/ent/client.go:149.39,151.3 1 0 +auth/ent/client.go:152.2,155.16 2 0 +auth/ent/client.go:155.16,157.3 1 0 +auth/ent/client.go:158.2,166.8 3 0 +auth/ent/client.go:175.34,176.13 1 0 +auth/ent/client.go:176.13,178.3 1 0 +auth/ent/client.go:179.2,183.15 5 0 +auth/ent/client.go:187.32,189.2 1 0 +auth/ent/client.go:193.37,197.2 3 0 +auth/ent/client.go:201.57,205.2 3 0 +auth/ent/client.go:208.73,209.23 1 0 +auth/ent/client.go:210.21,211.31 1 0 +auth/ent/client.go:212.22,213.32 1 0 +auth/ent/client.go:214.21,215.31 1 0 +auth/ent/client.go:216.10,217.61 1 0 +auth/ent/client.go:227.42,229.2 1 0 +auth/ent/client.go:233.41,235.2 1 0 +auth/ent/client.go:239.61,241.2 1 0 +auth/ent/client.go:244.43,247.2 2 0 +auth/ent/client.go:250.74,252.2 1 0 +auth/ent/client.go:256.95,258.32 2 0 +auth/ent/client.go:258.32,260.3 1 0 +auth/ent/client.go:261.2,262.32 2 0 +auth/ent/client.go:262.32,265.3 2 0 +auth/ent/client.go:266.2,266.62 1 0 +auth/ent/client.go:270.43,273.2 2 0 +auth/ent/client.go:276.56,279.2 2 0 +auth/ent/client.go:282.60,285.2 2 0 +auth/ent/client.go:288.43,291.2 2 0 +auth/ent/client.go:294.56,296.2 1 0 +auth/ent/client.go:299.60,304.2 4 0 +auth/ent/client.go:307.41,313.2 1 0 +auth/ent/client.go:316.73,318.2 1 0 +auth/ent/client.go:321.65,323.16 2 0 +auth/ent/client.go:323.16,324.13 1 0 +auth/ent/client.go:326.2,326.12 1 0 +auth/ent/client.go:330.53,332.68 2 0 +auth/ent/client.go:332.68,341.3 4 0 +auth/ent/client.go:342.2,342.14 1 0 +auth/ent/client.go:346.37,348.2 1 0 +auth/ent/client.go:351.51,353.2 1 0 +auth/ent/client.go:355.82,356.16 1 0 +auth/ent/client.go:357.16,358.82 1 0 +auth/ent/client.go:359.16,360.82 1 0 +auth/ent/client.go:361.19,362.85 1 0 +auth/ent/client.go:363.29,364.82 1 0 +auth/ent/client.go:365.10,366.70 1 0 +auth/ent/client.go:376.44,378.2 1 0 +auth/ent/client.go:382.42,384.2 1 0 +auth/ent/client.go:388.62,390.2 1 0 +auth/ent/client.go:393.45,396.2 2 0 +auth/ent/client.go:399.77,401.2 1 0 +auth/ent/client.go:405.98,407.32 2 0 +auth/ent/client.go:407.32,409.3 1 0 +auth/ent/client.go:410.2,411.32 2 0 +auth/ent/client.go:411.32,414.3 2 0 +auth/ent/client.go:415.2,415.63 1 0 +auth/ent/client.go:419.45,422.2 2 0 +auth/ent/client.go:425.59,428.2 2 0 +auth/ent/client.go:431.62,434.2 2 0 +auth/ent/client.go:437.45,440.2 2 0 +auth/ent/client.go:443.59,445.2 1 0 +auth/ent/client.go:448.62,453.2 4 0 +auth/ent/client.go:456.43,462.2 1 0 +auth/ent/client.go:465.75,467.2 1 0 +auth/ent/client.go:470.67,472.16 2 0 +auth/ent/client.go:472.16,473.13 1 0 +auth/ent/client.go:475.2,475.12 1 0 +auth/ent/client.go:479.54,481.68 2 0 +auth/ent/client.go:481.68,490.3 4 0 +auth/ent/client.go:491.2,491.14 1 0 +auth/ent/client.go:495.38,497.2 1 0 +auth/ent/client.go:500.52,502.2 1 0 +auth/ent/client.go:504.84,505.16 1 0 +auth/ent/client.go:506.16,507.83 1 0 +auth/ent/client.go:508.16,509.83 1 0 +auth/ent/client.go:510.19,511.86 1 0 +auth/ent/client.go:512.29,513.83 1 0 +auth/ent/client.go:514.10,515.71 1 0 +auth/ent/client.go:525.42,527.2 1 0 +auth/ent/client.go:531.41,533.2 1 0 +auth/ent/client.go:537.61,539.2 1 0 +auth/ent/client.go:542.43,545.2 2 0 +auth/ent/client.go:548.74,550.2 1 0 +auth/ent/client.go:554.95,556.32 2 0 +auth/ent/client.go:556.32,558.3 1 0 +auth/ent/client.go:559.2,560.32 2 0 +auth/ent/client.go:560.32,563.3 2 0 +auth/ent/client.go:564.2,564.62 1 0 +auth/ent/client.go:568.43,571.2 2 0 +auth/ent/client.go:574.56,577.2 2 0 +auth/ent/client.go:580.60,583.2 2 0 +auth/ent/client.go:586.43,589.2 2 0 +auth/ent/client.go:592.56,594.2 1 0 +auth/ent/client.go:597.60,602.2 4 0 +auth/ent/client.go:605.41,611.2 1 0 +auth/ent/client.go:614.73,616.2 1 0 +auth/ent/client.go:619.65,621.16 2 0 +auth/ent/client.go:621.16,622.13 1 0 +auth/ent/client.go:624.2,624.12 1 0 +auth/ent/client.go:628.53,630.68 2 0 +auth/ent/client.go:630.68,639.3 4 0 +auth/ent/client.go:640.2,640.14 1 0 +auth/ent/client.go:644.55,646.68 2 0 +auth/ent/client.go:646.68,655.3 4 0 +auth/ent/client.go:656.2,656.14 1 0 +auth/ent/client.go:660.37,663.2 2 0 +auth/ent/client.go:666.51,668.2 1 0 +auth/ent/client.go:670.82,671.16 1 0 +auth/ent/client.go:672.16,673.82 1 0 +auth/ent/client.go:674.16,675.82 1 0 +auth/ent/client.go:676.19,677.85 1 0 +auth/ent/client.go:678.29,679.82 1 0 +auth/ent/client.go:680.10,681.70 1 0 +auth/ent/ent.go:42.47,45.2 2 0 +auth/ent/ent.go:48.68,50.2 1 0 +auth/ent/ent.go:55.45,58.2 2 0 +auth/ent/ent.go:61.67,63.2 1 0 +auth/ent/ent.go:75.46,76.22 1 0 +auth/ent/ent.go:76.22,82.3 1 0 +auth/ent/ent.go:83.2,83.35 1 0 +auth/ent/ent.go:87.48,88.31 1 0 +auth/ent/ent.go:88.31,89.28 1 0 +auth/ent/ent.go:89.28,90.56 1 0 +auth/ent/ent.go:90.56,92.5 1 0 +auth/ent/ent.go:93.4,93.30 1 0 +auth/ent/ent.go:99.49,100.31 1 0 +auth/ent/ent.go:100.31,101.28 1 0 +auth/ent/ent.go:101.28,102.56 1 0 +auth/ent/ent.go:102.56,104.5 1 0 +auth/ent/ent.go:105.4,105.31 1 0 +auth/ent/ent.go:118.53,119.38 1 0 +auth/ent/ent.go:119.38,121.3 1 0 +auth/ent/ent.go:125.28,126.38 1 0 +auth/ent/ent.go:126.38,128.3 1 0 +auth/ent/ent.go:132.38,133.38 1 0 +auth/ent/ent.go:133.38,134.59 1 0 +auth/ent/ent.go:134.59,137.4 2 0 +auth/ent/ent.go:138.3,138.29 1 0 +auth/ent/ent.go:143.39,144.38 1 0 +auth/ent/ent.go:144.38,145.59 1 0 +auth/ent/ent.go:145.59,148.4 2 0 +auth/ent/ent.go:149.3,149.29 1 0 +auth/ent/ent.go:154.38,155.38 1 0 +auth/ent/ent.go:155.38,156.59 1 0 +auth/ent/ent.go:156.59,159.4 2 0 +auth/ent/ent.go:160.3,160.29 1 0 +auth/ent/ent.go:165.38,166.38 1 0 +auth/ent/ent.go:166.38,167.59 1 0 +auth/ent/ent.go:167.59,170.4 2 0 +auth/ent/ent.go:171.3,171.29 1 0 +auth/ent/ent.go:182.42,184.2 1 0 +auth/ent/ent.go:187.42,189.2 1 0 +auth/ent/ent.go:192.40,193.16 1 0 +auth/ent/ent.go:193.16,195.3 1 0 +auth/ent/ent.go:196.2,197.27 2 0 +auth/ent/ent.go:206.40,208.2 1 0 +auth/ent/ent.go:211.33,212.16 1 0 +auth/ent/ent.go:212.16,214.3 1 0 +auth/ent/ent.go:215.2,216.27 2 0 +auth/ent/ent.go:220.36,221.21 1 0 +auth/ent/ent.go:221.21,223.3 1 0 +auth/ent/ent.go:224.2,224.12 1 0 +auth/ent/ent.go:233.43,235.2 1 0 +auth/ent/ent.go:238.36,239.16 1 0 +auth/ent/ent.go:239.16,241.3 1 0 +auth/ent/ent.go:242.2,243.27 2 0 +auth/ent/ent.go:252.41,254.2 1 0 +auth/ent/ent.go:257.34,258.16 1 0 +auth/ent/ent.go:258.16,260.3 1 0 +auth/ent/ent.go:261.2,262.27 2 0 +auth/ent/ent.go:274.41,276.2 1 0 +auth/ent/ent.go:279.42,281.2 1 0 +auth/ent/ent.go:284.40,285.16 1 0 +auth/ent/ent.go:285.16,287.3 1 0 +auth/ent/ent.go:288.2,289.27 2 0 +auth/ent/ent.go:301.54,302.39 1 0 +auth/ent/ent.go:302.39,303.13 1 0 +auth/ent/ent.go:308.67,309.22 1 0 +auth/ent/ent.go:309.22,311.3 1 0 +auth/ent/ent.go:312.2,313.40 2 0 +auth/ent/ent.go:313.40,315.3 1 0 +auth/ent/ent.go:316.2,316.15 1 0 +auth/ent/ent.go:320.59,322.16 2 0 +auth/ent/ent.go:322.16,323.13 1 0 +auth/ent/ent.go:325.2,325.10 1 0 +auth/ent/ent.go:329.70,331.41 2 0 +auth/ent/ent.go:331.41,333.3 1 0 +auth/ent/ent.go:334.2,334.16 1 0 +auth/ent/ent.go:335.9,336.19 1 0 +auth/ent/ent.go:337.9,338.32 1 0 +auth/ent/ent.go:339.10,340.85 1 0 +auth/ent/ent.go:342.2,342.8 1 0 +auth/ent/ent.go:346.56,348.16 2 0 +auth/ent/ent.go:348.16,349.13 1 0 +auth/ent/ent.go:351.2,351.10 1 0 +auth/ent/ent.go:355.61,356.22 1 0 +auth/ent/ent.go:356.22,358.3 1 0 +auth/ent/ent.go:359.2,360.40 2 0 +auth/ent/ent.go:360.40,362.3 1 0 +auth/ent/ent.go:363.2,363.15 1 0 +auth/ent/ent.go:367.53,369.16 2 0 +auth/ent/ent.go:369.16,370.13 1 0 +auth/ent/ent.go:372.2,372.10 1 0 +auth/ent/ent.go:376.64,378.38 2 0 +auth/ent/ent.go:378.38,380.3 1 0 +auth/ent/ent.go:381.2,381.16 1 0 +auth/ent/ent.go:382.9,383.19 1 0 +auth/ent/ent.go:384.9,385.32 1 0 +auth/ent/ent.go:386.10,387.82 1 0 +auth/ent/ent.go:389.2,389.8 1 0 +auth/ent/ent.go:393.50,395.16 2 0 +auth/ent/ent.go:395.16,396.13 1 0 +auth/ent/ent.go:398.2,398.10 1 0 +auth/ent/ent.go:402.69,403.22 1 0 +auth/ent/ent.go:403.22,405.3 1 0 +auth/ent/ent.go:406.2,407.40 2 0 +auth/ent/ent.go:407.40,409.3 1 0 +auth/ent/ent.go:410.2,410.15 1 0 +auth/ent/ent.go:414.61,416.16 2 0 +auth/ent/ent.go:416.16,417.13 1 0 +auth/ent/ent.go:419.2,419.10 1 0 +auth/ent/ent.go:423.72,425.42 2 0 +auth/ent/ent.go:425.42,427.3 1 0 +auth/ent/ent.go:428.2,428.16 1 0 +auth/ent/ent.go:429.9,430.19 1 0 +auth/ent/ent.go:431.9,432.32 1 0 +auth/ent/ent.go:433.10,434.86 1 0 +auth/ent/ent.go:436.2,436.8 1 0 +auth/ent/ent.go:440.58,442.16 2 0 +auth/ent/ent.go:442.16,443.13 1 0 +auth/ent/ent.go:445.2,445.10 1 0 +auth/ent/ent.go:449.63,450.22 1 0 +auth/ent/ent.go:450.22,452.3 1 0 +auth/ent/ent.go:453.2,454.40 2 0 +auth/ent/ent.go:454.40,456.3 1 0 +auth/ent/ent.go:457.2,457.15 1 0 +auth/ent/ent.go:461.55,463.16 2 0 +auth/ent/ent.go:463.16,464.13 1 0 +auth/ent/ent.go:466.2,466.10 1 0 +auth/ent/ent.go:470.66,472.39 2 0 +auth/ent/ent.go:472.39,474.3 1 0 +auth/ent/ent.go:475.2,475.16 1 0 +auth/ent/ent.go:476.9,477.19 1 0 +auth/ent/ent.go:478.9,479.32 1 0 +auth/ent/ent.go:480.10,481.83 1 0 +auth/ent/ent.go:483.2,483.8 1 0 +auth/ent/ent.go:487.52,489.16 2 0 +auth/ent/ent.go:489.16,490.13 1 0 +auth/ent/ent.go:492.2,492.10 1 0 +auth/ent/ent.go:499.112,500.21 1 0 +auth/ent/ent.go:500.21,502.3 1 0 +auth/ent/ent.go:503.2,503.84 1 0 +auth/ent/ent.go:503.84,505.10 2 0 +auth/ent/ent.go:505.10,507.4 1 0 +auth/ent/ent.go:509.3,510.19 2 0 +auth/ent/ent.go:512.2,512.39 1 0 +auth/ent/ent.go:512.39,513.22 1 0 +auth/ent/ent.go:513.22,515.4 1 0 +auth/ent/ent.go:516.3,516.22 1 0 +auth/ent/ent.go:518.2,519.16 2 0 +auth/ent/ent.go:519.16,521.3 1 0 +auth/ent/ent.go:522.2,523.9 2 0 +auth/ent/ent.go:523.9,525.3 1 0 +auth/ent/ent.go:526.2,526.16 1 0 +auth/ent/ent.go:530.85,531.38 1 0 +auth/ent/ent.go:531.38,534.3 2 0 +auth/ent/ent.go:535.2,535.12 1 0 +auth/ent/ent.go:540.14,541.71 1 0 +auth/ent/ent.go:541.71,543.10 2 0 +auth/ent/ent.go:543.10,545.4 1 0 +auth/ent/ent.go:546.3,546.27 1 0 +auth/ent/ent.go:552.14,553.71 1 0 +auth/ent/ent.go:553.71,555.10 2 0 +auth/ent/ent.go:555.10,557.4 1 0 +auth/ent/ent.go:558.3,558.29 1 0 +auth/ent/ent.go:562.113,563.40 1 0 +auth/ent/ent.go:563.40,565.3 1 0 +auth/ent/ent.go:566.2,567.16 2 0 +auth/ent/ent.go:567.16,569.3 1 0 +auth/ent/ent.go:570.2,571.9 2 0 +auth/ent/ent.go:571.9,573.3 1 0 +auth/ent/ent.go:574.2,574.16 1 0 +auth/ent/ent.go:579.92,581.81 2 0 +auth/ent/ent.go:581.81,583.10 2 0 +auth/ent/ent.go:583.10,585.4 1 0 +auth/ent/ent.go:586.3,586.62 1 0 +auth/ent/ent.go:586.62,588.4 1 0 +auth/ent/ent.go:589.3,589.71 1 0 +auth/ent/ent.go:589.71,591.4 1 0 +auth/ent/ent.go:592.3,592.16 1 0 +auth/ent/ent.go:594.2,594.40 1 0 +auth/ent/ent.go:594.40,596.3 1 0 +auth/ent/ent.go:597.2,598.16 2 0 +auth/ent/ent.go:598.16,600.3 1 0 +auth/ent/ent.go:601.2,601.37 1 0 +auth/ent/ent.go:602.61,602.61 0 0 +auth/ent/ent.go:603.31,604.28 1 0 +auth/ent/ent.go:605.38,606.21 1 0 +auth/ent/ent.go:608.2,608.12 1 0 +auth/ent/mutation.go:60.73,67.27 2 0 +auth/ent/mutation.go:67.27,69.3 1 0 +auth/ent/mutation.go:70.2,70.10 1 0 +auth/ent/mutation.go:74.39,75.31 1 0 +auth/ent/mutation.go:75.31,81.57 2 0 +auth/ent/mutation.go:81.57,82.19 1 0 +auth/ent/mutation.go:82.19,83.15 1 0 +auth/ent/mutation.go:83.15,85.6 1 0 +auth/ent/mutation.go:85.11,87.6 1 0 +auth/ent/mutation.go:89.4,89.21 1 0 +auth/ent/mutation.go:91.3,91.13 1 0 +auth/ent/mutation.go:96.38,97.31 1 0 +auth/ent/mutation.go:97.31,98.53 1 0 +auth/ent/mutation.go:98.53,100.4 1 0 +auth/ent/mutation.go:101.3,101.18 1 0 +auth/ent/mutation.go:107.40,111.2 3 0 +auth/ent/mutation.go:115.41,116.40 1 0 +auth/ent/mutation.go:116.40,118.3 1 0 +auth/ent/mutation.go:119.2,121.16 3 0 +auth/ent/mutation.go:126.41,128.2 1 0 +auth/ent/mutation.go:132.54,133.17 1 0 +auth/ent/mutation.go:133.17,135.3 1 0 +auth/ent/mutation.go:136.2,136.20 1 0 +auth/ent/mutation.go:143.67,144.9 1 0 +auth/ent/mutation.go:145.42,147.13 2 0 +auth/ent/mutation.go:147.13,149.4 1 0 +auth/ent/mutation.go:150.3,150.14 1 0 +auth/ent/mutation.go:151.36,152.65 1 0 +auth/ent/mutation.go:153.10,154.70 1 0 +auth/ent/mutation.go:159.42,161.2 1 0 +auth/ent/mutation.go:164.55,166.14 2 0 +auth/ent/mutation.go:166.14,168.3 1 0 +auth/ent/mutation.go:169.2,169.17 1 0 +auth/ent/mutation.go:175.75,176.27 1 0 +auth/ent/mutation.go:176.27,178.3 1 0 +auth/ent/mutation.go:179.2,179.38 1 0 +auth/ent/mutation.go:179.38,181.3 1 0 +auth/ent/mutation.go:182.2,183.16 2 0 +auth/ent/mutation.go:183.16,185.3 1 0 +auth/ent/mutation.go:186.2,186.27 1 0 +auth/ent/mutation.go:190.36,192.2 1 0 +auth/ent/mutation.go:195.51,198.2 2 0 +auth/ent/mutation.go:201.64,203.14 2 0 +auth/ent/mutation.go:203.14,205.3 1 0 +auth/ent/mutation.go:206.2,206.17 1 0 +auth/ent/mutation.go:212.84,213.27 1 0 +auth/ent/mutation.go:213.27,215.3 1 0 +auth/ent/mutation.go:216.2,216.38 1 0 +auth/ent/mutation.go:216.38,218.3 1 0 +auth/ent/mutation.go:219.2,220.16 2 0 +auth/ent/mutation.go:220.16,222.3 1 0 +auth/ent/mutation.go:223.2,223.34 1 0 +auth/ent/mutation.go:227.54,229.2 1 0 +auth/ent/mutation.go:232.63,233.35 1 0 +auth/ent/mutation.go:233.35,235.3 1 0 +auth/ent/mutation.go:236.2,236.34 1 0 +auth/ent/mutation.go:240.43,243.2 2 0 +auth/ent/mutation.go:246.50,248.2 1 0 +auth/ent/mutation.go:251.63,253.14 2 0 +auth/ent/mutation.go:253.14,255.3 1 0 +auth/ent/mutation.go:256.2,256.17 1 0 +auth/ent/mutation.go:262.83,263.27 1 0 +auth/ent/mutation.go:263.27,265.3 1 0 +auth/ent/mutation.go:266.2,266.38 1 0 +auth/ent/mutation.go:266.38,268.3 1 0 +auth/ent/mutation.go:269.2,270.16 2 0 +auth/ent/mutation.go:270.16,272.3 1 0 +auth/ent/mutation.go:273.2,273.32 1 0 +auth/ent/mutation.go:277.41,279.2 1 0 +auth/ent/mutation.go:282.50,284.2 1 0 +auth/ent/mutation.go:287.63,289.14 2 0 +auth/ent/mutation.go:289.14,291.3 1 0 +auth/ent/mutation.go:292.2,292.17 1 0 +auth/ent/mutation.go:298.83,299.27 1 0 +auth/ent/mutation.go:299.27,301.3 1 0 +auth/ent/mutation.go:302.2,302.38 1 0 +auth/ent/mutation.go:302.38,304.3 1 0 +auth/ent/mutation.go:305.2,306.16 2 0 +auth/ent/mutation.go:306.16,308.3 1 0 +auth/ent/mutation.go:309.2,309.32 1 0 +auth/ent/mutation.go:313.41,315.2 1 0 +auth/ent/mutation.go:318.50,319.20 1 0 +auth/ent/mutation.go:319.20,321.3 1 0 +auth/ent/mutation.go:322.2,322.21 1 0 +auth/ent/mutation.go:322.21,324.3 1 0 +auth/ent/mutation.go:328.37,330.2 1 0 +auth/ent/mutation.go:333.44,335.2 1 0 +auth/ent/mutation.go:338.53,339.27 1 0 +auth/ent/mutation.go:339.27,341.3 1 0 +auth/ent/mutation.go:342.2,342.21 1 0 +auth/ent/mutation.go:342.21,345.3 2 0 +auth/ent/mutation.go:349.57,350.33 1 0 +auth/ent/mutation.go:350.33,352.3 1 0 +auth/ent/mutation.go:353.2,353.8 1 0 +auth/ent/mutation.go:357.50,358.26 1 0 +auth/ent/mutation.go:358.26,360.3 1 0 +auth/ent/mutation.go:361.2,361.8 1 0 +auth/ent/mutation.go:365.37,369.2 3 0 +auth/ent/mutation.go:372.52,374.2 1 0 +auth/ent/mutation.go:378.58,380.20 2 0 +auth/ent/mutation.go:380.20,382.3 1 0 +auth/ent/mutation.go:383.2,383.15 1 0 +auth/ent/mutation.go:387.32,389.2 1 0 +auth/ent/mutation.go:392.37,394.2 1 0 +auth/ent/mutation.go:397.38,399.2 1 0 +auth/ent/mutation.go:404.42,406.19 2 0 +auth/ent/mutation.go:406.19,408.3 1 0 +auth/ent/mutation.go:409.2,409.26 1 0 +auth/ent/mutation.go:409.26,411.3 1 0 +auth/ent/mutation.go:412.2,412.25 1 0 +auth/ent/mutation.go:412.25,414.3 1 0 +auth/ent/mutation.go:415.2,415.25 1 0 +auth/ent/mutation.go:415.25,417.3 1 0 +auth/ent/mutation.go:418.2,418.15 1 0 +auth/ent/mutation.go:424.61,425.14 1 0 +auth/ent/mutation.go:426.22,427.18 1 0 +auth/ent/mutation.go:428.29,429.25 1 0 +auth/ent/mutation.go:430.27,431.23 1 0 +auth/ent/mutation.go:432.27,433.23 1 0 +auth/ent/mutation.go:435.2,435.19 1 0 +auth/ent/mutation.go:441.86,442.14 1 0 +auth/ent/mutation.go:443.22,444.24 1 0 +auth/ent/mutation.go:445.29,446.31 1 0 +auth/ent/mutation.go:447.27,448.29 1 0 +auth/ent/mutation.go:449.27,450.29 1 0 +auth/ent/mutation.go:452.2,452.55 1 0 +auth/ent/mutation.go:458.69,459.14 1 0 +auth/ent/mutation.go:460.22,462.10 2 0 +auth/ent/mutation.go:462.10,464.4 1 0 +auth/ent/mutation.go:465.3,466.13 2 0 +auth/ent/mutation.go:467.29,469.10 2 0 +auth/ent/mutation.go:469.10,471.4 1 0 +auth/ent/mutation.go:472.3,473.13 2 0 +auth/ent/mutation.go:474.27,476.10 2 0 +auth/ent/mutation.go:476.10,478.4 1 0 +auth/ent/mutation.go:479.3,480.13 2 0 +auth/ent/mutation.go:481.27,483.10 2 0 +auth/ent/mutation.go:483.10,485.4 1 0 +auth/ent/mutation.go:486.3,487.13 2 0 +auth/ent/mutation.go:489.2,489.50 1 0 +auth/ent/mutation.go:494.47,496.2 1 0 +auth/ent/mutation.go:501.66,503.2 1 0 +auth/ent/mutation.go:508.69,509.14 1 0 +auth/ent/mutation.go:511.2,511.58 1 0 +auth/ent/mutation.go:516.49,518.2 1 0 +auth/ent/mutation.go:522.55,525.2 2 0 +auth/ent/mutation.go:529.54,531.2 1 0 +auth/ent/mutation.go:535.54,536.14 1 0 +auth/ent/mutation.go:537.22,539.13 2 0 +auth/ent/mutation.go:540.29,542.13 2 0 +auth/ent/mutation.go:543.27,545.13 2 0 +auth/ent/mutation.go:546.27,548.13 2 0 +auth/ent/mutation.go:550.2,550.50 1 0 +auth/ent/mutation.go:554.46,556.20 2 0 +auth/ent/mutation.go:556.20,558.3 1 0 +auth/ent/mutation.go:559.2,559.14 1 0 +auth/ent/mutation.go:564.58,565.14 1 0 +auth/ent/mutation.go:566.22,568.27 2 0 +auth/ent/mutation.go:568.27,570.4 1 0 +auth/ent/mutation.go:571.3,571.13 1 0 +auth/ent/mutation.go:573.2,573.12 1 0 +auth/ent/mutation.go:577.48,579.27 2 0 +auth/ent/mutation.go:579.27,581.3 1 0 +auth/ent/mutation.go:582.2,582.14 1 0 +auth/ent/mutation.go:587.60,588.14 1 0 +auth/ent/mutation.go:589.22,591.34 2 0 +auth/ent/mutation.go:591.34,593.4 1 0 +auth/ent/mutation.go:594.3,594.13 1 0 +auth/ent/mutation.go:596.2,596.12 1 0 +auth/ent/mutation.go:600.48,602.20 2 0 +auth/ent/mutation.go:602.20,604.3 1 0 +auth/ent/mutation.go:605.2,605.14 1 0 +auth/ent/mutation.go:610.54,611.14 1 0 +auth/ent/mutation.go:612.22,613.24 1 0 +auth/ent/mutation.go:615.2,615.14 1 0 +auth/ent/mutation.go:620.53,621.14 1 0 +auth/ent/mutation.go:623.2,623.56 1 0 +auth/ent/mutation.go:628.53,629.14 1 0 +auth/ent/mutation.go:630.22,632.13 2 0 +auth/ent/mutation.go:634.2,634.49 1 0 +auth/ent/mutation.go:663.76,670.27 2 0 +auth/ent/mutation.go:670.27,672.3 1 0 +auth/ent/mutation.go:673.2,673.10 1 0 +auth/ent/mutation.go:677.41,678.32 1 0 +auth/ent/mutation.go:678.32,684.58 2 0 +auth/ent/mutation.go:684.58,685.19 1 0 +auth/ent/mutation.go:685.19,686.15 1 0 +auth/ent/mutation.go:686.15,688.6 1 0 +auth/ent/mutation.go:688.11,690.6 1 0 +auth/ent/mutation.go:692.4,692.21 1 0 +auth/ent/mutation.go:694.3,694.13 1 0 +auth/ent/mutation.go:699.41,700.32 1 0 +auth/ent/mutation.go:700.32,701.54 1 0 +auth/ent/mutation.go:701.54,703.4 1 0 +auth/ent/mutation.go:704.3,704.18 1 0 +auth/ent/mutation.go:710.41,714.2 3 0 +auth/ent/mutation.go:718.42,719.40 1 0 +auth/ent/mutation.go:719.40,721.3 1 0 +auth/ent/mutation.go:722.2,724.16 3 0 +auth/ent/mutation.go:729.42,731.2 1 0 +auth/ent/mutation.go:735.55,736.17 1 0 +auth/ent/mutation.go:736.17,738.3 1 0 +auth/ent/mutation.go:739.2,739.20 1 0 +auth/ent/mutation.go:746.68,747.9 1 0 +auth/ent/mutation.go:748.42,750.13 2 0 +auth/ent/mutation.go:750.13,752.4 1 0 +auth/ent/mutation.go:753.3,753.14 1 0 +auth/ent/mutation.go:754.36,755.66 1 0 +auth/ent/mutation.go:756.10,757.70 1 0 +auth/ent/mutation.go:762.44,764.2 1 0 +auth/ent/mutation.go:767.57,769.14 2 0 +auth/ent/mutation.go:769.14,771.3 1 0 +auth/ent/mutation.go:772.2,772.17 1 0 +auth/ent/mutation.go:778.77,779.27 1 0 +auth/ent/mutation.go:779.27,781.3 1 0 +auth/ent/mutation.go:782.2,782.38 1 0 +auth/ent/mutation.go:782.38,784.3 1 0 +auth/ent/mutation.go:785.2,786.16 2 0 +auth/ent/mutation.go:786.16,788.3 1 0 +auth/ent/mutation.go:789.2,789.28 1 0 +auth/ent/mutation.go:793.38,795.2 1 0 +auth/ent/mutation.go:798.47,800.2 1 0 +auth/ent/mutation.go:803.63,805.14 2 0 +auth/ent/mutation.go:805.14,807.3 1 0 +auth/ent/mutation.go:808.2,808.17 1 0 +auth/ent/mutation.go:814.80,815.27 1 0 +auth/ent/mutation.go:815.27,817.3 1 0 +auth/ent/mutation.go:818.2,818.38 1 0 +auth/ent/mutation.go:818.38,820.3 1 0 +auth/ent/mutation.go:821.2,822.16 2 0 +auth/ent/mutation.go:822.16,824.3 1 0 +auth/ent/mutation.go:825.2,825.27 1 0 +auth/ent/mutation.go:829.37,831.2 1 0 +auth/ent/mutation.go:834.51,836.2 1 0 +auth/ent/mutation.go:839.64,841.14 2 0 +auth/ent/mutation.go:841.14,843.3 1 0 +auth/ent/mutation.go:844.2,844.17 1 0 +auth/ent/mutation.go:850.84,851.27 1 0 +auth/ent/mutation.go:851.27,853.3 1 0 +auth/ent/mutation.go:854.2,854.38 1 0 +auth/ent/mutation.go:854.38,856.3 1 0 +auth/ent/mutation.go:857.2,858.16 2 0 +auth/ent/mutation.go:858.16,860.3 1 0 +auth/ent/mutation.go:861.2,861.32 1 0 +auth/ent/mutation.go:865.42,867.2 1 0 +auth/ent/mutation.go:870.44,872.2 1 0 +auth/ent/mutation.go:875.57,877.14 2 0 +auth/ent/mutation.go:877.14,879.3 1 0 +auth/ent/mutation.go:880.2,880.17 1 0 +auth/ent/mutation.go:886.77,887.27 1 0 +auth/ent/mutation.go:887.27,889.3 1 0 +auth/ent/mutation.go:890.2,890.38 1 0 +auth/ent/mutation.go:890.38,892.3 1 0 +auth/ent/mutation.go:893.2,894.16 2 0 +auth/ent/mutation.go:894.16,896.3 1 0 +auth/ent/mutation.go:897.2,897.30 1 0 +auth/ent/mutation.go:901.40,903.2 1 0 +auth/ent/mutation.go:906.51,908.2 1 0 +auth/ent/mutation.go:911.64,913.14 2 0 +auth/ent/mutation.go:913.14,915.3 1 0 +auth/ent/mutation.go:916.2,916.17 1 0 +auth/ent/mutation.go:922.84,923.27 1 0 +auth/ent/mutation.go:923.27,925.3 1 0 +auth/ent/mutation.go:926.2,926.38 1 0 +auth/ent/mutation.go:926.38,928.3 1 0 +auth/ent/mutation.go:929.2,930.16 2 0 +auth/ent/mutation.go:930.16,932.3 1 0 +auth/ent/mutation.go:933.2,933.32 1 0 +auth/ent/mutation.go:937.42,939.2 1 0 +auth/ent/mutation.go:942.51,944.2 1 0 +auth/ent/mutation.go:947.64,949.14 2 0 +auth/ent/mutation.go:949.14,951.3 1 0 +auth/ent/mutation.go:952.2,952.17 1 0 +auth/ent/mutation.go:958.84,959.27 1 0 +auth/ent/mutation.go:959.27,961.3 1 0 +auth/ent/mutation.go:962.2,962.38 1 0 +auth/ent/mutation.go:962.38,964.3 1 0 +auth/ent/mutation.go:965.2,966.16 2 0 +auth/ent/mutation.go:966.16,968.3 1 0 +auth/ent/mutation.go:969.2,969.32 1 0 +auth/ent/mutation.go:973.42,975.2 1 0 +auth/ent/mutation.go:978.46,980.2 1 0 +auth/ent/mutation.go:983.37,985.2 1 0 +auth/ent/mutation.go:988.44,990.2 1 0 +auth/ent/mutation.go:993.59,994.19 1 0 +auth/ent/mutation.go:994.19,996.3 1 0 +auth/ent/mutation.go:997.2,997.8 1 0 +auth/ent/mutation.go:1003.50,1004.29 1 0 +auth/ent/mutation.go:1004.29,1006.3 1 0 +auth/ent/mutation.go:1007.2,1007.8 1 0 +auth/ent/mutation.go:1011.37,1014.2 2 0 +auth/ent/mutation.go:1017.54,1019.2 1 0 +auth/ent/mutation.go:1023.59,1025.20 2 0 +auth/ent/mutation.go:1025.20,1027.3 1 0 +auth/ent/mutation.go:1028.2,1028.15 1 0 +auth/ent/mutation.go:1032.33,1034.2 1 0 +auth/ent/mutation.go:1037.38,1039.2 1 0 +auth/ent/mutation.go:1042.39,1044.2 1 0 +auth/ent/mutation.go:1049.43,1051.20 2 0 +auth/ent/mutation.go:1051.20,1053.3 1 0 +auth/ent/mutation.go:1054.2,1054.20 1 0 +auth/ent/mutation.go:1054.20,1056.3 1 0 +auth/ent/mutation.go:1057.2,1057.25 1 0 +auth/ent/mutation.go:1057.25,1059.3 1 0 +auth/ent/mutation.go:1060.2,1060.22 1 0 +auth/ent/mutation.go:1060.22,1062.3 1 0 +auth/ent/mutation.go:1063.2,1063.25 1 0 +auth/ent/mutation.go:1063.25,1065.3 1 0 +auth/ent/mutation.go:1066.2,1066.25 1 0 +auth/ent/mutation.go:1066.25,1068.3 1 0 +auth/ent/mutation.go:1069.2,1069.15 1 0 +auth/ent/mutation.go:1075.62,1076.14 1 0 +auth/ent/mutation.go:1077.24,1078.19 1 0 +auth/ent/mutation.go:1079.23,1080.21 1 0 +auth/ent/mutation.go:1081.28,1082.23 1 0 +auth/ent/mutation.go:1083.26,1084.21 1 0 +auth/ent/mutation.go:1085.28,1086.23 1 0 +auth/ent/mutation.go:1087.28,1088.23 1 0 +auth/ent/mutation.go:1090.2,1090.19 1 0 +auth/ent/mutation.go:1096.87,1097.14 1 0 +auth/ent/mutation.go:1098.24,1099.25 1 0 +auth/ent/mutation.go:1100.23,1101.24 1 0 +auth/ent/mutation.go:1102.28,1103.29 1 0 +auth/ent/mutation.go:1104.26,1105.27 1 0 +auth/ent/mutation.go:1106.28,1107.29 1 0 +auth/ent/mutation.go:1108.28,1109.29 1 0 +auth/ent/mutation.go:1111.2,1111.56 1 0 +auth/ent/mutation.go:1117.70,1118.14 1 0 +auth/ent/mutation.go:1119.24,1121.10 2 0 +auth/ent/mutation.go:1121.10,1123.4 1 0 +auth/ent/mutation.go:1124.3,1125.13 2 0 +auth/ent/mutation.go:1126.23,1128.10 2 0 +auth/ent/mutation.go:1128.10,1130.4 1 0 +auth/ent/mutation.go:1131.3,1132.13 2 0 +auth/ent/mutation.go:1133.28,1135.10 2 0 +auth/ent/mutation.go:1135.10,1137.4 1 0 +auth/ent/mutation.go:1138.3,1139.13 2 0 +auth/ent/mutation.go:1140.26,1142.10 2 0 +auth/ent/mutation.go:1142.10,1144.4 1 0 +auth/ent/mutation.go:1145.3,1146.13 2 0 +auth/ent/mutation.go:1147.28,1149.10 2 0 +auth/ent/mutation.go:1149.10,1151.4 1 0 +auth/ent/mutation.go:1152.3,1153.13 2 0 +auth/ent/mutation.go:1154.28,1156.10 2 0 +auth/ent/mutation.go:1156.10,1158.4 1 0 +auth/ent/mutation.go:1159.3,1160.13 2 0 +auth/ent/mutation.go:1162.2,1162.51 1 0 +auth/ent/mutation.go:1167.48,1169.2 1 0 +auth/ent/mutation.go:1174.67,1176.2 1 0 +auth/ent/mutation.go:1181.70,1182.14 1 0 +auth/ent/mutation.go:1184.2,1184.59 1 0 +auth/ent/mutation.go:1189.50,1191.2 1 0 +auth/ent/mutation.go:1195.56,1198.2 2 0 +auth/ent/mutation.go:1202.55,1204.2 1 0 +auth/ent/mutation.go:1208.55,1209.14 1 0 +auth/ent/mutation.go:1210.24,1212.13 2 0 +auth/ent/mutation.go:1213.23,1215.13 2 0 +auth/ent/mutation.go:1216.28,1218.13 2 0 +auth/ent/mutation.go:1219.26,1221.13 2 0 +auth/ent/mutation.go:1222.28,1224.13 2 0 +auth/ent/mutation.go:1225.28,1227.13 2 0 +auth/ent/mutation.go:1229.2,1229.51 1 0 +auth/ent/mutation.go:1233.47,1235.19 2 0 +auth/ent/mutation.go:1235.19,1237.3 1 0 +auth/ent/mutation.go:1238.2,1238.14 1 0 +auth/ent/mutation.go:1243.59,1244.14 1 0 +auth/ent/mutation.go:1245.22,1246.30 1 0 +auth/ent/mutation.go:1246.30,1248.4 1 0 +auth/ent/mutation.go:1250.2,1250.12 1 0 +auth/ent/mutation.go:1254.49,1257.2 2 0 +auth/ent/mutation.go:1261.61,1263.2 1 0 +auth/ent/mutation.go:1266.49,1268.19 2 0 +auth/ent/mutation.go:1268.19,1270.3 1 0 +auth/ent/mutation.go:1271.2,1271.14 1 0 +auth/ent/mutation.go:1276.55,1277.14 1 0 +auth/ent/mutation.go:1278.22,1279.23 1 0 +auth/ent/mutation.go:1281.2,1281.14 1 0 +auth/ent/mutation.go:1286.54,1287.14 1 0 +auth/ent/mutation.go:1288.22,1290.13 2 0 +auth/ent/mutation.go:1292.2,1292.57 1 0 +auth/ent/mutation.go:1297.54,1298.14 1 0 +auth/ent/mutation.go:1299.22,1301.13 2 0 +auth/ent/mutation.go:1303.2,1303.50 1 0 +auth/ent/mutation.go:1335.73,1342.27 2 0 +auth/ent/mutation.go:1342.27,1344.3 1 0 +auth/ent/mutation.go:1345.2,1345.10 1 0 +auth/ent/mutation.go:1349.39,1350.31 1 0 +auth/ent/mutation.go:1350.31,1356.57 2 0 +auth/ent/mutation.go:1356.57,1357.19 1 0 +auth/ent/mutation.go:1357.19,1358.15 1 0 +auth/ent/mutation.go:1358.15,1360.6 1 0 +auth/ent/mutation.go:1360.11,1362.6 1 0 +auth/ent/mutation.go:1364.4,1364.21 1 0 +auth/ent/mutation.go:1366.3,1366.13 1 0 +auth/ent/mutation.go:1371.38,1372.31 1 0 +auth/ent/mutation.go:1372.31,1373.53 1 0 +auth/ent/mutation.go:1373.53,1375.4 1 0 +auth/ent/mutation.go:1376.3,1376.18 1 0 +auth/ent/mutation.go:1382.40,1386.2 3 0 +auth/ent/mutation.go:1390.41,1391.40 1 0 +auth/ent/mutation.go:1391.40,1393.3 1 0 +auth/ent/mutation.go:1394.2,1396.16 3 0 +auth/ent/mutation.go:1401.41,1403.2 1 0 +auth/ent/mutation.go:1407.54,1408.17 1 0 +auth/ent/mutation.go:1408.17,1410.3 1 0 +auth/ent/mutation.go:1411.2,1411.20 1 0 +auth/ent/mutation.go:1418.67,1419.9 1 0 +auth/ent/mutation.go:1420.42,1422.13 2 0 +auth/ent/mutation.go:1422.13,1424.4 1 0 +auth/ent/mutation.go:1425.3,1425.14 1 0 +auth/ent/mutation.go:1426.36,1427.65 1 0 +auth/ent/mutation.go:1428.10,1429.70 1 0 +auth/ent/mutation.go:1434.46,1436.2 1 0 +auth/ent/mutation.go:1439.59,1441.14 2 0 +auth/ent/mutation.go:1441.14,1443.3 1 0 +auth/ent/mutation.go:1444.2,1444.17 1 0 +auth/ent/mutation.go:1450.79,1451.27 1 0 +auth/ent/mutation.go:1451.27,1453.3 1 0 +auth/ent/mutation.go:1454.2,1454.38 1 0 +auth/ent/mutation.go:1454.38,1456.3 1 0 +auth/ent/mutation.go:1457.2,1458.16 2 0 +auth/ent/mutation.go:1458.16,1460.3 1 0 +auth/ent/mutation.go:1461.2,1461.31 1 0 +auth/ent/mutation.go:1465.40,1467.2 1 0 +auth/ent/mutation.go:1470.43,1472.2 1 0 +auth/ent/mutation.go:1475.56,1477.14 2 0 +auth/ent/mutation.go:1477.14,1479.3 1 0 +auth/ent/mutation.go:1480.2,1480.17 1 0 +auth/ent/mutation.go:1486.76,1487.27 1 0 +auth/ent/mutation.go:1487.27,1489.3 1 0 +auth/ent/mutation.go:1490.2,1490.38 1 0 +auth/ent/mutation.go:1490.38,1492.3 1 0 +auth/ent/mutation.go:1493.2,1494.16 2 0 +auth/ent/mutation.go:1494.16,1496.3 1 0 +auth/ent/mutation.go:1497.2,1497.28 1 0 +auth/ent/mutation.go:1501.37,1503.2 1 0 +auth/ent/mutation.go:1506.46,1508.2 1 0 +auth/ent/mutation.go:1511.59,1513.14 2 0 +auth/ent/mutation.go:1513.14,1515.3 1 0 +auth/ent/mutation.go:1516.2,1516.17 1 0 +auth/ent/mutation.go:1522.79,1523.27 1 0 +auth/ent/mutation.go:1523.27,1525.3 1 0 +auth/ent/mutation.go:1526.2,1526.38 1 0 +auth/ent/mutation.go:1526.38,1528.3 1 0 +auth/ent/mutation.go:1529.2,1530.16 2 0 +auth/ent/mutation.go:1530.16,1532.3 1 0 +auth/ent/mutation.go:1533.2,1533.31 1 0 +auth/ent/mutation.go:1537.40,1539.2 1 0 +auth/ent/mutation.go:1542.50,1544.2 1 0 +auth/ent/mutation.go:1547.63,1549.14 2 0 +auth/ent/mutation.go:1549.14,1551.3 1 0 +auth/ent/mutation.go:1552.2,1552.17 1 0 +auth/ent/mutation.go:1558.83,1559.27 1 0 +auth/ent/mutation.go:1559.27,1561.3 1 0 +auth/ent/mutation.go:1562.2,1562.38 1 0 +auth/ent/mutation.go:1562.38,1564.3 1 0 +auth/ent/mutation.go:1565.2,1566.16 2 0 +auth/ent/mutation.go:1566.16,1568.3 1 0 +auth/ent/mutation.go:1569.2,1569.32 1 0 +auth/ent/mutation.go:1573.41,1575.2 1 0 +auth/ent/mutation.go:1578.50,1580.2 1 0 +auth/ent/mutation.go:1583.63,1585.14 2 0 +auth/ent/mutation.go:1585.14,1587.3 1 0 +auth/ent/mutation.go:1588.2,1588.17 1 0 +auth/ent/mutation.go:1594.83,1595.27 1 0 +auth/ent/mutation.go:1595.27,1597.3 1 0 +auth/ent/mutation.go:1598.2,1598.38 1 0 +auth/ent/mutation.go:1598.38,1600.3 1 0 +auth/ent/mutation.go:1601.2,1602.16 2 0 +auth/ent/mutation.go:1602.16,1604.3 1 0 +auth/ent/mutation.go:1605.2,1605.32 1 0 +auth/ent/mutation.go:1609.41,1611.2 1 0 +auth/ent/mutation.go:1614.50,1615.20 1 0 +auth/ent/mutation.go:1615.20,1617.3 1 0 +auth/ent/mutation.go:1618.2,1618.21 1 0 +auth/ent/mutation.go:1618.21,1620.3 1 0 +auth/ent/mutation.go:1624.37,1626.2 1 0 +auth/ent/mutation.go:1629.44,1631.2 1 0 +auth/ent/mutation.go:1634.53,1635.27 1 0 +auth/ent/mutation.go:1635.27,1637.3 1 0 +auth/ent/mutation.go:1638.2,1638.21 1 0 +auth/ent/mutation.go:1638.21,1641.3 2 0 +auth/ent/mutation.go:1645.57,1646.33 1 0 +auth/ent/mutation.go:1646.33,1648.3 1 0 +auth/ent/mutation.go:1649.2,1649.8 1 0 +auth/ent/mutation.go:1653.50,1654.26 1 0 +auth/ent/mutation.go:1654.26,1656.3 1 0 +auth/ent/mutation.go:1657.2,1657.8 1 0 +auth/ent/mutation.go:1661.37,1665.2 3 0 +auth/ent/mutation.go:1668.51,1669.21 1 0 +auth/ent/mutation.go:1669.21,1671.3 1 0 +auth/ent/mutation.go:1672.2,1672.21 1 0 +auth/ent/mutation.go:1672.21,1674.3 1 0 +auth/ent/mutation.go:1678.38,1680.2 1 0 +auth/ent/mutation.go:1683.45,1685.2 1 0 +auth/ent/mutation.go:1688.54,1689.28 1 0 +auth/ent/mutation.go:1689.28,1691.3 1 0 +auth/ent/mutation.go:1692.2,1692.21 1 0 +auth/ent/mutation.go:1692.21,1695.3 2 0 +auth/ent/mutation.go:1699.58,1700.34 1 0 +auth/ent/mutation.go:1700.34,1702.3 1 0 +auth/ent/mutation.go:1703.2,1703.8 1 0 +auth/ent/mutation.go:1707.51,1708.27 1 0 +auth/ent/mutation.go:1708.27,1710.3 1 0 +auth/ent/mutation.go:1711.2,1711.8 1 0 +auth/ent/mutation.go:1715.38,1719.2 3 0 +auth/ent/mutation.go:1722.52,1724.2 1 0 +auth/ent/mutation.go:1728.58,1730.20 2 0 +auth/ent/mutation.go:1730.20,1732.3 1 0 +auth/ent/mutation.go:1733.2,1733.15 1 0 +auth/ent/mutation.go:1737.32,1739.2 1 0 +auth/ent/mutation.go:1742.37,1744.2 1 0 +auth/ent/mutation.go:1747.38,1749.2 1 0 +auth/ent/mutation.go:1754.42,1756.23 2 0 +auth/ent/mutation.go:1756.23,1758.3 1 0 +auth/ent/mutation.go:1759.2,1759.20 1 0 +auth/ent/mutation.go:1759.20,1761.3 1 0 +auth/ent/mutation.go:1762.2,1762.23 1 0 +auth/ent/mutation.go:1762.23,1764.3 1 0 +auth/ent/mutation.go:1765.2,1765.25 1 0 +auth/ent/mutation.go:1765.25,1767.3 1 0 +auth/ent/mutation.go:1768.2,1768.25 1 0 +auth/ent/mutation.go:1768.25,1770.3 1 0 +auth/ent/mutation.go:1771.2,1771.15 1 0 +auth/ent/mutation.go:1777.61,1778.14 1 0 +auth/ent/mutation.go:1779.26,1780.22 1 0 +auth/ent/mutation.go:1781.23,1782.19 1 0 +auth/ent/mutation.go:1783.26,1784.22 1 0 +auth/ent/mutation.go:1785.27,1786.23 1 0 +auth/ent/mutation.go:1787.27,1788.23 1 0 +auth/ent/mutation.go:1790.2,1790.19 1 0 +auth/ent/mutation.go:1796.86,1797.14 1 0 +auth/ent/mutation.go:1798.26,1799.28 1 0 +auth/ent/mutation.go:1800.23,1801.25 1 0 +auth/ent/mutation.go:1802.26,1803.28 1 0 +auth/ent/mutation.go:1804.27,1805.29 1 0 +auth/ent/mutation.go:1806.27,1807.29 1 0 +auth/ent/mutation.go:1809.2,1809.55 1 0 +auth/ent/mutation.go:1815.69,1816.14 1 0 +auth/ent/mutation.go:1817.26,1819.10 2 0 +auth/ent/mutation.go:1819.10,1821.4 1 0 +auth/ent/mutation.go:1822.3,1823.13 2 0 +auth/ent/mutation.go:1824.23,1826.10 2 0 +auth/ent/mutation.go:1826.10,1828.4 1 0 +auth/ent/mutation.go:1829.3,1830.13 2 0 +auth/ent/mutation.go:1831.26,1833.10 2 0 +auth/ent/mutation.go:1833.10,1835.4 1 0 +auth/ent/mutation.go:1836.3,1837.13 2 0 +auth/ent/mutation.go:1838.27,1840.10 2 0 +auth/ent/mutation.go:1840.10,1842.4 1 0 +auth/ent/mutation.go:1843.3,1844.13 2 0 +auth/ent/mutation.go:1845.27,1847.10 2 0 +auth/ent/mutation.go:1847.10,1849.4 1 0 +auth/ent/mutation.go:1850.3,1851.13 2 0 +auth/ent/mutation.go:1853.2,1853.50 1 0 +auth/ent/mutation.go:1858.47,1860.2 1 0 +auth/ent/mutation.go:1865.66,1867.2 1 0 +auth/ent/mutation.go:1872.69,1873.14 1 0 +auth/ent/mutation.go:1875.2,1875.58 1 0 +auth/ent/mutation.go:1880.49,1882.2 1 0 +auth/ent/mutation.go:1886.55,1889.2 2 0 +auth/ent/mutation.go:1893.54,1895.2 1 0 +auth/ent/mutation.go:1899.54,1900.14 1 0 +auth/ent/mutation.go:1901.26,1903.13 2 0 +auth/ent/mutation.go:1904.23,1906.13 2 0 +auth/ent/mutation.go:1907.26,1909.13 2 0 +auth/ent/mutation.go:1910.27,1912.13 2 0 +auth/ent/mutation.go:1913.27,1915.13 2 0 +auth/ent/mutation.go:1917.2,1917.50 1 0 +auth/ent/mutation.go:1921.46,1923.20 2 0 +auth/ent/mutation.go:1923.20,1925.3 1 0 +auth/ent/mutation.go:1926.2,1926.21 1 0 +auth/ent/mutation.go:1926.21,1928.3 1 0 +auth/ent/mutation.go:1929.2,1929.14 1 0 +auth/ent/mutation.go:1934.58,1935.14 1 0 +auth/ent/mutation.go:1936.22,1938.27 2 0 +auth/ent/mutation.go:1938.27,1940.4 1 0 +auth/ent/mutation.go:1941.3,1941.13 1 0 +auth/ent/mutation.go:1942.23,1944.28 2 0 +auth/ent/mutation.go:1944.28,1946.4 1 0 +auth/ent/mutation.go:1947.3,1947.13 1 0 +auth/ent/mutation.go:1949.2,1949.12 1 0 +auth/ent/mutation.go:1953.48,1955.27 2 0 +auth/ent/mutation.go:1955.27,1957.3 1 0 +auth/ent/mutation.go:1958.2,1958.28 1 0 +auth/ent/mutation.go:1958.28,1960.3 1 0 +auth/ent/mutation.go:1961.2,1961.14 1 0 +auth/ent/mutation.go:1966.60,1967.14 1 0 +auth/ent/mutation.go:1968.22,1970.34 2 0 +auth/ent/mutation.go:1970.34,1972.4 1 0 +auth/ent/mutation.go:1973.3,1973.13 1 0 +auth/ent/mutation.go:1974.23,1976.35 2 0 +auth/ent/mutation.go:1976.35,1978.4 1 0 +auth/ent/mutation.go:1979.3,1979.13 1 0 +auth/ent/mutation.go:1981.2,1981.12 1 0 +auth/ent/mutation.go:1985.48,1987.20 2 0 +auth/ent/mutation.go:1987.20,1989.3 1 0 +auth/ent/mutation.go:1990.2,1990.21 1 0 +auth/ent/mutation.go:1990.21,1992.3 1 0 +auth/ent/mutation.go:1993.2,1993.14 1 0 +auth/ent/mutation.go:1998.54,1999.14 1 0 +auth/ent/mutation.go:2000.22,2001.24 1 0 +auth/ent/mutation.go:2002.23,2003.25 1 0 +auth/ent/mutation.go:2005.2,2005.14 1 0 +auth/ent/mutation.go:2010.53,2011.14 1 0 +auth/ent/mutation.go:2013.2,2013.56 1 0 +auth/ent/mutation.go:2018.53,2019.14 1 0 +auth/ent/mutation.go:2020.22,2022.13 2 0 +auth/ent/mutation.go:2023.23,2025.13 2 0 +auth/ent/mutation.go:2027.2,2027.49 1 0 +auth/ent/role.go:46.50,47.22 1 0 +auth/ent/role.go:47.22,49.3 1 0 +auth/ent/role.go:50.2,50.44 1 0 +auth/ent/role.go:54.58,56.25 2 0 +auth/ent/role.go:56.25,57.21 1 0 +auth/ent/role.go:58.30,59.27 1 0 +auth/ent/role.go:60.37,61.35 1 0 +auth/ent/role.go:62.49,63.33 1 0 +auth/ent/role.go:64.11,65.36 1 0 +auth/ent/role.go:68.2,68.20 1 0 +auth/ent/role.go:73.67,74.46 1 0 +auth/ent/role.go:74.46,76.3 1 0 +auth/ent/role.go:77.2,77.25 1 0 +auth/ent/role.go:77.25,78.21 1 0 +auth/ent/role.go:79.21,80.53 1 0 +auth/ent/role.go:80.53,82.5 1 0 +auth/ent/role.go:82.10,82.26 1 0 +auth/ent/role.go:82.26,84.5 1 0 +auth/ent/role.go:85.23,86.53 1 0 +auth/ent/role.go:86.53,88.5 1 0 +auth/ent/role.go:88.10,88.26 1 0 +auth/ent/role.go:88.26,90.5 1 0 +auth/ent/role.go:91.30,92.45 1 0 +auth/ent/role.go:92.45,94.5 1 0 +auth/ent/role.go:94.10,94.46 1 0 +auth/ent/role.go:94.46,95.66 1 0 +auth/ent/role.go:95.66,97.6 1 0 +auth/ent/role.go:99.28,100.51 1 0 +auth/ent/role.go:100.51,102.5 1 0 +auth/ent/role.go:102.10,102.26 1 0 +auth/ent/role.go:102.26,104.5 1 0 +auth/ent/role.go:105.28,106.51 1 0 +auth/ent/role.go:106.51,108.5 1 0 +auth/ent/role.go:108.10,108.26 1 0 +auth/ent/role.go:108.26,110.5 1 0 +auth/ent/role.go:111.11,112.45 1 0 +auth/ent/role.go:115.2,115.12 1 0 +auth/ent/role.go:120.54,122.2 1 0 +auth/ent/role.go:125.40,127.2 1 0 +auth/ent/role.go:132.40,134.2 1 0 +auth/ent/role.go:138.31,140.9 2 0 +auth/ent/role.go:140.9,141.51 1 0 +auth/ent/role.go:143.2,144.10 2 0 +auth/ent/role.go:148.32,165.2 16 0 +auth/ent/role_create.go:25.53,28.2 2 0 +auth/ent/role_create.go:31.62,34.2 2 0 +auth/ent/role_create.go:37.61,40.2 2 0 +auth/ent/role_create.go:43.70,44.14 1 0 +auth/ent/role_create.go:44.14,46.3 1 0 +auth/ent/role_create.go:47.2,47.11 1 0 +auth/ent/role_create.go:51.61,54.2 2 0 +auth/ent/role_create.go:57.70,58.14 1 0 +auth/ent/role_create.go:58.14,60.3 1 0 +auth/ent/role_create.go:61.2,61.11 1 0 +auth/ent/role_create.go:65.51,68.2 2 0 +auth/ent/role_create.go:71.60,72.14 1 0 +auth/ent/role_create.go:72.14,74.3 1 0 +auth/ent/role_create.go:75.2,75.11 1 0 +auth/ent/role_create.go:79.61,82.2 2 0 +auth/ent/role_create.go:85.56,87.19 2 0 +auth/ent/role_create.go:87.19,89.3 1 0 +auth/ent/role_create.go:90.2,90.30 1 0 +auth/ent/role_create.go:94.48,96.2 1 0 +auth/ent/role_create.go:99.64,102.2 2 0 +auth/ent/role_create.go:105.56,107.16 2 0 +auth/ent/role_create.go:107.16,108.13 1 0 +auth/ent/role_create.go:110.2,110.10 1 0 +auth/ent/role_create.go:114.55,117.2 2 0 +auth/ent/role_create.go:120.50,121.37 1 0 +auth/ent/role_create.go:121.37,122.13 1 0 +auth/ent/role_create.go:127.34,128.43 1 0 +auth/ent/role_create.go:128.43,131.3 2 0 +auth/ent/role_create.go:132.2,132.43 1 0 +auth/ent/role_create.go:132.43,135.3 2 0 +auth/ent/role_create.go:136.2,136.36 1 0 +auth/ent/role_create.go:136.36,139.3 2 0 +auth/ent/role_create.go:143.37,144.38 1 0 +auth/ent/role_create.go:144.38,146.3 1 0 +auth/ent/role_create.go:147.2,147.45 1 0 +auth/ent/role_create.go:147.45,149.3 1 0 +auth/ent/role_create.go:150.2,150.43 1 0 +auth/ent/role_create.go:150.43,152.3 1 0 +auth/ent/role_create.go:153.2,153.43 1 0 +auth/ent/role_create.go:153.43,155.3 1 0 +auth/ent/role_create.go:156.2,156.12 1 0 +auth/ent/role_create.go:159.67,160.35 1 0 +auth/ent/role_create.go:160.35,162.3 1 0 +auth/ent/role_create.go:163.2,164.67 2 0 +auth/ent/role_create.go:164.67,165.38 1 0 +auth/ent/role_create.go:165.38,167.4 1 0 +auth/ent/role_create.go:168.3,168.18 1 0 +auth/ent/role_create.go:170.2,170.27 1 0 +auth/ent/role_create.go:170.27,171.44 1 0 +auth/ent/role_create.go:171.44,173.4 1 0 +auth/ent/role_create.go:173.9,175.4 1 0 +auth/ent/role_create.go:177.2,179.19 3 0 +auth/ent/role_create.go:182.66,187.36 2 0 +auth/ent/role_create.go:187.36,190.3 2 0 +auth/ent/role_create.go:191.2,191.41 1 0 +auth/ent/role_create.go:191.41,194.3 2 0 +auth/ent/role_create.go:195.2,195.48 1 0 +auth/ent/role_create.go:195.48,198.3 2 0 +auth/ent/role_create.go:199.2,199.46 1 0 +auth/ent/role_create.go:199.46,202.3 2 0 +auth/ent/role_create.go:203.2,203.46 1 0 +auth/ent/role_create.go:203.46,206.3 2 0 +auth/ent/role_create.go:207.2,207.53 1 0 +auth/ent/role_create.go:207.53,218.27 2 0 +auth/ent/role_create.go:218.27,220.4 1 0 +auth/ent/role_create.go:221.3,221.42 1 0 +auth/ent/role_create.go:223.2,223.21 1 0 +auth/ent/role_create.go:234.71,235.20 1 0 +auth/ent/role_create.go:235.20,237.3 1 0 +auth/ent/role_create.go:238.2,241.30 4 0 +auth/ent/role_create.go:241.30,242.37 1 0 +auth/ent/role_create.go:242.37,245.86 3 0 +auth/ent/role_create.go:245.86,247.12 2 0 +auth/ent/role_create.go:247.12,249.6 1 0 +auth/ent/role_create.go:250.5,250.43 1 0 +auth/ent/role_create.go:250.43,252.6 1 0 +auth/ent/role_create.go:253.5,256.28 4 0 +auth/ent/role_create.go:256.28,258.6 1 0 +auth/ent/role_create.go:258.11,261.71 2 0 +auth/ent/role_create.go:261.71,262.42 1 0 +auth/ent/role_create.go:262.42,264.8 1 0 +auth/ent/role_create.go:267.5,267.19 1 0 +auth/ent/role_create.go:267.19,269.6 1 0 +auth/ent/role_create.go:270.5,272.25 3 0 +auth/ent/role_create.go:274.4,274.49 1 0 +auth/ent/role_create.go:274.49,276.5 1 0 +auth/ent/role_create.go:277.4,277.21 1 0 +auth/ent/role_create.go:280.2,280.23 1 0 +auth/ent/role_create.go:280.23,281.78 1 0 +auth/ent/role_create.go:281.78,283.4 1 0 +auth/ent/role_create.go:285.2,285.19 1 0 +auth/ent/role_create.go:289.63,291.16 2 0 +auth/ent/role_create.go:291.16,292.13 1 0 +auth/ent/role_create.go:294.2,294.10 1 0 +auth/ent/role_create.go:298.60,301.2 2 0 +auth/ent/role_create.go:304.55,305.38 1 0 +auth/ent/role_create.go:305.38,306.13 1 0 +auth/ent/role_delete.go:23.63,26.2 2 0 +auth/ent/role_delete.go:29.62,31.2 1 0 +auth/ent/role_delete.go:34.54,36.16 2 0 +auth/ent/role_delete.go:36.16,37.13 1 0 +auth/ent/role_delete.go:39.2,39.10 1 0 +auth/ent/role_delete.go:42.65,44.47 2 0 +auth/ent/role_delete.go:44.47,45.50 1 0 +auth/ent/role_delete.go:45.50,46.22 1 0 +auth/ent/role_delete.go:46.22,48.5 1 0 +auth/ent/role_delete.go:51.2,52.51 2 0 +auth/ent/role_delete.go:52.51,54.3 1 0 +auth/ent/role_delete.go:55.2,56.22 2 0 +auth/ent/role_delete.go:65.70,68.2 2 0 +auth/ent/role_delete.go:71.59,73.9 2 0 +auth/ent/role_delete.go:74.18,75.13 1 0 +auth/ent/role_delete.go:76.14,77.36 1 0 +auth/ent/role_delete.go:78.10,79.13 1 0 +auth/ent/role_delete.go:84.54,85.38 1 0 +auth/ent/role_delete.go:85.38,86.13 1 0 +auth/ent/role_query.go:33.61,36.2 2 0 +auth/ent/role_query.go:39.50,42.2 2 0 +auth/ent/role_query.go:45.52,48.2 2 0 +auth/ent/role_query.go:52.53,55.2 2 0 +auth/ent/role_query.go:58.62,61.2 2 0 +auth/ent/role_query.go:64.46,66.74 2 0 +auth/ent/role_query.go:66.74,67.46 1 0 +auth/ent/role_query.go:67.46,69.4 1 0 +auth/ent/role_query.go:70.3,71.40 2 0 +auth/ent/role_query.go:71.40,73.4 1 0 +auth/ent/role_query.go:74.3,80.20 3 0 +auth/ent/role_query.go:82.2,82.14 1 0 +auth/ent/role_query.go:87.64,89.16 2 0 +auth/ent/role_query.go:89.16,91.3 1 0 +auth/ent/role_query.go:92.2,92.21 1 0 +auth/ent/role_query.go:92.21,94.3 1 0 +auth/ent/role_query.go:95.2,95.22 1 0 +auth/ent/role_query.go:99.56,101.36 2 0 +auth/ent/role_query.go:101.36,102.13 1 0 +auth/ent/role_query.go:104.2,104.13 1 0 +auth/ent/role_query.go:109.74,111.82 2 0 +auth/ent/role_query.go:111.82,113.3 1 0 +auth/ent/role_query.go:114.2,114.19 1 0 +auth/ent/role_query.go:114.19,117.3 2 0 +auth/ent/role_query.go:118.2,118.20 1 0 +auth/ent/role_query.go:122.59,124.36 2 0 +auth/ent/role_query.go:124.36,125.13 1 0 +auth/ent/role_query.go:127.2,127.11 1 0 +auth/ent/role_query.go:133.63,135.16 2 0 +auth/ent/role_query.go:135.16,137.3 1 0 +auth/ent/role_query.go:138.2,138.20 1 0 +auth/ent/role_query.go:139.9,140.23 1 0 +auth/ent/role_query.go:141.9,142.41 1 0 +auth/ent/role_query.go:143.10,144.44 1 0 +auth/ent/role_query.go:149.55,151.16 2 0 +auth/ent/role_query.go:151.16,152.13 1 0 +auth/ent/role_query.go:154.2,154.13 1 0 +auth/ent/role_query.go:160.73,162.81 2 0 +auth/ent/role_query.go:162.81,164.3 1 0 +auth/ent/role_query.go:165.2,165.18 1 0 +auth/ent/role_query.go:166.9,167.14 1 0 +auth/ent/role_query.go:168.9,169.35 1 0 +auth/ent/role_query.go:170.10,171.38 1 0 +auth/ent/role_query.go:173.2,173.8 1 0 +auth/ent/role_query.go:177.58,179.16 2 0 +auth/ent/role_query.go:179.16,180.13 1 0 +auth/ent/role_query.go:182.2,182.11 1 0 +auth/ent/role_query.go:186.64,188.45 2 0 +auth/ent/role_query.go:188.45,190.3 1 0 +auth/ent/role_query.go:191.2,192.58 2 0 +auth/ent/role_query.go:196.56,198.16 2 0 +auth/ent/role_query.go:198.16,199.13 1 0 +auth/ent/role_query.go:201.2,201.14 1 0 +auth/ent/role_query.go:205.73,206.44 1 0 +auth/ent/role_query.go:206.44,208.3 1 0 +auth/ent/role_query.go:209.2,210.63 2 0 +auth/ent/role_query.go:210.63,212.3 1 0 +auth/ent/role_query.go:213.2,213.17 1 0 +auth/ent/role_query.go:217.57,219.16 2 0 +auth/ent/role_query.go:219.16,220.13 1 0 +auth/ent/role_query.go:222.2,222.12 1 0 +auth/ent/role_query.go:226.62,228.45 2 0 +auth/ent/role_query.go:228.45,230.3 1 0 +auth/ent/role_query.go:231.2,231.78 1 0 +auth/ent/role_query.go:235.54,237.16 2 0 +auth/ent/role_query.go:237.16,238.13 1 0 +auth/ent/role_query.go:240.2,240.14 1 0 +auth/ent/role_query.go:244.63,246.36 2 0 +auth/ent/role_query.go:247.23,248.20 1 0 +auth/ent/role_query.go:249.18,250.60 1 0 +auth/ent/role_query.go:251.10,252.19 1 0 +auth/ent/role_query.go:257.55,259.16 2 0 +auth/ent/role_query.go:259.16,260.13 1 0 +auth/ent/role_query.go:262.2,262.14 1 0 +auth/ent/role_query.go:267.41,268.15 1 0 +auth/ent/role_query.go:268.15,270.3 1 0 +auth/ent/role_query.go:271.2,281.3 1 0 +auth/ent/role_query.go:286.69,288.27 2 0 +auth/ent/role_query.go:288.27,290.3 1 0 +auth/ent/role_query.go:291.2,292.11 2 0 +auth/ent/role_query.go:309.75,316.2 6 0 +auth/ent/role_query.go:330.59,336.2 5 0 +auth/ent/role_query.go:339.66,341.2 1 0 +auth/ent/role_query.go:343.62,344.34 1 0 +auth/ent/role_query.go:344.34,345.19 1 0 +auth/ent/role_query.go:345.19,347.4 1 0 +auth/ent/role_query.go:348.3,348.39 1 0 +auth/ent/role_query.go:348.39,349.48 1 0 +auth/ent/role_query.go:349.48,351.5 1 0 +auth/ent/role_query.go:354.2,354.34 1 0 +auth/ent/role_query.go:354.34,355.27 1 0 +auth/ent/role_query.go:355.27,357.4 1 0 +auth/ent/role_query.go:359.2,359.20 1 0 +auth/ent/role_query.go:359.20,361.17 2 0 +auth/ent/role_query.go:361.17,363.4 1 0 +auth/ent/role_query.go:364.3,364.16 1 0 +auth/ent/role_query.go:366.2,366.12 1 0 +auth/ent/role_query.go:369.87,377.59 2 0 +auth/ent/role_query.go:377.59,379.3 1 0 +auth/ent/role_query.go:380.2,380.60 1 0 +auth/ent/role_query.go:380.60,385.3 4 0 +auth/ent/role_query.go:386.2,386.23 1 0 +auth/ent/role_query.go:386.23,388.3 1 0 +auth/ent/role_query.go:389.2,389.67 1 0 +auth/ent/role_query.go:389.67,391.3 1 0 +auth/ent/role_query.go:392.2,392.21 1 0 +auth/ent/role_query.go:392.21,394.3 1 0 +auth/ent/role_query.go:395.2,395.41 1 0 +auth/ent/role_query.go:395.41,397.18 1 0 +auth/ent/role_query.go:397.18,397.47 1 0 +auth/ent/role_query.go:398.27,398.71 1 0 +auth/ent/role_query.go:398.85,400.4 1 0 +auth/ent/role_query.go:402.2,402.19 1 0 +auth/ent/role_query.go:405.137,409.29 4 0 +auth/ent/role_query.go:409.29,412.18 3 0 +auth/ent/role_query.go:412.18,414.4 1 0 +auth/ent/role_query.go:416.2,416.36 1 0 +auth/ent/role_query.go:416.36,424.3 7 0 +auth/ent/role_query.go:425.2,425.48 1 0 +auth/ent/role_query.go:425.48,427.3 1 0 +auth/ent/role_query.go:428.2,428.70 1 0 +auth/ent/role_query.go:428.70,429.78 1 0 +auth/ent/role_query.go:429.78,432.60 3 0 +auth/ent/role_query.go:432.60,434.19 2 0 +auth/ent/role_query.go:434.19,436.6 1 0 +auth/ent/role_query.go:437.5,437.62 1 0 +auth/ent/role_query.go:439.4,439.61 1 0 +auth/ent/role_query.go:439.61,442.29 3 0 +auth/ent/role_query.go:442.29,445.6 2 0 +auth/ent/role_query.go:446.5,447.15 2 0 +auth/ent/role_query.go:451.2,452.16 2 0 +auth/ent/role_query.go:452.16,454.3 1 0 +auth/ent/role_query.go:455.2,455.30 1 0 +auth/ent/role_query.go:455.30,457.10 2 0 +auth/ent/role_query.go:457.10,459.4 1 0 +auth/ent/role_query.go:460.3,460.25 1 0 +auth/ent/role_query.go:460.25,462.4 1 0 +auth/ent/role_query.go:464.2,464.12 1 0 +auth/ent/role_query.go:467.65,470.28 3 0 +auth/ent/role_query.go:470.28,472.3 1 0 +auth/ent/role_query.go:473.2,473.51 1 0 +auth/ent/role_query.go:476.54,479.44 3 0 +auth/ent/role_query.go:479.44,481.3 1 0 +auth/ent/role_query.go:481.8,481.27 1 0 +auth/ent/role_query.go:481.27,483.3 1 0 +auth/ent/role_query.go:484.2,484.46 1 0 +auth/ent/role_query.go:484.46,487.25 3 0 +auth/ent/role_query.go:487.25,488.33 1 0 +auth/ent/role_query.go:488.33,490.5 1 0 +auth/ent/role_query.go:493.2,493.38 1 0 +auth/ent/role_query.go:493.38,494.50 1 0 +auth/ent/role_query.go:494.50,495.22 1 0 +auth/ent/role_query.go:495.22,497.5 1 0 +auth/ent/role_query.go:500.2,500.41 1 0 +auth/ent/role_query.go:500.41,502.3 1 0 +auth/ent/role_query.go:503.2,503.44 1 0 +auth/ent/role_query.go:503.44,505.3 1 0 +auth/ent/role_query.go:506.2,506.33 1 0 +auth/ent/role_query.go:506.33,507.46 1 0 +auth/ent/role_query.go:507.46,508.22 1 0 +auth/ent/role_query.go:508.22,510.5 1 0 +auth/ent/role_query.go:513.2,513.14 1 0 +auth/ent/role_query.go:516.66,520.23 4 0 +auth/ent/role_query.go:520.23,522.3 1 0 +auth/ent/role_query.go:523.2,524.19 2 0 +auth/ent/role_query.go:524.19,527.3 2 0 +auth/ent/role_query.go:528.2,528.44 1 0 +auth/ent/role_query.go:528.44,530.3 1 0 +auth/ent/role_query.go:531.2,531.34 1 0 +auth/ent/role_query.go:531.34,533.3 1 0 +auth/ent/role_query.go:534.2,534.29 1 0 +auth/ent/role_query.go:534.29,536.3 1 0 +auth/ent/role_query.go:537.2,537.44 1 0 +auth/ent/role_query.go:537.44,541.3 1 0 +auth/ent/role_query.go:542.2,542.41 1 0 +auth/ent/role_query.go:542.41,544.3 1 0 +auth/ent/role_query.go:545.2,545.17 1 0 +auth/ent/role_query.go:555.70,558.2 2 0 +auth/ent/role_query.go:561.64,563.52 2 0 +auth/ent/role_query.go:563.52,565.3 1 0 +auth/ent/role_query.go:566.2,566.97 1 0 +auth/ent/role_query.go:569.84,572.29 3 0 +auth/ent/role_query.go:572.29,574.3 1 0 +auth/ent/role_query.go:575.2,575.42 1 0 +auth/ent/role_query.go:575.42,577.31 2 0 +auth/ent/role_query.go:577.31,579.4 1 0 +auth/ent/role_query.go:580.3,581.30 2 0 +auth/ent/role_query.go:583.2,584.39 2 0 +auth/ent/role_query.go:584.39,586.3 1 0 +auth/ent/role_query.go:587.2,589.71 3 0 +auth/ent/role_query.go:589.71,591.3 1 0 +auth/ent/role_query.go:592.2,593.31 2 0 +auth/ent/role_query.go:603.67,606.2 2 0 +auth/ent/role_query.go:609.62,611.45 2 0 +auth/ent/role_query.go:611.45,613.3 1 0 +auth/ent/role_query.go:614.2,614.91 1 0 +auth/ent/role_query.go:617.82,620.28 3 0 +auth/ent/role_query.go:620.28,622.3 1 0 +auth/ent/role_query.go:623.2,623.38 1 0 +auth/ent/role_query.go:624.38,625.34 1 0 +auth/ent/role_query.go:626.38,627.40 1 0 +auth/ent/role_query.go:629.2,631.64 3 0 +auth/ent/role_query.go:631.64,633.3 1 0 +auth/ent/role_query.go:634.2,635.31 2 0 +auth/ent/role_update.go:28.63,31.2 2 0 +auth/ent/role_update.go:34.53,37.2 2 0 +auth/ent/role_update.go:40.62,41.14 1 0 +auth/ent/role_update.go:41.14,43.3 1 0 +auth/ent/role_update.go:44.2,44.11 1 0 +auth/ent/role_update.go:48.62,51.2 2 0 +auth/ent/role_update.go:54.65,57.2 2 0 +auth/ent/role_update.go:60.61,63.2 2 0 +auth/ent/role_update.go:66.70,67.14 1 0 +auth/ent/role_update.go:67.14,69.3 1 0 +auth/ent/role_update.go:70.2,70.11 1 0 +auth/ent/role_update.go:74.61,77.2 2 0 +auth/ent/role_update.go:80.61,83.2 2 0 +auth/ent/role_update.go:86.56,88.19 2 0 +auth/ent/role_update.go:88.19,90.3 1 0 +auth/ent/role_update.go:91.2,91.30 1 0 +auth/ent/role_update.go:95.48,97.2 1 0 +auth/ent/role_update.go:100.48,103.2 2 0 +auth/ent/role_update.go:106.64,109.2 2 0 +auth/ent/role_update.go:112.59,114.19 2 0 +auth/ent/role_update.go:114.19,116.3 1 0 +auth/ent/role_update.go:117.2,117.33 1 0 +auth/ent/role_update.go:121.62,124.2 2 0 +auth/ent/role_update.go:127.54,129.16 2 0 +auth/ent/role_update.go:129.16,130.13 1 0 +auth/ent/role_update.go:132.2,132.17 1 0 +auth/ent/role_update.go:136.55,139.2 2 0 +auth/ent/role_update.go:142.50,143.37 1 0 +auth/ent/role_update.go:143.37,144.13 1 0 +auth/ent/role_update.go:149.34,150.43 1 0 +auth/ent/role_update.go:150.43,153.3 2 0 +auth/ent/role_update.go:156.71,158.47 2 0 +auth/ent/role_update.go:158.47,159.50 1 0 +auth/ent/role_update.go:159.50,160.22 1 0 +auth/ent/role_update.go:160.22,162.5 1 0 +auth/ent/role_update.go:165.2,165.41 1 0 +auth/ent/role_update.go:165.41,167.3 1 0 +auth/ent/role_update.go:168.2,168.48 1 0 +auth/ent/role_update.go:168.48,170.3 1 0 +auth/ent/role_update.go:171.2,171.56 1 0 +auth/ent/role_update.go:171.56,172.48 1 0 +auth/ent/role_update.go:172.48,174.4 1 0 +auth/ent/role_update.go:176.2,176.46 1 0 +auth/ent/role_update.go:176.46,178.3 1 0 +auth/ent/role_update.go:179.2,179.46 1 0 +auth/ent/role_update.go:179.46,181.3 1 0 +auth/ent/role_update.go:182.2,182.32 1 0 +auth/ent/role_update.go:182.32,194.3 2 0 +auth/ent/role_update.go:195.2,195.91 1 0 +auth/ent/role_update.go:195.91,206.27 2 0 +auth/ent/role_update.go:206.27,208.4 1 0 +auth/ent/role_update.go:209.3,209.54 1 0 +auth/ent/role_update.go:211.2,211.53 1 0 +auth/ent/role_update.go:211.53,222.27 2 0 +auth/ent/role_update.go:222.27,224.4 1 0 +auth/ent/role_update.go:225.3,225.50 1 0 +auth/ent/role_update.go:227.2,227.70 1 0 +auth/ent/role_update.go:227.70,228.49 1 0 +auth/ent/role_update.go:228.49,230.4 1 0 +auth/ent/role_update.go:230.9,230.45 1 0 +auth/ent/role_update.go:230.45,232.4 1 0 +auth/ent/role_update.go:233.3,233.16 1 0 +auth/ent/role_update.go:235.2,236.15 2 0 +auth/ent/role_update.go:248.60,251.2 2 0 +auth/ent/role_update.go:254.69,255.14 1 0 +auth/ent/role_update.go:255.14,257.3 1 0 +auth/ent/role_update.go:258.2,258.12 1 0 +auth/ent/role_update.go:262.69,265.2 2 0 +auth/ent/role_update.go:268.72,271.2 2 0 +auth/ent/role_update.go:274.68,277.2 2 0 +auth/ent/role_update.go:280.77,281.14 1 0 +auth/ent/role_update.go:281.14,283.3 1 0 +auth/ent/role_update.go:284.2,284.12 1 0 +auth/ent/role_update.go:288.68,291.2 2 0 +auth/ent/role_update.go:294.68,297.2 2 0 +auth/ent/role_update.go:300.63,302.19 2 0 +auth/ent/role_update.go:302.19,304.3 1 0 +auth/ent/role_update.go:305.2,305.31 1 0 +auth/ent/role_update.go:309.52,311.2 1 0 +auth/ent/role_update.go:314.55,317.2 2 0 +auth/ent/role_update.go:320.71,323.2 2 0 +auth/ent/role_update.go:326.66,328.19 2 0 +auth/ent/role_update.go:328.19,330.3 1 0 +auth/ent/role_update.go:331.2,331.34 1 0 +auth/ent/role_update.go:335.70,338.2 2 0 +auth/ent/role_update.go:342.81,345.2 2 0 +auth/ent/role_update.go:348.68,351.2 2 0 +auth/ent/role_update.go:354.60,356.16 2 0 +auth/ent/role_update.go:356.16,357.13 1 0 +auth/ent/role_update.go:359.2,359.13 1 0 +auth/ent/role_update.go:363.59,366.2 2 0 +auth/ent/role_update.go:369.54,370.38 1 0 +auth/ent/role_update.go:370.38,371.13 1 0 +auth/ent/role_update.go:376.38,377.44 1 0 +auth/ent/role_update.go:377.44,380.3 2 0 +auth/ent/role_update.go:383.81,386.9 3 0 +auth/ent/role_update.go:386.9,388.3 1 0 +auth/ent/role_update.go:389.2,390.43 2 0 +auth/ent/role_update.go:390.43,393.28 3 0 +auth/ent/role_update.go:393.28,394.28 1 0 +auth/ent/role_update.go:394.28,396.5 1 0 +auth/ent/role_update.go:397.4,397.25 1 0 +auth/ent/role_update.go:397.25,399.5 1 0 +auth/ent/role_update.go:402.2,402.48 1 0 +auth/ent/role_update.go:402.48,403.50 1 0 +auth/ent/role_update.go:403.50,404.22 1 0 +auth/ent/role_update.go:404.22,406.5 1 0 +auth/ent/role_update.go:409.2,409.42 1 0 +auth/ent/role_update.go:409.42,411.3 1 0 +auth/ent/role_update.go:412.2,412.49 1 0 +auth/ent/role_update.go:412.49,414.3 1 0 +auth/ent/role_update.go:415.2,415.57 1 0 +auth/ent/role_update.go:415.57,416.48 1 0 +auth/ent/role_update.go:416.48,418.4 1 0 +auth/ent/role_update.go:420.2,420.47 1 0 +auth/ent/role_update.go:420.47,422.3 1 0 +auth/ent/role_update.go:423.2,423.47 1 0 +auth/ent/role_update.go:423.47,425.3 1 0 +auth/ent/role_update.go:426.2,426.33 1 0 +auth/ent/role_update.go:426.33,438.3 2 0 +auth/ent/role_update.go:439.2,439.93 1 0 +auth/ent/role_update.go:439.93,450.27 2 0 +auth/ent/role_update.go:450.27,452.4 1 0 +auth/ent/role_update.go:453.3,453.54 1 0 +auth/ent/role_update.go:455.2,455.54 1 0 +auth/ent/role_update.go:455.54,466.27 2 0 +auth/ent/role_update.go:466.27,468.4 1 0 +auth/ent/role_update.go:469.3,469.50 1 0 +auth/ent/role_update.go:471.2,474.67 4 0 +auth/ent/role_update.go:474.67,475.49 1 0 +auth/ent/role_update.go:475.49,477.4 1 0 +auth/ent/role_update.go:477.9,477.45 1 0 +auth/ent/role_update.go:477.45,479.4 1 0 +auth/ent/role_update.go:480.3,480.18 1 0 +auth/ent/role_update.go:482.2,483.19 2 0 +auth/ent/token.go:51.48,52.19 1 0 +auth/ent/token.go:52.19,54.3 1 0 +auth/ent/token.go:54.8,54.29 1 0 +auth/ent/token.go:54.29,56.3 1 0 +auth/ent/token.go:57.2,57.43 1 0 +auth/ent/token.go:61.59,63.25 2 0 +auth/ent/token.go:63.25,64.21 1 0 +auth/ent/token.go:65.27,66.33 1 0 +auth/ent/token.go:67.57,68.35 1 0 +auth/ent/token.go:69.73,70.33 1 0 +auth/ent/token.go:71.29,72.35 1 0 +auth/ent/token.go:73.11,74.36 1 0 +auth/ent/token.go:77.2,77.20 1 0 +auth/ent/token.go:82.68,83.46 1 0 +auth/ent/token.go:83.46,85.3 1 0 +auth/ent/token.go:86.2,86.25 1 0 +auth/ent/token.go:86.25,87.21 1 0 +auth/ent/token.go:88.22,89.53 1 0 +auth/ent/token.go:89.53,91.5 1 0 +auth/ent/token.go:91.10,91.26 1 0 +auth/ent/token.go:91.26,93.5 1 0 +auth/ent/token.go:94.25,95.53 1 0 +auth/ent/token.go:95.53,97.5 1 0 +auth/ent/token.go:97.10,97.26 1 0 +auth/ent/token.go:97.26,99.5 1 0 +auth/ent/token.go:100.24,101.53 1 0 +auth/ent/token.go:101.53,103.5 1 0 +auth/ent/token.go:103.10,103.26 1 0 +auth/ent/token.go:103.26,105.5 1 0 +auth/ent/token.go:106.29,107.51 1 0 +auth/ent/token.go:107.51,109.5 1 0 +auth/ent/token.go:109.10,109.26 1 0 +auth/ent/token.go:109.26,111.5 1 0 +auth/ent/token.go:112.27,113.51 1 0 +auth/ent/token.go:113.51,115.5 1 0 +auth/ent/token.go:115.10,115.26 1 0 +auth/ent/token.go:115.26,117.5 1 0 +auth/ent/token.go:118.29,119.51 1 0 +auth/ent/token.go:119.51,121.5 1 0 +auth/ent/token.go:121.10,121.26 1 0 +auth/ent/token.go:121.26,123.5 1 0 +auth/ent/token.go:124.29,125.51 1 0 +auth/ent/token.go:125.51,127.5 1 0 +auth/ent/token.go:127.10,127.26 1 0 +auth/ent/token.go:127.26,129.5 1 0 +auth/ent/token.go:130.29,131.53 1 0 +auth/ent/token.go:131.53,133.5 1 0 +auth/ent/token.go:133.10,133.26 1 0 +auth/ent/token.go:133.26,136.5 2 0 +auth/ent/token.go:137.11,138.45 1 0 +auth/ent/token.go:141.2,141.12 1 0 +auth/ent/token.go:146.55,148.2 1 0 +auth/ent/token.go:151.40,153.2 1 0 +auth/ent/token.go:158.42,160.2 1 0 +auth/ent/token.go:164.33,166.9 2 0 +auth/ent/token.go:166.9,167.52 1 0 +auth/ent/token.go:169.2,170.10 2 0 +auth/ent/token.go:174.33,197.2 22 0 +auth/ent/token_create.go:25.56,28.2 2 0 +auth/ent/token_create.go:31.59,34.2 2 0 +auth/ent/token_create.go:37.63,40.2 2 0 +auth/ent/token_create.go:43.56,46.2 2 0 +auth/ent/token_create.go:49.65,50.14 1 0 +auth/ent/token_create.go:50.14,52.3 1 0 +auth/ent/token_create.go:53.2,53.11 1 0 +auth/ent/token_create.go:57.63,60.2 2 0 +auth/ent/token_create.go:63.72,64.14 1 0 +auth/ent/token_create.go:64.14,66.3 1 0 +auth/ent/token_create.go:67.2,67.11 1 0 +auth/ent/token_create.go:71.63,74.2 2 0 +auth/ent/token_create.go:77.72,78.14 1 0 +auth/ent/token_create.go:78.14,80.3 1 0 +auth/ent/token_create.go:81.2,81.11 1 0 +auth/ent/token_create.go:85.53,88.2 2 0 +auth/ent/token_create.go:91.62,92.14 1 0 +auth/ent/token_create.go:92.14,94.3 1 0 +auth/ent/token_create.go:95.2,95.11 1 0 +auth/ent/token_create.go:99.58,102.2 2 0 +auth/ent/token_create.go:105.54,107.2 1 0 +auth/ent/token_create.go:110.50,112.2 1 0 +auth/ent/token_create.go:115.66,118.2 2 0 +auth/ent/token_create.go:121.58,123.16 2 0 +auth/ent/token_create.go:123.16,124.13 1 0 +auth/ent/token_create.go:126.2,126.10 1 0 +auth/ent/token_create.go:130.56,133.2 2 0 +auth/ent/token_create.go:136.51,137.37 1 0 +auth/ent/token_create.go:137.37,138.13 1 0 +auth/ent/token_create.go:143.35,144.41 1 0 +auth/ent/token_create.go:144.41,147.3 2 0 +auth/ent/token_create.go:148.2,148.43 1 0 +auth/ent/token_create.go:148.43,151.3 2 0 +auth/ent/token_create.go:152.2,152.43 1 0 +auth/ent/token_create.go:152.43,155.3 2 0 +auth/ent/token_create.go:156.2,156.36 1 0 +auth/ent/token_create.go:156.36,159.3 2 0 +auth/ent/token_create.go:163.38,164.39 1 0 +auth/ent/token_create.go:164.39,166.3 1 0 +auth/ent/token_create.go:167.2,167.41 1 0 +auth/ent/token_create.go:167.41,169.3 1 0 +auth/ent/token_create.go:170.2,170.40 1 0 +auth/ent/token_create.go:170.40,171.48 1 0 +auth/ent/token_create.go:171.48,173.4 1 0 +auth/ent/token_create.go:175.2,175.43 1 0 +auth/ent/token_create.go:175.43,177.3 1 0 +auth/ent/token_create.go:178.2,178.41 1 0 +auth/ent/token_create.go:178.41,180.3 1 0 +auth/ent/token_create.go:181.2,181.43 1 0 +auth/ent/token_create.go:181.43,183.3 1 0 +auth/ent/token_create.go:184.2,184.43 1 0 +auth/ent/token_create.go:184.43,186.3 1 0 +auth/ent/token_create.go:187.2,187.40 1 0 +auth/ent/token_create.go:187.40,189.3 1 0 +auth/ent/token_create.go:190.2,190.12 1 0 +auth/ent/token_create.go:193.69,194.35 1 0 +auth/ent/token_create.go:194.35,196.3 1 0 +auth/ent/token_create.go:197.2,198.67 2 0 +auth/ent/token_create.go:198.67,199.38 1 0 +auth/ent/token_create.go:199.38,201.4 1 0 +auth/ent/token_create.go:202.3,202.18 1 0 +auth/ent/token_create.go:204.2,204.27 1 0 +auth/ent/token_create.go:204.27,205.44 1 0 +auth/ent/token_create.go:205.44,207.4 1 0 +auth/ent/token_create.go:207.9,209.4 1 0 +auth/ent/token_create.go:211.2,213.19 3 0 +auth/ent/token_create.go:216.68,221.36 2 0 +auth/ent/token_create.go:221.36,224.3 2 0 +auth/ent/token_create.go:225.2,225.42 1 0 +auth/ent/token_create.go:225.42,228.3 2 0 +auth/ent/token_create.go:229.2,229.44 1 0 +auth/ent/token_create.go:229.44,232.3 2 0 +auth/ent/token_create.go:233.2,233.46 1 0 +auth/ent/token_create.go:233.46,236.3 2 0 +auth/ent/token_create.go:237.2,237.44 1 0 +auth/ent/token_create.go:237.44,240.3 2 0 +auth/ent/token_create.go:241.2,241.46 1 0 +auth/ent/token_create.go:241.46,244.3 2 0 +auth/ent/token_create.go:245.2,245.46 1 0 +auth/ent/token_create.go:245.46,248.3 2 0 +auth/ent/token_create.go:249.2,249.52 1 0 +auth/ent/token_create.go:249.52,260.27 2 0 +auth/ent/token_create.go:260.27,262.4 1 0 +auth/ent/token_create.go:263.3,264.42 2 0 +auth/ent/token_create.go:266.2,266.21 1 0 +auth/ent/token_create.go:277.73,278.20 1 0 +auth/ent/token_create.go:278.20,280.3 1 0 +auth/ent/token_create.go:281.2,284.30 4 0 +auth/ent/token_create.go:284.30,285.37 1 0 +auth/ent/token_create.go:285.37,288.86 3 0 +auth/ent/token_create.go:288.86,290.12 2 0 +auth/ent/token_create.go:290.12,292.6 1 0 +auth/ent/token_create.go:293.5,293.43 1 0 +auth/ent/token_create.go:293.43,295.6 1 0 +auth/ent/token_create.go:296.5,299.28 4 0 +auth/ent/token_create.go:299.28,301.6 1 0 +auth/ent/token_create.go:301.11,304.71 2 0 +auth/ent/token_create.go:304.71,305.42 1 0 +auth/ent/token_create.go:305.42,307.8 1 0 +auth/ent/token_create.go:310.5,310.19 1 0 +auth/ent/token_create.go:310.19,312.6 1 0 +auth/ent/token_create.go:313.5,315.25 3 0 +auth/ent/token_create.go:317.4,317.49 1 0 +auth/ent/token_create.go:317.49,319.5 1 0 +auth/ent/token_create.go:320.4,320.21 1 0 +auth/ent/token_create.go:323.2,323.23 1 0 +auth/ent/token_create.go:323.23,324.78 1 0 +auth/ent/token_create.go:324.78,326.4 1 0 +auth/ent/token_create.go:328.2,328.19 1 0 +auth/ent/token_create.go:332.65,334.16 2 0 +auth/ent/token_create.go:334.16,335.13 1 0 +auth/ent/token_create.go:337.2,337.10 1 0 +auth/ent/token_create.go:341.61,344.2 2 0 +auth/ent/token_create.go:347.56,348.38 1 0 +auth/ent/token_create.go:348.38,349.13 1 0 +auth/ent/token_delete.go:23.66,26.2 2 0 +auth/ent/token_delete.go:29.63,31.2 1 0 +auth/ent/token_delete.go:34.55,36.16 2 0 +auth/ent/token_delete.go:36.16,37.13 1 0 +auth/ent/token_delete.go:39.2,39.10 1 0 +auth/ent/token_delete.go:42.66,44.47 2 0 +auth/ent/token_delete.go:44.47,45.50 1 0 +auth/ent/token_delete.go:45.50,46.22 1 0 +auth/ent/token_delete.go:46.22,48.5 1 0 +auth/ent/token_delete.go:51.2,52.51 2 0 +auth/ent/token_delete.go:52.51,54.3 1 0 +auth/ent/token_delete.go:55.2,56.22 2 0 +auth/ent/token_delete.go:65.73,68.2 2 0 +auth/ent/token_delete.go:71.60,73.9 2 0 +auth/ent/token_delete.go:74.18,75.13 1 0 +auth/ent/token_delete.go:76.14,77.37 1 0 +auth/ent/token_delete.go:78.10,79.13 1 0 +auth/ent/token_delete.go:84.55,85.38 1 0 +auth/ent/token_delete.go:85.38,86.13 1 0 +auth/ent/token_query.go:33.64,36.2 2 0 +auth/ent/token_query.go:39.52,42.2 2 0 +auth/ent/token_query.go:45.54,48.2 2 0 +auth/ent/token_query.go:52.55,55.2 2 0 +auth/ent/token_query.go:58.65,61.2 2 0 +auth/ent/token_query.go:64.46,66.74 2 0 +auth/ent/token_query.go:66.74,67.46 1 0 +auth/ent/token_query.go:67.46,69.4 1 0 +auth/ent/token_query.go:70.3,71.40 2 0 +auth/ent/token_query.go:71.40,73.4 1 0 +auth/ent/token_query.go:74.3,80.20 3 0 +auth/ent/token_query.go:82.2,82.14 1 0 +auth/ent/token_query.go:87.66,89.16 2 0 +auth/ent/token_query.go:89.16,91.3 1 0 +auth/ent/token_query.go:92.2,92.21 1 0 +auth/ent/token_query.go:92.21,94.3 1 0 +auth/ent/token_query.go:95.2,95.22 1 0 +auth/ent/token_query.go:99.58,101.36 2 0 +auth/ent/token_query.go:101.36,102.13 1 0 +auth/ent/token_query.go:104.2,104.13 1 0 +auth/ent/token_query.go:109.75,111.82 2 0 +auth/ent/token_query.go:111.82,113.3 1 0 +auth/ent/token_query.go:114.2,114.19 1 0 +auth/ent/token_query.go:114.19,117.3 2 0 +auth/ent/token_query.go:118.2,118.20 1 0 +auth/ent/token_query.go:122.60,124.36 2 0 +auth/ent/token_query.go:124.36,125.13 1 0 +auth/ent/token_query.go:127.2,127.11 1 0 +auth/ent/token_query.go:133.65,135.16 2 0 +auth/ent/token_query.go:135.16,137.3 1 0 +auth/ent/token_query.go:138.2,138.20 1 0 +auth/ent/token_query.go:139.9,140.23 1 0 +auth/ent/token_query.go:141.9,142.42 1 0 +auth/ent/token_query.go:143.10,144.45 1 0 +auth/ent/token_query.go:149.57,151.16 2 0 +auth/ent/token_query.go:151.16,152.13 1 0 +auth/ent/token_query.go:154.2,154.13 1 0 +auth/ent/token_query.go:160.74,162.81 2 0 +auth/ent/token_query.go:162.81,164.3 1 0 +auth/ent/token_query.go:165.2,165.18 1 0 +auth/ent/token_query.go:166.9,167.14 1 0 +auth/ent/token_query.go:168.9,169.36 1 0 +auth/ent/token_query.go:170.10,171.39 1 0 +auth/ent/token_query.go:173.2,173.8 1 0 +auth/ent/token_query.go:177.59,179.16 2 0 +auth/ent/token_query.go:179.16,180.13 1 0 +auth/ent/token_query.go:182.2,182.11 1 0 +auth/ent/token_query.go:186.66,188.45 2 0 +auth/ent/token_query.go:188.45,190.3 1 0 +auth/ent/token_query.go:191.2,192.59 2 0 +auth/ent/token_query.go:196.58,198.16 2 0 +auth/ent/token_query.go:198.16,199.13 1 0 +auth/ent/token_query.go:201.2,201.14 1 0 +auth/ent/token_query.go:205.74,206.44 1 0 +auth/ent/token_query.go:206.44,208.3 1 0 +auth/ent/token_query.go:209.2,210.64 2 0 +auth/ent/token_query.go:210.64,212.3 1 0 +auth/ent/token_query.go:213.2,213.17 1 0 +auth/ent/token_query.go:217.58,219.16 2 0 +auth/ent/token_query.go:219.16,220.13 1 0 +auth/ent/token_query.go:222.2,222.12 1 0 +auth/ent/token_query.go:226.63,228.45 2 0 +auth/ent/token_query.go:228.45,230.3 1 0 +auth/ent/token_query.go:231.2,231.79 1 0 +auth/ent/token_query.go:235.55,237.16 2 0 +auth/ent/token_query.go:237.16,238.13 1 0 +auth/ent/token_query.go:240.2,240.14 1 0 +auth/ent/token_query.go:244.64,246.36 2 0 +auth/ent/token_query.go:247.23,248.20 1 0 +auth/ent/token_query.go:249.18,250.60 1 0 +auth/ent/token_query.go:251.10,252.19 1 0 +auth/ent/token_query.go:257.56,259.16 2 0 +auth/ent/token_query.go:259.16,260.13 1 0 +auth/ent/token_query.go:262.2,262.14 1 0 +auth/ent/token_query.go:267.43,268.15 1 0 +auth/ent/token_query.go:268.15,270.3 1 0 +auth/ent/token_query.go:271.2,281.3 1 0 +auth/ent/token_query.go:286.70,288.27 2 0 +auth/ent/token_query.go:288.27,290.3 1 0 +auth/ent/token_query.go:291.2,292.11 2 0 +auth/ent/token_query.go:309.77,316.2 6 0 +auth/ent/token_query.go:330.61,336.2 5 0 +auth/ent/token_query.go:339.68,341.2 1 0 +auth/ent/token_query.go:343.63,344.34 1 0 +auth/ent/token_query.go:344.34,345.19 1 0 +auth/ent/token_query.go:345.19,347.4 1 0 +auth/ent/token_query.go:348.3,348.39 1 0 +auth/ent/token_query.go:348.39,349.48 1 0 +auth/ent/token_query.go:349.48,351.5 1 0 +auth/ent/token_query.go:354.2,354.34 1 0 +auth/ent/token_query.go:354.34,355.28 1 0 +auth/ent/token_query.go:355.28,357.4 1 0 +auth/ent/token_query.go:359.2,359.20 1 0 +auth/ent/token_query.go:359.20,361.17 2 0 +auth/ent/token_query.go:361.17,363.4 1 0 +auth/ent/token_query.go:364.3,364.16 1 0 +auth/ent/token_query.go:366.2,366.12 1 0 +auth/ent/token_query.go:369.89,378.24 2 0 +auth/ent/token_query.go:378.24,380.3 1 0 +auth/ent/token_query.go:381.2,381.13 1 0 +auth/ent/token_query.go:381.13,383.3 1 0 +auth/ent/token_query.go:384.2,384.59 1 0 +auth/ent/token_query.go:384.59,386.3 1 0 +auth/ent/token_query.go:387.2,387.60 1 0 +auth/ent/token_query.go:387.60,392.3 4 0 +auth/ent/token_query.go:393.2,393.23 1 0 +auth/ent/token_query.go:393.23,395.3 1 0 +auth/ent/token_query.go:396.2,396.67 1 0 +auth/ent/token_query.go:396.67,398.3 1 0 +auth/ent/token_query.go:399.2,399.21 1 0 +auth/ent/token_query.go:399.21,401.3 1 0 +auth/ent/token_query.go:402.2,402.40 1 0 +auth/ent/token_query.go:402.40,404.28 1 0 +auth/ent/token_query.go:404.28,404.48 1 0 +auth/ent/token_query.go:404.62,406.4 1 0 +auth/ent/token_query.go:408.2,408.19 1 0 +auth/ent/token_query.go:411.140,414.23 3 0 +auth/ent/token_query.go:414.23,415.34 1 0 +auth/ent/token_query.go:415.34,416.12 1 0 +auth/ent/token_query.go:418.3,419.32 2 0 +auth/ent/token_query.go:419.32,421.4 1 0 +auth/ent/token_query.go:422.3,422.46 1 0 +auth/ent/token_query.go:424.2,424.19 1 0 +auth/ent/token_query.go:424.19,426.3 1 0 +auth/ent/token_query.go:427.2,429.16 3 0 +auth/ent/token_query.go:429.16,431.3 1 0 +auth/ent/token_query.go:432.2,432.30 1 0 +auth/ent/token_query.go:432.30,434.10 2 0 +auth/ent/token_query.go:434.10,436.4 1 0 +auth/ent/token_query.go:437.3,437.24 1 0 +auth/ent/token_query.go:437.24,439.4 1 0 +auth/ent/token_query.go:441.2,441.12 1 0 +auth/ent/token_query.go:444.66,447.28 3 0 +auth/ent/token_query.go:447.28,449.3 1 0 +auth/ent/token_query.go:450.2,450.51 1 0 +auth/ent/token_query.go:453.55,456.44 3 0 +auth/ent/token_query.go:456.44,458.3 1 0 +auth/ent/token_query.go:458.8,458.27 1 0 +auth/ent/token_query.go:458.27,460.3 1 0 +auth/ent/token_query.go:461.2,461.46 1 0 +auth/ent/token_query.go:461.46,464.25 3 0 +auth/ent/token_query.go:464.25,465.34 1 0 +auth/ent/token_query.go:465.34,467.5 1 0 +auth/ent/token_query.go:470.2,470.38 1 0 +auth/ent/token_query.go:470.38,471.50 1 0 +auth/ent/token_query.go:471.50,472.22 1 0 +auth/ent/token_query.go:472.22,474.5 1 0 +auth/ent/token_query.go:477.2,477.41 1 0 +auth/ent/token_query.go:477.41,479.3 1 0 +auth/ent/token_query.go:480.2,480.44 1 0 +auth/ent/token_query.go:480.44,482.3 1 0 +auth/ent/token_query.go:483.2,483.33 1 0 +auth/ent/token_query.go:483.33,484.46 1 0 +auth/ent/token_query.go:484.46,485.22 1 0 +auth/ent/token_query.go:485.22,487.5 1 0 +auth/ent/token_query.go:490.2,490.14 1 0 +auth/ent/token_query.go:493.67,497.23 4 0 +auth/ent/token_query.go:497.23,499.3 1 0 +auth/ent/token_query.go:500.2,501.19 2 0 +auth/ent/token_query.go:501.19,504.3 2 0 +auth/ent/token_query.go:505.2,505.44 1 0 +auth/ent/token_query.go:505.44,507.3 1 0 +auth/ent/token_query.go:508.2,508.34 1 0 +auth/ent/token_query.go:508.34,510.3 1 0 +auth/ent/token_query.go:511.2,511.29 1 0 +auth/ent/token_query.go:511.29,513.3 1 0 +auth/ent/token_query.go:514.2,514.44 1 0 +auth/ent/token_query.go:514.44,518.3 1 0 +auth/ent/token_query.go:519.2,519.41 1 0 +auth/ent/token_query.go:519.41,521.3 1 0 +auth/ent/token_query.go:522.2,522.17 1 0 +auth/ent/token_query.go:532.72,535.2 2 0 +auth/ent/token_query.go:538.65,540.52 2 0 +auth/ent/token_query.go:540.52,542.3 1 0 +auth/ent/token_query.go:543.2,543.99 1 0 +auth/ent/token_query.go:546.86,549.29 3 0 +auth/ent/token_query.go:549.29,551.3 1 0 +auth/ent/token_query.go:552.2,552.42 1 0 +auth/ent/token_query.go:552.42,554.31 2 0 +auth/ent/token_query.go:554.31,556.4 1 0 +auth/ent/token_query.go:557.3,558.30 2 0 +auth/ent/token_query.go:560.2,561.39 2 0 +auth/ent/token_query.go:561.39,563.3 1 0 +auth/ent/token_query.go:564.2,566.71 3 0 +auth/ent/token_query.go:566.71,568.3 1 0 +auth/ent/token_query.go:569.2,570.31 2 0 +auth/ent/token_query.go:580.69,583.2 2 0 +auth/ent/token_query.go:586.63,588.45 2 0 +auth/ent/token_query.go:588.45,590.3 1 0 +auth/ent/token_query.go:591.2,591.94 1 0 +auth/ent/token_query.go:594.84,597.28 3 0 +auth/ent/token_query.go:597.28,599.3 1 0 +auth/ent/token_query.go:600.2,600.38 1 0 +auth/ent/token_query.go:601.38,602.34 1 0 +auth/ent/token_query.go:603.38,604.40 1 0 +auth/ent/token_query.go:606.2,608.64 3 0 +auth/ent/token_query.go:608.64,610.3 1 0 +auth/ent/token_query.go:611.2,612.31 2 0 +auth/ent/token_update.go:27.66,30.2 2 0 +auth/ent/token_update.go:33.56,36.2 2 0 +auth/ent/token_update.go:39.65,40.14 1 0 +auth/ent/token_update.go:40.14,42.3 1 0 +auth/ent/token_update.go:43.2,43.11 1 0 +auth/ent/token_update.go:47.59,50.2 2 0 +auth/ent/token_update.go:53.68,54.14 1 0 +auth/ent/token_update.go:54.14,56.3 1 0 +auth/ent/token_update.go:57.2,57.11 1 0 +auth/ent/token_update.go:61.63,64.2 2 0 +auth/ent/token_update.go:67.72,68.14 1 0 +auth/ent/token_update.go:68.14,70.3 1 0 +auth/ent/token_update.go:71.2,71.11 1 0 +auth/ent/token_update.go:75.56,78.2 2 0 +auth/ent/token_update.go:81.65,82.14 1 0 +auth/ent/token_update.go:82.14,84.3 1 0 +auth/ent/token_update.go:85.2,85.11 1 0 +auth/ent/token_update.go:89.63,92.2 2 0 +auth/ent/token_update.go:95.72,96.14 1 0 +auth/ent/token_update.go:96.14,98.3 1 0 +auth/ent/token_update.go:99.2,99.11 1 0 +auth/ent/token_update.go:103.63,106.2 2 0 +auth/ent/token_update.go:109.58,112.2 2 0 +auth/ent/token_update.go:115.54,117.2 1 0 +auth/ent/token_update.go:120.50,122.2 1 0 +auth/ent/token_update.go:125.49,128.2 2 0 +auth/ent/token_update.go:131.63,134.2 2 0 +auth/ent/token_update.go:137.55,139.16 2 0 +auth/ent/token_update.go:139.16,140.13 1 0 +auth/ent/token_update.go:142.2,142.17 1 0 +auth/ent/token_update.go:146.56,149.2 2 0 +auth/ent/token_update.go:152.51,153.37 1 0 +auth/ent/token_update.go:153.37,154.13 1 0 +auth/ent/token_update.go:159.35,160.43 1 0 +auth/ent/token_update.go:160.43,163.3 2 0 +auth/ent/token_update.go:167.38,168.40 1 0 +auth/ent/token_update.go:168.40,169.48 1 0 +auth/ent/token_update.go:169.48,171.4 1 0 +auth/ent/token_update.go:173.2,173.69 1 0 +auth/ent/token_update.go:173.69,175.3 1 0 +auth/ent/token_update.go:176.2,176.12 1 0 +auth/ent/token_update.go:179.72,180.35 1 0 +auth/ent/token_update.go:180.35,182.3 1 0 +auth/ent/token_update.go:183.2,184.47 2 0 +auth/ent/token_update.go:184.47,185.50 1 0 +auth/ent/token_update.go:185.50,186.22 1 0 +auth/ent/token_update.go:186.22,188.5 1 0 +auth/ent/token_update.go:191.2,191.42 1 0 +auth/ent/token_update.go:191.42,193.3 1 0 +auth/ent/token_update.go:194.2,194.44 1 0 +auth/ent/token_update.go:194.44,196.3 1 0 +auth/ent/token_update.go:197.2,197.46 1 0 +auth/ent/token_update.go:197.46,199.3 1 0 +auth/ent/token_update.go:200.2,200.44 1 0 +auth/ent/token_update.go:200.44,202.3 1 0 +auth/ent/token_update.go:203.2,203.46 1 0 +auth/ent/token_update.go:203.46,205.3 1 0 +auth/ent/token_update.go:206.2,206.46 1 0 +auth/ent/token_update.go:206.46,208.3 1 0 +auth/ent/token_update.go:209.2,209.31 1 0 +auth/ent/token_update.go:209.31,221.3 2 0 +auth/ent/token_update.go:222.2,222.52 1 0 +auth/ent/token_update.go:222.52,233.27 2 0 +auth/ent/token_update.go:233.27,235.4 1 0 +auth/ent/token_update.go:236.3,236.50 1 0 +auth/ent/token_update.go:238.2,238.70 1 0 +auth/ent/token_update.go:238.70,239.49 1 0 +auth/ent/token_update.go:239.49,241.4 1 0 +auth/ent/token_update.go:241.9,241.45 1 0 +auth/ent/token_update.go:241.45,243.4 1 0 +auth/ent/token_update.go:244.3,244.16 1 0 +auth/ent/token_update.go:246.2,247.15 2 0 +auth/ent/token_update.go:259.63,262.2 2 0 +auth/ent/token_update.go:265.72,266.14 1 0 +auth/ent/token_update.go:266.14,268.3 1 0 +auth/ent/token_update.go:269.2,269.12 1 0 +auth/ent/token_update.go:273.66,276.2 2 0 +auth/ent/token_update.go:279.75,280.14 1 0 +auth/ent/token_update.go:280.14,282.3 1 0 +auth/ent/token_update.go:283.2,283.12 1 0 +auth/ent/token_update.go:287.70,290.2 2 0 +auth/ent/token_update.go:293.79,294.14 1 0 +auth/ent/token_update.go:294.14,296.3 1 0 +auth/ent/token_update.go:297.2,297.12 1 0 +auth/ent/token_update.go:301.63,304.2 2 0 +auth/ent/token_update.go:307.72,308.14 1 0 +auth/ent/token_update.go:308.14,310.3 1 0 +auth/ent/token_update.go:311.2,311.12 1 0 +auth/ent/token_update.go:315.70,318.2 2 0 +auth/ent/token_update.go:321.79,322.14 1 0 +auth/ent/token_update.go:322.14,324.3 1 0 +auth/ent/token_update.go:325.2,325.12 1 0 +auth/ent/token_update.go:329.70,332.2 2 0 +auth/ent/token_update.go:335.65,338.2 2 0 +auth/ent/token_update.go:341.61,343.2 1 0 +auth/ent/token_update.go:346.54,348.2 1 0 +auth/ent/token_update.go:351.56,354.2 2 0 +auth/ent/token_update.go:357.73,360.2 2 0 +auth/ent/token_update.go:364.83,367.2 2 0 +auth/ent/token_update.go:370.70,373.2 2 0 +auth/ent/token_update.go:376.62,378.16 2 0 +auth/ent/token_update.go:378.16,379.13 1 0 +auth/ent/token_update.go:381.2,381.13 1 0 +auth/ent/token_update.go:385.60,388.2 2 0 +auth/ent/token_update.go:391.55,392.38 1 0 +auth/ent/token_update.go:392.38,393.13 1 0 +auth/ent/token_update.go:398.39,399.44 1 0 +auth/ent/token_update.go:399.44,402.3 2 0 +auth/ent/token_update.go:406.42,407.41 1 0 +auth/ent/token_update.go:407.41,408.48 1 0 +auth/ent/token_update.go:408.48,410.4 1 0 +auth/ent/token_update.go:412.2,412.71 1 0 +auth/ent/token_update.go:412.71,414.3 1 0 +auth/ent/token_update.go:415.2,415.12 1 0 +auth/ent/token_update.go:418.83,419.36 1 0 +auth/ent/token_update.go:419.36,421.3 1 0 +auth/ent/token_update.go:422.2,424.9 3 0 +auth/ent/token_update.go:424.9,426.3 1 0 +auth/ent/token_update.go:427.2,428.43 2 0 +auth/ent/token_update.go:428.43,431.28 3 0 +auth/ent/token_update.go:431.28,432.29 1 0 +auth/ent/token_update.go:432.29,434.5 1 0 +auth/ent/token_update.go:435.4,435.26 1 0 +auth/ent/token_update.go:435.26,437.5 1 0 +auth/ent/token_update.go:440.2,440.48 1 0 +auth/ent/token_update.go:440.48,441.50 1 0 +auth/ent/token_update.go:441.50,442.22 1 0 +auth/ent/token_update.go:442.22,444.5 1 0 +auth/ent/token_update.go:447.2,447.43 1 0 +auth/ent/token_update.go:447.43,449.3 1 0 +auth/ent/token_update.go:450.2,450.45 1 0 +auth/ent/token_update.go:450.45,452.3 1 0 +auth/ent/token_update.go:453.2,453.47 1 0 +auth/ent/token_update.go:453.47,455.3 1 0 +auth/ent/token_update.go:456.2,456.45 1 0 +auth/ent/token_update.go:456.45,458.3 1 0 +auth/ent/token_update.go:459.2,459.47 1 0 +auth/ent/token_update.go:459.47,461.3 1 0 +auth/ent/token_update.go:462.2,462.47 1 0 +auth/ent/token_update.go:462.47,464.3 1 0 +auth/ent/token_update.go:465.2,465.32 1 0 +auth/ent/token_update.go:465.32,477.3 2 0 +auth/ent/token_update.go:478.2,478.53 1 0 +auth/ent/token_update.go:478.53,489.27 2 0 +auth/ent/token_update.go:489.27,491.4 1 0 +auth/ent/token_update.go:492.3,492.50 1 0 +auth/ent/token_update.go:494.2,497.67 4 0 +auth/ent/token_update.go:497.67,498.49 1 0 +auth/ent/token_update.go:498.49,500.4 1 0 +auth/ent/token_update.go:500.9,500.45 1 0 +auth/ent/token_update.go:500.45,502.4 1 0 +auth/ent/token_update.go:503.3,503.18 1 0 +auth/ent/token_update.go:505.2,506.19 2 0 +auth/ent/tx.go:59.63,61.2 1 0 +auth/ent/tx.go:64.30,66.65 2 0 +auth/ent/tx.go:66.65,68.3 1 0 +auth/ent/tx.go:69.2,72.39 4 0 +auth/ent/tx.go:72.39,74.3 1 0 +auth/ent/tx.go:75.2,75.30 1 0 +auth/ent/tx.go:79.38,84.2 4 0 +auth/ent/tx.go:115.67,117.2 1 0 +auth/ent/tx.go:120.32,122.68 2 0 +auth/ent/tx.go:122.68,124.3 1 0 +auth/ent/tx.go:125.2,128.39 4 0 +auth/ent/tx.go:128.39,130.3 1 0 +auth/ent/tx.go:131.2,131.32 1 0 +auth/ent/tx.go:135.42,140.2 4 0 +auth/ent/tx.go:143.32,144.26 1 0 +auth/ent/tx.go:144.26,147.3 2 0 +auth/ent/tx.go:148.2,148.18 1 0 +auth/ent/tx.go:151.22,155.2 3 0 +auth/ent/tx.go:180.72,182.16 2 0 +auth/ent/tx.go:182.16,184.3 1 0 +auth/ent/tx.go:185.2,185.41 1 0 +auth/ent/tx.go:190.61,190.79 1 0 +auth/ent/tx.go:193.38,193.65 1 0 +auth/ent/tx.go:196.32,196.46 1 0 +auth/ent/tx.go:200.33,200.47 1 0 +auth/ent/tx.go:204.35,204.49 1 0 +auth/ent/tx.go:207.80,209.2 1 0 +auth/ent/tx.go:212.81,214.2 1 0 +auth/ent/user.go:49.50,50.22 1 0 +auth/ent/user.go:50.22,52.3 1 0 +auth/ent/user.go:53.2,53.44 1 0 +auth/ent/user.go:58.52,59.22 1 0 +auth/ent/user.go:59.22,61.3 1 0 +auth/ent/user.go:62.2,62.45 1 0 +auth/ent/user.go:66.58,68.25 2 0 +auth/ent/user.go:68.25,69.21 1 0 +auth/ent/user.go:70.78,71.35 1 0 +auth/ent/user.go:72.49,73.33 1 0 +auth/ent/user.go:74.11,75.36 1 0 +auth/ent/user.go:78.2,78.20 1 0 +auth/ent/user.go:83.67,84.46 1 0 +auth/ent/user.go:84.46,86.3 1 0 +auth/ent/user.go:87.2,87.25 1 0 +auth/ent/user.go:87.25,88.21 1 0 +auth/ent/user.go:89.21,90.53 1 0 +auth/ent/user.go:90.53,92.5 1 0 +auth/ent/user.go:92.10,92.26 1 0 +auth/ent/user.go:92.26,94.5 1 0 +auth/ent/user.go:95.27,96.53 1 0 +auth/ent/user.go:96.53,98.5 1 0 +auth/ent/user.go:98.10,98.26 1 0 +auth/ent/user.go:98.26,100.5 1 0 +auth/ent/user.go:101.24,102.53 1 0 +auth/ent/user.go:102.53,104.5 1 0 +auth/ent/user.go:104.10,104.26 1 0 +auth/ent/user.go:104.26,106.5 1 0 +auth/ent/user.go:107.27,108.53 1 0 +auth/ent/user.go:108.53,110.5 1 0 +auth/ent/user.go:110.10,110.26 1 0 +auth/ent/user.go:110.26,112.5 1 0 +auth/ent/user.go:113.28,114.51 1 0 +auth/ent/user.go:114.51,116.5 1 0 +auth/ent/user.go:116.10,116.26 1 0 +auth/ent/user.go:116.26,118.5 1 0 +auth/ent/user.go:119.28,120.51 1 0 +auth/ent/user.go:120.51,122.5 1 0 +auth/ent/user.go:122.10,122.26 1 0 +auth/ent/user.go:122.26,124.5 1 0 +auth/ent/user.go:125.11,126.45 1 0 +auth/ent/user.go:129.2,129.12 1 0 +auth/ent/user.go:134.54,136.2 1 0 +auth/ent/user.go:139.40,141.2 1 0 +auth/ent/user.go:144.42,146.2 1 0 +auth/ent/user.go:151.40,153.2 1 0 +auth/ent/user.go:157.31,159.9 2 0 +auth/ent/user.go:159.9,160.51 1 0 +auth/ent/user.go:162.2,163.10 2 0 +auth/ent/user.go:167.32,187.2 19 0 +auth/ent/user_create.go:26.57,29.2 2 0 +auth/ent/user_create.go:32.54,35.2 2 0 +auth/ent/user_create.go:38.57,41.2 2 0 +auth/ent/user_create.go:44.61,47.2 2 0 +auth/ent/user_create.go:50.70,51.14 1 0 +auth/ent/user_create.go:51.14,53.3 1 0 +auth/ent/user_create.go:54.2,54.11 1 0 +auth/ent/user_create.go:58.61,61.2 2 0 +auth/ent/user_create.go:64.70,65.14 1 0 +auth/ent/user_create.go:65.14,67.3 1 0 +auth/ent/user_create.go:68.2,68.11 1 0 +auth/ent/user_create.go:72.51,75.2 2 0 +auth/ent/user_create.go:78.60,79.14 1 0 +auth/ent/user_create.go:79.14,81.3 1 0 +auth/ent/user_create.go:82.2,82.11 1 0 +auth/ent/user_create.go:86.61,89.2 2 0 +auth/ent/user_create.go:92.56,94.19 2 0 +auth/ent/user_create.go:94.19,96.3 1 0 +auth/ent/user_create.go:97.2,97.30 1 0 +auth/ent/user_create.go:101.62,104.2 2 0 +auth/ent/user_create.go:107.58,109.19 2 0 +auth/ent/user_create.go:109.19,111.3 1 0 +auth/ent/user_create.go:112.2,112.31 1 0 +auth/ent/user_create.go:116.48,118.2 1 0 +auth/ent/user_create.go:121.64,122.38 1 0 +auth/ent/user_create.go:122.38,124.3 1 0 +auth/ent/user_create.go:125.2,125.58 1 0 +auth/ent/user_create.go:129.56,131.16 2 0 +auth/ent/user_create.go:131.16,132.13 1 0 +auth/ent/user_create.go:134.2,134.10 1 0 +auth/ent/user_create.go:138.55,141.2 2 0 +auth/ent/user_create.go:144.50,145.37 1 0 +auth/ent/user_create.go:145.37,146.13 1 0 +auth/ent/user_create.go:151.40,152.43 1 0 +auth/ent/user_create.go:152.43,153.35 1 0 +auth/ent/user_create.go:153.35,155.4 1 0 +auth/ent/user_create.go:156.3,157.30 2 0 +auth/ent/user_create.go:159.2,159.43 1 0 +auth/ent/user_create.go:159.43,160.35 1 0 +auth/ent/user_create.go:160.35,162.4 1 0 +auth/ent/user_create.go:163.3,164.30 2 0 +auth/ent/user_create.go:166.2,166.36 1 0 +auth/ent/user_create.go:166.36,167.28 1 0 +auth/ent/user_create.go:167.28,169.4 1 0 +auth/ent/user_create.go:170.3,171.23 2 0 +auth/ent/user_create.go:173.2,173.12 1 0 +auth/ent/user_create.go:177.37,178.42 1 0 +auth/ent/user_create.go:178.42,180.3 1 0 +auth/ent/user_create.go:181.2,181.39 1 0 +auth/ent/user_create.go:181.39,183.3 1 0 +auth/ent/user_create.go:184.2,184.42 1 0 +auth/ent/user_create.go:184.42,186.3 1 0 +auth/ent/user_create.go:187.2,187.43 1 0 +auth/ent/user_create.go:187.43,189.3 1 0 +auth/ent/user_create.go:190.2,190.43 1 0 +auth/ent/user_create.go:190.43,192.3 1 0 +auth/ent/user_create.go:193.2,193.12 1 0 +auth/ent/user_create.go:196.67,197.35 1 0 +auth/ent/user_create.go:197.35,199.3 1 0 +auth/ent/user_create.go:200.2,201.67 2 0 +auth/ent/user_create.go:201.67,202.38 1 0 +auth/ent/user_create.go:202.38,204.4 1 0 +auth/ent/user_create.go:205.3,205.18 1 0 +auth/ent/user_create.go:207.2,207.27 1 0 +auth/ent/user_create.go:207.27,208.44 1 0 +auth/ent/user_create.go:208.44,210.4 1 0 +auth/ent/user_create.go:210.9,212.4 1 0 +auth/ent/user_create.go:214.2,216.19 3 0 +auth/ent/user_create.go:219.66,224.36 2 0 +auth/ent/user_create.go:224.36,227.3 2 0 +auth/ent/user_create.go:228.2,228.45 1 0 +auth/ent/user_create.go:228.45,231.3 2 0 +auth/ent/user_create.go:232.2,232.42 1 0 +auth/ent/user_create.go:232.42,235.3 2 0 +auth/ent/user_create.go:236.2,236.45 1 0 +auth/ent/user_create.go:236.45,239.3 2 0 +auth/ent/user_create.go:240.2,240.46 1 0 +auth/ent/user_create.go:240.46,243.3 2 0 +auth/ent/user_create.go:244.2,244.46 1 0 +auth/ent/user_create.go:244.46,247.3 2 0 +auth/ent/user_create.go:248.2,248.53 1 0 +auth/ent/user_create.go:248.53,259.27 2 0 +auth/ent/user_create.go:259.27,261.4 1 0 +auth/ent/user_create.go:262.3,262.42 1 0 +auth/ent/user_create.go:264.2,264.54 1 0 +auth/ent/user_create.go:264.54,275.27 2 0 +auth/ent/user_create.go:275.27,277.4 1 0 +auth/ent/user_create.go:278.3,278.42 1 0 +auth/ent/user_create.go:280.2,280.21 1 0 +auth/ent/user_create.go:291.71,292.20 1 0 +auth/ent/user_create.go:292.20,294.3 1 0 +auth/ent/user_create.go:295.2,298.30 4 0 +auth/ent/user_create.go:298.30,299.37 1 0 +auth/ent/user_create.go:299.37,302.86 3 0 +auth/ent/user_create.go:302.86,304.12 2 0 +auth/ent/user_create.go:304.12,306.6 1 0 +auth/ent/user_create.go:307.5,307.43 1 0 +auth/ent/user_create.go:307.43,309.6 1 0 +auth/ent/user_create.go:310.5,313.28 4 0 +auth/ent/user_create.go:313.28,315.6 1 0 +auth/ent/user_create.go:315.11,318.71 2 0 +auth/ent/user_create.go:318.71,319.42 1 0 +auth/ent/user_create.go:319.42,321.8 1 0 +auth/ent/user_create.go:324.5,324.19 1 0 +auth/ent/user_create.go:324.19,326.6 1 0 +auth/ent/user_create.go:327.5,329.25 3 0 +auth/ent/user_create.go:331.4,331.49 1 0 +auth/ent/user_create.go:331.49,333.5 1 0 +auth/ent/user_create.go:334.4,334.21 1 0 +auth/ent/user_create.go:337.2,337.23 1 0 +auth/ent/user_create.go:337.23,338.78 1 0 +auth/ent/user_create.go:338.78,340.4 1 0 +auth/ent/user_create.go:342.2,342.19 1 0 +auth/ent/user_create.go:346.63,348.16 2 0 +auth/ent/user_create.go:348.16,349.13 1 0 +auth/ent/user_create.go:351.2,351.10 1 0 +auth/ent/user_create.go:355.60,358.2 2 0 +auth/ent/user_create.go:361.55,362.38 1 0 +auth/ent/user_create.go:362.38,363.13 1 0 +auth/ent/user_delete.go:23.63,26.2 2 0 +auth/ent/user_delete.go:29.62,31.2 1 0 +auth/ent/user_delete.go:34.54,36.16 2 0 +auth/ent/user_delete.go:36.16,37.13 1 0 +auth/ent/user_delete.go:39.2,39.10 1 0 +auth/ent/user_delete.go:42.65,44.47 2 0 +auth/ent/user_delete.go:44.47,45.50 1 0 +auth/ent/user_delete.go:45.50,46.22 1 0 +auth/ent/user_delete.go:46.22,48.5 1 0 +auth/ent/user_delete.go:51.2,52.51 2 0 +auth/ent/user_delete.go:52.51,54.3 1 0 +auth/ent/user_delete.go:55.2,56.22 2 0 +auth/ent/user_delete.go:65.70,68.2 2 0 +auth/ent/user_delete.go:71.59,73.9 2 0 +auth/ent/user_delete.go:74.18,75.13 1 0 +auth/ent/user_delete.go:76.14,77.36 1 0 +auth/ent/user_delete.go:78.10,79.13 1 0 +auth/ent/user_delete.go:84.54,85.38 1 0 +auth/ent/user_delete.go:85.38,86.13 1 0 +auth/ent/user_query.go:35.61,38.2 2 0 +auth/ent/user_query.go:41.50,44.2 2 0 +auth/ent/user_query.go:47.52,50.2 2 0 +auth/ent/user_query.go:54.53,57.2 2 0 +auth/ent/user_query.go:60.62,63.2 2 0 +auth/ent/user_query.go:66.46,68.74 2 0 +auth/ent/user_query.go:68.74,69.46 1 0 +auth/ent/user_query.go:69.46,71.4 1 0 +auth/ent/user_query.go:72.3,73.40 2 0 +auth/ent/user_query.go:73.40,75.4 1 0 +auth/ent/user_query.go:76.3,82.20 3 0 +auth/ent/user_query.go:84.2,84.14 1 0 +auth/ent/user_query.go:88.48,90.74 2 0 +auth/ent/user_query.go:90.74,91.46 1 0 +auth/ent/user_query.go:91.46,93.4 1 0 +auth/ent/user_query.go:94.3,95.40 2 0 +auth/ent/user_query.go:95.40,97.4 1 0 +auth/ent/user_query.go:98.3,104.20 3 0 +auth/ent/user_query.go:106.2,106.14 1 0 +auth/ent/user_query.go:111.64,113.16 2 0 +auth/ent/user_query.go:113.16,115.3 1 0 +auth/ent/user_query.go:116.2,116.21 1 0 +auth/ent/user_query.go:116.21,118.3 1 0 +auth/ent/user_query.go:119.2,119.22 1 0 +auth/ent/user_query.go:123.56,125.36 2 0 +auth/ent/user_query.go:125.36,126.13 1 0 +auth/ent/user_query.go:128.2,128.13 1 0 +auth/ent/user_query.go:133.74,135.82 2 0 +auth/ent/user_query.go:135.82,137.3 1 0 +auth/ent/user_query.go:138.2,138.19 1 0 +auth/ent/user_query.go:138.19,141.3 2 0 +auth/ent/user_query.go:142.2,142.20 1 0 +auth/ent/user_query.go:146.59,148.36 2 0 +auth/ent/user_query.go:148.36,149.13 1 0 +auth/ent/user_query.go:151.2,151.11 1 0 +auth/ent/user_query.go:157.63,159.16 2 0 +auth/ent/user_query.go:159.16,161.3 1 0 +auth/ent/user_query.go:162.2,162.20 1 0 +auth/ent/user_query.go:163.9,164.23 1 0 +auth/ent/user_query.go:165.9,166.41 1 0 +auth/ent/user_query.go:167.10,168.44 1 0 +auth/ent/user_query.go:173.55,175.16 2 0 +auth/ent/user_query.go:175.16,176.13 1 0 +auth/ent/user_query.go:178.2,178.13 1 0 +auth/ent/user_query.go:184.73,186.81 2 0 +auth/ent/user_query.go:186.81,188.3 1 0 +auth/ent/user_query.go:189.2,189.18 1 0 +auth/ent/user_query.go:190.9,191.14 1 0 +auth/ent/user_query.go:192.9,193.35 1 0 +auth/ent/user_query.go:194.10,195.38 1 0 +auth/ent/user_query.go:197.2,197.8 1 0 +auth/ent/user_query.go:201.58,203.16 2 0 +auth/ent/user_query.go:203.16,204.13 1 0 +auth/ent/user_query.go:206.2,206.11 1 0 +auth/ent/user_query.go:210.64,212.45 2 0 +auth/ent/user_query.go:212.45,214.3 1 0 +auth/ent/user_query.go:215.2,216.58 2 0 +auth/ent/user_query.go:220.56,222.16 2 0 +auth/ent/user_query.go:222.16,223.13 1 0 +auth/ent/user_query.go:225.2,225.14 1 0 +auth/ent/user_query.go:229.73,230.44 1 0 +auth/ent/user_query.go:230.44,232.3 1 0 +auth/ent/user_query.go:233.2,234.63 2 0 +auth/ent/user_query.go:234.63,236.3 1 0 +auth/ent/user_query.go:237.2,237.17 1 0 +auth/ent/user_query.go:241.57,243.16 2 0 +auth/ent/user_query.go:243.16,244.13 1 0 +auth/ent/user_query.go:246.2,246.12 1 0 +auth/ent/user_query.go:250.62,252.45 2 0 +auth/ent/user_query.go:252.45,254.3 1 0 +auth/ent/user_query.go:255.2,255.78 1 0 +auth/ent/user_query.go:259.54,261.16 2 0 +auth/ent/user_query.go:261.16,262.13 1 0 +auth/ent/user_query.go:264.2,264.14 1 0 +auth/ent/user_query.go:268.63,270.36 2 0 +auth/ent/user_query.go:271.23,272.20 1 0 +auth/ent/user_query.go:273.18,274.60 1 0 +auth/ent/user_query.go:275.10,276.19 1 0 +auth/ent/user_query.go:281.55,283.16 2 0 +auth/ent/user_query.go:283.16,284.13 1 0 +auth/ent/user_query.go:286.2,286.14 1 0 +auth/ent/user_query.go:291.41,292.15 1 0 +auth/ent/user_query.go:292.15,294.3 1 0 +auth/ent/user_query.go:295.2,306.3 1 0 +auth/ent/user_query.go:311.69,313.27 2 0 +auth/ent/user_query.go:313.27,315.3 1 0 +auth/ent/user_query.go:316.2,317.11 2 0 +auth/ent/user_query.go:322.71,324.27 2 0 +auth/ent/user_query.go:324.27,326.3 1 0 +auth/ent/user_query.go:327.2,328.11 2 0 +auth/ent/user_query.go:345.75,352.2 6 0 +auth/ent/user_query.go:366.59,372.2 5 0 +auth/ent/user_query.go:375.66,377.2 1 0 +auth/ent/user_query.go:379.62,380.34 1 0 +auth/ent/user_query.go:380.34,381.19 1 0 +auth/ent/user_query.go:381.19,383.4 1 0 +auth/ent/user_query.go:384.3,384.39 1 0 +auth/ent/user_query.go:384.39,385.48 1 0 +auth/ent/user_query.go:385.48,387.5 1 0 +auth/ent/user_query.go:390.2,390.34 1 0 +auth/ent/user_query.go:390.34,391.27 1 0 +auth/ent/user_query.go:391.27,393.4 1 0 +auth/ent/user_query.go:395.2,395.20 1 0 +auth/ent/user_query.go:395.20,397.17 2 0 +auth/ent/user_query.go:397.17,399.4 1 0 +auth/ent/user_query.go:400.3,400.16 1 0 +auth/ent/user_query.go:402.2,402.12 1 0 +auth/ent/user_query.go:405.87,414.59 2 0 +auth/ent/user_query.go:414.59,416.3 1 0 +auth/ent/user_query.go:417.2,417.60 1 0 +auth/ent/user_query.go:417.60,422.3 4 0 +auth/ent/user_query.go:423.2,423.23 1 0 +auth/ent/user_query.go:423.23,425.3 1 0 +auth/ent/user_query.go:426.2,426.67 1 0 +auth/ent/user_query.go:426.67,428.3 1 0 +auth/ent/user_query.go:429.2,429.21 1 0 +auth/ent/user_query.go:429.21,431.3 1 0 +auth/ent/user_query.go:432.2,432.41 1 0 +auth/ent/user_query.go:432.41,434.18 1 0 +auth/ent/user_query.go:434.18,434.47 1 0 +auth/ent/user_query.go:435.27,435.71 1 0 +auth/ent/user_query.go:435.85,437.4 1 0 +auth/ent/user_query.go:439.2,439.42 1 0 +auth/ent/user_query.go:439.42,441.18 1 0 +auth/ent/user_query.go:441.18,441.49 1 0 +auth/ent/user_query.go:442.28,442.74 1 0 +auth/ent/user_query.go:442.88,444.4 1 0 +auth/ent/user_query.go:446.2,446.19 1 0 +auth/ent/user_query.go:449.137,453.29 4 0 +auth/ent/user_query.go:453.29,456.18 3 0 +auth/ent/user_query.go:456.18,458.4 1 0 +auth/ent/user_query.go:460.2,460.36 1 0 +auth/ent/user_query.go:460.36,468.3 7 0 +auth/ent/user_query.go:469.2,469.48 1 0 +auth/ent/user_query.go:469.48,471.3 1 0 +auth/ent/user_query.go:472.2,472.70 1 0 +auth/ent/user_query.go:472.70,473.78 1 0 +auth/ent/user_query.go:473.78,476.60 3 0 +auth/ent/user_query.go:476.60,478.19 2 0 +auth/ent/user_query.go:478.19,480.6 1 0 +auth/ent/user_query.go:481.5,481.62 1 0 +auth/ent/user_query.go:483.4,483.61 1 0 +auth/ent/user_query.go:483.61,486.29 3 0 +auth/ent/user_query.go:486.29,489.6 2 0 +auth/ent/user_query.go:490.5,491.15 2 0 +auth/ent/user_query.go:495.2,496.16 2 0 +auth/ent/user_query.go:496.16,498.3 1 0 +auth/ent/user_query.go:499.2,499.30 1 0 +auth/ent/user_query.go:499.30,501.10 2 0 +auth/ent/user_query.go:501.10,503.4 1 0 +auth/ent/user_query.go:504.3,504.25 1 0 +auth/ent/user_query.go:504.25,506.4 1 0 +auth/ent/user_query.go:508.2,508.12 1 0 +auth/ent/user_query.go:510.140,513.23 3 0 +auth/ent/user_query.go:513.23,516.18 3 0 +auth/ent/user_query.go:516.18,518.4 1 0 +auth/ent/user_query.go:520.2,521.52 2 0 +auth/ent/user_query.go:521.52,523.3 1 0 +auth/ent/user_query.go:524.2,525.16 2 0 +auth/ent/user_query.go:525.16,527.3 1 0 +auth/ent/user_query.go:528.2,528.30 1 0 +auth/ent/user_query.go:528.30,530.16 2 0 +auth/ent/user_query.go:530.16,532.4 1 0 +auth/ent/user_query.go:533.3,534.10 2 0 +auth/ent/user_query.go:534.10,536.4 1 0 +auth/ent/user_query.go:537.3,537.18 1 0 +auth/ent/user_query.go:539.2,539.12 1 0 +auth/ent/user_query.go:542.65,545.28 3 0 +auth/ent/user_query.go:545.28,547.3 1 0 +auth/ent/user_query.go:548.2,548.51 1 0 +auth/ent/user_query.go:551.54,554.44 3 0 +auth/ent/user_query.go:554.44,556.3 1 0 +auth/ent/user_query.go:556.8,556.27 1 0 +auth/ent/user_query.go:556.27,558.3 1 0 +auth/ent/user_query.go:559.2,559.46 1 0 +auth/ent/user_query.go:559.46,562.25 3 0 +auth/ent/user_query.go:562.25,563.33 1 0 +auth/ent/user_query.go:563.33,565.5 1 0 +auth/ent/user_query.go:568.2,568.38 1 0 +auth/ent/user_query.go:568.38,569.50 1 0 +auth/ent/user_query.go:569.50,570.22 1 0 +auth/ent/user_query.go:570.22,572.5 1 0 +auth/ent/user_query.go:575.2,575.41 1 0 +auth/ent/user_query.go:575.41,577.3 1 0 +auth/ent/user_query.go:578.2,578.44 1 0 +auth/ent/user_query.go:578.44,580.3 1 0 +auth/ent/user_query.go:581.2,581.33 1 0 +auth/ent/user_query.go:581.33,582.46 1 0 +auth/ent/user_query.go:582.46,583.22 1 0 +auth/ent/user_query.go:583.22,585.5 1 0 +auth/ent/user_query.go:588.2,588.14 1 0 +auth/ent/user_query.go:591.66,595.23 4 0 +auth/ent/user_query.go:595.23,597.3 1 0 +auth/ent/user_query.go:598.2,599.19 2 0 +auth/ent/user_query.go:599.19,602.3 2 0 +auth/ent/user_query.go:603.2,603.44 1 0 +auth/ent/user_query.go:603.44,605.3 1 0 +auth/ent/user_query.go:606.2,606.34 1 0 +auth/ent/user_query.go:606.34,608.3 1 0 +auth/ent/user_query.go:609.2,609.29 1 0 +auth/ent/user_query.go:609.29,611.3 1 0 +auth/ent/user_query.go:612.2,612.44 1 0 +auth/ent/user_query.go:612.44,616.3 1 0 +auth/ent/user_query.go:617.2,617.41 1 0 +auth/ent/user_query.go:617.41,619.3 1 0 +auth/ent/user_query.go:620.2,620.17 1 0 +auth/ent/user_query.go:630.70,633.2 2 0 +auth/ent/user_query.go:636.64,638.52 2 0 +auth/ent/user_query.go:638.52,640.3 1 0 +auth/ent/user_query.go:641.2,641.97 1 0 +auth/ent/user_query.go:644.84,647.29 3 0 +auth/ent/user_query.go:647.29,649.3 1 0 +auth/ent/user_query.go:650.2,650.42 1 0 +auth/ent/user_query.go:650.42,652.31 2 0 +auth/ent/user_query.go:652.31,654.4 1 0 +auth/ent/user_query.go:655.3,656.30 2 0 +auth/ent/user_query.go:658.2,659.39 2 0 +auth/ent/user_query.go:659.39,661.3 1 0 +auth/ent/user_query.go:662.2,664.71 3 0 +auth/ent/user_query.go:664.71,666.3 1 0 +auth/ent/user_query.go:667.2,668.31 2 0 +auth/ent/user_query.go:678.67,681.2 2 0 +auth/ent/user_query.go:684.62,686.45 2 0 +auth/ent/user_query.go:686.45,688.3 1 0 +auth/ent/user_query.go:689.2,689.91 1 0 +auth/ent/user_query.go:692.82,695.28 3 0 +auth/ent/user_query.go:695.28,697.3 1 0 +auth/ent/user_query.go:698.2,698.38 1 0 +auth/ent/user_query.go:699.38,700.34 1 0 +auth/ent/user_query.go:701.38,702.40 1 0 +auth/ent/user_query.go:704.2,706.64 3 0 +auth/ent/user_query.go:706.64,708.3 1 0 +auth/ent/user_query.go:709.2,710.31 2 0 +auth/ent/user_update.go:28.63,31.2 2 0 +auth/ent/user_update.go:34.57,37.2 2 0 +auth/ent/user_update.go:40.66,41.14 1 0 +auth/ent/user_update.go:41.14,43.3 1 0 +auth/ent/user_update.go:44.2,44.11 1 0 +auth/ent/user_update.go:48.54,51.2 2 0 +auth/ent/user_update.go:54.63,55.14 1 0 +auth/ent/user_update.go:55.14,57.3 1 0 +auth/ent/user_update.go:58.2,58.11 1 0 +auth/ent/user_update.go:62.57,65.2 2 0 +auth/ent/user_update.go:68.66,69.14 1 0 +auth/ent/user_update.go:69.14,71.3 1 0 +auth/ent/user_update.go:72.2,72.11 1 0 +auth/ent/user_update.go:76.61,79.2 2 0 +auth/ent/user_update.go:82.70,83.14 1 0 +auth/ent/user_update.go:83.14,85.3 1 0 +auth/ent/user_update.go:86.2,86.11 1 0 +auth/ent/user_update.go:90.61,93.2 2 0 +auth/ent/user_update.go:96.61,99.2 2 0 +auth/ent/user_update.go:102.56,104.19 2 0 +auth/ent/user_update.go:104.19,106.3 1 0 +auth/ent/user_update.go:107.2,107.30 1 0 +auth/ent/user_update.go:111.62,114.2 2 0 +auth/ent/user_update.go:117.58,119.19 2 0 +auth/ent/user_update.go:119.19,121.3 1 0 +auth/ent/user_update.go:122.2,122.31 1 0 +auth/ent/user_update.go:126.48,128.2 1 0 +auth/ent/user_update.go:131.48,134.2 2 0 +auth/ent/user_update.go:137.64,140.2 2 0 +auth/ent/user_update.go:143.59,145.19 2 0 +auth/ent/user_update.go:145.19,147.3 1 0 +auth/ent/user_update.go:148.2,148.33 1 0 +auth/ent/user_update.go:152.49,155.2 2 0 +auth/ent/user_update.go:158.65,161.2 2 0 +auth/ent/user_update.go:164.61,166.19 2 0 +auth/ent/user_update.go:166.19,168.3 1 0 +auth/ent/user_update.go:169.2,169.34 1 0 +auth/ent/user_update.go:173.62,174.38 1 0 +auth/ent/user_update.go:174.38,176.3 1 0 +auth/ent/user_update.go:177.2,177.58 1 0 +auth/ent/user_update.go:181.54,183.16 2 0 +auth/ent/user_update.go:183.16,184.13 1 0 +auth/ent/user_update.go:186.2,186.17 1 0 +auth/ent/user_update.go:190.55,193.2 2 0 +auth/ent/user_update.go:196.50,197.37 1 0 +auth/ent/user_update.go:197.37,198.13 1 0 +auth/ent/user_update.go:203.40,204.43 1 0 +auth/ent/user_update.go:204.43,205.41 1 0 +auth/ent/user_update.go:205.41,207.4 1 0 +auth/ent/user_update.go:208.3,209.30 2 0 +auth/ent/user_update.go:211.2,211.12 1 0 +auth/ent/user_update.go:214.71,216.47 2 0 +auth/ent/user_update.go:216.47,217.50 1 0 +auth/ent/user_update.go:217.50,218.22 1 0 +auth/ent/user_update.go:218.22,220.5 1 0 +auth/ent/user_update.go:223.2,223.45 1 0 +auth/ent/user_update.go:223.45,225.3 1 0 +auth/ent/user_update.go:226.2,226.42 1 0 +auth/ent/user_update.go:226.42,228.3 1 0 +auth/ent/user_update.go:229.2,229.45 1 0 +auth/ent/user_update.go:229.45,231.3 1 0 +auth/ent/user_update.go:232.2,232.46 1 0 +auth/ent/user_update.go:232.46,234.3 1 0 +auth/ent/user_update.go:235.2,235.46 1 0 +auth/ent/user_update.go:235.46,237.3 1 0 +auth/ent/user_update.go:238.2,238.32 1 0 +auth/ent/user_update.go:238.32,250.3 2 0 +auth/ent/user_update.go:251.2,251.91 1 0 +auth/ent/user_update.go:251.91,262.27 2 0 +auth/ent/user_update.go:262.27,264.4 1 0 +auth/ent/user_update.go:265.3,265.54 1 0 +auth/ent/user_update.go:267.2,267.53 1 0 +auth/ent/user_update.go:267.53,278.27 2 0 +auth/ent/user_update.go:278.27,280.4 1 0 +auth/ent/user_update.go:281.3,281.50 1 0 +auth/ent/user_update.go:283.2,283.33 1 0 +auth/ent/user_update.go:283.33,295.3 2 0 +auth/ent/user_update.go:296.2,296.93 1 0 +auth/ent/user_update.go:296.93,307.27 2 0 +auth/ent/user_update.go:307.27,309.4 1 0 +auth/ent/user_update.go:310.3,310.54 1 0 +auth/ent/user_update.go:312.2,312.54 1 0 +auth/ent/user_update.go:312.54,323.27 2 0 +auth/ent/user_update.go:323.27,325.4 1 0 +auth/ent/user_update.go:326.3,326.50 1 0 +auth/ent/user_update.go:328.2,328.70 1 0 +auth/ent/user_update.go:328.70,329.49 1 0 +auth/ent/user_update.go:329.49,331.4 1 0 +auth/ent/user_update.go:331.9,331.45 1 0 +auth/ent/user_update.go:331.45,333.4 1 0 +auth/ent/user_update.go:334.3,334.16 1 0 +auth/ent/user_update.go:336.2,337.15 2 0 +auth/ent/user_update.go:349.64,352.2 2 0 +auth/ent/user_update.go:355.73,356.14 1 0 +auth/ent/user_update.go:356.14,358.3 1 0 +auth/ent/user_update.go:359.2,359.12 1 0 +auth/ent/user_update.go:363.61,366.2 2 0 +auth/ent/user_update.go:369.70,370.14 1 0 +auth/ent/user_update.go:370.14,372.3 1 0 +auth/ent/user_update.go:373.2,373.12 1 0 +auth/ent/user_update.go:377.64,380.2 2 0 +auth/ent/user_update.go:383.73,384.14 1 0 +auth/ent/user_update.go:384.14,386.3 1 0 +auth/ent/user_update.go:387.2,387.12 1 0 +auth/ent/user_update.go:391.68,394.2 2 0 +auth/ent/user_update.go:397.77,398.14 1 0 +auth/ent/user_update.go:398.14,400.3 1 0 +auth/ent/user_update.go:401.2,401.12 1 0 +auth/ent/user_update.go:405.68,408.2 2 0 +auth/ent/user_update.go:411.68,414.2 2 0 +auth/ent/user_update.go:417.63,419.19 2 0 +auth/ent/user_update.go:419.19,421.3 1 0 +auth/ent/user_update.go:422.2,422.31 1 0 +auth/ent/user_update.go:426.69,429.2 2 0 +auth/ent/user_update.go:432.65,434.19 2 0 +auth/ent/user_update.go:434.19,436.3 1 0 +auth/ent/user_update.go:437.2,437.32 1 0 +auth/ent/user_update.go:441.52,443.2 1 0 +auth/ent/user_update.go:446.55,449.2 2 0 +auth/ent/user_update.go:452.71,455.2 2 0 +auth/ent/user_update.go:458.66,460.19 2 0 +auth/ent/user_update.go:460.19,462.3 1 0 +auth/ent/user_update.go:463.2,463.34 1 0 +auth/ent/user_update.go:467.56,470.2 2 0 +auth/ent/user_update.go:473.72,476.2 2 0 +auth/ent/user_update.go:479.68,481.19 2 0 +auth/ent/user_update.go:481.19,483.3 1 0 +auth/ent/user_update.go:484.2,484.35 1 0 +auth/ent/user_update.go:488.70,491.2 2 0 +auth/ent/user_update.go:495.81,498.2 2 0 +auth/ent/user_update.go:501.68,502.39 1 0 +auth/ent/user_update.go:502.39,504.3 1 0 +auth/ent/user_update.go:505.2,505.61 1 0 +auth/ent/user_update.go:509.60,511.16 2 0 +auth/ent/user_update.go:511.16,512.13 1 0 +auth/ent/user_update.go:514.2,514.13 1 0 +auth/ent/user_update.go:518.59,521.2 2 0 +auth/ent/user_update.go:524.54,525.38 1 0 +auth/ent/user_update.go:525.38,526.13 1 0 +auth/ent/user_update.go:531.44,532.44 1 0 +auth/ent/user_update.go:532.44,533.41 1 0 +auth/ent/user_update.go:533.41,535.4 1 0 +auth/ent/user_update.go:536.3,537.31 2 0 +auth/ent/user_update.go:539.2,539.12 1 0 +auth/ent/user_update.go:542.81,545.9 3 0 +auth/ent/user_update.go:545.9,547.3 1 0 +auth/ent/user_update.go:548.2,549.43 2 0 +auth/ent/user_update.go:549.43,552.28 3 0 +auth/ent/user_update.go:552.28,553.28 1 0 +auth/ent/user_update.go:553.28,555.5 1 0 +auth/ent/user_update.go:556.4,556.25 1 0 +auth/ent/user_update.go:556.25,558.5 1 0 +auth/ent/user_update.go:561.2,561.48 1 0 +auth/ent/user_update.go:561.48,562.50 1 0 +auth/ent/user_update.go:562.50,563.22 1 0 +auth/ent/user_update.go:563.22,565.5 1 0 +auth/ent/user_update.go:568.2,568.46 1 0 +auth/ent/user_update.go:568.46,570.3 1 0 +auth/ent/user_update.go:571.2,571.43 1 0 +auth/ent/user_update.go:571.43,573.3 1 0 +auth/ent/user_update.go:574.2,574.46 1 0 +auth/ent/user_update.go:574.46,576.3 1 0 +auth/ent/user_update.go:577.2,577.47 1 0 +auth/ent/user_update.go:577.47,579.3 1 0 +auth/ent/user_update.go:580.2,580.47 1 0 +auth/ent/user_update.go:580.47,582.3 1 0 +auth/ent/user_update.go:583.2,583.33 1 0 +auth/ent/user_update.go:583.33,595.3 2 0 +auth/ent/user_update.go:596.2,596.93 1 0 +auth/ent/user_update.go:596.93,607.27 2 0 +auth/ent/user_update.go:607.27,609.4 1 0 +auth/ent/user_update.go:610.3,610.54 1 0 +auth/ent/user_update.go:612.2,612.54 1 0 +auth/ent/user_update.go:612.54,623.27 2 0 +auth/ent/user_update.go:623.27,625.4 1 0 +auth/ent/user_update.go:626.3,626.50 1 0 +auth/ent/user_update.go:628.2,628.34 1 0 +auth/ent/user_update.go:628.34,640.3 2 0 +auth/ent/user_update.go:641.2,641.95 1 0 +auth/ent/user_update.go:641.95,652.27 2 0 +auth/ent/user_update.go:652.27,654.4 1 0 +auth/ent/user_update.go:655.3,655.54 1 0 +auth/ent/user_update.go:657.2,657.55 1 0 +auth/ent/user_update.go:657.55,668.27 2 0 +auth/ent/user_update.go:668.27,670.4 1 0 +auth/ent/user_update.go:671.3,671.50 1 0 +auth/ent/user_update.go:673.2,676.67 4 0 +auth/ent/user_update.go:676.67,677.49 1 0 +auth/ent/user_update.go:677.49,679.4 1 0 +auth/ent/user_update.go:679.9,679.45 1 0 +auth/ent/user_update.go:679.45,681.4 1 0 +auth/ent/user_update.go:682.3,682.18 1 0 +auth/ent/user_update.go:684.2,685.19 2 0 +auth/ent/enttest/enttest.go:35.45,36.26 1 0 +auth/ent/enttest/enttest.go:36.26,38.3 1 0 +auth/ent/enttest/enttest.go:42.62,43.26 1 0 +auth/ent/enttest/enttest.go:43.26,45.3 1 0 +auth/ent/enttest/enttest.go:48.41,50.27 2 0 +auth/ent/enttest/enttest.go:50.27,52.3 1 0 +auth/ent/enttest/enttest.go:53.2,53.10 1 0 +auth/ent/enttest/enttest.go:57.86,60.16 3 0 +auth/ent/enttest/enttest.go:60.16,63.3 2 0 +auth/ent/enttest/enttest.go:64.2,65.10 2 0 +auth/ent/enttest/enttest.go:69.56,74.2 4 0 +auth/ent/enttest/enttest.go:75.59,77.16 2 0 +auth/ent/enttest/enttest.go:77.16,80.3 2 0 +auth/ent/enttest/enttest.go:81.2,81.97 1 0 +auth/ent/enttest/enttest.go:81.97,84.3 2 0 +auth/ent/schema/role.go:18.34,21.30 1 0 +auth/ent/schema/role.go:21.30,23.5 1 0 +auth/ent/schema/role.go:35.32,40.2 1 0 +auth/ent/schema/token.go:18.35,21.30 1 0 +auth/ent/schema/token.go:21.30,23.5 1 0 +auth/ent/schema/token.go:39.33,46.2 1 0 +auth/ent/schema/user.go:20.34,23.30 1 0 +auth/ent/schema/user.go:23.30,25.5 1 0 +auth/ent/schema/user.go:38.32,43.2 1 0 +auth/ent/schema/user.go:46.32,50.2 1 0 +auth/ent/schema/user.go:53.30,54.44 1 0 +auth/ent/schema/user.go:54.44,55.86 1 0 +auth/ent/schema/user.go:55.86,56.47 1 0 +auth/ent/schema/user.go:56.47,58.19 2 0 +auth/ent/schema/user.go:58.19,60.6 1 0 +auth/ent/schema/user.go:61.5,61.41 1 0 +auth/ent/schema/user.go:63.4,63.30 1 0 +auth/ent/hook/hook.go:16.82,17.41 1 0 +auth/ent/hook/hook.go:17.41,19.3 1 0 +auth/ent/hook/hook.go:20.2,20.84 1 0 +auth/ent/hook/hook.go:28.83,29.42 1 0 +auth/ent/hook/hook.go:29.42,31.3 1 0 +auth/ent/hook/hook.go:32.2,32.85 1 0 +auth/ent/hook/hook.go:40.82,41.41 1 0 +auth/ent/hook/hook.go:41.41,43.3 1 0 +auth/ent/hook/hook.go:44.2,44.84 1 0 +auth/ent/hook/hook.go:51.64,52.56 1 0 +auth/ent/hook/hook.go:52.56,53.40 1 0 +auth/ent/hook/hook.go:53.40,55.4 1 0 +auth/ent/hook/hook.go:56.3,56.29 1 0 +auth/ent/hook/hook.go:56.29,57.21 1 0 +auth/ent/hook/hook.go:57.21,59.5 1 0 +auth/ent/hook/hook.go:61.3,61.14 1 0 +auth/ent/hook/hook.go:66.63,67.56 1 0 +auth/ent/hook/hook.go:67.56,68.38 1 0 +auth/ent/hook/hook.go:68.38,70.4 1 0 +auth/ent/hook/hook.go:71.3,71.29 1 0 +auth/ent/hook/hook.go:71.29,72.20 1 0 +auth/ent/hook/hook.go:72.20,74.5 1 0 +auth/ent/hook/hook.go:76.3,76.15 1 0 +auth/ent/hook/hook.go:81.36,82.56 1 0 +auth/ent/hook/hook.go:82.56,84.3 1 0 +auth/ent/hook/hook.go:88.33,89.54 1 0 +auth/ent/hook/hook.go:89.54,91.3 1 0 +auth/ent/hook/hook.go:95.63,96.54 1 0 +auth/ent/hook/hook.go:96.54,97.48 1 0 +auth/ent/hook/hook.go:97.48,99.4 1 0 +auth/ent/hook/hook.go:100.3,100.32 1 0 +auth/ent/hook/hook.go:100.32,101.49 1 0 +auth/ent/hook/hook.go:101.49,103.5 1 0 +auth/ent/hook/hook.go:105.3,105.14 1 0 +auth/ent/hook/hook.go:110.65,111.54 1 0 +auth/ent/hook/hook.go:111.54,112.47 1 0 +auth/ent/hook/hook.go:112.47,114.4 1 0 +auth/ent/hook/hook.go:115.3,115.32 1 0 +auth/ent/hook/hook.go:115.32,116.48 1 0 +auth/ent/hook/hook.go:116.48,118.5 1 0 +auth/ent/hook/hook.go:120.3,120.14 1 0 +auth/ent/hook/hook.go:125.58,126.54 1 0 +auth/ent/hook/hook.go:126.54,127.43 1 0 +auth/ent/hook/hook.go:127.43,129.4 1 0 +auth/ent/hook/hook.go:130.3,130.32 1 0 +auth/ent/hook/hook.go:130.32,131.44 1 0 +auth/ent/hook/hook.go:131.44,133.5 1 0 +auth/ent/hook/hook.go:135.3,135.14 1 0 +auth/ent/hook/hook.go:142.47,143.44 1 0 +auth/ent/hook/hook.go:143.44,144.86 1 0 +auth/ent/hook/hook.go:144.86,145.20 1 0 +auth/ent/hook/hook.go:145.20,147.5 1 0 +auth/ent/hook/hook.go:148.4,148.30 1 0 +auth/ent/hook/hook.go:156.42,158.2 1 0 +auth/ent/hook/hook.go:163.46,165.2 1 0 +auth/ent/hook/hook.go:168.37,169.39 1 0 +auth/ent/hook/hook.go:169.39,170.80 1 0 +auth/ent/hook/hook.go:170.80,172.4 1 0 +auth/ent/hook/hook.go:183.33,186.2 2 0 +auth/ent/hook/hook.go:195.40,197.2 1 0 +auth/ent/hook/hook.go:200.32,201.47 1 0 +auth/ent/hook/hook.go:201.47,202.42 1 0 +auth/ent/hook/hook.go:202.42,204.4 1 0 +auth/ent/hook/hook.go:205.3,205.17 1 0 +auth/ent/hook/hook.go:211.48,216.2 4 0 +auth/ent/hook/hook.go:220.42,222.2 1 0 +auth/ent/runtime/runtime.go:16.13,71.2 31 0 +auth/ent/migrate/migrate.go:41.44,41.72 1 0 +auth/ent/migrate/migrate.go:44.82,46.2 1 0 +auth/ent/migrate/migrate.go:49.105,51.16 2 0 +auth/ent/migrate/migrate.go:51.16,53.3 1 0 +auth/ent/migrate/migrate.go:54.2,54.39 1 0 +auth/ent/migrate/migrate.go:62.96,64.2 1 0 +auth/ent/migrate/schema.go:99.13,103.2 3 0 +auth/ent/token/token.go:61.38,62.25 1 0 +auth/ent/token/token.go:62.25,63.27 1 0 +auth/ent/token/token.go:63.27,65.4 1 0 +auth/ent/token/token.go:67.2,67.29 1 0 +auth/ent/token/token.go:67.29,68.31 1 0 +auth/ent/token/token.go:68.31,70.4 1 0 +auth/ent/token/token.go:72.2,72.14 1 0 +auth/ent/token/token.go:97.35,99.2 1 0 +auth/ent/token/token.go:102.38,103.15 1 0 +auth/ent/token/token.go:104.31,105.13 1 0 +auth/ent/token/token.go:106.10,107.75 1 0 +auth/ent/token/token.go:115.52,117.2 1 0 +auth/ent/token/token.go:120.55,122.2 1 0 +auth/ent/token/token.go:125.54,127.2 1 0 +auth/ent/token/token.go:130.59,132.2 1 0 +auth/ent/token/token.go:135.57,137.2 1 0 +auth/ent/token/token.go:140.59,142.2 1 0 +auth/ent/token/token.go:145.59,147.2 1 0 +auth/ent/token/token.go:150.73,151.31 1 0 +auth/ent/token/token.go:151.31,153.3 1 0 +auth/ent/token/token.go:155.35,161.2 1 0 +auth/ent/token/where.go:14.36,16.2 1 0 +auth/ent/token/where.go:19.38,21.2 1 0 +auth/ent/token/where.go:24.39,26.2 1 0 +auth/ent/token/where.go:29.42,31.2 1 0 +auth/ent/token/where.go:34.45,36.2 1 0 +auth/ent/token/where.go:39.38,41.2 1 0 +auth/ent/token/where.go:44.39,46.2 1 0 +auth/ent/token/where.go:49.38,51.2 1 0 +auth/ent/token/where.go:54.39,56.2 1 0 +auth/ent/token/where.go:59.45,61.2 1 0 +auth/ent/token/where.go:64.48,66.2 1 0 +auth/ent/token/where.go:69.38,71.2 1 0 +auth/ent/token/where.go:74.45,76.2 1 0 +auth/ent/token/where.go:79.38,81.2 1 0 +auth/ent/token/where.go:84.45,86.2 1 0 +auth/ent/token/where.go:89.45,91.2 1 0 +auth/ent/token/where.go:94.40,96.2 1 0 +auth/ent/token/where.go:99.41,101.2 1 0 +auth/ent/token/where.go:104.44,106.2 1 0 +auth/ent/token/where.go:109.47,111.2 1 0 +auth/ent/token/where.go:114.40,116.2 1 0 +auth/ent/token/where.go:119.41,121.2 1 0 +auth/ent/token/where.go:124.40,126.2 1 0 +auth/ent/token/where.go:129.41,131.2 1 0 +auth/ent/token/where.go:134.46,136.2 1 0 +auth/ent/token/where.go:139.47,141.2 1 0 +auth/ent/token/where.go:144.47,146.2 1 0 +auth/ent/token/where.go:149.47,151.2 1 0 +auth/ent/token/where.go:154.50,156.2 1 0 +auth/ent/token/where.go:159.37,161.2 1 0 +auth/ent/token/where.go:164.38,166.2 1 0 +auth/ent/token/where.go:169.41,171.2 1 0 +auth/ent/token/where.go:174.44,176.2 1 0 +auth/ent/token/where.go:179.47,181.2 1 0 +auth/ent/token/where.go:184.48,186.2 1 0 +auth/ent/token/where.go:189.51,191.2 1 0 +auth/ent/token/where.go:194.54,196.2 1 0 +auth/ent/token/where.go:199.47,201.2 1 0 +auth/ent/token/where.go:204.48,206.2 1 0 +auth/ent/token/where.go:209.47,211.2 1 0 +auth/ent/token/where.go:214.48,216.2 1 0 +auth/ent/token/where.go:219.40,221.2 1 0 +auth/ent/token/where.go:224.41,226.2 1 0 +auth/ent/token/where.go:229.47,231.2 1 0 +auth/ent/token/where.go:234.48,236.2 1 0 +auth/ent/token/where.go:239.51,241.2 1 0 +auth/ent/token/where.go:244.54,246.2 1 0 +auth/ent/token/where.go:249.47,251.2 1 0 +auth/ent/token/where.go:254.48,256.2 1 0 +auth/ent/token/where.go:259.47,261.2 1 0 +auth/ent/token/where.go:264.48,266.2 1 0 +auth/ent/token/where.go:269.47,271.2 1 0 +auth/ent/token/where.go:274.48,276.2 1 0 +auth/ent/token/where.go:279.51,281.2 1 0 +auth/ent/token/where.go:284.54,286.2 1 0 +auth/ent/token/where.go:289.47,291.2 1 0 +auth/ent/token/where.go:294.48,296.2 1 0 +auth/ent/token/where.go:299.47,301.2 1 0 +auth/ent/token/where.go:304.48,306.2 1 0 +auth/ent/token/where.go:309.32,310.47 1 0 +auth/ent/token/where.go:310.47,316.3 2 0 +auth/ent/token/where.go:320.59,321.47 1 0 +auth/ent/token/where.go:321.47,323.60 2 0 +auth/ent/token/where.go:323.60,324.28 1 0 +auth/ent/token/where.go:324.28,326.5 1 0 +auth/ent/token/where.go:332.57,334.2 1 0 +auth/ent/token/where.go:337.56,339.2 1 0 +auth/ent/token/where.go:342.45,344.2 1 0 +auth/ent/user/user.go:65.38,66.25 1 0 +auth/ent/user/user.go:66.25,67.27 1 0 +auth/ent/user/user.go:67.27,69.4 1 0 +auth/ent/user/user.go:71.2,71.14 1 0 +auth/ent/user/user.go:95.52,97.2 1 0 +auth/ent/user/user.go:100.58,102.2 1 0 +auth/ent/user/user.go:105.55,107.2 1 0 +auth/ent/user/user.go:110.58,112.2 1 0 +auth/ent/user/user.go:115.59,117.2 1 0 +auth/ent/user/user.go:120.59,122.2 1 0 +auth/ent/user/user.go:125.60,126.31 1 0 +auth/ent/user/user.go:126.31,128.3 1 0 +auth/ent/user/user.go:132.70,133.31 1 0 +auth/ent/user/user.go:133.31,135.3 1 0 +auth/ent/user/user.go:139.61,140.31 1 0 +auth/ent/user/user.go:140.31,142.3 1 0 +auth/ent/user/user.go:146.71,147.31 1 0 +auth/ent/user/user.go:147.31,149.3 1 0 +auth/ent/user/user.go:151.36,157.2 1 0 +auth/ent/user/user.go:158.37,164.2 1 0 +auth/ent/user/where.go:14.35,16.2 1 0 +auth/ent/user/where.go:19.37,21.2 1 0 +auth/ent/user/where.go:24.38,26.2 1 0 +auth/ent/user/where.go:29.41,31.2 1 0 +auth/ent/user/where.go:34.44,36.2 1 0 +auth/ent/user/where.go:39.37,41.2 1 0 +auth/ent/user/where.go:44.38,46.2 1 0 +auth/ent/user/where.go:49.37,51.2 1 0 +auth/ent/user/where.go:54.38,56.2 1 0 +auth/ent/user/where.go:59.44,61.2 1 0 +auth/ent/user/where.go:64.47,66.2 1 0 +auth/ent/user/where.go:69.40,71.2 1 0 +auth/ent/user/where.go:74.37,76.2 1 0 +auth/ent/user/where.go:79.40,81.2 1 0 +auth/ent/user/where.go:84.44,86.2 1 0 +auth/ent/user/where.go:89.44,91.2 1 0 +auth/ent/user/where.go:94.42,96.2 1 0 +auth/ent/user/where.go:99.43,101.2 1 0 +auth/ent/user/where.go:104.46,106.2 1 0 +auth/ent/user/where.go:109.49,111.2 1 0 +auth/ent/user/where.go:114.42,116.2 1 0 +auth/ent/user/where.go:119.43,121.2 1 0 +auth/ent/user/where.go:124.42,126.2 1 0 +auth/ent/user/where.go:129.43,131.2 1 0 +auth/ent/user/where.go:134.48,136.2 1 0 +auth/ent/user/where.go:139.49,141.2 1 0 +auth/ent/user/where.go:144.49,146.2 1 0 +auth/ent/user/where.go:149.49,151.2 1 0 +auth/ent/user/where.go:154.52,156.2 1 0 +auth/ent/user/where.go:159.39,161.2 1 0 +auth/ent/user/where.go:164.40,166.2 1 0 +auth/ent/user/where.go:169.43,171.2 1 0 +auth/ent/user/where.go:174.46,176.2 1 0 +auth/ent/user/where.go:179.39,181.2 1 0 +auth/ent/user/where.go:184.40,186.2 1 0 +auth/ent/user/where.go:189.39,191.2 1 0 +auth/ent/user/where.go:194.40,196.2 1 0 +auth/ent/user/where.go:199.45,201.2 1 0 +auth/ent/user/where.go:204.46,206.2 1 0 +auth/ent/user/where.go:209.46,211.2 1 0 +auth/ent/user/where.go:214.46,216.2 1 0 +auth/ent/user/where.go:219.49,221.2 1 0 +auth/ent/user/where.go:224.42,226.2 1 0 +auth/ent/user/where.go:229.43,231.2 1 0 +auth/ent/user/where.go:234.46,236.2 1 0 +auth/ent/user/where.go:239.49,241.2 1 0 +auth/ent/user/where.go:244.42,246.2 1 0 +auth/ent/user/where.go:249.43,251.2 1 0 +auth/ent/user/where.go:254.42,256.2 1 0 +auth/ent/user/where.go:259.43,261.2 1 0 +auth/ent/user/where.go:264.48,266.2 1 0 +auth/ent/user/where.go:269.49,271.2 1 0 +auth/ent/user/where.go:274.49,276.2 1 0 +auth/ent/user/where.go:279.49,281.2 1 0 +auth/ent/user/where.go:284.52,286.2 1 0 +auth/ent/user/where.go:289.46,291.2 1 0 +auth/ent/user/where.go:294.47,296.2 1 0 +auth/ent/user/where.go:299.50,301.2 1 0 +auth/ent/user/where.go:304.53,306.2 1 0 +auth/ent/user/where.go:309.46,311.2 1 0 +auth/ent/user/where.go:314.47,316.2 1 0 +auth/ent/user/where.go:319.46,321.2 1 0 +auth/ent/user/where.go:324.47,326.2 1 0 +auth/ent/user/where.go:329.46,331.2 1 0 +auth/ent/user/where.go:334.47,336.2 1 0 +auth/ent/user/where.go:339.50,341.2 1 0 +auth/ent/user/where.go:344.53,346.2 1 0 +auth/ent/user/where.go:349.46,351.2 1 0 +auth/ent/user/where.go:354.47,356.2 1 0 +auth/ent/user/where.go:359.46,361.2 1 0 +auth/ent/user/where.go:364.47,366.2 1 0 +auth/ent/user/where.go:369.32,370.46 1 0 +auth/ent/user/where.go:370.46,376.3 2 0 +auth/ent/user/where.go:380.59,381.46 1 0 +auth/ent/user/where.go:381.46,383.60 2 0 +auth/ent/user/where.go:383.60,384.28 1 0 +auth/ent/user/where.go:384.28,386.5 1 0 +auth/ent/user/where.go:392.33,393.46 1 0 +auth/ent/user/where.go:393.46,399.3 2 0 +auth/ent/user/where.go:403.61,404.46 1 0 +auth/ent/user/where.go:404.46,406.60 2 0 +auth/ent/user/where.go:406.60,407.28 1 0 +auth/ent/user/where.go:407.28,409.5 1 0 +auth/ent/user/where.go:415.55,417.2 1 0 +auth/ent/user/where.go:420.54,422.2 1 0 +auth/ent/user/where.go:425.43,427.2 1 0 +auth/ent/role/role.go:52.38,53.25 1 0 +auth/ent/role/role.go:53.25,54.27 1 0 +auth/ent/role/role.go:54.27,56.4 1 0 +auth/ent/role/role.go:58.2,58.14 1 0 +auth/ent/role/role.go:76.52,78.2 1 0 +auth/ent/role/role.go:81.54,83.2 1 0 +auth/ent/role/role.go:86.59,88.2 1 0 +auth/ent/role/role.go:91.59,93.2 1 0 +auth/ent/role/role.go:96.60,97.31 1 0 +auth/ent/role/role.go:97.31,99.3 1 0 +auth/ent/role/role.go:103.70,104.31 1 0 +auth/ent/role/role.go:104.31,106.3 1 0 +auth/ent/role/role.go:108.36,114.2 1 0 +auth/ent/role/where.go:14.35,16.2 1 0 +auth/ent/role/where.go:19.37,21.2 1 0 +auth/ent/role/where.go:24.38,26.2 1 0 +auth/ent/role/where.go:29.41,31.2 1 0 +auth/ent/role/where.go:34.44,36.2 1 0 +auth/ent/role/where.go:39.37,41.2 1 0 +auth/ent/role/where.go:44.38,46.2 1 0 +auth/ent/role/where.go:49.37,51.2 1 0 +auth/ent/role/where.go:54.38,56.2 1 0 +auth/ent/role/where.go:59.44,61.2 1 0 +auth/ent/role/where.go:64.47,66.2 1 0 +auth/ent/role/where.go:69.36,71.2 1 0 +auth/ent/role/where.go:74.44,76.2 1 0 +auth/ent/role/where.go:79.44,81.2 1 0 +auth/ent/role/where.go:84.38,86.2 1 0 +auth/ent/role/where.go:89.39,91.2 1 0 +auth/ent/role/where.go:94.42,96.2 1 0 +auth/ent/role/where.go:99.45,101.2 1 0 +auth/ent/role/where.go:104.38,106.2 1 0 +auth/ent/role/where.go:109.39,111.2 1 0 +auth/ent/role/where.go:114.38,116.2 1 0 +auth/ent/role/where.go:119.39,121.2 1 0 +auth/ent/role/where.go:124.44,126.2 1 0 +auth/ent/role/where.go:129.45,131.2 1 0 +auth/ent/role/where.go:134.45,136.2 1 0 +auth/ent/role/where.go:139.45,141.2 1 0 +auth/ent/role/where.go:144.48,146.2 1 0 +auth/ent/role/where.go:149.46,151.2 1 0 +auth/ent/role/where.go:154.47,156.2 1 0 +auth/ent/role/where.go:159.50,161.2 1 0 +auth/ent/role/where.go:164.53,166.2 1 0 +auth/ent/role/where.go:169.46,171.2 1 0 +auth/ent/role/where.go:174.47,176.2 1 0 +auth/ent/role/where.go:179.46,181.2 1 0 +auth/ent/role/where.go:184.47,186.2 1 0 +auth/ent/role/where.go:189.46,191.2 1 0 +auth/ent/role/where.go:194.47,196.2 1 0 +auth/ent/role/where.go:199.50,201.2 1 0 +auth/ent/role/where.go:204.53,206.2 1 0 +auth/ent/role/where.go:209.46,211.2 1 0 +auth/ent/role/where.go:214.47,216.2 1 0 +auth/ent/role/where.go:219.46,221.2 1 0 +auth/ent/role/where.go:224.47,226.2 1 0 +auth/ent/role/where.go:229.32,230.46 1 0 +auth/ent/role/where.go:230.46,236.3 2 0 +auth/ent/role/where.go:240.59,241.46 1 0 +auth/ent/role/where.go:241.46,243.60 2 0 +auth/ent/role/where.go:243.60,244.28 1 0 +auth/ent/role/where.go:244.28,246.5 1 0 +auth/ent/role/where.go:252.55,254.2 1 0 +auth/ent/role/where.go:257.54,259.2 1 0 +auth/ent/role/where.go:262.43,264.2 1 0 +auth/internal/auth/main.go:19.13,21.16 2 0 +auth/internal/auth/main.go:21.16,23.3 1 0 +auth/internal/auth/main.go:26.2,29.16 2 0 +auth/internal/auth/main.go:29.16,31.3 1 0 +auth/internal/auth/main.go:32.2,39.16 6 0 +auth/internal/auth/main.go:39.16,41.3 1 0 +auth/internal/auth/main.go:43.2,60.46 7 0 +auth/internal/auth/main.go:60.46,62.3 1 0 +auth/internal/authz/main.go:18.13,20.16 2 0 +auth/internal/authz/main.go:20.16,22.3 1 0 +auth/internal/authz/main.go:25.2,28.16 2 0 +auth/internal/authz/main.go:28.16,30.3 1 0 +auth/internal/authz/main.go:31.2,38.16 6 0 +auth/internal/authz/main.go:38.16,40.3 1 0 +auth/internal/authz/main.go:41.2,57.46 7 0 +auth/internal/authz/main.go:57.46,59.3 1 0 +auth/internal/auth/service/auth_service.go:143.155,150.2 1 0 +auth/internal/auth/service/auth_service.go:152.99,154.16 2 0 +auth/internal/auth/service/auth_service.go:154.16,156.3 1 0 +auth/internal/auth/service/auth_service.go:158.2,158.80 1 0 +auth/internal/auth/service/auth_service.go:158.80,160.3 1 0 +auth/internal/auth/service/auth_service.go:162.2,163.16 2 0 +auth/internal/auth/service/auth_service.go:163.16,165.3 1 0 +auth/internal/auth/service/auth_service.go:167.2,168.16 2 0 +auth/internal/auth/service/auth_service.go:168.16,170.3 1 0 +auth/internal/auth/service/auth_service.go:173.2,174.16 2 0 +auth/internal/auth/service/auth_service.go:174.16,176.3 1 0 +auth/internal/auth/service/auth_service.go:178.2,179.16 2 0 +auth/internal/auth/service/auth_service.go:179.16,181.3 1 0 +auth/internal/auth/service/auth_service.go:183.2,187.8 1 0 +auth/internal/auth/service/auth_service.go:190.98,191.70 1 0 +auth/internal/auth/service/auth_service.go:191.70,193.3 1 0 +auth/internal/auth/service/auth_service.go:194.2,194.30 1 0 +auth/internal/auth/service/auth_service.go:197.120,199.16 2 0 +auth/internal/auth/service/auth_service.go:199.16,201.3 1 0 +auth/internal/auth/service/auth_service.go:203.2,203.84 1 0 +auth/internal/auth/service/auth_service.go:203.84,205.3 1 0 +auth/internal/auth/service/auth_service.go:207.2,208.16 2 0 +auth/internal/auth/service/auth_service.go:208.16,210.3 1 0 +auth/internal/auth/service/auth_service.go:212.2,213.16 2 0 +auth/internal/auth/service/auth_service.go:213.16,215.3 1 0 +auth/internal/auth/service/auth_service.go:217.2,218.16 2 0 +auth/internal/auth/service/auth_service.go:218.16,220.3 1 0 +auth/internal/auth/service/auth_service.go:223.2,223.71 1 0 +auth/internal/auth/service/auth_service.go:223.71,225.3 1 0 +auth/internal/auth/service/auth_service.go:228.2,229.16 2 0 +auth/internal/auth/service/auth_service.go:229.16,231.3 1 0 +auth/internal/auth/service/auth_service.go:233.2,234.16 2 0 +auth/internal/auth/service/auth_service.go:234.16,236.3 1 0 +auth/internal/auth/service/auth_service.go:238.2,242.8 1 0 +auth/internal/auth/service/auth_service.go:245.123,247.16 2 0 +auth/internal/auth/service/auth_service.go:247.16,249.3 1 0 +auth/internal/auth/service/auth_service.go:251.2,251.57 1 0 +auth/internal/auth/service/auth_service.go:251.57,253.3 1 0 +auth/internal/auth/service/auth_service.go:255.2,256.16 2 0 +auth/internal/auth/service/auth_service.go:256.16,258.3 1 0 +auth/internal/auth/service/auth_service.go:260.2,266.8 1 0 +auth/internal/auth/service/auth_service.go:269.120,271.25 2 0 +auth/internal/auth/service/auth_service.go:271.25,273.3 1 0 +auth/internal/auth/service/auth_service.go:275.2,276.25 2 0 +auth/internal/auth/service/auth_service.go:276.25,278.3 1 0 +auth/internal/auth/service/auth_service.go:280.2,281.16 2 0 +auth/internal/auth/service/auth_service.go:281.16,283.3 1 0 +auth/internal/auth/service/auth_service.go:285.2,291.58 2 0 +auth/internal/auth/service/auth_service.go:291.58,293.3 1 0 +auth/internal/auth/service/auth_service.go:295.2,301.8 1 0 +auth/internal/auth/service/auth_service.go:304.114,306.16 2 0 +auth/internal/auth/service/auth_service.go:306.16,308.3 1 0 +auth/internal/auth/service/auth_service.go:310.2,310.25 1 0 +auth/internal/auth/service/auth_service.go:310.25,312.3 1 0 +auth/internal/auth/service/auth_service.go:313.2,313.22 1 0 +auth/internal/auth/service/auth_service.go:313.22,315.3 1 0 +auth/internal/auth/service/auth_service.go:316.2,316.25 1 0 +auth/internal/auth/service/auth_service.go:316.25,318.17 2 0 +auth/internal/auth/service/auth_service.go:318.17,320.4 1 0 +auth/internal/auth/service/auth_service.go:321.3,321.41 1 0 +auth/internal/auth/service/auth_service.go:324.2,324.58 1 0 +auth/internal/auth/service/auth_service.go:324.58,326.3 1 0 +auth/internal/auth/service/auth_service.go:329.2,329.70 1 0 +auth/internal/auth/service/auth_service.go:329.70,331.3 1 0 +auth/internal/auth/service/auth_service.go:333.2,339.8 1 0 +auth/internal/auth/service/auth_service.go:342.106,344.73 1 0 +auth/internal/auth/service/auth_service.go:344.73,346.3 1 0 +auth/internal/auth/service/auth_service.go:348.2,348.59 1 0 +auth/internal/auth/service/auth_service.go:348.59,350.3 1 0 +auth/internal/auth/service/auth_service.go:352.2,352.30 1 0 +auth/internal/auth/service/auth_service.go:355.105,357.16 2 0 +auth/internal/auth/service/auth_service.go:357.16,359.3 1 0 +auth/internal/auth/service/auth_service.go:361.2,367.8 1 0 +auth/internal/auth/service/auth_service.go:370.67,379.2 3 0 +auth/internal/auth/service/auth_service.go:381.76,389.2 3 0 +auth/internal/authz/service/authz_service.go:179.110,184.2 1 0 +auth/internal/authz/service/authz_service.go:186.130,188.16 2 0 +auth/internal/authz/service/authz_service.go:188.16,190.3 1 0 +auth/internal/authz/service/authz_service.go:192.2,192.29 1 0 +auth/internal/authz/service/authz_service.go:192.29,193.74 1 0 +auth/internal/authz/service/authz_service.go:193.74,195.4 1 0 +auth/internal/authz/service/authz_service.go:198.2,198.63 1 0 +auth/internal/authz/service/authz_service.go:201.121,203.16 2 0 +auth/internal/authz/service/authz_service.go:203.16,205.3 1 0 +auth/internal/authz/service/authz_service.go:207.2,208.29 2 0 +auth/internal/authz/service/authz_service.go:208.29,214.3 1 0 +auth/internal/authz/service/authz_service.go:216.2,216.54 1 0 +auth/internal/authz/service/authz_service.go:219.119,220.81 1 0 +auth/internal/authz/service/authz_service.go:220.81,222.3 1 0 +auth/internal/authz/service/authz_service.go:223.2,223.30 1 0 +auth/internal/authz/service/authz_service.go:226.123,227.83 1 0 +auth/internal/authz/service/authz_service.go:227.83,229.3 1 0 +auth/internal/authz/service/authz_service.go:230.2,230.30 1 0 +auth/internal/authz/service/authz_service.go:233.115,238.39 2 0 +auth/internal/authz/service/authz_service.go:238.39,240.3 1 0 +auth/internal/authz/service/authz_service.go:242.2,244.58 2 0 +auth/internal/authz/service/authz_service.go:244.58,246.3 1 0 +auth/internal/authz/service/authz_service.go:248.2,254.8 1 0 +auth/internal/authz/service/authz_service.go:257.115,259.16 2 0 +auth/internal/authz/service/authz_service.go:259.16,261.3 1 0 +auth/internal/authz/service/authz_service.go:263.2,263.21 1 0 +auth/internal/authz/service/authz_service.go:263.21,265.3 1 0 +auth/internal/authz/service/authz_service.go:266.2,266.28 1 0 +auth/internal/authz/service/authz_service.go:266.28,268.40 2 0 +auth/internal/authz/service/authz_service.go:268.40,270.4 1 0 +auth/internal/authz/service/authz_service.go:273.2,273.58 1 0 +auth/internal/authz/service/authz_service.go:273.58,275.3 1 0 +auth/internal/authz/service/authz_service.go:277.2,283.8 1 0 +auth/internal/authz/service/authz_service.go:286.107,287.59 1 0 +auth/internal/authz/service/authz_service.go:287.59,290.3 1 0 +auth/internal/authz/service/authz_service.go:292.2,292.30 1 0 +auth/internal/authz/service/authz_service.go:295.106,297.16 2 0 +auth/internal/authz/service/authz_service.go:297.16,299.3 1 0 +auth/internal/authz/service/authz_service.go:301.2,307.8 1 0 +auth/internal/authz/service/authz_service.go:310.112,312.16 2 0 +auth/internal/authz/service/authz_service.go:312.16,314.3 1 0 +auth/internal/authz/service/authz_service.go:315.2,317.16 3 0 +auth/internal/authz/service/authz_service.go:317.16,319.3 1 0 +auth/internal/authz/service/authz_service.go:321.2,322.29 2 0 +auth/internal/authz/service/authz_service.go:322.29,328.3 1 0 +auth/internal/authz/service/authz_service.go:330.2,333.8 1 0 +auth/internal/authz/service/authz_service.go:336.125,338.78 2 0 +auth/internal/authz/service/authz_service.go:338.78,340.3 1 0 +auth/internal/authz/service/authz_service.go:341.2,341.30 1 0 +auth/internal/authz/service/authz_service.go:344.135,346.81 2 0 +auth/internal/authz/service/authz_service.go:346.81,348.3 1 0 +auth/internal/authz/service/authz_service.go:349.2,349.30 1 0 +auth/internal/authz/service/authz_service.go:352.66,354.40 2 0 +auth/internal/authz/service/authz_service.go:354.40,355.25 1 0 +auth/internal/authz/service/authz_service.go:355.25,357.4 1 0 +auth/internal/authz/service/authz_service.go:359.2,359.14 1 0 +auth/internal/db/db.go:36.50,39.16 2 0 +auth/internal/db/db.go:39.16,41.3 1 0 +auth/internal/db/db.go:44.2,45.16 2 0 +auth/internal/db/db.go:45.16,47.3 1 0 +auth/internal/db/db.go:49.2,57.20 2 0 +auth/internal/db/db.go:68.57,70.16 2 0 +auth/internal/db/db.go:70.16,72.3 1 0 +auth/internal/db/db.go:74.2,75.29 2 0 +auth/internal/db/db.go:75.29,76.59 1 0 +auth/internal/db/db.go:76.59,77.60 1 0 +auth/internal/db/db.go:77.60,79.5 1 0 +auth/internal/db/db.go:83.2,83.23 1 0 +auth/internal/db/db.go:83.23,85.3 1 0 +auth/internal/db/db.go:87.2,88.16 2 0 +auth/internal/db/db.go:88.16,90.3 1 0 +auth/internal/db/db.go:92.2,92.29 1 0 +auth/internal/db/db.go:103.59,106.16 2 0 +auth/internal/db/db.go:106.16,108.3 1 0 +auth/internal/db/db.go:111.2,114.64 2 0 +auth/internal/db/db.go:114.64,116.3 1 0 +auth/internal/db/db.go:118.2,118.20 1 0 +auth/pb/auth.pb.go:34.32,36.29 2 0 +auth/pb/auth.pb.go:36.29,40.3 3 0 +auth/pb/auth.pb.go:43.40,45.2 1 0 +auth/pb/auth.pb.go:47.38,47.39 0 0 +auth/pb/auth.pb.go:49.60,51.41 2 0 +auth/pb/auth.pb.go:51.41,53.34 2 0 +auth/pb/auth.pb.go:53.34,55.4 1 0 +auth/pb/auth.pb.go:56.3,56.12 1 0 +auth/pb/auth.pb.go:58.2,58.24 1 0 +auth/pb/auth.pb.go:62.51,64.2 1 0 +auth/pb/auth.pb.go:66.45,67.14 1 0 +auth/pb/auth.pb.go:67.14,69.3 1 0 +auth/pb/auth.pb.go:70.2,70.11 1 0 +auth/pb/auth.pb.go:73.45,74.14 1 0 +auth/pb/auth.pb.go:74.14,76.3 1 0 +auth/pb/auth.pb.go:77.2,77.11 1 0 +auth/pb/auth.pb.go:90.33,92.29 2 0 +auth/pb/auth.pb.go:92.29,96.3 3 0 +auth/pb/auth.pb.go:99.41,101.2 1 0 +auth/pb/auth.pb.go:103.39,103.40 0 0 +auth/pb/auth.pb.go:105.61,107.41 2 0 +auth/pb/auth.pb.go:107.41,109.34 2 0 +auth/pb/auth.pb.go:109.34,111.4 1 0 +auth/pb/auth.pb.go:112.3,112.12 1 0 +auth/pb/auth.pb.go:114.2,114.24 1 0 +auth/pb/auth.pb.go:118.52,120.2 1 0 +auth/pb/auth.pb.go:122.49,123.14 1 0 +auth/pb/auth.pb.go:123.14,125.3 1 0 +auth/pb/auth.pb.go:126.2,126.11 1 0 +auth/pb/auth.pb.go:129.50,130.14 1 0 +auth/pb/auth.pb.go:130.14,132.3 1 0 +auth/pb/auth.pb.go:133.2,133.11 1 0 +auth/pb/auth.pb.go:136.46,137.14 1 0 +auth/pb/auth.pb.go:137.14,139.3 1 0 +auth/pb/auth.pb.go:140.2,140.10 1 0 +auth/pb/auth.pb.go:151.33,153.29 2 0 +auth/pb/auth.pb.go:153.29,157.3 3 0 +auth/pb/auth.pb.go:160.41,162.2 1 0 +auth/pb/auth.pb.go:164.39,164.40 0 0 +auth/pb/auth.pb.go:166.61,168.41 2 0 +auth/pb/auth.pb.go:168.41,170.34 2 0 +auth/pb/auth.pb.go:170.34,172.4 1 0 +auth/pb/auth.pb.go:173.3,173.12 1 0 +auth/pb/auth.pb.go:175.2,175.24 1 0 +auth/pb/auth.pb.go:179.52,181.2 1 0 +auth/pb/auth.pb.go:183.49,184.14 1 0 +auth/pb/auth.pb.go:184.14,186.3 1 0 +auth/pb/auth.pb.go:187.2,187.11 1 0 +auth/pb/auth.pb.go:198.39,200.29 2 0 +auth/pb/auth.pb.go:200.29,204.3 3 0 +auth/pb/auth.pb.go:207.47,209.2 1 0 +auth/pb/auth.pb.go:211.45,211.46 0 0 +auth/pb/auth.pb.go:213.67,215.41 2 0 +auth/pb/auth.pb.go:215.41,217.34 2 0 +auth/pb/auth.pb.go:217.34,219.4 1 0 +auth/pb/auth.pb.go:220.3,220.12 1 0 +auth/pb/auth.pb.go:222.2,222.24 1 0 +auth/pb/auth.pb.go:226.58,228.2 1 0 +auth/pb/auth.pb.go:230.56,231.14 1 0 +auth/pb/auth.pb.go:231.14,233.3 1 0 +auth/pb/auth.pb.go:234.2,234.11 1 0 +auth/pb/auth.pb.go:247.40,249.29 2 0 +auth/pb/auth.pb.go:249.29,253.3 3 0 +auth/pb/auth.pb.go:256.48,258.2 1 0 +auth/pb/auth.pb.go:260.46,260.47 0 0 +auth/pb/auth.pb.go:262.68,264.41 2 0 +auth/pb/auth.pb.go:264.41,266.34 2 0 +auth/pb/auth.pb.go:266.34,268.4 1 0 +auth/pb/auth.pb.go:269.3,269.12 1 0 +auth/pb/auth.pb.go:271.2,271.24 1 0 +auth/pb/auth.pb.go:275.59,277.2 1 0 +auth/pb/auth.pb.go:279.56,280.14 1 0 +auth/pb/auth.pb.go:280.14,282.3 1 0 +auth/pb/auth.pb.go:283.2,283.11 1 0 +auth/pb/auth.pb.go:286.57,287.14 1 0 +auth/pb/auth.pb.go:287.14,289.3 1 0 +auth/pb/auth.pb.go:290.2,290.11 1 0 +auth/pb/auth.pb.go:293.53,294.14 1 0 +auth/pb/auth.pb.go:294.14,296.3 1 0 +auth/pb/auth.pb.go:297.2,297.10 1 0 +auth/pb/auth.pb.go:308.40,310.29 2 0 +auth/pb/auth.pb.go:310.29,314.3 3 0 +auth/pb/auth.pb.go:317.48,319.2 1 0 +auth/pb/auth.pb.go:321.46,321.47 0 0 +auth/pb/auth.pb.go:323.68,325.41 2 0 +auth/pb/auth.pb.go:325.41,327.34 2 0 +auth/pb/auth.pb.go:327.34,329.4 1 0 +auth/pb/auth.pb.go:330.3,330.12 1 0 +auth/pb/auth.pb.go:332.2,332.24 1 0 +auth/pb/auth.pb.go:336.59,338.2 1 0 +auth/pb/auth.pb.go:340.50,341.14 1 0 +auth/pb/auth.pb.go:341.14,343.3 1 0 +auth/pb/auth.pb.go:344.2,344.11 1 0 +auth/pb/auth.pb.go:355.41,357.29 2 0 +auth/pb/auth.pb.go:357.29,361.3 3 0 +auth/pb/auth.pb.go:364.49,366.2 1 0 +auth/pb/auth.pb.go:368.47,368.48 0 0 +auth/pb/auth.pb.go:370.69,372.41 2 0 +auth/pb/auth.pb.go:372.41,374.34 2 0 +auth/pb/auth.pb.go:374.34,376.4 1 0 +auth/pb/auth.pb.go:377.3,377.12 1 0 +auth/pb/auth.pb.go:379.2,379.24 1 0 +auth/pb/auth.pb.go:383.60,385.2 1 0 +auth/pb/auth.pb.go:387.49,388.14 1 0 +auth/pb/auth.pb.go:388.14,390.3 1 0 +auth/pb/auth.pb.go:391.2,391.12 1 0 +auth/pb/auth.pb.go:404.39,406.29 2 0 +auth/pb/auth.pb.go:406.29,410.3 3 0 +auth/pb/auth.pb.go:413.47,415.2 1 0 +auth/pb/auth.pb.go:417.45,417.46 0 0 +auth/pb/auth.pb.go:419.67,421.41 2 0 +auth/pb/auth.pb.go:421.41,423.34 2 0 +auth/pb/auth.pb.go:423.34,425.4 1 0 +auth/pb/auth.pb.go:426.3,426.12 1 0 +auth/pb/auth.pb.go:428.2,428.24 1 0 +auth/pb/auth.pb.go:432.58,434.2 1 0 +auth/pb/auth.pb.go:436.52,437.14 1 0 +auth/pb/auth.pb.go:437.14,439.3 1 0 +auth/pb/auth.pb.go:440.2,440.11 1 0 +auth/pb/auth.pb.go:443.49,444.14 1 0 +auth/pb/auth.pb.go:444.14,446.3 1 0 +auth/pb/auth.pb.go:447.2,447.11 1 0 +auth/pb/auth.pb.go:450.52,451.14 1 0 +auth/pb/auth.pb.go:451.14,453.3 1 0 +auth/pb/auth.pb.go:454.2,454.11 1 0 +auth/pb/auth.pb.go:465.40,467.29 2 0 +auth/pb/auth.pb.go:467.29,471.3 3 0 +auth/pb/auth.pb.go:474.48,476.2 1 0 +auth/pb/auth.pb.go:478.46,478.47 0 0 +auth/pb/auth.pb.go:480.68,482.41 2 0 +auth/pb/auth.pb.go:482.41,484.34 2 0 +auth/pb/auth.pb.go:484.34,486.4 1 0 +auth/pb/auth.pb.go:487.3,487.12 1 0 +auth/pb/auth.pb.go:489.2,489.24 1 0 +auth/pb/auth.pb.go:493.59,495.2 1 0 +auth/pb/auth.pb.go:497.48,498.14 1 0 +auth/pb/auth.pb.go:498.14,500.3 1 0 +auth/pb/auth.pb.go:501.2,501.12 1 0 +auth/pb/auth.pb.go:515.37,517.29 2 0 +auth/pb/auth.pb.go:517.29,521.3 3 0 +auth/pb/auth.pb.go:524.45,526.2 1 0 +auth/pb/auth.pb.go:528.43,528.44 0 0 +auth/pb/auth.pb.go:530.65,532.41 2 0 +auth/pb/auth.pb.go:532.41,534.34 2 0 +auth/pb/auth.pb.go:534.34,536.4 1 0 +auth/pb/auth.pb.go:537.3,537.12 1 0 +auth/pb/auth.pb.go:539.2,539.24 1 0 +auth/pb/auth.pb.go:543.56,545.2 1 0 +auth/pb/auth.pb.go:547.48,548.14 1 0 +auth/pb/auth.pb.go:548.14,550.3 1 0 +auth/pb/auth.pb.go:551.2,551.11 1 0 +auth/pb/auth.pb.go:554.50,555.35 1 0 +auth/pb/auth.pb.go:555.35,557.3 1 0 +auth/pb/auth.pb.go:558.2,558.11 1 0 +auth/pb/auth.pb.go:561.47,562.32 1 0 +auth/pb/auth.pb.go:562.32,564.3 1 0 +auth/pb/auth.pb.go:565.2,565.11 1 0 +auth/pb/auth.pb.go:568.50,569.35 1 0 +auth/pb/auth.pb.go:569.35,571.3 1 0 +auth/pb/auth.pb.go:572.2,572.11 1 0 +auth/pb/auth.pb.go:583.38,585.29 2 0 +auth/pb/auth.pb.go:585.29,589.3 3 0 +auth/pb/auth.pb.go:592.46,594.2 1 0 +auth/pb/auth.pb.go:596.44,596.45 0 0 +auth/pb/auth.pb.go:598.66,600.41 2 0 +auth/pb/auth.pb.go:600.41,602.34 2 0 +auth/pb/auth.pb.go:602.34,604.4 1 0 +auth/pb/auth.pb.go:605.3,605.12 1 0 +auth/pb/auth.pb.go:607.2,607.24 1 0 +auth/pb/auth.pb.go:611.57,613.2 1 0 +auth/pb/auth.pb.go:615.46,616.14 1 0 +auth/pb/auth.pb.go:616.14,618.3 1 0 +auth/pb/auth.pb.go:619.2,619.12 1 0 +auth/pb/auth.pb.go:630.37,632.29 2 0 +auth/pb/auth.pb.go:632.29,636.3 3 0 +auth/pb/auth.pb.go:639.45,641.2 1 0 +auth/pb/auth.pb.go:643.43,643.44 0 0 +auth/pb/auth.pb.go:645.65,647.41 2 0 +auth/pb/auth.pb.go:647.41,649.34 2 0 +auth/pb/auth.pb.go:649.34,651.4 1 0 +auth/pb/auth.pb.go:652.3,652.12 1 0 +auth/pb/auth.pb.go:654.2,654.24 1 0 +auth/pb/auth.pb.go:658.56,660.2 1 0 +auth/pb/auth.pb.go:662.48,663.14 1 0 +auth/pb/auth.pb.go:663.14,665.3 1 0 +auth/pb/auth.pb.go:666.2,666.11 1 0 +auth/pb/auth.pb.go:677.34,679.29 2 0 +auth/pb/auth.pb.go:679.29,683.3 3 0 +auth/pb/auth.pb.go:686.42,688.2 1 0 +auth/pb/auth.pb.go:690.40,690.41 0 0 +auth/pb/auth.pb.go:692.62,694.41 2 0 +auth/pb/auth.pb.go:694.41,696.34 2 0 +auth/pb/auth.pb.go:696.34,698.4 1 0 +auth/pb/auth.pb.go:699.3,699.12 1 0 +auth/pb/auth.pb.go:701.2,701.24 1 0 +auth/pb/auth.pb.go:705.53,707.2 1 0 +auth/pb/auth.pb.go:709.45,710.14 1 0 +auth/pb/auth.pb.go:710.14,712.3 1 0 +auth/pb/auth.pb.go:713.2,713.11 1 0 +auth/pb/auth.pb.go:724.35,726.29 2 0 +auth/pb/auth.pb.go:726.29,730.3 3 0 +auth/pb/auth.pb.go:733.43,735.2 1 0 +auth/pb/auth.pb.go:737.41,737.42 0 0 +auth/pb/auth.pb.go:739.63,741.41 2 0 +auth/pb/auth.pb.go:741.41,743.34 2 0 +auth/pb/auth.pb.go:743.34,745.4 1 0 +auth/pb/auth.pb.go:746.3,746.12 1 0 +auth/pb/auth.pb.go:748.2,748.24 1 0 +auth/pb/auth.pb.go:752.54,754.2 1 0 +auth/pb/auth.pb.go:756.43,757.14 1 0 +auth/pb/auth.pb.go:757.14,759.3 1 0 +auth/pb/auth.pb.go:760.2,760.12 1 0 +auth/pb/auth.pb.go:892.43,893.40 1 0 +auth/pb/auth.pb.go:893.40,895.3 1 0 +auth/pb/auth.pb.go:896.2,896.36 1 0 +auth/pb/auth.pb.go:946.13,946.39 1 0 +auth/pb/auth.pb.go:947.29,948.28 1 0 +auth/pb/auth.pb.go:948.28,950.3 1 0 +auth/pb/auth.pb.go:951.2,952.30 2 0 +auth/pb/auth.pb.go:952.30,953.65 1 0 +auth/pb/auth.pb.go:953.65,954.37 1 0 +auth/pb/auth.pb.go:955.11,956.20 1 0 +auth/pb/auth.pb.go:957.11,958.24 1 0 +auth/pb/auth.pb.go:959.11,960.28 1 0 +auth/pb/auth.pb.go:961.12,962.15 1 0 +auth/pb/auth.pb.go:965.3,965.65 1 0 +auth/pb/auth.pb.go:965.65,966.38 1 0 +auth/pb/auth.pb.go:967.11,968.20 1 0 +auth/pb/auth.pb.go:969.11,970.24 1 0 +auth/pb/auth.pb.go:971.11,972.28 1 0 +auth/pb/auth.pb.go:973.12,974.15 1 0 +auth/pb/auth.pb.go:977.3,977.65 1 0 +auth/pb/auth.pb.go:977.65,978.38 1 0 +auth/pb/auth.pb.go:979.11,980.20 1 0 +auth/pb/auth.pb.go:981.11,982.24 1 0 +auth/pb/auth.pb.go:983.11,984.28 1 0 +auth/pb/auth.pb.go:985.12,986.15 1 0 +auth/pb/auth.pb.go:989.3,989.65 1 0 +auth/pb/auth.pb.go:989.65,990.44 1 0 +auth/pb/auth.pb.go:991.11,992.20 1 0 +auth/pb/auth.pb.go:993.11,994.24 1 0 +auth/pb/auth.pb.go:995.11,996.28 1 0 +auth/pb/auth.pb.go:997.12,998.15 1 0 +auth/pb/auth.pb.go:1001.3,1001.65 1 0 +auth/pb/auth.pb.go:1001.65,1002.45 1 0 +auth/pb/auth.pb.go:1003.11,1004.20 1 0 +auth/pb/auth.pb.go:1005.11,1006.24 1 0 +auth/pb/auth.pb.go:1007.11,1008.28 1 0 +auth/pb/auth.pb.go:1009.12,1010.15 1 0 +auth/pb/auth.pb.go:1013.3,1013.65 1 0 +auth/pb/auth.pb.go:1013.65,1014.45 1 0 +auth/pb/auth.pb.go:1015.11,1016.20 1 0 +auth/pb/auth.pb.go:1017.11,1018.24 1 0 +auth/pb/auth.pb.go:1019.11,1020.28 1 0 +auth/pb/auth.pb.go:1021.12,1022.15 1 0 +auth/pb/auth.pb.go:1025.3,1025.65 1 0 +auth/pb/auth.pb.go:1025.65,1026.46 1 0 +auth/pb/auth.pb.go:1027.11,1028.20 1 0 +auth/pb/auth.pb.go:1029.11,1030.24 1 0 +auth/pb/auth.pb.go:1031.11,1032.28 1 0 +auth/pb/auth.pb.go:1033.12,1034.15 1 0 +auth/pb/auth.pb.go:1037.3,1037.65 1 0 +auth/pb/auth.pb.go:1037.65,1038.44 1 0 +auth/pb/auth.pb.go:1039.11,1040.20 1 0 +auth/pb/auth.pb.go:1041.11,1042.24 1 0 +auth/pb/auth.pb.go:1043.11,1044.28 1 0 +auth/pb/auth.pb.go:1045.12,1046.15 1 0 +auth/pb/auth.pb.go:1049.3,1049.65 1 0 +auth/pb/auth.pb.go:1049.65,1050.45 1 0 +auth/pb/auth.pb.go:1051.11,1052.20 1 0 +auth/pb/auth.pb.go:1053.11,1054.24 1 0 +auth/pb/auth.pb.go:1055.11,1056.28 1 0 +auth/pb/auth.pb.go:1057.12,1058.15 1 0 +auth/pb/auth.pb.go:1061.3,1061.65 1 0 +auth/pb/auth.pb.go:1061.65,1062.42 1 0 +auth/pb/auth.pb.go:1063.11,1064.20 1 0 +auth/pb/auth.pb.go:1065.11,1066.24 1 0 +auth/pb/auth.pb.go:1067.11,1068.28 1 0 +auth/pb/auth.pb.go:1069.12,1070.15 1 0 +auth/pb/auth.pb.go:1073.3,1073.66 1 0 +auth/pb/auth.pb.go:1073.66,1074.43 1 0 +auth/pb/auth.pb.go:1075.11,1076.20 1 0 +auth/pb/auth.pb.go:1077.11,1078.24 1 0 +auth/pb/auth.pb.go:1079.11,1080.28 1 0 +auth/pb/auth.pb.go:1081.12,1082.15 1 0 +auth/pb/auth.pb.go:1085.3,1085.66 1 0 +auth/pb/auth.pb.go:1085.66,1086.42 1 0 +auth/pb/auth.pb.go:1087.11,1088.20 1 0 +auth/pb/auth.pb.go:1089.11,1090.24 1 0 +auth/pb/auth.pb.go:1091.11,1092.28 1 0 +auth/pb/auth.pb.go:1093.12,1094.15 1 0 +auth/pb/auth.pb.go:1097.3,1097.66 1 0 +auth/pb/auth.pb.go:1097.66,1098.39 1 0 +auth/pb/auth.pb.go:1099.11,1100.20 1 0 +auth/pb/auth.pb.go:1101.11,1102.24 1 0 +auth/pb/auth.pb.go:1103.11,1104.28 1 0 +auth/pb/auth.pb.go:1105.12,1106.15 1 0 +auth/pb/auth.pb.go:1109.3,1109.66 1 0 +auth/pb/auth.pb.go:1109.66,1110.40 1 0 +auth/pb/auth.pb.go:1111.11,1112.20 1 0 +auth/pb/auth.pb.go:1113.11,1114.24 1 0 +auth/pb/auth.pb.go:1115.11,1116.28 1 0 +auth/pb/auth.pb.go:1117.12,1118.15 1 0 +auth/pb/auth.pb.go:1122.2,1140.31 7 0 +auth/pb/auth_grpc.pb.go:60.74,62.2 1 0 +auth/pb/auth_grpc.pb.go:64.123,68.16 4 0 +auth/pb/auth_grpc.pb.go:68.16,70.3 1 0 +auth/pb/auth_grpc.pb.go:71.2,71.17 1 0 +auth/pb/auth_grpc.pb.go:74.125,78.16 4 0 +auth/pb/auth_grpc.pb.go:78.16,80.3 1 0 +auth/pb/auth_grpc.pb.go:81.2,81.17 1 0 +auth/pb/auth_grpc.pb.go:84.144,88.16 4 0 +auth/pb/auth_grpc.pb.go:88.16,90.3 1 0 +auth/pb/auth_grpc.pb.go:91.2,91.17 1 0 +auth/pb/auth_grpc.pb.go:94.147,98.16 4 0 +auth/pb/auth_grpc.pb.go:98.16,100.3 1 0 +auth/pb/auth_grpc.pb.go:101.2,101.17 1 0 +auth/pb/auth_grpc.pb.go:104.144,108.16 4 0 +auth/pb/auth_grpc.pb.go:108.16,110.3 1 0 +auth/pb/auth_grpc.pb.go:111.2,111.17 1 0 +auth/pb/auth_grpc.pb.go:114.138,118.16 4 0 +auth/pb/auth_grpc.pb.go:118.16,120.3 1 0 +auth/pb/auth_grpc.pb.go:121.2,121.17 1 0 +auth/pb/auth_grpc.pb.go:124.133,128.16 4 0 +auth/pb/auth_grpc.pb.go:128.16,130.3 1 0 +auth/pb/auth_grpc.pb.go:131.2,131.17 1 0 +auth/pb/auth_grpc.pb.go:134.129,138.16 4 0 +auth/pb/auth_grpc.pb.go:138.16,140.3 1 0 +auth/pb/auth_grpc.pb.go:141.2,141.17 1 0 +auth/pb/auth_grpc.pb.go:171.101,173.2 1 0 +auth/pb/auth_grpc.pb.go:174.103,176.2 1 0 +auth/pb/auth_grpc.pb.go:177.122,179.2 1 0 +auth/pb/auth_grpc.pb.go:180.125,182.2 1 0 +auth/pb/auth_grpc.pb.go:183.122,185.2 1 0 +auth/pb/auth_grpc.pb.go:186.116,188.2 1 0 +auth/pb/auth_grpc.pb.go:189.111,191.2 1 0 +auth/pb/auth_grpc.pb.go:192.107,194.2 1 0 +auth/pb/auth_grpc.pb.go:195.82,195.83 0 0 +auth/pb/auth_grpc.pb.go:204.80,206.2 1 0 +auth/pb/auth_grpc.pb.go:208.162,210.32 2 0 +auth/pb/auth_grpc.pb.go:210.32,212.3 1 0 +auth/pb/auth_grpc.pb.go:213.2,213.24 1 0 +auth/pb/auth_grpc.pb.go:213.24,215.3 1 0 +auth/pb/auth_grpc.pb.go:216.2,220.77 2 0 +auth/pb/auth_grpc.pb.go:220.77,222.3 1 0 +auth/pb/auth_grpc.pb.go:223.2,223.44 1 0 +auth/pb/auth_grpc.pb.go:226.163,228.32 2 0 +auth/pb/auth_grpc.pb.go:228.32,230.3 1 0 +auth/pb/auth_grpc.pb.go:231.2,231.24 1 0 +auth/pb/auth_grpc.pb.go:231.24,233.3 1 0 +auth/pb/auth_grpc.pb.go:234.2,238.77 2 0 +auth/pb/auth_grpc.pb.go:238.77,240.3 1 0 +auth/pb/auth_grpc.pb.go:241.2,241.44 1 0 +auth/pb/auth_grpc.pb.go:244.169,246.32 2 0 +auth/pb/auth_grpc.pb.go:246.32,248.3 1 0 +auth/pb/auth_grpc.pb.go:249.2,249.24 1 0 +auth/pb/auth_grpc.pb.go:249.24,251.3 1 0 +auth/pb/auth_grpc.pb.go:252.2,256.77 2 0 +auth/pb/auth_grpc.pb.go:256.77,258.3 1 0 +auth/pb/auth_grpc.pb.go:259.2,259.44 1 0 +auth/pb/auth_grpc.pb.go:262.170,264.32 2 0 +auth/pb/auth_grpc.pb.go:264.32,266.3 1 0 +auth/pb/auth_grpc.pb.go:267.2,267.24 1 0 +auth/pb/auth_grpc.pb.go:267.24,269.3 1 0 +auth/pb/auth_grpc.pb.go:270.2,274.77 2 0 +auth/pb/auth_grpc.pb.go:274.77,276.3 1 0 +auth/pb/auth_grpc.pb.go:277.2,277.44 1 0 +auth/pb/auth_grpc.pb.go:280.169,282.32 2 0 +auth/pb/auth_grpc.pb.go:282.32,284.3 1 0 +auth/pb/auth_grpc.pb.go:285.2,285.24 1 0 +auth/pb/auth_grpc.pb.go:285.24,287.3 1 0 +auth/pb/auth_grpc.pb.go:288.2,292.77 2 0 +auth/pb/auth_grpc.pb.go:292.77,294.3 1 0 +auth/pb/auth_grpc.pb.go:295.2,295.44 1 0 +auth/pb/auth_grpc.pb.go:298.167,300.32 2 0 +auth/pb/auth_grpc.pb.go:300.32,302.3 1 0 +auth/pb/auth_grpc.pb.go:303.2,303.24 1 0 +auth/pb/auth_grpc.pb.go:303.24,305.3 1 0 +auth/pb/auth_grpc.pb.go:306.2,310.77 2 0 +auth/pb/auth_grpc.pb.go:310.77,312.3 1 0 +auth/pb/auth_grpc.pb.go:313.2,313.44 1 0 +auth/pb/auth_grpc.pb.go:316.167,318.32 2 0 +auth/pb/auth_grpc.pb.go:318.32,320.3 1 0 +auth/pb/auth_grpc.pb.go:321.2,321.24 1 0 +auth/pb/auth_grpc.pb.go:321.24,323.3 1 0 +auth/pb/auth_grpc.pb.go:324.2,328.77 2 0 +auth/pb/auth_grpc.pb.go:328.77,330.3 1 0 +auth/pb/auth_grpc.pb.go:331.2,331.44 1 0 +auth/pb/auth_grpc.pb.go:334.164,336.32 2 0 +auth/pb/auth_grpc.pb.go:336.32,338.3 1 0 +auth/pb/auth_grpc.pb.go:339.2,339.24 1 0 +auth/pb/auth_grpc.pb.go:339.24,341.3 1 0 +auth/pb/auth_grpc.pb.go:342.2,346.77 2 0 +auth/pb/auth_grpc.pb.go:346.77,348.3 1 0 +auth/pb/auth_grpc.pb.go:349.2,349.44 1 0 +auth/pb/authorization.pb.go:34.42,36.29 2 0 +auth/pb/authorization.pb.go:36.29,40.3 3 0 +auth/pb/authorization.pb.go:43.50,45.2 1 0 +auth/pb/authorization.pb.go:47.48,47.49 0 0 +auth/pb/authorization.pb.go:49.70,51.41 2 0 +auth/pb/authorization.pb.go:51.41,53.34 2 0 +auth/pb/authorization.pb.go:53.34,55.4 1 0 +auth/pb/authorization.pb.go:56.3,56.12 1 0 +auth/pb/authorization.pb.go:58.2,58.24 1 0 +auth/pb/authorization.pb.go:62.61,64.2 1 0 +auth/pb/authorization.pb.go:66.53,67.14 1 0 +auth/pb/authorization.pb.go:67.14,69.3 1 0 +auth/pb/authorization.pb.go:70.2,70.11 1 0 +auth/pb/authorization.pb.go:73.62,74.14 1 0 +auth/pb/authorization.pb.go:74.14,76.3 1 0 +auth/pb/authorization.pb.go:77.2,77.12 1 0 +auth/pb/authorization.pb.go:88.43,90.29 2 0 +auth/pb/authorization.pb.go:90.29,94.3 3 0 +auth/pb/authorization.pb.go:97.51,99.2 1 0 +auth/pb/authorization.pb.go:101.49,101.50 0 0 +auth/pb/authorization.pb.go:103.71,105.41 2 0 +auth/pb/authorization.pb.go:105.41,107.34 2 0 +auth/pb/authorization.pb.go:107.34,109.4 1 0 +auth/pb/authorization.pb.go:110.3,110.12 1 0 +auth/pb/authorization.pb.go:112.2,112.24 1 0 +auth/pb/authorization.pb.go:116.62,118.2 1 0 +auth/pb/authorization.pb.go:120.59,121.14 1 0 +auth/pb/authorization.pb.go:121.14,123.3 1 0 +auth/pb/authorization.pb.go:124.2,124.14 1 0 +auth/pb/authorization.pb.go:135.39,137.29 2 0 +auth/pb/authorization.pb.go:137.29,141.3 3 0 +auth/pb/authorization.pb.go:144.47,146.2 1 0 +auth/pb/authorization.pb.go:148.45,148.46 0 0 +auth/pb/authorization.pb.go:150.67,152.41 2 0 +auth/pb/authorization.pb.go:152.41,154.34 2 0 +auth/pb/authorization.pb.go:154.34,156.4 1 0 +auth/pb/authorization.pb.go:157.3,157.12 1 0 +auth/pb/authorization.pb.go:159.2,159.24 1 0 +auth/pb/authorization.pb.go:163.58,165.2 1 0 +auth/pb/authorization.pb.go:167.50,168.14 1 0 +auth/pb/authorization.pb.go:168.14,170.3 1 0 +auth/pb/authorization.pb.go:171.2,171.11 1 0 +auth/pb/authorization.pb.go:182.40,184.29 2 0 +auth/pb/authorization.pb.go:184.29,188.3 3 0 +auth/pb/authorization.pb.go:191.48,193.2 1 0 +auth/pb/authorization.pb.go:195.46,195.47 0 0 +auth/pb/authorization.pb.go:197.68,199.41 2 0 +auth/pb/authorization.pb.go:199.41,201.34 2 0 +auth/pb/authorization.pb.go:201.34,203.4 1 0 +auth/pb/authorization.pb.go:204.3,204.12 1 0 +auth/pb/authorization.pb.go:206.2,206.24 1 0 +auth/pb/authorization.pb.go:210.59,212.2 1 0 +auth/pb/authorization.pb.go:214.51,215.14 1 0 +auth/pb/authorization.pb.go:215.14,217.3 1 0 +auth/pb/authorization.pb.go:218.2,218.12 1 0 +auth/pb/authorization.pb.go:230.43,232.29 2 0 +auth/pb/authorization.pb.go:232.29,236.3 3 0 +auth/pb/authorization.pb.go:239.51,241.2 1 0 +auth/pb/authorization.pb.go:243.49,243.50 0 0 +auth/pb/authorization.pb.go:245.71,247.41 2 0 +auth/pb/authorization.pb.go:247.41,249.34 2 0 +auth/pb/authorization.pb.go:249.34,251.4 1 0 +auth/pb/authorization.pb.go:252.3,252.12 1 0 +auth/pb/authorization.pb.go:254.2,254.24 1 0 +auth/pb/authorization.pb.go:258.62,260.2 1 0 +auth/pb/authorization.pb.go:262.54,263.14 1 0 +auth/pb/authorization.pb.go:263.14,265.3 1 0 +auth/pb/authorization.pb.go:266.2,266.11 1 0 +auth/pb/authorization.pb.go:269.54,270.14 1 0 +auth/pb/authorization.pb.go:270.14,272.3 1 0 +auth/pb/authorization.pb.go:273.2,273.11 1 0 +auth/pb/authorization.pb.go:285.45,287.29 2 0 +auth/pb/authorization.pb.go:287.29,291.3 3 0 +auth/pb/authorization.pb.go:294.53,296.2 1 0 +auth/pb/authorization.pb.go:298.51,298.52 0 0 +auth/pb/authorization.pb.go:300.73,302.41 2 0 +auth/pb/authorization.pb.go:302.41,304.34 2 0 +auth/pb/authorization.pb.go:304.34,306.4 1 0 +auth/pb/authorization.pb.go:307.3,307.12 1 0 +auth/pb/authorization.pb.go:309.2,309.24 1 0 +auth/pb/authorization.pb.go:313.64,315.2 1 0 +auth/pb/authorization.pb.go:317.56,318.14 1 0 +auth/pb/authorization.pb.go:318.14,320.3 1 0 +auth/pb/authorization.pb.go:321.2,321.11 1 0 +auth/pb/authorization.pb.go:324.56,325.14 1 0 +auth/pb/authorization.pb.go:325.14,327.3 1 0 +auth/pb/authorization.pb.go:328.2,328.11 1 0 +auth/pb/authorization.pb.go:340.37,342.29 2 0 +auth/pb/authorization.pb.go:342.29,346.3 3 0 +auth/pb/authorization.pb.go:349.45,351.2 1 0 +auth/pb/authorization.pb.go:353.43,353.44 0 0 +auth/pb/authorization.pb.go:355.65,357.41 2 0 +auth/pb/authorization.pb.go:357.41,359.34 2 0 +auth/pb/authorization.pb.go:359.34,361.4 1 0 +auth/pb/authorization.pb.go:362.3,362.12 1 0 +auth/pb/authorization.pb.go:364.2,364.24 1 0 +auth/pb/authorization.pb.go:368.56,370.2 1 0 +auth/pb/authorization.pb.go:372.46,373.14 1 0 +auth/pb/authorization.pb.go:373.14,375.3 1 0 +auth/pb/authorization.pb.go:376.2,376.11 1 0 +auth/pb/authorization.pb.go:379.60,380.14 1 0 +auth/pb/authorization.pb.go:380.14,382.3 1 0 +auth/pb/authorization.pb.go:383.2,383.12 1 0 +auth/pb/authorization.pb.go:394.38,396.29 2 0 +auth/pb/authorization.pb.go:396.29,400.3 3 0 +auth/pb/authorization.pb.go:403.46,405.2 1 0 +auth/pb/authorization.pb.go:407.44,407.45 0 0 +auth/pb/authorization.pb.go:409.66,411.41 2 0 +auth/pb/authorization.pb.go:411.41,413.34 2 0 +auth/pb/authorization.pb.go:413.34,415.4 1 0 +auth/pb/authorization.pb.go:416.3,416.12 1 0 +auth/pb/authorization.pb.go:418.2,418.24 1 0 +auth/pb/authorization.pb.go:422.57,424.2 1 0 +auth/pb/authorization.pb.go:426.46,427.14 1 0 +auth/pb/authorization.pb.go:427.14,429.3 1 0 +auth/pb/authorization.pb.go:430.2,430.12 1 0 +auth/pb/authorization.pb.go:443.37,445.29 2 0 +auth/pb/authorization.pb.go:445.29,449.3 3 0 +auth/pb/authorization.pb.go:452.45,454.2 1 0 +auth/pb/authorization.pb.go:456.43,456.44 0 0 +auth/pb/authorization.pb.go:458.65,460.41 2 0 +auth/pb/authorization.pb.go:460.41,462.34 2 0 +auth/pb/authorization.pb.go:462.34,464.4 1 0 +auth/pb/authorization.pb.go:465.3,465.12 1 0 +auth/pb/authorization.pb.go:467.2,467.24 1 0 +auth/pb/authorization.pb.go:471.56,473.2 1 0 +auth/pb/authorization.pb.go:475.48,476.14 1 0 +auth/pb/authorization.pb.go:476.14,478.3 1 0 +auth/pb/authorization.pb.go:479.2,479.11 1 0 +auth/pb/authorization.pb.go:482.46,483.31 1 0 +auth/pb/authorization.pb.go:483.31,485.3 1 0 +auth/pb/authorization.pb.go:486.2,486.11 1 0 +auth/pb/authorization.pb.go:489.60,490.14 1 0 +auth/pb/authorization.pb.go:490.14,492.3 1 0 +auth/pb/authorization.pb.go:493.2,493.12 1 0 +auth/pb/authorization.pb.go:504.38,506.29 2 0 +auth/pb/authorization.pb.go:506.29,510.3 3 0 +auth/pb/authorization.pb.go:513.46,515.2 1 0 +auth/pb/authorization.pb.go:517.44,517.45 0 0 +auth/pb/authorization.pb.go:519.66,521.41 2 0 +auth/pb/authorization.pb.go:521.41,523.34 2 0 +auth/pb/authorization.pb.go:523.34,525.4 1 0 +auth/pb/authorization.pb.go:526.3,526.12 1 0 +auth/pb/authorization.pb.go:528.2,528.24 1 0 +auth/pb/authorization.pb.go:532.57,534.2 1 0 +auth/pb/authorization.pb.go:536.46,537.14 1 0 +auth/pb/authorization.pb.go:537.14,539.3 1 0 +auth/pb/authorization.pb.go:540.2,540.12 1 0 +auth/pb/authorization.pb.go:551.37,553.29 2 0 +auth/pb/authorization.pb.go:553.29,557.3 3 0 +auth/pb/authorization.pb.go:560.45,562.2 1 0 +auth/pb/authorization.pb.go:564.43,564.44 0 0 +auth/pb/authorization.pb.go:566.65,568.41 2 0 +auth/pb/authorization.pb.go:568.41,570.34 2 0 +auth/pb/authorization.pb.go:570.34,572.4 1 0 +auth/pb/authorization.pb.go:573.3,573.12 1 0 +auth/pb/authorization.pb.go:575.2,575.24 1 0 +auth/pb/authorization.pb.go:579.56,581.2 1 0 +auth/pb/authorization.pb.go:583.48,584.14 1 0 +auth/pb/authorization.pb.go:584.14,586.3 1 0 +auth/pb/authorization.pb.go:587.2,587.11 1 0 +auth/pb/authorization.pb.go:598.34,600.29 2 0 +auth/pb/authorization.pb.go:600.29,604.3 3 0 +auth/pb/authorization.pb.go:607.42,609.2 1 0 +auth/pb/authorization.pb.go:611.40,611.41 0 0 +auth/pb/authorization.pb.go:613.62,615.41 2 0 +auth/pb/authorization.pb.go:615.41,617.34 2 0 +auth/pb/authorization.pb.go:617.34,619.4 1 0 +auth/pb/authorization.pb.go:620.3,620.12 1 0 +auth/pb/authorization.pb.go:622.2,622.24 1 0 +auth/pb/authorization.pb.go:626.53,628.2 1 0 +auth/pb/authorization.pb.go:630.45,631.14 1 0 +auth/pb/authorization.pb.go:631.14,633.3 1 0 +auth/pb/authorization.pb.go:634.2,634.11 1 0 +auth/pb/authorization.pb.go:645.35,647.29 2 0 +auth/pb/authorization.pb.go:647.29,651.3 3 0 +auth/pb/authorization.pb.go:654.43,656.2 1 0 +auth/pb/authorization.pb.go:658.41,658.42 0 0 +auth/pb/authorization.pb.go:660.63,662.41 2 0 +auth/pb/authorization.pb.go:662.41,664.34 2 0 +auth/pb/authorization.pb.go:664.34,666.4 1 0 +auth/pb/authorization.pb.go:667.3,667.12 1 0 +auth/pb/authorization.pb.go:669.2,669.24 1 0 +auth/pb/authorization.pb.go:673.54,675.2 1 0 +auth/pb/authorization.pb.go:677.43,678.14 1 0 +auth/pb/authorization.pb.go:678.14,680.3 1 0 +auth/pb/authorization.pb.go:681.2,681.12 1 0 +auth/pb/authorization.pb.go:693.36,695.29 2 0 +auth/pb/authorization.pb.go:695.29,699.3 3 0 +auth/pb/authorization.pb.go:702.44,704.2 1 0 +auth/pb/authorization.pb.go:706.42,706.43 0 0 +auth/pb/authorization.pb.go:708.64,710.41 2 0 +auth/pb/authorization.pb.go:710.41,712.34 2 0 +auth/pb/authorization.pb.go:712.34,714.4 1 0 +auth/pb/authorization.pb.go:715.3,715.12 1 0 +auth/pb/authorization.pb.go:717.2,717.24 1 0 +auth/pb/authorization.pb.go:721.55,723.2 1 0 +auth/pb/authorization.pb.go:725.48,726.14 1 0 +auth/pb/authorization.pb.go:726.14,728.3 1 0 +auth/pb/authorization.pb.go:729.2,729.10 1 0 +auth/pb/authorization.pb.go:732.50,733.14 1 0 +auth/pb/authorization.pb.go:733.14,735.3 1 0 +auth/pb/authorization.pb.go:736.2,736.11 1 0 +auth/pb/authorization.pb.go:748.37,750.29 2 0 +auth/pb/authorization.pb.go:750.29,754.3 3 0 +auth/pb/authorization.pb.go:757.45,759.2 1 0 +auth/pb/authorization.pb.go:761.43,761.44 0 0 +auth/pb/authorization.pb.go:763.65,765.41 2 0 +auth/pb/authorization.pb.go:765.41,767.34 2 0 +auth/pb/authorization.pb.go:767.34,769.4 1 0 +auth/pb/authorization.pb.go:770.3,770.12 1 0 +auth/pb/authorization.pb.go:772.2,772.24 1 0 +auth/pb/authorization.pb.go:776.56,778.2 1 0 +auth/pb/authorization.pb.go:780.48,781.14 1 0 +auth/pb/authorization.pb.go:781.14,783.3 1 0 +auth/pb/authorization.pb.go:784.2,784.12 1 0 +auth/pb/authorization.pb.go:787.55,788.14 1 0 +auth/pb/authorization.pb.go:788.14,790.3 1 0 +auth/pb/authorization.pb.go:791.2,791.11 1 0 +auth/pb/authorization.pb.go:803.46,805.29 2 0 +auth/pb/authorization.pb.go:805.29,809.3 3 0 +auth/pb/authorization.pb.go:812.54,814.2 1 0 +auth/pb/authorization.pb.go:816.52,816.53 0 0 +auth/pb/authorization.pb.go:818.74,820.41 2 0 +auth/pb/authorization.pb.go:820.41,822.34 2 0 +auth/pb/authorization.pb.go:822.34,824.4 1 0 +auth/pb/authorization.pb.go:825.3,825.12 1 0 +auth/pb/authorization.pb.go:827.2,827.24 1 0 +auth/pb/authorization.pb.go:831.65,833.2 1 0 +auth/pb/authorization.pb.go:835.57,836.14 1 0 +auth/pb/authorization.pb.go:836.14,838.3 1 0 +auth/pb/authorization.pb.go:839.2,839.11 1 0 +auth/pb/authorization.pb.go:842.66,843.14 1 0 +auth/pb/authorization.pb.go:843.14,845.3 1 0 +auth/pb/authorization.pb.go:846.2,846.12 1 0 +auth/pb/authorization.pb.go:858.51,860.29 2 0 +auth/pb/authorization.pb.go:860.29,864.3 3 0 +auth/pb/authorization.pb.go:867.59,869.2 1 0 +auth/pb/authorization.pb.go:871.57,871.58 0 0 +auth/pb/authorization.pb.go:873.79,875.41 2 0 +auth/pb/authorization.pb.go:875.41,877.34 2 0 +auth/pb/authorization.pb.go:877.34,879.4 1 0 +auth/pb/authorization.pb.go:880.3,880.12 1 0 +auth/pb/authorization.pb.go:882.2,882.24 1 0 +auth/pb/authorization.pb.go:886.70,888.2 1 0 +auth/pb/authorization.pb.go:890.62,891.14 1 0 +auth/pb/authorization.pb.go:891.14,893.3 1 0 +auth/pb/authorization.pb.go:894.2,894.11 1 0 +auth/pb/authorization.pb.go:897.71,898.14 1 0 +auth/pb/authorization.pb.go:898.14,900.3 1 0 +auth/pb/authorization.pb.go:901.2,901.12 1 0 +auth/pb/authorization.pb.go:1072.52,1073.49 1 0 +auth/pb/authorization.pb.go:1073.49,1075.3 1 0 +auth/pb/authorization.pb.go:1076.2,1076.45 1 0 +auth/pb/authorization.pb.go:1142.13,1142.48 1 0 +auth/pb/authorization.pb.go:1143.38,1144.37 1 0 +auth/pb/authorization.pb.go:1144.37,1146.3 1 0 +auth/pb/authorization.pb.go:1147.2,1148.30 2 0 +auth/pb/authorization.pb.go:1148.30,1149.74 1 0 +auth/pb/authorization.pb.go:1149.74,1150.47 1 0 +auth/pb/authorization.pb.go:1151.11,1152.20 1 0 +auth/pb/authorization.pb.go:1153.11,1154.24 1 0 +auth/pb/authorization.pb.go:1155.11,1156.28 1 0 +auth/pb/authorization.pb.go:1157.12,1158.15 1 0 +auth/pb/authorization.pb.go:1161.3,1161.74 1 0 +auth/pb/authorization.pb.go:1161.74,1162.48 1 0 +auth/pb/authorization.pb.go:1163.11,1164.20 1 0 +auth/pb/authorization.pb.go:1165.11,1166.24 1 0 +auth/pb/authorization.pb.go:1167.11,1168.28 1 0 +auth/pb/authorization.pb.go:1169.12,1170.15 1 0 +auth/pb/authorization.pb.go:1173.3,1173.74 1 0 +auth/pb/authorization.pb.go:1173.74,1174.44 1 0 +auth/pb/authorization.pb.go:1175.11,1176.20 1 0 +auth/pb/authorization.pb.go:1177.11,1178.24 1 0 +auth/pb/authorization.pb.go:1179.11,1180.28 1 0 +auth/pb/authorization.pb.go:1181.12,1182.15 1 0 +auth/pb/authorization.pb.go:1185.3,1185.74 1 0 +auth/pb/authorization.pb.go:1185.74,1186.45 1 0 +auth/pb/authorization.pb.go:1187.11,1188.20 1 0 +auth/pb/authorization.pb.go:1189.11,1190.24 1 0 +auth/pb/authorization.pb.go:1191.11,1192.28 1 0 +auth/pb/authorization.pb.go:1193.12,1194.15 1 0 +auth/pb/authorization.pb.go:1197.3,1197.74 1 0 +auth/pb/authorization.pb.go:1197.74,1198.48 1 0 +auth/pb/authorization.pb.go:1199.11,1200.20 1 0 +auth/pb/authorization.pb.go:1201.11,1202.24 1 0 +auth/pb/authorization.pb.go:1203.11,1204.28 1 0 +auth/pb/authorization.pb.go:1205.12,1206.15 1 0 +auth/pb/authorization.pb.go:1209.3,1209.74 1 0 +auth/pb/authorization.pb.go:1209.74,1210.50 1 0 +auth/pb/authorization.pb.go:1211.11,1212.20 1 0 +auth/pb/authorization.pb.go:1213.11,1214.24 1 0 +auth/pb/authorization.pb.go:1215.11,1216.28 1 0 +auth/pb/authorization.pb.go:1217.12,1218.15 1 0 +auth/pb/authorization.pb.go:1221.3,1221.74 1 0 +auth/pb/authorization.pb.go:1221.74,1222.42 1 0 +auth/pb/authorization.pb.go:1223.11,1224.20 1 0 +auth/pb/authorization.pb.go:1225.11,1226.24 1 0 +auth/pb/authorization.pb.go:1227.11,1228.28 1 0 +auth/pb/authorization.pb.go:1229.12,1230.15 1 0 +auth/pb/authorization.pb.go:1233.3,1233.74 1 0 +auth/pb/authorization.pb.go:1233.74,1234.43 1 0 +auth/pb/authorization.pb.go:1235.11,1236.20 1 0 +auth/pb/authorization.pb.go:1237.11,1238.24 1 0 +auth/pb/authorization.pb.go:1239.11,1240.28 1 0 +auth/pb/authorization.pb.go:1241.12,1242.15 1 0 +auth/pb/authorization.pb.go:1245.3,1245.74 1 0 +auth/pb/authorization.pb.go:1245.74,1246.42 1 0 +auth/pb/authorization.pb.go:1247.11,1248.20 1 0 +auth/pb/authorization.pb.go:1249.11,1250.24 1 0 +auth/pb/authorization.pb.go:1251.11,1252.28 1 0 +auth/pb/authorization.pb.go:1253.12,1254.15 1 0 +auth/pb/authorization.pb.go:1257.3,1257.74 1 0 +auth/pb/authorization.pb.go:1257.74,1258.43 1 0 +auth/pb/authorization.pb.go:1259.11,1260.20 1 0 +auth/pb/authorization.pb.go:1261.11,1262.24 1 0 +auth/pb/authorization.pb.go:1263.11,1264.28 1 0 +auth/pb/authorization.pb.go:1265.12,1266.15 1 0 +auth/pb/authorization.pb.go:1269.3,1269.75 1 0 +auth/pb/authorization.pb.go:1269.75,1270.42 1 0 +auth/pb/authorization.pb.go:1271.11,1272.20 1 0 +auth/pb/authorization.pb.go:1273.11,1274.24 1 0 +auth/pb/authorization.pb.go:1275.11,1276.28 1 0 +auth/pb/authorization.pb.go:1277.12,1278.15 1 0 +auth/pb/authorization.pb.go:1281.3,1281.75 1 0 +auth/pb/authorization.pb.go:1281.75,1282.39 1 0 +auth/pb/authorization.pb.go:1283.11,1284.20 1 0 +auth/pb/authorization.pb.go:1285.11,1286.24 1 0 +auth/pb/authorization.pb.go:1287.11,1288.28 1 0 +auth/pb/authorization.pb.go:1289.12,1290.15 1 0 +auth/pb/authorization.pb.go:1293.3,1293.75 1 0 +auth/pb/authorization.pb.go:1293.75,1294.40 1 0 +auth/pb/authorization.pb.go:1295.11,1296.20 1 0 +auth/pb/authorization.pb.go:1297.11,1298.24 1 0 +auth/pb/authorization.pb.go:1299.11,1300.28 1 0 +auth/pb/authorization.pb.go:1301.12,1302.15 1 0 +auth/pb/authorization.pb.go:1305.3,1305.75 1 0 +auth/pb/authorization.pb.go:1305.75,1306.41 1 0 +auth/pb/authorization.pb.go:1307.11,1308.20 1 0 +auth/pb/authorization.pb.go:1309.11,1310.24 1 0 +auth/pb/authorization.pb.go:1311.11,1312.28 1 0 +auth/pb/authorization.pb.go:1313.12,1314.15 1 0 +auth/pb/authorization.pb.go:1317.3,1317.75 1 0 +auth/pb/authorization.pb.go:1317.75,1318.42 1 0 +auth/pb/authorization.pb.go:1319.11,1320.20 1 0 +auth/pb/authorization.pb.go:1321.11,1322.24 1 0 +auth/pb/authorization.pb.go:1323.11,1324.28 1 0 +auth/pb/authorization.pb.go:1325.12,1326.15 1 0 +auth/pb/authorization.pb.go:1329.3,1329.75 1 0 +auth/pb/authorization.pb.go:1329.75,1330.51 1 0 +auth/pb/authorization.pb.go:1331.11,1332.20 1 0 +auth/pb/authorization.pb.go:1333.11,1334.24 1 0 +auth/pb/authorization.pb.go:1335.11,1336.28 1 0 +auth/pb/authorization.pb.go:1337.12,1338.15 1 0 +auth/pb/authorization.pb.go:1341.3,1341.75 1 0 +auth/pb/authorization.pb.go:1341.75,1342.56 1 0 +auth/pb/authorization.pb.go:1343.11,1344.20 1 0 +auth/pb/authorization.pb.go:1345.11,1346.24 1 0 +auth/pb/authorization.pb.go:1347.11,1348.28 1 0 +auth/pb/authorization.pb.go:1349.12,1350.15 1 0 +auth/pb/authorization.pb.go:1354.2,1372.40 7 0 +auth/pb/authorization_grpc.pb.go:69.92,71.2 1 0 +auth/pb/authorization_grpc.pb.go:73.162,77.16 4 0 +auth/pb/authorization_grpc.pb.go:77.16,79.3 1 0 +auth/pb/authorization_grpc.pb.go:80.2,80.17 1 0 +auth/pb/authorization_grpc.pb.go:83.153,87.16 4 0 +auth/pb/authorization_grpc.pb.go:87.16,89.3 1 0 +auth/pb/authorization_grpc.pb.go:90.2,90.17 1 0 +auth/pb/authorization_grpc.pb.go:93.154,97.16 4 0 +auth/pb/authorization_grpc.pb.go:97.16,99.3 1 0 +auth/pb/authorization_grpc.pb.go:100.2,100.17 1 0 +auth/pb/authorization_grpc.pb.go:103.158,107.16 4 0 +auth/pb/authorization_grpc.pb.go:107.16,109.3 1 0 +auth/pb/authorization_grpc.pb.go:110.2,110.17 1 0 +auth/pb/authorization_grpc.pb.go:113.147,117.16 4 0 +auth/pb/authorization_grpc.pb.go:117.16,119.3 1 0 +auth/pb/authorization_grpc.pb.go:120.2,120.17 1 0 +auth/pb/authorization_grpc.pb.go:123.147,127.16 4 0 +auth/pb/authorization_grpc.pb.go:127.16,129.3 1 0 +auth/pb/authorization_grpc.pb.go:130.2,130.17 1 0 +auth/pb/authorization_grpc.pb.go:133.142,137.16 4 0 +auth/pb/authorization_grpc.pb.go:137.16,139.3 1 0 +auth/pb/authorization_grpc.pb.go:140.2,140.17 1 0 +auth/pb/authorization_grpc.pb.go:143.138,147.16 4 0 +auth/pb/authorization_grpc.pb.go:147.16,149.3 1 0 +auth/pb/authorization_grpc.pb.go:150.2,150.17 1 0 +auth/pb/authorization_grpc.pb.go:153.144,157.16 4 0 +auth/pb/authorization_grpc.pb.go:157.16,159.3 1 0 +auth/pb/authorization_grpc.pb.go:160.2,160.17 1 0 +auth/pb/authorization_grpc.pb.go:163.160,167.16 4 0 +auth/pb/authorization_grpc.pb.go:167.16,169.3 1 0 +auth/pb/authorization_grpc.pb.go:170.2,170.17 1 0 +auth/pb/authorization_grpc.pb.go:173.170,177.16 4 0 +auth/pb/authorization_grpc.pb.go:177.16,179.3 1 0 +auth/pb/authorization_grpc.pb.go:180.2,180.17 1 0 +auth/pb/authorization_grpc.pb.go:216.140,218.2 1 0 +auth/pb/authorization_grpc.pb.go:219.131,221.2 1 0 +auth/pb/authorization_grpc.pb.go:222.132,224.2 1 0 +auth/pb/authorization_grpc.pb.go:225.136,227.2 1 0 +auth/pb/authorization_grpc.pb.go:228.125,230.2 1 0 +auth/pb/authorization_grpc.pb.go:231.125,233.2 1 0 +auth/pb/authorization_grpc.pb.go:234.120,236.2 1 0 +auth/pb/authorization_grpc.pb.go:237.116,239.2 1 0 +auth/pb/authorization_grpc.pb.go:240.122,242.2 1 0 +auth/pb/authorization_grpc.pb.go:243.138,245.2 1 0 +auth/pb/authorization_grpc.pb.go:246.148,248.2 1 0 +auth/pb/authorization_grpc.pb.go:249.100,249.101 0 0 +auth/pb/authorization_grpc.pb.go:258.98,260.2 1 0 +auth/pb/authorization_grpc.pb.go:262.181,264.32 2 0 +auth/pb/authorization_grpc.pb.go:264.32,266.3 1 0 +auth/pb/authorization_grpc.pb.go:267.2,267.24 1 0 +auth/pb/authorization_grpc.pb.go:267.24,269.3 1 0 +auth/pb/authorization_grpc.pb.go:270.2,274.77 2 0 +auth/pb/authorization_grpc.pb.go:274.77,276.3 1 0 +auth/pb/authorization_grpc.pb.go:277.2,277.44 1 0 +auth/pb/authorization_grpc.pb.go:280.178,282.32 2 0 +auth/pb/authorization_grpc.pb.go:282.32,284.3 1 0 +auth/pb/authorization_grpc.pb.go:285.2,285.24 1 0 +auth/pb/authorization_grpc.pb.go:285.24,287.3 1 0 +auth/pb/authorization_grpc.pb.go:288.2,292.77 2 0 +auth/pb/authorization_grpc.pb.go:292.77,294.3 1 0 +auth/pb/authorization_grpc.pb.go:295.2,295.44 1 0 +auth/pb/authorization_grpc.pb.go:298.182,300.32 2 0 +auth/pb/authorization_grpc.pb.go:300.32,302.3 1 0 +auth/pb/authorization_grpc.pb.go:303.2,303.24 1 0 +auth/pb/authorization_grpc.pb.go:303.24,305.3 1 0 +auth/pb/authorization_grpc.pb.go:306.2,310.77 2 0 +auth/pb/authorization_grpc.pb.go:310.77,312.3 1 0 +auth/pb/authorization_grpc.pb.go:313.2,313.44 1 0 +auth/pb/authorization_grpc.pb.go:316.184,318.32 2 0 +auth/pb/authorization_grpc.pb.go:318.32,320.3 1 0 +auth/pb/authorization_grpc.pb.go:321.2,321.24 1 0 +auth/pb/authorization_grpc.pb.go:321.24,323.3 1 0 +auth/pb/authorization_grpc.pb.go:324.2,328.77 2 0 +auth/pb/authorization_grpc.pb.go:328.77,330.3 1 0 +auth/pb/authorization_grpc.pb.go:331.2,331.44 1 0 +auth/pb/authorization_grpc.pb.go:334.176,336.32 2 0 +auth/pb/authorization_grpc.pb.go:336.32,338.3 1 0 +auth/pb/authorization_grpc.pb.go:339.2,339.24 1 0 +auth/pb/authorization_grpc.pb.go:339.24,341.3 1 0 +auth/pb/authorization_grpc.pb.go:342.2,346.77 2 0 +auth/pb/authorization_grpc.pb.go:346.77,348.3 1 0 +auth/pb/authorization_grpc.pb.go:349.2,349.44 1 0 +auth/pb/authorization_grpc.pb.go:352.176,354.32 2 0 +auth/pb/authorization_grpc.pb.go:354.32,356.3 1 0 +auth/pb/authorization_grpc.pb.go:357.2,357.24 1 0 +auth/pb/authorization_grpc.pb.go:357.24,359.3 1 0 +auth/pb/authorization_grpc.pb.go:360.2,364.77 2 0 +auth/pb/authorization_grpc.pb.go:364.77,366.3 1 0 +auth/pb/authorization_grpc.pb.go:367.2,367.44 1 0 +auth/pb/authorization_grpc.pb.go:370.176,372.32 2 0 +auth/pb/authorization_grpc.pb.go:372.32,374.3 1 0 +auth/pb/authorization_grpc.pb.go:375.2,375.24 1 0 +auth/pb/authorization_grpc.pb.go:375.24,377.3 1 0 +auth/pb/authorization_grpc.pb.go:378.2,382.77 2 0 +auth/pb/authorization_grpc.pb.go:382.77,384.3 1 0 +auth/pb/authorization_grpc.pb.go:385.2,385.44 1 0 +auth/pb/authorization_grpc.pb.go:388.173,390.32 2 0 +auth/pb/authorization_grpc.pb.go:390.32,392.3 1 0 +auth/pb/authorization_grpc.pb.go:393.2,393.24 1 0 +auth/pb/authorization_grpc.pb.go:393.24,395.3 1 0 +auth/pb/authorization_grpc.pb.go:396.2,400.77 2 0 +auth/pb/authorization_grpc.pb.go:400.77,402.3 1 0 +auth/pb/authorization_grpc.pb.go:403.2,403.44 1 0 +auth/pb/authorization_grpc.pb.go:406.175,408.32 2 0 +auth/pb/authorization_grpc.pb.go:408.32,410.3 1 0 +auth/pb/authorization_grpc.pb.go:411.2,411.24 1 0 +auth/pb/authorization_grpc.pb.go:411.24,413.3 1 0 +auth/pb/authorization_grpc.pb.go:414.2,418.77 2 0 +auth/pb/authorization_grpc.pb.go:418.77,420.3 1 0 +auth/pb/authorization_grpc.pb.go:421.2,421.44 1 0 +auth/pb/authorization_grpc.pb.go:424.185,426.32 2 0 +auth/pb/authorization_grpc.pb.go:426.32,428.3 1 0 +auth/pb/authorization_grpc.pb.go:429.2,429.24 1 0 +auth/pb/authorization_grpc.pb.go:429.24,431.3 1 0 +auth/pb/authorization_grpc.pb.go:432.2,436.77 2 0 +auth/pb/authorization_grpc.pb.go:436.77,438.3 1 0 +auth/pb/authorization_grpc.pb.go:439.2,439.44 1 0 +auth/pb/authorization_grpc.pb.go:442.190,444.32 2 0 +auth/pb/authorization_grpc.pb.go:444.32,446.3 1 0 +auth/pb/authorization_grpc.pb.go:447.2,447.24 1 0 +auth/pb/authorization_grpc.pb.go:447.24,449.3 1 0 +auth/pb/authorization_grpc.pb.go:450.2,454.77 2 0 +auth/pb/authorization_grpc.pb.go:454.77,456.3 1 0 +auth/pb/authorization_grpc.pb.go:457.2,457.44 1 0 +auth/pb/common.pb.go:39.24,41.29 2 0 +auth/pb/common.pb.go:41.29,45.3 3 0 +auth/pb/common.pb.go:48.32,50.2 1 0 +auth/pb/common.pb.go:52.30,52.31 0 0 +auth/pb/common.pb.go:54.52,56.41 2 0 +auth/pb/common.pb.go:56.41,58.34 2 0 +auth/pb/common.pb.go:58.34,60.4 1 0 +auth/pb/common.pb.go:61.3,61.12 1 0 +auth/pb/common.pb.go:63.2,63.24 1 0 +auth/pb/common.pb.go:67.43,69.2 1 0 +auth/pb/common.pb.go:71.31,72.14 1 0 +auth/pb/common.pb.go:72.14,74.3 1 0 +auth/pb/common.pb.go:75.2,75.11 1 0 +auth/pb/common.pb.go:78.37,79.14 1 0 +auth/pb/common.pb.go:79.14,81.3 1 0 +auth/pb/common.pb.go:82.2,82.11 1 0 +auth/pb/common.pb.go:85.34,86.14 1 0 +auth/pb/common.pb.go:86.14,88.3 1 0 +auth/pb/common.pb.go:89.2,89.11 1 0 +auth/pb/common.pb.go:92.36,93.14 1 0 +auth/pb/common.pb.go:93.14,95.3 1 0 +auth/pb/common.pb.go:96.2,96.12 1 0 +auth/pb/common.pb.go:99.54,100.14 1 0 +auth/pb/common.pb.go:100.14,102.3 1 0 +auth/pb/common.pb.go:103.2,103.12 1 0 +auth/pb/common.pb.go:106.54,107.14 1 0 +auth/pb/common.pb.go:107.14,109.3 1 0 +auth/pb/common.pb.go:110.2,110.12 1 0 +auth/pb/common.pb.go:126.24,128.29 2 0 +auth/pb/common.pb.go:128.29,132.3 3 0 +auth/pb/common.pb.go:135.32,137.2 1 0 +auth/pb/common.pb.go:139.30,139.31 0 0 +auth/pb/common.pb.go:141.52,143.41 2 0 +auth/pb/common.pb.go:143.41,145.34 2 0 +auth/pb/common.pb.go:145.34,147.4 1 0 +auth/pb/common.pb.go:148.3,148.12 1 0 +auth/pb/common.pb.go:150.2,150.24 1 0 +auth/pb/common.pb.go:154.43,156.2 1 0 +auth/pb/common.pb.go:158.31,159.14 1 0 +auth/pb/common.pb.go:159.14,161.3 1 0 +auth/pb/common.pb.go:162.2,162.11 1 0 +auth/pb/common.pb.go:165.33,166.14 1 0 +auth/pb/common.pb.go:166.14,168.3 1 0 +auth/pb/common.pb.go:169.2,169.11 1 0 +auth/pb/common.pb.go:172.42,173.14 1 0 +auth/pb/common.pb.go:173.14,175.3 1 0 +auth/pb/common.pb.go:176.2,176.12 1 0 +auth/pb/common.pb.go:179.54,180.14 1 0 +auth/pb/common.pb.go:180.14,182.3 1 0 +auth/pb/common.pb.go:183.2,183.12 1 0 +auth/pb/common.pb.go:186.54,187.14 1 0 +auth/pb/common.pb.go:187.14,189.3 1 0 +auth/pb/common.pb.go:190.2,190.12 1 0 +auth/pb/common.pb.go:203.30,205.29 2 0 +auth/pb/common.pb.go:205.29,209.3 3 0 +auth/pb/common.pb.go:212.38,214.2 1 0 +auth/pb/common.pb.go:216.36,216.37 0 0 +auth/pb/common.pb.go:218.58,220.41 2 0 +auth/pb/common.pb.go:220.41,222.34 2 0 +auth/pb/common.pb.go:222.34,224.4 1 0 +auth/pb/common.pb.go:225.3,225.12 1 0 +auth/pb/common.pb.go:227.2,227.24 1 0 +auth/pb/common.pb.go:231.49,233.2 1 0 +auth/pb/common.pb.go:235.43,236.14 1 0 +auth/pb/common.pb.go:236.14,238.3 1 0 +auth/pb/common.pb.go:239.2,239.11 1 0 +auth/pb/common.pb.go:242.41,243.14 1 0 +auth/pb/common.pb.go:243.14,245.3 1 0 +auth/pb/common.pb.go:246.2,246.11 1 0 +auth/pb/common.pb.go:259.25,261.29 2 0 +auth/pb/common.pb.go:261.29,265.3 3 0 +auth/pb/common.pb.go:268.33,270.2 1 0 +auth/pb/common.pb.go:272.31,272.32 0 0 +auth/pb/common.pb.go:274.53,276.41 2 0 +auth/pb/common.pb.go:276.41,278.34 2 0 +auth/pb/common.pb.go:278.34,280.4 1 0 +auth/pb/common.pb.go:281.3,281.12 1 0 +auth/pb/common.pb.go:283.2,283.24 1 0 +auth/pb/common.pb.go:287.44,289.2 1 0 +auth/pb/common.pb.go:291.34,292.14 1 0 +auth/pb/common.pb.go:292.14,294.3 1 0 +auth/pb/common.pb.go:295.2,295.11 1 0 +auth/pb/common.pb.go:298.37,299.14 1 0 +auth/pb/common.pb.go:299.14,301.3 1 0 +auth/pb/common.pb.go:302.2,302.11 1 0 +auth/pb/common.pb.go:355.45,356.42 1 0 +auth/pb/common.pb.go:356.42,358.3 1 0 +auth/pb/common.pb.go:359.2,359.38 1 0 +auth/pb/common.pb.go:382.13,382.41 1 0 +auth/pb/common.pb.go:383.31,384.30 1 0 +auth/pb/common.pb.go:384.30,386.3 1 0 +auth/pb/common.pb.go:387.2,387.30 1 0 +auth/pb/common.pb.go:387.30,388.67 1 0 +auth/pb/common.pb.go:388.67,389.29 1 0 +auth/pb/common.pb.go:390.11,391.20 1 0 +auth/pb/common.pb.go:392.11,393.24 1 0 +auth/pb/common.pb.go:394.11,395.28 1 0 +auth/pb/common.pb.go:396.12,397.15 1 0 +auth/pb/common.pb.go:400.3,400.67 1 0 +auth/pb/common.pb.go:400.67,401.29 1 0 +auth/pb/common.pb.go:402.11,403.20 1 0 +auth/pb/common.pb.go:404.11,405.24 1 0 +auth/pb/common.pb.go:406.11,407.28 1 0 +auth/pb/common.pb.go:408.12,409.15 1 0 +auth/pb/common.pb.go:412.3,412.67 1 0 +auth/pb/common.pb.go:412.67,413.35 1 0 +auth/pb/common.pb.go:414.11,415.20 1 0 +auth/pb/common.pb.go:416.11,417.24 1 0 +auth/pb/common.pb.go:418.11,419.28 1 0 +auth/pb/common.pb.go:420.12,421.15 1 0 +auth/pb/common.pb.go:424.3,424.67 1 0 +auth/pb/common.pb.go:424.67,425.30 1 0 +auth/pb/common.pb.go:426.11,427.20 1 0 +auth/pb/common.pb.go:428.11,429.24 1 0 +auth/pb/common.pb.go:430.11,431.28 1 0 +auth/pb/common.pb.go:432.12,433.15 1 0 +auth/pb/common.pb.go:437.2,454.33 6 0 +auth/internal/interceptor/interceptor.go:53.94,54.45 1 1 +auth/internal/interceptor/interceptor.go:54.45,56.3 1 1 +auth/internal/interceptor/interceptor.go:60.86,61.45 1 1 +auth/internal/interceptor/interceptor.go:61.45,63.3 1 1 +auth/internal/interceptor/interceptor.go:67.56,68.45 1 1 +auth/internal/interceptor/interceptor.go:68.45,70.3 1 1 +auth/internal/interceptor/interceptor.go:74.59,75.45 1 1 +auth/internal/interceptor/interceptor.go:75.45,77.3 1 1 +auth/internal/interceptor/interceptor.go:81.67,82.45 1 1 +auth/internal/interceptor/interceptor.go:82.45,84.3 1 1 +auth/internal/interceptor/interceptor.go:88.91,89.45 1 1 +auth/internal/interceptor/interceptor.go:89.45,91.3 1 1 +auth/internal/interceptor/interceptor.go:95.72,96.45 1 1 +auth/internal/interceptor/interceptor.go:96.45,98.3 1 1 +auth/internal/interceptor/interceptor.go:102.73,103.45 1 1 +auth/internal/interceptor/interceptor.go:103.45,105.3 1 1 +auth/internal/interceptor/interceptor.go:109.64,110.45 1 1 +auth/internal/interceptor/interceptor.go:110.45,112.3 1 1 +auth/internal/interceptor/interceptor.go:125.84,138.27 2 2 +auth/internal/interceptor/interceptor.go:138.27,140.3 1 9 +auth/internal/interceptor/interceptor.go:142.2,142.128 1 2 +auth/internal/interceptor/interceptor.go:142.128,144.3 1 0 +auth/internal/interceptor/interceptor.go:148.167,149.47 1 4 +auth/internal/interceptor/interceptor.go:149.47,151.3 1 0 +auth/internal/interceptor/interceptor.go:153.2,153.55 1 4 +auth/internal/interceptor/interceptor.go:153.55,155.3 1 0 +auth/internal/interceptor/interceptor.go:157.2,158.16 2 4 +auth/internal/interceptor/interceptor.go:158.16,160.3 1 1 +auth/internal/interceptor/interceptor.go:162.2,163.16 2 3 +auth/internal/interceptor/interceptor.go:163.16,165.3 1 1 +auth/internal/interceptor/interceptor.go:167.2,170.29 3 2 +auth/internal/interceptor/utils.go:20.58,21.19 1 7 +auth/internal/interceptor/utils.go:21.19,23.3 1 1 +auth/internal/interceptor/utils.go:24.2,24.26 1 6 +auth/internal/interceptor/utils.go:24.26,26.3 1 1 +auth/internal/interceptor/utils.go:27.2,27.12 1 6 +auth/internal/interceptor/utils.go:31.82,32.31 1 5 +auth/internal/interceptor/utils.go:32.31,33.54 1 0 +auth/internal/interceptor/utils.go:33.54,36.4 2 0 +auth/internal/interceptor/utils.go:38.2,38.12 1 5 +auth/internal/interceptor/utils.go:42.102,44.9 2 9 +auth/internal/interceptor/utils.go:44.9,47.3 2 2 +auth/internal/interceptor/utils.go:49.2,50.33 2 7 +auth/internal/interceptor/utils.go:50.33,53.3 2 1 +auth/internal/interceptor/utils.go:55.2,56.25 2 6 +auth/internal/interceptor/utils.go:56.25,59.3 2 1 +auth/internal/interceptor/utils.go:61.2,61.52 1 5 +auth/internal/interceptor/utils.go:65.142,66.20 1 6 +auth/internal/interceptor/utils.go:67.11,68.49 1 2 +auth/internal/interceptor/utils.go:69.14,70.47 1 2 +auth/internal/interceptor/utils.go:71.10,73.88 2 2 +auth/internal/interceptor/utils.go:78.115,79.34 1 8 +auth/internal/interceptor/utils.go:79.34,81.3 1 0 +auth/internal/interceptor/utils.go:83.2,84.16 2 8 +auth/internal/interceptor/utils.go:84.16,87.3 2 1 +auth/internal/interceptor/utils.go:89.2,90.16 2 7 +auth/internal/interceptor/utils.go:90.16,92.3 1 1 +auth/internal/interceptor/utils.go:92.8,92.27 1 6 +auth/internal/interceptor/utils.go:92.27,94.10 2 2 +auth/internal/interceptor/utils.go:94.10,96.4 1 0 +auth/internal/interceptor/utils.go:97.3,100.28 4 2 +auth/internal/interceptor/utils.go:103.2,103.20 1 7 +auth/internal/interceptor/utils.go:107.135,108.44 1 7 +auth/internal/interceptor/utils.go:108.44,110.88 2 5 +auth/internal/interceptor/utils.go:110.88,112.18 2 3 +auth/internal/interceptor/utils.go:112.18,114.5 1 1 +auth/internal/interceptor/utils.go:115.4,115.24 1 2 +auth/internal/interceptor/utils.go:118.2,118.16 1 4 +auth/internal/interceptor/utils.go:122.94,123.35 1 6 +auth/internal/interceptor/utils.go:123.35,125.3 1 0 +auth/internal/interceptor/utils.go:127.2,128.26 2 6 +auth/internal/interceptor/utils.go:128.26,131.3 2 1 +auth/internal/interceptor/utils.go:133.2,133.46 1 5 +auth/internal/interceptor/utils.go:140.132,141.43 1 3 +auth/internal/interceptor/utils.go:141.43,143.3 1 0 +auth/internal/interceptor/utils.go:145.2,146.52 2 3 +auth/internal/interceptor/utils.go:146.52,148.3 1 0 +auth/internal/interceptor/utils.go:150.2,151.17 2 3 +auth/internal/interceptor/utils.go:151.17,153.3 1 3 +auth/internal/interceptor/utils.go:155.2,159.3 1 3 +auth/internal/interceptor/utils.go:168.71,170.83 2 3 +auth/internal/interceptor/utils.go:170.83,171.58 1 2 +auth/internal/interceptor/utils.go:171.58,173.4 1 0 +auth/internal/interceptor/utils.go:174.3,174.32 1 2 +auth/internal/interceptor/utils.go:177.2,177.16 1 3 +auth/internal/interceptor/utils.go:177.16,179.3 1 2 +auth/internal/interceptor/utils.go:181.2,181.67 1 1 +auth/internal/interceptor/utils.go:181.67,183.3 1 1 +auth/internal/interceptor/utils.go:185.2,185.41 1 0 +auth/internal/interceptor/utils.go:189.58,197.13 3 2 +auth/internal/interceptor/utils.go:197.13,199.3 1 1 +auth/internal/interceptor/utils.go:200.2,200.21 1 1 +auth/internal/interceptor/utils.go:204.81,206.65 1 10 +auth/internal/interceptor/utils.go:206.65,208.10 2 2 +auth/internal/interceptor/utils.go:208.10,210.4 1 0 +auth/internal/interceptor/utils.go:211.3,211.20 1 2 +auth/internal/interceptor/utils.go:215.2,216.16 2 8 +auth/internal/interceptor/utils.go:216.16,218.3 1 0 +auth/internal/interceptor/utils.go:221.2,222.19 2 8 +auth/internal/interceptor/utils.go:226.63,228.2 1 1 +auth/internal/interceptor/utils.go:244.60,246.62 2 4 +auth/internal/interceptor/utils.go:246.62,248.3 1 2 +auth/internal/interceptor/utils.go:249.2,249.22 1 2 +auth/internal/interceptor/utils.go:266.58,268.9 2 4 +auth/internal/interceptor/utils.go:268.9,270.3 1 1 +auth/internal/interceptor/utils.go:272.2,273.41 2 3 +auth/internal/interceptor/utils.go:273.41,275.3 1 2 +auth/internal/interceptor/utils.go:277.2,277.24 1 1 +auth/internal/interceptor/utils.go:294.63,297.2 2 3 +auth/pkg/limiter.go:31.65,39.2 2 7 +auth/pkg/limiter.go:53.59,58.13 4 12 +auth/pkg/limiter.go:58.13,63.3 3 11 +auth/pkg/limiter.go:65.2,65.16 1 12 +auth/pkg/limiter.go:79.64,84.13 4 506 +auth/pkg/limiter.go:84.13,86.3 1 11 +auth/pkg/limiter.go:88.2,88.16 1 495 +auth/pkg/password_hash.go:22.50,23.15 1 8 +auth/pkg/password_hash.go:23.15,25.3 1 2 +auth/pkg/password_hash.go:26.2,26.36 1 8 +auth/pkg/password_hash.go:40.73,41.20 1 8 +auth/pkg/password_hash.go:41.20,43.3 1 1 +auth/pkg/password_hash.go:44.2,44.58 1 7 +auth/pkg/password_hash.go:44.58,46.3 1 1 +auth/pkg/password_hash.go:47.2,48.27 2 6 +auth/pkg/password_hash.go:63.89,64.26 1 3 +auth/pkg/password_hash.go:64.26,66.3 1 0 +auth/pkg/password_hash.go:67.2,67.20 1 3 +auth/pkg/password_hash.go:67.20,69.3 1 1 +auth/pkg/password_hash.go:70.2,71.16 2 2 +auth/pkg/password_hash.go:71.16,72.49 1 1 +auth/pkg/password_hash.go:72.49,74.4 1 1 +auth/pkg/password_hash.go:75.3,75.20 1 0 +auth/pkg/password_hash.go:77.2,77.18 1 1 +auth/pkg/token_generator.go:17.97,23.2 1 2 +auth/pkg/token_generator.go:26.78,27.19 1 4 +auth/pkg/token_generator.go:27.19,29.3 1 1 +auth/pkg/token_generator.go:30.2,35.40 6 4 +auth/ent/client.go:38.40,42.2 3 6 +auth/ent/client.go:44.25,49.2 4 6 +auth/ent/client.go:70.39,74.2 3 6 +auth/ent/client.go:77.42,78.27 1 6 +auth/ent/client.go:78.27,80.3 1 6 +auth/ent/client.go:81.2,81.13 1 6 +auth/ent/client.go:81.13,83.3 1 0 +auth/ent/client.go:87.21,88.25 1 0 +auth/ent/client.go:88.25,90.3 1 0 +auth/ent/client.go:94.34,95.25 1 0 +auth/ent/client.go:95.25,97.3 1 0 +auth/ent/client.go:101.43,102.25 1 6 +auth/ent/client.go:102.25,104.3 1 6 +auth/ent/client.go:110.82,111.20 1 6 +auth/ent/client.go:112.55,114.17 2 6 +auth/ent/client.go:114.17,116.4 1 0 +auth/ent/client.go:117.3,117.57 1 6 +auth/ent/client.go:118.10,119.63 1 0 +auth/ent/client.go:128.55,129.39 1 0 +auth/ent/client.go:129.39,131.3 1 0 +auth/ent/client.go:132.2,133.16 2 0 +auth/ent/client.go:133.16,135.3 1 0 +auth/ent/client.go:136.2,144.8 3 0 +auth/ent/client.go:148.81,149.39 1 0 +auth/ent/client.go:149.39,151.3 1 0 +auth/ent/client.go:152.2,155.16 2 0 +auth/ent/client.go:155.16,157.3 1 0 +auth/ent/client.go:158.2,166.8 3 0 +auth/ent/client.go:175.34,176.13 1 0 +auth/ent/client.go:176.13,178.3 1 0 +auth/ent/client.go:179.2,183.15 5 0 +auth/ent/client.go:187.32,189.2 1 6 +auth/ent/client.go:193.37,197.2 3 0 +auth/ent/client.go:201.57,205.2 3 0 +auth/ent/client.go:208.73,209.23 1 0 +auth/ent/client.go:210.21,211.31 1 0 +auth/ent/client.go:212.22,213.32 1 0 +auth/ent/client.go:214.21,215.31 1 0 +auth/ent/client.go:216.10,217.61 1 0 +auth/ent/client.go:227.42,229.2 1 7 +auth/ent/client.go:233.41,235.2 1 0 +auth/ent/client.go:239.61,241.2 1 0 +auth/ent/client.go:244.43,247.2 2 34 +auth/ent/client.go:250.74,252.2 1 0 +auth/ent/client.go:256.95,258.32 2 0 +auth/ent/client.go:258.32,260.3 1 0 +auth/ent/client.go:261.2,262.32 2 0 +auth/ent/client.go:262.32,265.3 2 0 +auth/ent/client.go:266.2,266.62 1 0 +auth/ent/client.go:270.43,273.2 2 0 +auth/ent/client.go:276.56,279.2 2 1 +auth/ent/client.go:282.60,285.2 2 3 +auth/ent/client.go:288.43,291.2 2 3 +auth/ent/client.go:294.56,296.2 1 0 +auth/ent/client.go:299.60,304.2 4 1 +auth/ent/client.go:307.41,313.2 1 18 +auth/ent/client.go:316.73,318.2 1 0 +auth/ent/client.go:321.65,323.16 2 0 +auth/ent/client.go:323.16,324.13 1 0 +auth/ent/client.go:326.2,326.12 1 0 +auth/ent/client.go:330.53,332.68 2 1 +auth/ent/client.go:332.68,341.3 4 1 +auth/ent/client.go:342.2,342.14 1 1 +auth/ent/client.go:346.37,348.2 1 41 +auth/ent/client.go:351.51,353.2 1 18 +auth/ent/client.go:355.82,356.16 1 0 +auth/ent/client.go:357.16,358.82 1 0 +auth/ent/client.go:359.16,360.82 1 0 +auth/ent/client.go:361.19,362.85 1 0 +auth/ent/client.go:363.29,364.82 1 0 +auth/ent/client.go:365.10,366.70 1 0 +auth/ent/client.go:376.44,378.2 1 8 +auth/ent/client.go:382.42,384.2 1 0 +auth/ent/client.go:388.62,390.2 1 0 +auth/ent/client.go:393.45,396.2 2 13 +auth/ent/client.go:399.77,401.2 1 0 +auth/ent/client.go:405.98,407.32 2 0 +auth/ent/client.go:407.32,409.3 1 0 +auth/ent/client.go:410.2,411.32 2 0 +auth/ent/client.go:411.32,414.3 2 0 +auth/ent/client.go:415.2,415.63 1 0 +auth/ent/client.go:419.45,422.2 2 4 +auth/ent/client.go:425.59,428.2 2 1 +auth/ent/client.go:431.62,434.2 2 0 +auth/ent/client.go:437.45,440.2 2 1 +auth/ent/client.go:443.59,445.2 1 0 +auth/ent/client.go:448.62,453.2 4 0 +auth/ent/client.go:456.43,462.2 1 10 +auth/ent/client.go:465.75,467.2 1 4 +auth/ent/client.go:470.67,472.16 2 0 +auth/ent/client.go:472.16,473.13 1 0 +auth/ent/client.go:475.2,475.12 1 0 +auth/ent/client.go:479.54,481.68 2 1 +auth/ent/client.go:481.68,490.3 4 1 +auth/ent/client.go:491.2,491.14 1 1 +auth/ent/client.go:495.38,497.2 1 19 +auth/ent/client.go:500.52,502.2 1 10 +auth/ent/client.go:504.84,505.16 1 0 +auth/ent/client.go:506.16,507.83 1 0 +auth/ent/client.go:508.16,509.83 1 0 +auth/ent/client.go:510.19,511.86 1 0 +auth/ent/client.go:512.29,513.83 1 0 +auth/ent/client.go:514.10,515.71 1 0 +auth/ent/client.go:525.42,527.2 1 8 +auth/ent/client.go:531.41,533.2 1 0 +auth/ent/client.go:537.61,539.2 1 0 +auth/ent/client.go:542.43,545.2 2 44 +auth/ent/client.go:548.74,550.2 1 0 +auth/ent/client.go:554.95,556.32 2 0 +auth/ent/client.go:556.32,558.3 1 0 +auth/ent/client.go:559.2,560.32 2 0 +auth/ent/client.go:560.32,563.3 2 0 +auth/ent/client.go:564.2,564.62 1 0 +auth/ent/client.go:568.43,571.2 2 0 +auth/ent/client.go:574.56,577.2 2 3 +auth/ent/client.go:580.60,583.2 2 10 +auth/ent/client.go:586.43,589.2 2 3 +auth/ent/client.go:592.56,594.2 1 0 +auth/ent/client.go:597.60,602.2 4 2 +auth/ent/client.go:605.41,611.2 1 30 +auth/ent/client.go:614.73,616.2 1 1 +auth/ent/client.go:619.65,621.16 2 0 +auth/ent/client.go:621.16,622.13 1 0 +auth/ent/client.go:624.2,624.12 1 0 +auth/ent/client.go:628.53,630.68 2 1 +auth/ent/client.go:630.68,639.3 4 1 +auth/ent/client.go:640.2,640.14 1 1 +auth/ent/client.go:644.55,646.68 2 1 +auth/ent/client.go:646.68,655.3 4 1 +auth/ent/client.go:656.2,656.14 1 1 +auth/ent/client.go:660.37,663.2 2 60 +auth/ent/client.go:666.51,668.2 1 30 +auth/ent/client.go:670.82,671.16 1 0 +auth/ent/client.go:672.16,673.82 1 0 +auth/ent/client.go:674.16,675.82 1 0 +auth/ent/client.go:676.19,677.85 1 0 +auth/ent/client.go:678.29,679.82 1 0 +auth/ent/client.go:680.10,681.70 1 0 +auth/ent/ent.go:42.47,45.2 2 0 +auth/ent/ent.go:48.68,50.2 1 0 +auth/ent/ent.go:55.45,58.2 2 0 +auth/ent/ent.go:61.67,63.2 1 0 +auth/ent/ent.go:75.46,76.22 1 0 +auth/ent/ent.go:76.22,82.3 1 0 +auth/ent/ent.go:83.2,83.35 1 0 +auth/ent/ent.go:87.48,88.31 1 0 +auth/ent/ent.go:88.31,89.28 1 0 +auth/ent/ent.go:89.28,90.56 1 0 +auth/ent/ent.go:90.56,92.5 1 0 +auth/ent/ent.go:93.4,93.30 1 0 +auth/ent/ent.go:99.49,100.31 1 0 +auth/ent/ent.go:100.31,101.28 1 0 +auth/ent/ent.go:101.28,102.56 1 0 +auth/ent/ent.go:102.56,104.5 1 0 +auth/ent/ent.go:105.4,105.31 1 0 +auth/ent/ent.go:118.53,119.38 1 0 +auth/ent/ent.go:119.38,121.3 1 0 +auth/ent/ent.go:125.28,126.38 1 0 +auth/ent/ent.go:126.38,128.3 1 0 +auth/ent/ent.go:132.38,133.38 1 0 +auth/ent/ent.go:133.38,134.59 1 0 +auth/ent/ent.go:134.59,137.4 2 0 +auth/ent/ent.go:138.3,138.29 1 0 +auth/ent/ent.go:143.39,144.38 1 0 +auth/ent/ent.go:144.38,145.59 1 0 +auth/ent/ent.go:145.59,148.4 2 0 +auth/ent/ent.go:149.3,149.29 1 0 +auth/ent/ent.go:154.38,155.38 1 0 +auth/ent/ent.go:155.38,156.59 1 0 +auth/ent/ent.go:156.59,159.4 2 0 +auth/ent/ent.go:160.3,160.29 1 0 +auth/ent/ent.go:165.38,166.38 1 0 +auth/ent/ent.go:166.38,167.59 1 0 +auth/ent/ent.go:167.59,170.4 2 0 +auth/ent/ent.go:171.3,171.29 1 0 +auth/ent/ent.go:182.42,184.2 1 0 +auth/ent/ent.go:187.42,189.2 1 0 +auth/ent/ent.go:192.40,193.16 1 0 +auth/ent/ent.go:193.16,195.3 1 0 +auth/ent/ent.go:196.2,197.27 2 0 +auth/ent/ent.go:206.40,208.2 1 0 +auth/ent/ent.go:211.33,212.16 1 1 +auth/ent/ent.go:212.16,214.3 1 0 +auth/ent/ent.go:215.2,216.27 2 1 +auth/ent/ent.go:220.36,221.21 1 0 +auth/ent/ent.go:221.21,223.3 1 0 +auth/ent/ent.go:224.2,224.12 1 0 +auth/ent/ent.go:233.43,235.2 1 0 +auth/ent/ent.go:238.36,239.16 1 0 +auth/ent/ent.go:239.16,241.3 1 0 +auth/ent/ent.go:242.2,243.27 2 0 +auth/ent/ent.go:252.41,254.2 1 0 +auth/ent/ent.go:257.34,258.16 1 0 +auth/ent/ent.go:258.16,260.3 1 0 +auth/ent/ent.go:261.2,262.27 2 0 +auth/ent/ent.go:274.41,276.2 1 4 +auth/ent/ent.go:279.42,281.2 1 0 +auth/ent/ent.go:284.40,285.16 1 0 +auth/ent/ent.go:285.16,287.3 1 0 +auth/ent/ent.go:288.2,289.27 2 0 +auth/ent/ent.go:301.54,302.39 1 0 +auth/ent/ent.go:302.39,303.13 1 0 +auth/ent/ent.go:308.67,309.22 1 0 +auth/ent/ent.go:309.22,311.3 1 0 +auth/ent/ent.go:312.2,313.40 2 0 +auth/ent/ent.go:313.40,315.3 1 0 +auth/ent/ent.go:316.2,316.15 1 0 +auth/ent/ent.go:320.59,322.16 2 0 +auth/ent/ent.go:322.16,323.13 1 0 +auth/ent/ent.go:325.2,325.10 1 0 +auth/ent/ent.go:329.70,331.41 2 0 +auth/ent/ent.go:331.41,333.3 1 0 +auth/ent/ent.go:334.2,334.16 1 0 +auth/ent/ent.go:335.9,336.19 1 0 +auth/ent/ent.go:337.9,338.32 1 0 +auth/ent/ent.go:339.10,340.85 1 0 +auth/ent/ent.go:342.2,342.8 1 0 +auth/ent/ent.go:346.56,348.16 2 0 +auth/ent/ent.go:348.16,349.13 1 0 +auth/ent/ent.go:351.2,351.10 1 0 +auth/ent/ent.go:355.61,356.22 1 0 +auth/ent/ent.go:356.22,358.3 1 0 +auth/ent/ent.go:359.2,360.40 2 0 +auth/ent/ent.go:360.40,362.3 1 0 +auth/ent/ent.go:363.2,363.15 1 0 +auth/ent/ent.go:367.53,369.16 2 0 +auth/ent/ent.go:369.16,370.13 1 0 +auth/ent/ent.go:372.2,372.10 1 0 +auth/ent/ent.go:376.64,378.38 2 0 +auth/ent/ent.go:378.38,380.3 1 0 +auth/ent/ent.go:381.2,381.16 1 0 +auth/ent/ent.go:382.9,383.19 1 0 +auth/ent/ent.go:384.9,385.32 1 0 +auth/ent/ent.go:386.10,387.82 1 0 +auth/ent/ent.go:389.2,389.8 1 0 +auth/ent/ent.go:393.50,395.16 2 0 +auth/ent/ent.go:395.16,396.13 1 0 +auth/ent/ent.go:398.2,398.10 1 0 +auth/ent/ent.go:402.69,403.22 1 0 +auth/ent/ent.go:403.22,405.3 1 0 +auth/ent/ent.go:406.2,407.40 2 0 +auth/ent/ent.go:407.40,409.3 1 0 +auth/ent/ent.go:410.2,410.15 1 0 +auth/ent/ent.go:414.61,416.16 2 0 +auth/ent/ent.go:416.16,417.13 1 0 +auth/ent/ent.go:419.2,419.10 1 0 +auth/ent/ent.go:423.72,425.42 2 0 +auth/ent/ent.go:425.42,427.3 1 0 +auth/ent/ent.go:428.2,428.16 1 0 +auth/ent/ent.go:429.9,430.19 1 0 +auth/ent/ent.go:431.9,432.32 1 0 +auth/ent/ent.go:433.10,434.86 1 0 +auth/ent/ent.go:436.2,436.8 1 0 +auth/ent/ent.go:440.58,442.16 2 0 +auth/ent/ent.go:442.16,443.13 1 0 +auth/ent/ent.go:445.2,445.10 1 0 +auth/ent/ent.go:449.63,450.22 1 0 +auth/ent/ent.go:450.22,452.3 1 0 +auth/ent/ent.go:453.2,454.40 2 0 +auth/ent/ent.go:454.40,456.3 1 0 +auth/ent/ent.go:457.2,457.15 1 0 +auth/ent/ent.go:461.55,463.16 2 0 +auth/ent/ent.go:463.16,464.13 1 0 +auth/ent/ent.go:466.2,466.10 1 0 +auth/ent/ent.go:470.66,472.39 2 0 +auth/ent/ent.go:472.39,474.3 1 0 +auth/ent/ent.go:475.2,475.16 1 0 +auth/ent/ent.go:476.9,477.19 1 0 +auth/ent/ent.go:478.9,479.32 1 0 +auth/ent/ent.go:480.10,481.83 1 0 +auth/ent/ent.go:483.2,483.8 1 0 +auth/ent/ent.go:487.52,489.16 2 0 +auth/ent/ent.go:489.16,490.13 1 0 +auth/ent/ent.go:492.2,492.10 1 0 +auth/ent/ent.go:499.112,500.21 1 120 +auth/ent/ent.go:500.21,502.3 1 60 +auth/ent/ent.go:503.2,503.84 1 60 +auth/ent/ent.go:503.84,505.10 2 60 +auth/ent/ent.go:505.10,507.4 1 0 +auth/ent/ent.go:509.3,510.19 2 60 +auth/ent/ent.go:512.2,512.39 1 60 +auth/ent/ent.go:512.39,513.22 1 60 +auth/ent/ent.go:513.22,515.4 1 0 +auth/ent/ent.go:516.3,516.22 1 60 +auth/ent/ent.go:518.2,519.16 2 60 +auth/ent/ent.go:519.16,521.3 1 2 +auth/ent/ent.go:522.2,523.9 2 58 +auth/ent/ent.go:523.9,525.3 1 0 +auth/ent/ent.go:526.2,526.16 1 58 +auth/ent/ent.go:530.85,531.38 1 90 +auth/ent/ent.go:531.38,534.3 2 54 +auth/ent/ent.go:535.2,535.12 1 90 +auth/ent/ent.go:540.14,541.71 1 50 +auth/ent/ent.go:541.71,543.10 2 50 +auth/ent/ent.go:543.10,545.4 1 0 +auth/ent/ent.go:546.3,546.27 1 50 +auth/ent/ent.go:552.14,553.71 1 4 +auth/ent/ent.go:553.71,555.10 2 4 +auth/ent/ent.go:555.10,557.4 1 0 +auth/ent/ent.go:558.3,558.29 1 4 +auth/ent/ent.go:562.113,563.40 1 58 +auth/ent/ent.go:563.40,565.3 1 0 +auth/ent/ent.go:566.2,567.16 2 58 +auth/ent/ent.go:567.16,569.3 1 0 +auth/ent/ent.go:570.2,571.9 2 58 +auth/ent/ent.go:571.9,573.3 1 0 +auth/ent/ent.go:574.2,574.16 1 58 +auth/ent/ent.go:579.92,581.81 2 0 +auth/ent/ent.go:581.81,583.10 2 0 +auth/ent/ent.go:583.10,585.4 1 0 +auth/ent/ent.go:586.3,586.62 1 0 +auth/ent/ent.go:586.62,588.4 1 0 +auth/ent/ent.go:589.3,589.71 1 0 +auth/ent/ent.go:589.71,591.4 1 0 +auth/ent/ent.go:592.3,592.16 1 0 +auth/ent/ent.go:594.2,594.40 1 0 +auth/ent/ent.go:594.40,596.3 1 0 +auth/ent/ent.go:597.2,598.16 2 0 +auth/ent/ent.go:598.16,600.3 1 0 +auth/ent/ent.go:601.2,601.37 1 0 +auth/ent/ent.go:602.61,602.61 0 0 +auth/ent/ent.go:603.31,604.28 1 0 +auth/ent/ent.go:605.38,606.21 1 0 +auth/ent/ent.go:608.2,608.12 1 0 +auth/ent/mutation.go:60.73,67.27 2 41 +auth/ent/mutation.go:67.27,69.3 1 4 +auth/ent/mutation.go:70.2,70.10 1 41 +auth/ent/mutation.go:74.39,75.31 1 3 +auth/ent/mutation.go:75.31,81.57 2 3 +auth/ent/mutation.go:81.57,82.19 1 0 +auth/ent/mutation.go:82.19,83.15 1 0 +auth/ent/mutation.go:83.15,85.6 1 0 +auth/ent/mutation.go:85.11,87.6 1 0 +auth/ent/mutation.go:89.4,89.21 1 0 +auth/ent/mutation.go:91.3,91.13 1 3 +auth/ent/mutation.go:96.38,97.31 1 1 +auth/ent/mutation.go:97.31,98.53 1 1 +auth/ent/mutation.go:98.53,100.4 1 0 +auth/ent/mutation.go:101.3,101.18 1 1 +auth/ent/mutation.go:107.40,111.2 3 0 +auth/ent/mutation.go:115.41,116.40 1 0 +auth/ent/mutation.go:116.40,118.3 1 0 +auth/ent/mutation.go:119.2,121.16 3 0 +auth/ent/mutation.go:126.41,128.2 1 34 +auth/ent/mutation.go:132.54,133.17 1 72 +auth/ent/mutation.go:133.17,135.3 1 34 +auth/ent/mutation.go:136.2,136.20 1 38 +auth/ent/mutation.go:143.67,144.9 1 0 +auth/ent/mutation.go:145.42,147.13 2 0 +auth/ent/mutation.go:147.13,149.4 1 0 +auth/ent/mutation.go:150.3,150.14 1 0 +auth/ent/mutation.go:151.36,152.65 1 0 +auth/ent/mutation.go:153.10,154.70 1 0 +auth/ent/mutation.go:159.42,161.2 1 35 +auth/ent/mutation.go:164.55,166.14 2 72 +auth/ent/mutation.go:166.14,168.3 1 3 +auth/ent/mutation.go:169.2,169.17 1 69 +auth/ent/mutation.go:175.75,176.27 1 0 +auth/ent/mutation.go:176.27,178.3 1 0 +auth/ent/mutation.go:179.2,179.38 1 0 +auth/ent/mutation.go:179.38,181.3 1 0 +auth/ent/mutation.go:182.2,183.16 2 0 +auth/ent/mutation.go:183.16,185.3 1 0 +auth/ent/mutation.go:186.2,186.27 1 0 +auth/ent/mutation.go:190.36,192.2 1 0 +auth/ent/mutation.go:195.51,198.2 2 36 +auth/ent/mutation.go:201.64,203.14 2 72 +auth/ent/mutation.go:203.14,205.3 1 2 +auth/ent/mutation.go:206.2,206.17 1 70 +auth/ent/mutation.go:212.84,213.27 1 0 +auth/ent/mutation.go:213.27,215.3 1 0 +auth/ent/mutation.go:216.2,216.38 1 0 +auth/ent/mutation.go:216.38,218.3 1 0 +auth/ent/mutation.go:219.2,220.16 2 0 +auth/ent/mutation.go:220.16,222.3 1 0 +auth/ent/mutation.go:223.2,223.34 1 0 +auth/ent/mutation.go:227.54,229.2 1 1 +auth/ent/mutation.go:232.63,233.35 1 4 +auth/ent/mutation.go:233.35,235.3 1 3 +auth/ent/mutation.go:236.2,236.34 1 1 +auth/ent/mutation.go:240.43,243.2 2 0 +auth/ent/mutation.go:246.50,248.2 1 34 +auth/ent/mutation.go:251.63,253.14 2 106 +auth/ent/mutation.go:253.14,255.3 1 38 +auth/ent/mutation.go:256.2,256.17 1 68 +auth/ent/mutation.go:262.83,263.27 1 0 +auth/ent/mutation.go:263.27,265.3 1 0 +auth/ent/mutation.go:266.2,266.38 1 0 +auth/ent/mutation.go:266.38,268.3 1 0 +auth/ent/mutation.go:269.2,270.16 2 0 +auth/ent/mutation.go:270.16,272.3 1 0 +auth/ent/mutation.go:273.2,273.32 1 0 +auth/ent/mutation.go:277.41,279.2 1 0 +auth/ent/mutation.go:282.50,284.2 1 38 +auth/ent/mutation.go:287.63,289.14 2 110 +auth/ent/mutation.go:289.14,291.3 1 37 +auth/ent/mutation.go:292.2,292.17 1 73 +auth/ent/mutation.go:298.83,299.27 1 0 +auth/ent/mutation.go:299.27,301.3 1 0 +auth/ent/mutation.go:302.2,302.38 1 0 +auth/ent/mutation.go:302.38,304.3 1 0 +auth/ent/mutation.go:305.2,306.16 2 0 +auth/ent/mutation.go:306.16,308.3 1 0 +auth/ent/mutation.go:309.2,309.32 1 0 +auth/ent/mutation.go:313.41,315.2 1 0 +auth/ent/mutation.go:318.50,319.20 1 2 +auth/ent/mutation.go:319.20,321.3 1 2 +auth/ent/mutation.go:322.2,322.21 1 2 +auth/ent/mutation.go:322.21,324.3 1 2 +auth/ent/mutation.go:328.37,330.2 1 0 +auth/ent/mutation.go:333.44,335.2 1 4 +auth/ent/mutation.go:338.53,339.27 1 0 +auth/ent/mutation.go:339.27,341.3 1 0 +auth/ent/mutation.go:342.2,342.21 1 0 +auth/ent/mutation.go:342.21,345.3 2 0 +auth/ent/mutation.go:349.57,350.33 1 4 +auth/ent/mutation.go:350.33,352.3 1 0 +auth/ent/mutation.go:353.2,353.8 1 4 +auth/ent/mutation.go:357.50,358.26 1 38 +auth/ent/mutation.go:358.26,360.3 1 2 +auth/ent/mutation.go:361.2,361.8 1 38 +auth/ent/mutation.go:365.37,369.2 3 0 +auth/ent/mutation.go:372.52,374.2 1 1 +auth/ent/mutation.go:378.58,380.20 2 0 +auth/ent/mutation.go:380.20,382.3 1 0 +auth/ent/mutation.go:383.2,383.15 1 0 +auth/ent/mutation.go:387.32,389.2 1 0 +auth/ent/mutation.go:392.37,394.2 1 0 +auth/ent/mutation.go:397.38,399.2 1 0 +auth/ent/mutation.go:404.42,406.19 2 0 +auth/ent/mutation.go:406.19,408.3 1 0 +auth/ent/mutation.go:409.2,409.26 1 0 +auth/ent/mutation.go:409.26,411.3 1 0 +auth/ent/mutation.go:412.2,412.25 1 0 +auth/ent/mutation.go:412.25,414.3 1 0 +auth/ent/mutation.go:415.2,415.25 1 0 +auth/ent/mutation.go:415.25,417.3 1 0 +auth/ent/mutation.go:418.2,418.15 1 0 +auth/ent/mutation.go:424.61,425.14 1 0 +auth/ent/mutation.go:426.22,427.18 1 0 +auth/ent/mutation.go:428.29,429.25 1 0 +auth/ent/mutation.go:430.27,431.23 1 0 +auth/ent/mutation.go:432.27,433.23 1 0 +auth/ent/mutation.go:435.2,435.19 1 0 +auth/ent/mutation.go:441.86,442.14 1 0 +auth/ent/mutation.go:443.22,444.24 1 0 +auth/ent/mutation.go:445.29,446.31 1 0 +auth/ent/mutation.go:447.27,448.29 1 0 +auth/ent/mutation.go:449.27,450.29 1 0 +auth/ent/mutation.go:452.2,452.55 1 0 +auth/ent/mutation.go:458.69,459.14 1 0 +auth/ent/mutation.go:460.22,462.10 2 0 +auth/ent/mutation.go:462.10,464.4 1 0 +auth/ent/mutation.go:465.3,466.13 2 0 +auth/ent/mutation.go:467.29,469.10 2 0 +auth/ent/mutation.go:469.10,471.4 1 0 +auth/ent/mutation.go:472.3,473.13 2 0 +auth/ent/mutation.go:474.27,476.10 2 0 +auth/ent/mutation.go:476.10,478.4 1 0 +auth/ent/mutation.go:479.3,480.13 2 0 +auth/ent/mutation.go:481.27,483.10 2 0 +auth/ent/mutation.go:483.10,485.4 1 0 +auth/ent/mutation.go:486.3,487.13 2 0 +auth/ent/mutation.go:489.2,489.50 1 0 +auth/ent/mutation.go:494.47,496.2 1 0 +auth/ent/mutation.go:501.66,503.2 1 0 +auth/ent/mutation.go:508.69,509.14 1 0 +auth/ent/mutation.go:511.2,511.58 1 0 +auth/ent/mutation.go:516.49,518.2 1 0 +auth/ent/mutation.go:522.55,525.2 2 0 +auth/ent/mutation.go:529.54,531.2 1 0 +auth/ent/mutation.go:535.54,536.14 1 0 +auth/ent/mutation.go:537.22,539.13 2 0 +auth/ent/mutation.go:540.29,542.13 2 0 +auth/ent/mutation.go:543.27,545.13 2 0 +auth/ent/mutation.go:546.27,548.13 2 0 +auth/ent/mutation.go:550.2,550.50 1 0 +auth/ent/mutation.go:554.46,556.20 2 0 +auth/ent/mutation.go:556.20,558.3 1 0 +auth/ent/mutation.go:559.2,559.14 1 0 +auth/ent/mutation.go:564.58,565.14 1 0 +auth/ent/mutation.go:566.22,568.27 2 0 +auth/ent/mutation.go:568.27,570.4 1 0 +auth/ent/mutation.go:571.3,571.13 1 0 +auth/ent/mutation.go:573.2,573.12 1 0 +auth/ent/mutation.go:577.48,579.27 2 0 +auth/ent/mutation.go:579.27,581.3 1 0 +auth/ent/mutation.go:582.2,582.14 1 0 +auth/ent/mutation.go:587.60,588.14 1 0 +auth/ent/mutation.go:589.22,591.34 2 0 +auth/ent/mutation.go:591.34,593.4 1 0 +auth/ent/mutation.go:594.3,594.13 1 0 +auth/ent/mutation.go:596.2,596.12 1 0 +auth/ent/mutation.go:600.48,602.20 2 0 +auth/ent/mutation.go:602.20,604.3 1 0 +auth/ent/mutation.go:605.2,605.14 1 0 +auth/ent/mutation.go:610.54,611.14 1 0 +auth/ent/mutation.go:612.22,613.24 1 0 +auth/ent/mutation.go:615.2,615.14 1 0 +auth/ent/mutation.go:620.53,621.14 1 0 +auth/ent/mutation.go:623.2,623.56 1 0 +auth/ent/mutation.go:628.53,629.14 1 0 +auth/ent/mutation.go:630.22,632.13 2 0 +auth/ent/mutation.go:634.2,634.49 1 0 +auth/ent/mutation.go:663.76,670.27 2 19 +auth/ent/mutation.go:670.27,672.3 1 1 +auth/ent/mutation.go:673.2,673.10 1 19 +auth/ent/mutation.go:677.41,678.32 1 0 +auth/ent/mutation.go:678.32,684.58 2 0 +auth/ent/mutation.go:684.58,685.19 1 0 +auth/ent/mutation.go:685.19,686.15 1 0 +auth/ent/mutation.go:686.15,688.6 1 0 +auth/ent/mutation.go:688.11,690.6 1 0 +auth/ent/mutation.go:692.4,692.21 1 0 +auth/ent/mutation.go:694.3,694.13 1 0 +auth/ent/mutation.go:699.41,700.32 1 1 +auth/ent/mutation.go:700.32,701.54 1 1 +auth/ent/mutation.go:701.54,703.4 1 0 +auth/ent/mutation.go:704.3,704.18 1 1 +auth/ent/mutation.go:710.41,714.2 3 0 +auth/ent/mutation.go:718.42,719.40 1 0 +auth/ent/mutation.go:719.40,721.3 1 0 +auth/ent/mutation.go:722.2,724.16 3 0 +auth/ent/mutation.go:729.42,731.2 1 13 +auth/ent/mutation.go:735.55,736.17 1 27 +auth/ent/mutation.go:736.17,738.3 1 13 +auth/ent/mutation.go:739.2,739.20 1 14 +auth/ent/mutation.go:746.68,747.9 1 0 +auth/ent/mutation.go:748.42,750.13 2 0 +auth/ent/mutation.go:750.13,752.4 1 0 +auth/ent/mutation.go:753.3,753.14 1 0 +auth/ent/mutation.go:754.36,755.66 1 0 +auth/ent/mutation.go:756.10,757.70 1 0 +auth/ent/mutation.go:762.44,764.2 1 13 +auth/ent/mutation.go:767.57,769.14 2 31 +auth/ent/mutation.go:769.14,771.3 1 5 +auth/ent/mutation.go:772.2,772.17 1 26 +auth/ent/mutation.go:778.77,779.27 1 0 +auth/ent/mutation.go:779.27,781.3 1 0 +auth/ent/mutation.go:782.2,782.38 1 0 +auth/ent/mutation.go:782.38,784.3 1 0 +auth/ent/mutation.go:785.2,786.16 2 0 +auth/ent/mutation.go:786.16,788.3 1 0 +auth/ent/mutation.go:789.2,789.28 1 0 +auth/ent/mutation.go:793.38,795.2 1 0 +auth/ent/mutation.go:798.47,800.2 1 13 +auth/ent/mutation.go:803.63,805.14 2 49 +auth/ent/mutation.go:805.14,807.3 1 10 +auth/ent/mutation.go:808.2,808.17 1 39 +auth/ent/mutation.go:814.80,815.27 1 0 +auth/ent/mutation.go:815.27,817.3 1 0 +auth/ent/mutation.go:818.2,818.38 1 0 +auth/ent/mutation.go:818.38,820.3 1 0 +auth/ent/mutation.go:821.2,822.16 2 0 +auth/ent/mutation.go:822.16,824.3 1 0 +auth/ent/mutation.go:825.2,825.27 1 0 +auth/ent/mutation.go:829.37,831.2 1 0 +auth/ent/mutation.go:834.51,836.2 1 13 +auth/ent/mutation.go:839.64,841.14 2 31 +auth/ent/mutation.go:841.14,843.3 1 5 +auth/ent/mutation.go:844.2,844.17 1 26 +auth/ent/mutation.go:850.84,851.27 1 0 +auth/ent/mutation.go:851.27,853.3 1 0 +auth/ent/mutation.go:854.2,854.38 1 0 +auth/ent/mutation.go:854.38,856.3 1 0 +auth/ent/mutation.go:857.2,858.16 2 0 +auth/ent/mutation.go:858.16,860.3 1 0 +auth/ent/mutation.go:861.2,861.32 1 0 +auth/ent/mutation.go:865.42,867.2 1 0 +auth/ent/mutation.go:870.44,872.2 1 18 +auth/ent/mutation.go:875.57,877.14 2 44 +auth/ent/mutation.go:877.14,879.3 1 13 +auth/ent/mutation.go:880.2,880.17 1 31 +auth/ent/mutation.go:886.77,887.27 1 0 +auth/ent/mutation.go:887.27,889.3 1 0 +auth/ent/mutation.go:890.2,890.38 1 0 +auth/ent/mutation.go:890.38,892.3 1 0 +auth/ent/mutation.go:893.2,894.16 2 0 +auth/ent/mutation.go:894.16,896.3 1 0 +auth/ent/mutation.go:897.2,897.30 1 0 +auth/ent/mutation.go:901.40,903.2 1 0 +auth/ent/mutation.go:906.51,908.2 1 13 +auth/ent/mutation.go:911.64,913.14 2 44 +auth/ent/mutation.go:913.14,915.3 1 18 +auth/ent/mutation.go:916.2,916.17 1 26 +auth/ent/mutation.go:922.84,923.27 1 0 +auth/ent/mutation.go:923.27,925.3 1 0 +auth/ent/mutation.go:926.2,926.38 1 0 +auth/ent/mutation.go:926.38,928.3 1 0 +auth/ent/mutation.go:929.2,930.16 2 0 +auth/ent/mutation.go:930.16,932.3 1 0 +auth/ent/mutation.go:933.2,933.32 1 0 +auth/ent/mutation.go:937.42,939.2 1 0 +auth/ent/mutation.go:942.51,944.2 1 18 +auth/ent/mutation.go:947.64,949.14 2 49 +auth/ent/mutation.go:949.14,951.3 1 18 +auth/ent/mutation.go:952.2,952.17 1 31 +auth/ent/mutation.go:958.84,959.27 1 0 +auth/ent/mutation.go:959.27,961.3 1 0 +auth/ent/mutation.go:962.2,962.38 1 0 +auth/ent/mutation.go:962.38,964.3 1 0 +auth/ent/mutation.go:965.2,966.16 2 0 +auth/ent/mutation.go:966.16,968.3 1 0 +auth/ent/mutation.go:969.2,969.32 1 0 +auth/ent/mutation.go:973.42,975.2 1 0 +auth/ent/mutation.go:978.46,980.2 1 13 +auth/ent/mutation.go:983.37,985.2 1 0 +auth/ent/mutation.go:988.44,990.2 1 10 +auth/ent/mutation.go:993.59,994.19 1 18 +auth/ent/mutation.go:994.19,996.3 1 13 +auth/ent/mutation.go:997.2,997.8 1 5 +auth/ent/mutation.go:1003.50,1004.29 1 18 +auth/ent/mutation.go:1004.29,1006.3 1 13 +auth/ent/mutation.go:1007.2,1007.8 1 18 +auth/ent/mutation.go:1011.37,1014.2 2 0 +auth/ent/mutation.go:1017.54,1019.2 1 5 +auth/ent/mutation.go:1023.59,1025.20 2 0 +auth/ent/mutation.go:1025.20,1027.3 1 0 +auth/ent/mutation.go:1028.2,1028.15 1 0 +auth/ent/mutation.go:1032.33,1034.2 1 0 +auth/ent/mutation.go:1037.38,1039.2 1 0 +auth/ent/mutation.go:1042.39,1044.2 1 0 +auth/ent/mutation.go:1049.43,1051.20 2 0 +auth/ent/mutation.go:1051.20,1053.3 1 0 +auth/ent/mutation.go:1054.2,1054.20 1 0 +auth/ent/mutation.go:1054.20,1056.3 1 0 +auth/ent/mutation.go:1057.2,1057.25 1 0 +auth/ent/mutation.go:1057.25,1059.3 1 0 +auth/ent/mutation.go:1060.2,1060.22 1 0 +auth/ent/mutation.go:1060.22,1062.3 1 0 +auth/ent/mutation.go:1063.2,1063.25 1 0 +auth/ent/mutation.go:1063.25,1065.3 1 0 +auth/ent/mutation.go:1066.2,1066.25 1 0 +auth/ent/mutation.go:1066.25,1068.3 1 0 +auth/ent/mutation.go:1069.2,1069.15 1 0 +auth/ent/mutation.go:1075.62,1076.14 1 0 +auth/ent/mutation.go:1077.24,1078.19 1 0 +auth/ent/mutation.go:1079.23,1080.21 1 0 +auth/ent/mutation.go:1081.28,1082.23 1 0 +auth/ent/mutation.go:1083.26,1084.21 1 0 +auth/ent/mutation.go:1085.28,1086.23 1 0 +auth/ent/mutation.go:1087.28,1088.23 1 0 +auth/ent/mutation.go:1090.2,1090.19 1 0 +auth/ent/mutation.go:1096.87,1097.14 1 0 +auth/ent/mutation.go:1098.24,1099.25 1 0 +auth/ent/mutation.go:1100.23,1101.24 1 0 +auth/ent/mutation.go:1102.28,1103.29 1 0 +auth/ent/mutation.go:1104.26,1105.27 1 0 +auth/ent/mutation.go:1106.28,1107.29 1 0 +auth/ent/mutation.go:1108.28,1109.29 1 0 +auth/ent/mutation.go:1111.2,1111.56 1 0 +auth/ent/mutation.go:1117.70,1118.14 1 0 +auth/ent/mutation.go:1119.24,1121.10 2 0 +auth/ent/mutation.go:1121.10,1123.4 1 0 +auth/ent/mutation.go:1124.3,1125.13 2 0 +auth/ent/mutation.go:1126.23,1128.10 2 0 +auth/ent/mutation.go:1128.10,1130.4 1 0 +auth/ent/mutation.go:1131.3,1132.13 2 0 +auth/ent/mutation.go:1133.28,1135.10 2 0 +auth/ent/mutation.go:1135.10,1137.4 1 0 +auth/ent/mutation.go:1138.3,1139.13 2 0 +auth/ent/mutation.go:1140.26,1142.10 2 0 +auth/ent/mutation.go:1142.10,1144.4 1 0 +auth/ent/mutation.go:1145.3,1146.13 2 0 +auth/ent/mutation.go:1147.28,1149.10 2 0 +auth/ent/mutation.go:1149.10,1151.4 1 0 +auth/ent/mutation.go:1152.3,1153.13 2 0 +auth/ent/mutation.go:1154.28,1156.10 2 0 +auth/ent/mutation.go:1156.10,1158.4 1 0 +auth/ent/mutation.go:1159.3,1160.13 2 0 +auth/ent/mutation.go:1162.2,1162.51 1 0 +auth/ent/mutation.go:1167.48,1169.2 1 0 +auth/ent/mutation.go:1174.67,1176.2 1 0 +auth/ent/mutation.go:1181.70,1182.14 1 0 +auth/ent/mutation.go:1184.2,1184.59 1 0 +auth/ent/mutation.go:1189.50,1191.2 1 0 +auth/ent/mutation.go:1195.56,1198.2 2 0 +auth/ent/mutation.go:1202.55,1204.2 1 0 +auth/ent/mutation.go:1208.55,1209.14 1 0 +auth/ent/mutation.go:1210.24,1212.13 2 0 +auth/ent/mutation.go:1213.23,1215.13 2 0 +auth/ent/mutation.go:1216.28,1218.13 2 0 +auth/ent/mutation.go:1219.26,1221.13 2 0 +auth/ent/mutation.go:1222.28,1224.13 2 0 +auth/ent/mutation.go:1225.28,1227.13 2 0 +auth/ent/mutation.go:1229.2,1229.51 1 0 +auth/ent/mutation.go:1233.47,1235.19 2 0 +auth/ent/mutation.go:1235.19,1237.3 1 0 +auth/ent/mutation.go:1238.2,1238.14 1 0 +auth/ent/mutation.go:1243.59,1244.14 1 0 +auth/ent/mutation.go:1245.22,1246.30 1 0 +auth/ent/mutation.go:1246.30,1248.4 1 0 +auth/ent/mutation.go:1250.2,1250.12 1 0 +auth/ent/mutation.go:1254.49,1257.2 2 0 +auth/ent/mutation.go:1261.61,1263.2 1 0 +auth/ent/mutation.go:1266.49,1268.19 2 0 +auth/ent/mutation.go:1268.19,1270.3 1 0 +auth/ent/mutation.go:1271.2,1271.14 1 0 +auth/ent/mutation.go:1276.55,1277.14 1 0 +auth/ent/mutation.go:1278.22,1279.23 1 0 +auth/ent/mutation.go:1281.2,1281.14 1 0 +auth/ent/mutation.go:1286.54,1287.14 1 0 +auth/ent/mutation.go:1288.22,1290.13 2 0 +auth/ent/mutation.go:1292.2,1292.57 1 0 +auth/ent/mutation.go:1297.54,1298.14 1 0 +auth/ent/mutation.go:1299.22,1301.13 2 0 +auth/ent/mutation.go:1303.2,1303.50 1 0 +auth/ent/mutation.go:1335.73,1342.27 2 60 +auth/ent/mutation.go:1342.27,1344.3 1 13 +auth/ent/mutation.go:1345.2,1345.10 1 60 +auth/ent/mutation.go:1349.39,1350.31 1 10 +auth/ent/mutation.go:1350.31,1356.57 2 10 +auth/ent/mutation.go:1356.57,1357.19 1 0 +auth/ent/mutation.go:1357.19,1358.15 1 0 +auth/ent/mutation.go:1358.15,1360.6 1 0 +auth/ent/mutation.go:1360.11,1362.6 1 0 +auth/ent/mutation.go:1364.4,1364.21 1 0 +auth/ent/mutation.go:1366.3,1366.13 1 10 +auth/ent/mutation.go:1371.38,1372.31 1 3 +auth/ent/mutation.go:1372.31,1373.53 1 3 +auth/ent/mutation.go:1373.53,1375.4 1 0 +auth/ent/mutation.go:1376.3,1376.18 1 3 +auth/ent/mutation.go:1382.40,1386.2 3 0 +auth/ent/mutation.go:1390.41,1391.40 1 0 +auth/ent/mutation.go:1391.40,1393.3 1 0 +auth/ent/mutation.go:1394.2,1396.16 3 0 +auth/ent/mutation.go:1401.41,1403.2 1 44 +auth/ent/mutation.go:1407.54,1408.17 1 101 +auth/ent/mutation.go:1408.17,1410.3 1 38 +auth/ent/mutation.go:1411.2,1411.20 1 63 +auth/ent/mutation.go:1418.67,1419.9 1 0 +auth/ent/mutation.go:1420.42,1422.13 2 0 +auth/ent/mutation.go:1422.13,1424.4 1 0 +auth/ent/mutation.go:1425.3,1425.14 1 0 +auth/ent/mutation.go:1426.36,1427.65 1 0 +auth/ent/mutation.go:1428.10,1429.70 1 0 +auth/ent/mutation.go:1434.46,1436.2 1 45 +auth/ent/mutation.go:1439.59,1441.14 2 101 +auth/ent/mutation.go:1441.14,1443.3 1 12 +auth/ent/mutation.go:1444.2,1444.17 1 89 +auth/ent/mutation.go:1450.79,1451.27 1 0 +auth/ent/mutation.go:1451.27,1453.3 1 0 +auth/ent/mutation.go:1454.2,1454.38 1 0 +auth/ent/mutation.go:1454.38,1456.3 1 0 +auth/ent/mutation.go:1457.2,1458.16 2 0 +auth/ent/mutation.go:1458.16,1460.3 1 0 +auth/ent/mutation.go:1461.2,1461.31 1 0 +auth/ent/mutation.go:1465.40,1467.2 1 0 +auth/ent/mutation.go:1470.43,1472.2 1 45 +auth/ent/mutation.go:1475.56,1477.14 2 101 +auth/ent/mutation.go:1477.14,1479.3 1 12 +auth/ent/mutation.go:1480.2,1480.17 1 89 +auth/ent/mutation.go:1486.76,1487.27 1 0 +auth/ent/mutation.go:1487.27,1489.3 1 0 +auth/ent/mutation.go:1490.2,1490.38 1 0 +auth/ent/mutation.go:1490.38,1492.3 1 0 +auth/ent/mutation.go:1493.2,1494.16 2 0 +auth/ent/mutation.go:1494.16,1496.3 1 0 +auth/ent/mutation.go:1497.2,1497.28 1 0 +auth/ent/mutation.go:1501.37,1503.2 1 0 +auth/ent/mutation.go:1506.46,1508.2 1 94 +auth/ent/mutation.go:1511.59,1513.14 2 161 +auth/ent/mutation.go:1513.14,1515.3 1 23 +auth/ent/mutation.go:1516.2,1516.17 1 138 +auth/ent/mutation.go:1522.79,1523.27 1 0 +auth/ent/mutation.go:1523.27,1525.3 1 0 +auth/ent/mutation.go:1526.2,1526.38 1 0 +auth/ent/mutation.go:1526.38,1528.3 1 0 +auth/ent/mutation.go:1529.2,1530.16 2 0 +auth/ent/mutation.go:1530.16,1532.3 1 0 +auth/ent/mutation.go:1533.2,1533.31 1 0 +auth/ent/mutation.go:1537.40,1539.2 1 0 +auth/ent/mutation.go:1542.50,1544.2 1 44 +auth/ent/mutation.go:1547.63,1549.14 2 145 +auth/ent/mutation.go:1549.14,1551.3 1 57 +auth/ent/mutation.go:1552.2,1552.17 1 88 +auth/ent/mutation.go:1558.83,1559.27 1 0 +auth/ent/mutation.go:1559.27,1561.3 1 0 +auth/ent/mutation.go:1562.2,1562.38 1 0 +auth/ent/mutation.go:1562.38,1564.3 1 0 +auth/ent/mutation.go:1565.2,1566.16 2 0 +auth/ent/mutation.go:1566.16,1568.3 1 0 +auth/ent/mutation.go:1569.2,1569.32 1 0 +auth/ent/mutation.go:1573.41,1575.2 1 0 +auth/ent/mutation.go:1578.50,1580.2 1 57 +auth/ent/mutation.go:1583.63,1585.14 2 158 +auth/ent/mutation.go:1585.14,1587.3 1 55 +auth/ent/mutation.go:1588.2,1588.17 1 103 +auth/ent/mutation.go:1594.83,1595.27 1 0 +auth/ent/mutation.go:1595.27,1597.3 1 0 +auth/ent/mutation.go:1598.2,1598.38 1 0 +auth/ent/mutation.go:1598.38,1600.3 1 0 +auth/ent/mutation.go:1601.2,1602.16 2 0 +auth/ent/mutation.go:1602.16,1604.3 1 0 +auth/ent/mutation.go:1605.2,1605.32 1 0 +auth/ent/mutation.go:1609.41,1611.2 1 0 +auth/ent/mutation.go:1614.50,1615.20 1 8 +auth/ent/mutation.go:1615.20,1617.3 1 8 +auth/ent/mutation.go:1618.2,1618.21 1 8 +auth/ent/mutation.go:1618.21,1620.3 1 8 +auth/ent/mutation.go:1624.37,1626.2 1 0 +auth/ent/mutation.go:1629.44,1631.2 1 15 +auth/ent/mutation.go:1634.53,1635.27 1 2 +auth/ent/mutation.go:1635.27,1637.3 1 2 +auth/ent/mutation.go:1638.2,1638.21 1 2 +auth/ent/mutation.go:1638.21,1641.3 2 2 +auth/ent/mutation.go:1645.57,1646.33 1 13 +auth/ent/mutation.go:1646.33,1648.3 1 2 +auth/ent/mutation.go:1649.2,1649.8 1 13 +auth/ent/mutation.go:1653.50,1654.26 1 57 +auth/ent/mutation.go:1654.26,1656.3 1 8 +auth/ent/mutation.go:1657.2,1657.8 1 57 +auth/ent/mutation.go:1661.37,1665.2 3 0 +auth/ent/mutation.go:1668.51,1669.21 1 0 +auth/ent/mutation.go:1669.21,1671.3 1 0 +auth/ent/mutation.go:1672.2,1672.21 1 0 +auth/ent/mutation.go:1672.21,1674.3 1 0 +auth/ent/mutation.go:1678.38,1680.2 1 0 +auth/ent/mutation.go:1683.45,1685.2 1 13 +auth/ent/mutation.go:1688.54,1689.28 1 0 +auth/ent/mutation.go:1689.28,1691.3 1 0 +auth/ent/mutation.go:1692.2,1692.21 1 0 +auth/ent/mutation.go:1692.21,1695.3 2 0 +auth/ent/mutation.go:1699.58,1700.34 1 13 +auth/ent/mutation.go:1700.34,1702.3 1 0 +auth/ent/mutation.go:1703.2,1703.8 1 13 +auth/ent/mutation.go:1707.51,1708.27 1 57 +auth/ent/mutation.go:1708.27,1710.3 1 0 +auth/ent/mutation.go:1711.2,1711.8 1 57 +auth/ent/mutation.go:1715.38,1719.2 3 0 +auth/ent/mutation.go:1722.52,1724.2 1 2 +auth/ent/mutation.go:1728.58,1730.20 2 0 +auth/ent/mutation.go:1730.20,1732.3 1 0 +auth/ent/mutation.go:1733.2,1733.15 1 0 +auth/ent/mutation.go:1737.32,1739.2 1 0 +auth/ent/mutation.go:1742.37,1744.2 1 0 +auth/ent/mutation.go:1747.38,1749.2 1 0 +auth/ent/mutation.go:1754.42,1756.23 2 0 +auth/ent/mutation.go:1756.23,1758.3 1 0 +auth/ent/mutation.go:1759.2,1759.20 1 0 +auth/ent/mutation.go:1759.20,1761.3 1 0 +auth/ent/mutation.go:1762.2,1762.23 1 0 +auth/ent/mutation.go:1762.23,1764.3 1 0 +auth/ent/mutation.go:1765.2,1765.25 1 0 +auth/ent/mutation.go:1765.25,1767.3 1 0 +auth/ent/mutation.go:1768.2,1768.25 1 0 +auth/ent/mutation.go:1768.25,1770.3 1 0 +auth/ent/mutation.go:1771.2,1771.15 1 0 +auth/ent/mutation.go:1777.61,1778.14 1 60 +auth/ent/mutation.go:1779.26,1780.22 1 0 +auth/ent/mutation.go:1781.23,1782.19 1 0 +auth/ent/mutation.go:1783.26,1784.22 1 60 +auth/ent/mutation.go:1785.27,1786.23 1 0 +auth/ent/mutation.go:1787.27,1788.23 1 0 +auth/ent/mutation.go:1790.2,1790.19 1 0 +auth/ent/mutation.go:1796.86,1797.14 1 0 +auth/ent/mutation.go:1798.26,1799.28 1 0 +auth/ent/mutation.go:1800.23,1801.25 1 0 +auth/ent/mutation.go:1802.26,1803.28 1 0 +auth/ent/mutation.go:1804.27,1805.29 1 0 +auth/ent/mutation.go:1806.27,1807.29 1 0 +auth/ent/mutation.go:1809.2,1809.55 1 0 +auth/ent/mutation.go:1815.69,1816.14 1 47 +auth/ent/mutation.go:1817.26,1819.10 2 0 +auth/ent/mutation.go:1819.10,1821.4 1 0 +auth/ent/mutation.go:1822.3,1823.13 2 0 +auth/ent/mutation.go:1824.23,1826.10 2 0 +auth/ent/mutation.go:1826.10,1828.4 1 0 +auth/ent/mutation.go:1829.3,1830.13 2 0 +auth/ent/mutation.go:1831.26,1833.10 2 47 +auth/ent/mutation.go:1833.10,1835.4 1 0 +auth/ent/mutation.go:1836.3,1837.13 2 47 +auth/ent/mutation.go:1838.27,1840.10 2 0 +auth/ent/mutation.go:1840.10,1842.4 1 0 +auth/ent/mutation.go:1843.3,1844.13 2 0 +auth/ent/mutation.go:1845.27,1847.10 2 0 +auth/ent/mutation.go:1847.10,1849.4 1 0 +auth/ent/mutation.go:1850.3,1851.13 2 0 +auth/ent/mutation.go:1853.2,1853.50 1 0 +auth/ent/mutation.go:1858.47,1860.2 1 0 +auth/ent/mutation.go:1865.66,1867.2 1 0 +auth/ent/mutation.go:1872.69,1873.14 1 0 +auth/ent/mutation.go:1875.2,1875.58 1 0 +auth/ent/mutation.go:1880.49,1882.2 1 0 +auth/ent/mutation.go:1886.55,1889.2 2 0 +auth/ent/mutation.go:1893.54,1895.2 1 0 +auth/ent/mutation.go:1899.54,1900.14 1 0 +auth/ent/mutation.go:1901.26,1903.13 2 0 +auth/ent/mutation.go:1904.23,1906.13 2 0 +auth/ent/mutation.go:1907.26,1909.13 2 0 +auth/ent/mutation.go:1910.27,1912.13 2 0 +auth/ent/mutation.go:1913.27,1915.13 2 0 +auth/ent/mutation.go:1917.2,1917.50 1 0 +auth/ent/mutation.go:1921.46,1923.20 2 0 +auth/ent/mutation.go:1923.20,1925.3 1 0 +auth/ent/mutation.go:1926.2,1926.21 1 0 +auth/ent/mutation.go:1926.21,1928.3 1 0 +auth/ent/mutation.go:1929.2,1929.14 1 0 +auth/ent/mutation.go:1934.58,1935.14 1 0 +auth/ent/mutation.go:1936.22,1938.27 2 0 +auth/ent/mutation.go:1938.27,1940.4 1 0 +auth/ent/mutation.go:1941.3,1941.13 1 0 +auth/ent/mutation.go:1942.23,1944.28 2 0 +auth/ent/mutation.go:1944.28,1946.4 1 0 +auth/ent/mutation.go:1947.3,1947.13 1 0 +auth/ent/mutation.go:1949.2,1949.12 1 0 +auth/ent/mutation.go:1953.48,1955.27 2 0 +auth/ent/mutation.go:1955.27,1957.3 1 0 +auth/ent/mutation.go:1958.2,1958.28 1 0 +auth/ent/mutation.go:1958.28,1960.3 1 0 +auth/ent/mutation.go:1961.2,1961.14 1 0 +auth/ent/mutation.go:1966.60,1967.14 1 0 +auth/ent/mutation.go:1968.22,1970.34 2 0 +auth/ent/mutation.go:1970.34,1972.4 1 0 +auth/ent/mutation.go:1973.3,1973.13 1 0 +auth/ent/mutation.go:1974.23,1976.35 2 0 +auth/ent/mutation.go:1976.35,1978.4 1 0 +auth/ent/mutation.go:1979.3,1979.13 1 0 +auth/ent/mutation.go:1981.2,1981.12 1 0 +auth/ent/mutation.go:1985.48,1987.20 2 0 +auth/ent/mutation.go:1987.20,1989.3 1 0 +auth/ent/mutation.go:1990.2,1990.21 1 0 +auth/ent/mutation.go:1990.21,1992.3 1 0 +auth/ent/mutation.go:1993.2,1993.14 1 0 +auth/ent/mutation.go:1998.54,1999.14 1 0 +auth/ent/mutation.go:2000.22,2001.24 1 0 +auth/ent/mutation.go:2002.23,2003.25 1 0 +auth/ent/mutation.go:2005.2,2005.14 1 0 +auth/ent/mutation.go:2010.53,2011.14 1 0 +auth/ent/mutation.go:2013.2,2013.56 1 0 +auth/ent/mutation.go:2018.53,2019.14 1 0 +auth/ent/mutation.go:2020.22,2022.13 2 0 +auth/ent/mutation.go:2023.23,2025.13 2 0 +auth/ent/mutation.go:2027.2,2027.49 1 0 +auth/ent/role.go:46.50,47.22 1 0 +auth/ent/role.go:47.22,49.3 1 0 +auth/ent/role.go:50.2,50.44 1 0 +auth/ent/role.go:54.58,56.25 2 21 +auth/ent/role.go:56.25,57.21 1 105 +auth/ent/role.go:58.30,59.27 1 21 +auth/ent/role.go:60.37,61.35 1 42 +auth/ent/role.go:62.49,63.33 1 42 +auth/ent/role.go:64.11,65.36 1 0 +auth/ent/role.go:68.2,68.20 1 21 +auth/ent/role.go:73.67,74.46 1 21 +auth/ent/role.go:74.46,76.3 1 0 +auth/ent/role.go:77.2,77.25 1 21 +auth/ent/role.go:77.25,78.21 1 105 +auth/ent/role.go:79.21,80.53 1 21 +auth/ent/role.go:80.53,82.5 1 0 +auth/ent/role.go:82.10,82.26 1 21 +auth/ent/role.go:82.26,84.5 1 21 +auth/ent/role.go:85.23,86.53 1 21 +auth/ent/role.go:86.53,88.5 1 0 +auth/ent/role.go:88.10,88.26 1 21 +auth/ent/role.go:88.26,90.5 1 21 +auth/ent/role.go:91.30,92.45 1 21 +auth/ent/role.go:92.45,94.5 1 0 +auth/ent/role.go:94.10,94.46 1 21 +auth/ent/role.go:94.46,95.66 1 21 +auth/ent/role.go:95.66,97.6 1 0 +auth/ent/role.go:99.28,100.51 1 21 +auth/ent/role.go:100.51,102.5 1 0 +auth/ent/role.go:102.10,102.26 1 21 +auth/ent/role.go:102.26,104.5 1 21 +auth/ent/role.go:105.28,106.51 1 21 +auth/ent/role.go:106.51,108.5 1 0 +auth/ent/role.go:108.10,108.26 1 21 +auth/ent/role.go:108.26,110.5 1 21 +auth/ent/role.go:111.11,112.45 1 0 +auth/ent/role.go:115.2,115.12 1 21 +auth/ent/role.go:120.54,122.2 1 0 +auth/ent/role.go:125.40,127.2 1 1 +auth/ent/role.go:132.40,134.2 1 0 +auth/ent/role.go:138.31,140.9 2 0 +auth/ent/role.go:140.9,141.51 1 0 +auth/ent/role.go:143.2,144.10 2 0 +auth/ent/role.go:148.32,165.2 16 0 +auth/ent/role_create.go:25.53,28.2 2 34 +auth/ent/role_create.go:31.62,34.2 2 34 +auth/ent/role_create.go:37.61,40.2 2 0 +auth/ent/role_create.go:43.70,44.14 1 0 +auth/ent/role_create.go:44.14,46.3 1 0 +auth/ent/role_create.go:47.2,47.11 1 0 +auth/ent/role_create.go:51.61,54.2 2 0 +auth/ent/role_create.go:57.70,58.14 1 0 +auth/ent/role_create.go:58.14,60.3 1 0 +auth/ent/role_create.go:61.2,61.11 1 0 +auth/ent/role_create.go:65.51,68.2 2 0 +auth/ent/role_create.go:71.60,72.14 1 0 +auth/ent/role_create.go:72.14,74.3 1 0 +auth/ent/role_create.go:75.2,75.11 1 0 +auth/ent/role_create.go:79.61,82.2 2 1 +auth/ent/role_create.go:85.56,87.19 2 1 +auth/ent/role_create.go:87.19,89.3 1 1 +auth/ent/role_create.go:90.2,90.30 1 1 +auth/ent/role_create.go:94.48,96.2 1 0 +auth/ent/role_create.go:99.64,102.2 2 34 +auth/ent/role_create.go:105.56,107.16 2 0 +auth/ent/role_create.go:107.16,108.13 1 0 +auth/ent/role_create.go:110.2,110.10 1 0 +auth/ent/role_create.go:114.55,117.2 2 0 +auth/ent/role_create.go:120.50,121.37 1 0 +auth/ent/role_create.go:121.37,122.13 1 0 +auth/ent/role_create.go:127.34,128.43 1 34 +auth/ent/role_create.go:128.43,131.3 2 34 +auth/ent/role_create.go:132.2,132.43 1 34 +auth/ent/role_create.go:132.43,135.3 2 34 +auth/ent/role_create.go:136.2,136.36 1 34 +auth/ent/role_create.go:136.36,139.3 2 34 +auth/ent/role_create.go:143.37,144.38 1 34 +auth/ent/role_create.go:144.38,146.3 1 0 +auth/ent/role_create.go:147.2,147.45 1 34 +auth/ent/role_create.go:147.45,149.3 1 0 +auth/ent/role_create.go:150.2,150.43 1 34 +auth/ent/role_create.go:150.43,152.3 1 0 +auth/ent/role_create.go:153.2,153.43 1 34 +auth/ent/role_create.go:153.43,155.3 1 0 +auth/ent/role_create.go:156.2,156.12 1 34 +auth/ent/role_create.go:159.67,160.35 1 34 +auth/ent/role_create.go:160.35,162.3 1 0 +auth/ent/role_create.go:163.2,164.67 2 34 +auth/ent/role_create.go:164.67,165.38 1 1 +auth/ent/role_create.go:165.38,167.4 1 1 +auth/ent/role_create.go:168.3,168.18 1 1 +auth/ent/role_create.go:170.2,170.27 1 33 +auth/ent/role_create.go:170.27,171.44 1 33 +auth/ent/role_create.go:171.44,173.4 1 33 +auth/ent/role_create.go:173.9,175.4 1 0 +auth/ent/role_create.go:177.2,179.19 3 33 +auth/ent/role_create.go:182.66,187.36 2 34 +auth/ent/role_create.go:187.36,190.3 2 34 +auth/ent/role_create.go:191.2,191.41 1 34 +auth/ent/role_create.go:191.41,194.3 2 34 +auth/ent/role_create.go:195.2,195.48 1 34 +auth/ent/role_create.go:195.48,198.3 2 34 +auth/ent/role_create.go:199.2,199.46 1 34 +auth/ent/role_create.go:199.46,202.3 2 34 +auth/ent/role_create.go:203.2,203.46 1 34 +auth/ent/role_create.go:203.46,206.3 2 34 +auth/ent/role_create.go:207.2,207.53 1 34 +auth/ent/role_create.go:207.53,218.27 2 1 +auth/ent/role_create.go:218.27,220.4 1 1 +auth/ent/role_create.go:221.3,221.42 1 1 +auth/ent/role_create.go:223.2,223.21 1 34 +auth/ent/role_create.go:234.71,235.20 1 0 +auth/ent/role_create.go:235.20,237.3 1 0 +auth/ent/role_create.go:238.2,241.30 4 0 +auth/ent/role_create.go:241.30,242.37 1 0 +auth/ent/role_create.go:242.37,245.86 3 0 +auth/ent/role_create.go:245.86,247.12 2 0 +auth/ent/role_create.go:247.12,249.6 1 0 +auth/ent/role_create.go:250.5,250.43 1 0 +auth/ent/role_create.go:250.43,252.6 1 0 +auth/ent/role_create.go:253.5,256.28 4 0 +auth/ent/role_create.go:256.28,258.6 1 0 +auth/ent/role_create.go:258.11,261.71 2 0 +auth/ent/role_create.go:261.71,262.42 1 0 +auth/ent/role_create.go:262.42,264.8 1 0 +auth/ent/role_create.go:267.5,267.19 1 0 +auth/ent/role_create.go:267.19,269.6 1 0 +auth/ent/role_create.go:270.5,272.25 3 0 +auth/ent/role_create.go:274.4,274.49 1 0 +auth/ent/role_create.go:274.49,276.5 1 0 +auth/ent/role_create.go:277.4,277.21 1 0 +auth/ent/role_create.go:280.2,280.23 1 0 +auth/ent/role_create.go:280.23,281.78 1 0 +auth/ent/role_create.go:281.78,283.4 1 0 +auth/ent/role_create.go:285.2,285.19 1 0 +auth/ent/role_create.go:289.63,291.16 2 0 +auth/ent/role_create.go:291.16,292.13 1 0 +auth/ent/role_create.go:294.2,294.10 1 0 +auth/ent/role_create.go:298.60,301.2 2 0 +auth/ent/role_create.go:304.55,305.38 1 0 +auth/ent/role_create.go:305.38,306.13 1 0 +auth/ent/role_delete.go:23.63,26.2 2 1 +auth/ent/role_delete.go:29.62,31.2 1 3 +auth/ent/role_delete.go:34.54,36.16 2 0 +auth/ent/role_delete.go:36.16,37.13 1 0 +auth/ent/role_delete.go:39.2,39.10 1 0 +auth/ent/role_delete.go:42.65,44.47 2 3 +auth/ent/role_delete.go:44.47,45.50 1 1 +auth/ent/role_delete.go:45.50,46.22 1 1 +auth/ent/role_delete.go:46.22,48.5 1 1 +auth/ent/role_delete.go:51.2,52.51 2 3 +auth/ent/role_delete.go:52.51,54.3 1 0 +auth/ent/role_delete.go:55.2,56.22 2 3 +auth/ent/role_delete.go:65.70,68.2 2 0 +auth/ent/role_delete.go:71.59,73.9 2 1 +auth/ent/role_delete.go:74.18,75.13 1 0 +auth/ent/role_delete.go:76.14,77.36 1 0 +auth/ent/role_delete.go:78.10,79.13 1 1 +auth/ent/role_delete.go:84.54,85.38 1 0 +auth/ent/role_delete.go:85.38,86.13 1 0 +auth/ent/role_query.go:33.61,36.2 2 14 +auth/ent/role_query.go:39.50,42.2 2 8 +auth/ent/role_query.go:45.52,48.2 2 1 +auth/ent/role_query.go:52.53,55.2 2 0 +auth/ent/role_query.go:58.62,61.2 2 0 +auth/ent/role_query.go:64.46,66.74 2 0 +auth/ent/role_query.go:66.74,67.46 1 0 +auth/ent/role_query.go:67.46,69.4 1 0 +auth/ent/role_query.go:70.3,71.40 2 0 +auth/ent/role_query.go:71.40,73.4 1 0 +auth/ent/role_query.go:74.3,80.20 3 0 +auth/ent/role_query.go:82.2,82.14 1 0 +auth/ent/role_query.go:87.64,89.16 2 0 +auth/ent/role_query.go:89.16,91.3 1 0 +auth/ent/role_query.go:92.2,92.21 1 0 +auth/ent/role_query.go:92.21,94.3 1 0 +auth/ent/role_query.go:95.2,95.22 1 0 +auth/ent/role_query.go:99.56,101.36 2 0 +auth/ent/role_query.go:101.36,102.13 1 0 +auth/ent/role_query.go:104.2,104.13 1 0 +auth/ent/role_query.go:109.74,111.82 2 0 +auth/ent/role_query.go:111.82,113.3 1 0 +auth/ent/role_query.go:114.2,114.19 1 0 +auth/ent/role_query.go:114.19,117.3 2 0 +auth/ent/role_query.go:118.2,118.20 1 0 +auth/ent/role_query.go:122.59,124.36 2 0 +auth/ent/role_query.go:124.36,125.13 1 0 +auth/ent/role_query.go:127.2,127.11 1 0 +auth/ent/role_query.go:133.63,135.16 2 7 +auth/ent/role_query.go:135.16,137.3 1 0 +auth/ent/role_query.go:138.2,138.20 1 7 +auth/ent/role_query.go:139.9,140.23 1 6 +auth/ent/role_query.go:141.9,142.41 1 1 +auth/ent/role_query.go:143.10,144.44 1 0 +auth/ent/role_query.go:149.55,151.16 2 0 +auth/ent/role_query.go:151.16,152.13 1 0 +auth/ent/role_query.go:154.2,154.13 1 0 +auth/ent/role_query.go:160.73,162.81 2 0 +auth/ent/role_query.go:162.81,164.3 1 0 +auth/ent/role_query.go:165.2,165.18 1 0 +auth/ent/role_query.go:166.9,167.14 1 0 +auth/ent/role_query.go:168.9,169.35 1 0 +auth/ent/role_query.go:170.10,171.38 1 0 +auth/ent/role_query.go:173.2,173.8 1 0 +auth/ent/role_query.go:177.58,179.16 2 0 +auth/ent/role_query.go:179.16,180.13 1 0 +auth/ent/role_query.go:182.2,182.11 1 0 +auth/ent/role_query.go:186.64,188.45 2 13 +auth/ent/role_query.go:188.45,190.3 1 0 +auth/ent/role_query.go:191.2,192.58 2 13 +auth/ent/role_query.go:196.56,198.16 2 0 +auth/ent/role_query.go:198.16,199.13 1 0 +auth/ent/role_query.go:201.2,201.14 1 0 +auth/ent/role_query.go:205.73,206.44 1 0 +auth/ent/role_query.go:206.44,208.3 1 0 +auth/ent/role_query.go:209.2,210.63 2 0 +auth/ent/role_query.go:210.63,212.3 1 0 +auth/ent/role_query.go:213.2,213.17 1 0 +auth/ent/role_query.go:217.57,219.16 2 0 +auth/ent/role_query.go:219.16,220.13 1 0 +auth/ent/role_query.go:222.2,222.12 1 0 +auth/ent/role_query.go:226.62,228.45 2 2 +auth/ent/role_query.go:228.45,230.3 1 0 +auth/ent/role_query.go:231.2,231.78 1 2 +auth/ent/role_query.go:235.54,237.16 2 0 +auth/ent/role_query.go:237.16,238.13 1 0 +auth/ent/role_query.go:240.2,240.14 1 0 +auth/ent/role_query.go:244.63,246.36 2 0 +auth/ent/role_query.go:247.23,248.20 1 0 +auth/ent/role_query.go:249.18,250.60 1 0 +auth/ent/role_query.go:251.10,252.19 1 0 +auth/ent/role_query.go:257.55,259.16 2 0 +auth/ent/role_query.go:259.16,260.13 1 0 +auth/ent/role_query.go:262.2,262.14 1 0 +auth/ent/role_query.go:267.41,268.15 1 0 +auth/ent/role_query.go:268.15,270.3 1 0 +auth/ent/role_query.go:271.2,281.3 1 0 +auth/ent/role_query.go:286.69,288.27 2 1 +auth/ent/role_query.go:288.27,290.3 1 0 +auth/ent/role_query.go:291.2,292.11 2 1 +auth/ent/role_query.go:309.75,316.2 6 0 +auth/ent/role_query.go:330.59,336.2 5 0 +auth/ent/role_query.go:339.66,341.2 1 0 +auth/ent/role_query.go:343.62,344.34 1 18 +auth/ent/role_query.go:344.34,345.19 1 0 +auth/ent/role_query.go:345.19,347.4 1 0 +auth/ent/role_query.go:348.3,348.39 1 0 +auth/ent/role_query.go:348.39,349.48 1 0 +auth/ent/role_query.go:349.48,351.5 1 0 +auth/ent/role_query.go:354.2,354.34 1 18 +auth/ent/role_query.go:354.34,355.27 1 0 +auth/ent/role_query.go:355.27,357.4 1 0 +auth/ent/role_query.go:359.2,359.20 1 18 +auth/ent/role_query.go:359.20,361.17 2 1 +auth/ent/role_query.go:361.17,363.4 1 0 +auth/ent/role_query.go:364.3,364.16 1 1 +auth/ent/role_query.go:366.2,366.12 1 18 +auth/ent/role_query.go:369.87,377.59 2 16 +auth/ent/role_query.go:377.59,379.3 1 17 +auth/ent/role_query.go:380.2,380.60 1 16 +auth/ent/role_query.go:380.60,385.3 4 17 +auth/ent/role_query.go:386.2,386.23 1 16 +auth/ent/role_query.go:386.23,388.3 1 3 +auth/ent/role_query.go:389.2,389.67 1 16 +auth/ent/role_query.go:389.67,391.3 1 0 +auth/ent/role_query.go:392.2,392.21 1 16 +auth/ent/role_query.go:392.21,394.3 1 3 +auth/ent/role_query.go:395.2,395.41 1 13 +auth/ent/role_query.go:395.41,397.18 1 1 +auth/ent/role_query.go:397.18,397.47 1 1 +auth/ent/role_query.go:398.27,398.71 1 1 +auth/ent/role_query.go:398.85,400.4 1 0 +auth/ent/role_query.go:402.2,402.19 1 13 +auth/ent/role_query.go:405.137,409.29 4 1 +auth/ent/role_query.go:409.29,412.18 3 1 +auth/ent/role_query.go:412.18,414.4 1 1 +auth/ent/role_query.go:416.2,416.36 1 1 +auth/ent/role_query.go:416.36,424.3 7 1 +auth/ent/role_query.go:425.2,425.48 1 1 +auth/ent/role_query.go:425.48,427.3 1 0 +auth/ent/role_query.go:428.2,428.70 1 1 +auth/ent/role_query.go:428.70,429.78 1 1 +auth/ent/role_query.go:429.78,432.60 3 1 +auth/ent/role_query.go:432.60,434.19 2 1 +auth/ent/role_query.go:434.19,436.6 1 0 +auth/ent/role_query.go:437.5,437.62 1 1 +auth/ent/role_query.go:439.4,439.61 1 1 +auth/ent/role_query.go:439.61,442.29 3 1 +auth/ent/role_query.go:442.29,445.6 2 1 +auth/ent/role_query.go:446.5,447.15 2 0 +auth/ent/role_query.go:451.2,452.16 2 1 +auth/ent/role_query.go:452.16,454.3 1 0 +auth/ent/role_query.go:455.2,455.30 1 1 +auth/ent/role_query.go:455.30,457.10 2 1 +auth/ent/role_query.go:457.10,459.4 1 0 +auth/ent/role_query.go:460.3,460.25 1 1 +auth/ent/role_query.go:460.25,462.4 1 1 +auth/ent/role_query.go:464.2,464.12 1 1 +auth/ent/role_query.go:467.65,470.28 3 2 +auth/ent/role_query.go:470.28,472.3 1 0 +auth/ent/role_query.go:473.2,473.51 1 2 +auth/ent/role_query.go:476.54,479.44 3 18 +auth/ent/role_query.go:479.44,481.3 1 0 +auth/ent/role_query.go:481.8,481.27 1 18 +auth/ent/role_query.go:481.27,483.3 1 1 +auth/ent/role_query.go:484.2,484.46 1 18 +auth/ent/role_query.go:484.46,487.25 3 0 +auth/ent/role_query.go:487.25,488.33 1 0 +auth/ent/role_query.go:488.33,490.5 1 0 +auth/ent/role_query.go:493.2,493.38 1 18 +auth/ent/role_query.go:493.38,494.50 1 14 +auth/ent/role_query.go:494.50,495.22 1 14 +auth/ent/role_query.go:495.22,497.5 1 14 +auth/ent/role_query.go:500.2,500.41 1 18 +auth/ent/role_query.go:500.41,502.3 1 8 +auth/ent/role_query.go:503.2,503.44 1 18 +auth/ent/role_query.go:503.44,505.3 1 1 +auth/ent/role_query.go:506.2,506.33 1 18 +auth/ent/role_query.go:506.33,507.46 1 0 +auth/ent/role_query.go:507.46,508.22 1 0 +auth/ent/role_query.go:508.22,510.5 1 0 +auth/ent/role_query.go:513.2,513.14 1 18 +auth/ent/role_query.go:516.66,520.23 4 0 +auth/ent/role_query.go:520.23,522.3 1 0 +auth/ent/role_query.go:523.2,524.19 2 0 +auth/ent/role_query.go:524.19,527.3 2 0 +auth/ent/role_query.go:528.2,528.44 1 0 +auth/ent/role_query.go:528.44,530.3 1 0 +auth/ent/role_query.go:531.2,531.34 1 0 +auth/ent/role_query.go:531.34,533.3 1 0 +auth/ent/role_query.go:534.2,534.29 1 0 +auth/ent/role_query.go:534.29,536.3 1 0 +auth/ent/role_query.go:537.2,537.44 1 0 +auth/ent/role_query.go:537.44,541.3 1 0 +auth/ent/role_query.go:542.2,542.41 1 0 +auth/ent/role_query.go:542.41,544.3 1 0 +auth/ent/role_query.go:545.2,545.17 1 0 +auth/ent/role_query.go:555.70,558.2 2 0 +auth/ent/role_query.go:561.64,563.52 2 0 +auth/ent/role_query.go:563.52,565.3 1 0 +auth/ent/role_query.go:566.2,566.97 1 0 +auth/ent/role_query.go:569.84,572.29 3 0 +auth/ent/role_query.go:572.29,574.3 1 0 +auth/ent/role_query.go:575.2,575.42 1 0 +auth/ent/role_query.go:575.42,577.31 2 0 +auth/ent/role_query.go:577.31,579.4 1 0 +auth/ent/role_query.go:580.3,581.30 2 0 +auth/ent/role_query.go:583.2,584.39 2 0 +auth/ent/role_query.go:584.39,586.3 1 0 +auth/ent/role_query.go:587.2,589.71 3 0 +auth/ent/role_query.go:589.71,591.3 1 0 +auth/ent/role_query.go:592.2,593.31 2 0 +auth/ent/role_query.go:603.67,606.2 2 0 +auth/ent/role_query.go:609.62,611.45 2 0 +auth/ent/role_query.go:611.45,613.3 1 0 +auth/ent/role_query.go:614.2,614.91 1 0 +auth/ent/role_query.go:617.82,620.28 3 0 +auth/ent/role_query.go:620.28,622.3 1 0 +auth/ent/role_query.go:623.2,623.38 1 0 +auth/ent/role_query.go:624.38,625.34 1 0 +auth/ent/role_query.go:626.38,627.40 1 0 +auth/ent/role_query.go:629.2,631.64 3 0 +auth/ent/role_query.go:631.64,633.3 1 0 +auth/ent/role_query.go:634.2,635.31 2 0 +auth/ent/role_update.go:28.63,31.2 2 0 +auth/ent/role_update.go:34.53,37.2 2 0 +auth/ent/role_update.go:40.62,41.14 1 0 +auth/ent/role_update.go:41.14,43.3 1 0 +auth/ent/role_update.go:44.2,44.11 1 0 +auth/ent/role_update.go:48.62,51.2 2 0 +auth/ent/role_update.go:54.65,57.2 2 0 +auth/ent/role_update.go:60.61,63.2 2 0 +auth/ent/role_update.go:66.70,67.14 1 0 +auth/ent/role_update.go:67.14,69.3 1 0 +auth/ent/role_update.go:70.2,70.11 1 0 +auth/ent/role_update.go:74.61,77.2 2 0 +auth/ent/role_update.go:80.61,83.2 2 0 +auth/ent/role_update.go:86.56,88.19 2 0 +auth/ent/role_update.go:88.19,90.3 1 0 +auth/ent/role_update.go:91.2,91.30 1 0 +auth/ent/role_update.go:95.48,97.2 1 0 +auth/ent/role_update.go:100.48,103.2 2 0 +auth/ent/role_update.go:106.64,109.2 2 0 +auth/ent/role_update.go:112.59,114.19 2 0 +auth/ent/role_update.go:114.19,116.3 1 0 +auth/ent/role_update.go:117.2,117.33 1 0 +auth/ent/role_update.go:121.62,124.2 2 0 +auth/ent/role_update.go:127.54,129.16 2 0 +auth/ent/role_update.go:129.16,130.13 1 0 +auth/ent/role_update.go:132.2,132.17 1 0 +auth/ent/role_update.go:136.55,139.2 2 0 +auth/ent/role_update.go:142.50,143.37 1 0 +auth/ent/role_update.go:143.37,144.13 1 0 +auth/ent/role_update.go:149.34,150.43 1 0 +auth/ent/role_update.go:150.43,153.3 2 0 +auth/ent/role_update.go:156.71,158.47 2 0 +auth/ent/role_update.go:158.47,159.50 1 0 +auth/ent/role_update.go:159.50,160.22 1 0 +auth/ent/role_update.go:160.22,162.5 1 0 +auth/ent/role_update.go:165.2,165.41 1 0 +auth/ent/role_update.go:165.41,167.3 1 0 +auth/ent/role_update.go:168.2,168.48 1 0 +auth/ent/role_update.go:168.48,170.3 1 0 +auth/ent/role_update.go:171.2,171.56 1 0 +auth/ent/role_update.go:171.56,172.48 1 0 +auth/ent/role_update.go:172.48,174.4 1 0 +auth/ent/role_update.go:176.2,176.46 1 0 +auth/ent/role_update.go:176.46,178.3 1 0 +auth/ent/role_update.go:179.2,179.46 1 0 +auth/ent/role_update.go:179.46,181.3 1 0 +auth/ent/role_update.go:182.2,182.32 1 0 +auth/ent/role_update.go:182.32,194.3 2 0 +auth/ent/role_update.go:195.2,195.91 1 0 +auth/ent/role_update.go:195.91,206.27 2 0 +auth/ent/role_update.go:206.27,208.4 1 0 +auth/ent/role_update.go:209.3,209.54 1 0 +auth/ent/role_update.go:211.2,211.53 1 0 +auth/ent/role_update.go:211.53,222.27 2 0 +auth/ent/role_update.go:222.27,224.4 1 0 +auth/ent/role_update.go:225.3,225.50 1 0 +auth/ent/role_update.go:227.2,227.70 1 0 +auth/ent/role_update.go:227.70,228.49 1 0 +auth/ent/role_update.go:228.49,230.4 1 0 +auth/ent/role_update.go:230.9,230.45 1 0 +auth/ent/role_update.go:230.45,232.4 1 0 +auth/ent/role_update.go:233.3,233.16 1 0 +auth/ent/role_update.go:235.2,236.15 2 0 +auth/ent/role_update.go:248.60,251.2 2 1 +auth/ent/role_update.go:254.69,255.14 1 0 +auth/ent/role_update.go:255.14,257.3 1 0 +auth/ent/role_update.go:258.2,258.12 1 0 +auth/ent/role_update.go:262.69,265.2 2 2 +auth/ent/role_update.go:268.72,271.2 2 1 +auth/ent/role_update.go:274.68,277.2 2 0 +auth/ent/role_update.go:280.77,281.14 1 0 +auth/ent/role_update.go:281.14,283.3 1 0 +auth/ent/role_update.go:284.2,284.12 1 0 +auth/ent/role_update.go:288.68,291.2 2 1 +auth/ent/role_update.go:294.68,297.2 2 1 +auth/ent/role_update.go:300.63,302.19 2 0 +auth/ent/role_update.go:302.19,304.3 1 0 +auth/ent/role_update.go:305.2,305.31 1 0 +auth/ent/role_update.go:309.52,311.2 1 0 +auth/ent/role_update.go:314.55,317.2 2 0 +auth/ent/role_update.go:320.71,323.2 2 0 +auth/ent/role_update.go:326.66,328.19 2 0 +auth/ent/role_update.go:328.19,330.3 1 0 +auth/ent/role_update.go:331.2,331.34 1 0 +auth/ent/role_update.go:335.70,338.2 2 0 +auth/ent/role_update.go:342.81,345.2 2 0 +auth/ent/role_update.go:348.68,351.2 2 4 +auth/ent/role_update.go:354.60,356.16 2 0 +auth/ent/role_update.go:356.16,357.13 1 0 +auth/ent/role_update.go:359.2,359.13 1 0 +auth/ent/role_update.go:363.59,366.2 2 3 +auth/ent/role_update.go:369.54,370.38 1 0 +auth/ent/role_update.go:370.38,371.13 1 0 +auth/ent/role_update.go:376.38,377.44 1 4 +auth/ent/role_update.go:377.44,380.3 2 3 +auth/ent/role_update.go:383.81,386.9 3 4 +auth/ent/role_update.go:386.9,388.3 1 0 +auth/ent/role_update.go:389.2,390.43 2 4 +auth/ent/role_update.go:390.43,393.28 3 0 +auth/ent/role_update.go:393.28,394.28 1 0 +auth/ent/role_update.go:394.28,396.5 1 0 +auth/ent/role_update.go:397.4,397.25 1 0 +auth/ent/role_update.go:397.25,399.5 1 0 +auth/ent/role_update.go:402.2,402.48 1 4 +auth/ent/role_update.go:402.48,403.50 1 0 +auth/ent/role_update.go:403.50,404.22 1 0 +auth/ent/role_update.go:404.22,406.5 1 0 +auth/ent/role_update.go:409.2,409.42 1 4 +auth/ent/role_update.go:409.42,411.3 1 1 +auth/ent/role_update.go:412.2,412.49 1 4 +auth/ent/role_update.go:412.49,414.3 1 2 +auth/ent/role_update.go:415.2,415.57 1 4 +auth/ent/role_update.go:415.57,416.48 1 1 +auth/ent/role_update.go:416.48,418.4 1 1 +auth/ent/role_update.go:420.2,420.47 1 4 +auth/ent/role_update.go:420.47,422.3 1 0 +auth/ent/role_update.go:423.2,423.47 1 4 +auth/ent/role_update.go:423.47,425.3 1 4 +auth/ent/role_update.go:426.2,426.33 1 4 +auth/ent/role_update.go:426.33,438.3 2 0 +auth/ent/role_update.go:439.2,439.93 1 4 +auth/ent/role_update.go:439.93,450.27 2 0 +auth/ent/role_update.go:450.27,452.4 1 0 +auth/ent/role_update.go:453.3,453.54 1 0 +auth/ent/role_update.go:455.2,455.54 1 4 +auth/ent/role_update.go:455.54,466.27 2 1 +auth/ent/role_update.go:466.27,468.4 1 1 +auth/ent/role_update.go:469.3,469.50 1 1 +auth/ent/role_update.go:471.2,474.67 4 4 +auth/ent/role_update.go:474.67,475.49 1 0 +auth/ent/role_update.go:475.49,477.4 1 0 +auth/ent/role_update.go:477.9,477.45 1 0 +auth/ent/role_update.go:477.45,479.4 1 0 +auth/ent/role_update.go:480.3,480.18 1 0 +auth/ent/role_update.go:482.2,483.19 2 4 +auth/ent/token.go:51.48,52.19 1 0 +auth/ent/token.go:52.19,54.3 1 0 +auth/ent/token.go:54.8,54.29 1 0 +auth/ent/token.go:54.29,56.3 1 0 +auth/ent/token.go:57.2,57.43 1 0 +auth/ent/token.go:61.59,63.25 2 8 +auth/ent/token.go:63.25,64.21 1 56 +auth/ent/token.go:65.27,66.33 1 8 +auth/ent/token.go:67.57,68.35 1 24 +auth/ent/token.go:69.73,70.33 1 24 +auth/ent/token.go:71.29,72.35 1 0 +auth/ent/token.go:73.11,74.36 1 0 +auth/ent/token.go:77.2,77.20 1 8 +auth/ent/token.go:82.68,83.46 1 8 +auth/ent/token.go:83.46,85.3 1 0 +auth/ent/token.go:86.2,86.25 1 8 +auth/ent/token.go:86.25,87.21 1 56 +auth/ent/token.go:88.22,89.53 1 8 +auth/ent/token.go:89.53,91.5 1 0 +auth/ent/token.go:91.10,91.26 1 8 +auth/ent/token.go:91.26,93.5 1 8 +auth/ent/token.go:94.25,95.53 1 8 +auth/ent/token.go:95.53,97.5 1 0 +auth/ent/token.go:97.10,97.26 1 8 +auth/ent/token.go:97.26,99.5 1 8 +auth/ent/token.go:100.24,101.53 1 8 +auth/ent/token.go:101.53,103.5 1 0 +auth/ent/token.go:103.10,103.26 1 8 +auth/ent/token.go:103.26,105.5 1 8 +auth/ent/token.go:106.29,107.51 1 8 +auth/ent/token.go:107.51,109.5 1 0 +auth/ent/token.go:109.10,109.26 1 8 +auth/ent/token.go:109.26,111.5 1 8 +auth/ent/token.go:112.27,113.51 1 8 +auth/ent/token.go:113.51,115.5 1 0 +auth/ent/token.go:115.10,115.26 1 8 +auth/ent/token.go:115.26,117.5 1 8 +auth/ent/token.go:118.29,119.51 1 8 +auth/ent/token.go:119.51,121.5 1 0 +auth/ent/token.go:121.10,121.26 1 8 +auth/ent/token.go:121.26,123.5 1 8 +auth/ent/token.go:124.29,125.51 1 8 +auth/ent/token.go:125.51,127.5 1 0 +auth/ent/token.go:127.10,127.26 1 8 +auth/ent/token.go:127.26,129.5 1 8 +auth/ent/token.go:130.29,131.53 1 0 +auth/ent/token.go:131.53,133.5 1 0 +auth/ent/token.go:133.10,133.26 1 0 +auth/ent/token.go:133.26,136.5 2 0 +auth/ent/token.go:137.11,138.45 1 0 +auth/ent/token.go:141.2,141.12 1 8 +auth/ent/token.go:146.55,148.2 1 0 +auth/ent/token.go:151.40,153.2 1 1 +auth/ent/token.go:158.42,160.2 1 1 +auth/ent/token.go:164.33,166.9 2 0 +auth/ent/token.go:166.9,167.52 1 0 +auth/ent/token.go:169.2,170.10 2 0 +auth/ent/token.go:174.33,197.2 22 0 +auth/ent/token_create.go:25.56,28.2 2 13 +auth/ent/token_create.go:31.59,34.2 2 13 +auth/ent/token_create.go:37.63,40.2 2 13 +auth/ent/token_create.go:43.56,46.2 2 0 +auth/ent/token_create.go:49.65,50.14 1 0 +auth/ent/token_create.go:50.14,52.3 1 0 +auth/ent/token_create.go:53.2,53.11 1 0 +auth/ent/token_create.go:57.63,60.2 2 0 +auth/ent/token_create.go:63.72,64.14 1 0 +auth/ent/token_create.go:64.14,66.3 1 0 +auth/ent/token_create.go:67.2,67.11 1 0 +auth/ent/token_create.go:71.63,74.2 2 0 +auth/ent/token_create.go:77.72,78.14 1 0 +auth/ent/token_create.go:78.14,80.3 1 0 +auth/ent/token_create.go:81.2,81.11 1 0 +auth/ent/token_create.go:85.53,88.2 2 0 +auth/ent/token_create.go:91.62,92.14 1 0 +auth/ent/token_create.go:92.14,94.3 1 0 +auth/ent/token_create.go:95.2,95.11 1 0 +auth/ent/token_create.go:99.58,102.2 2 13 +auth/ent/token_create.go:105.54,107.2 1 4 +auth/ent/token_create.go:110.50,112.2 1 0 +auth/ent/token_create.go:115.66,118.2 2 13 +auth/ent/token_create.go:121.58,123.16 2 0 +auth/ent/token_create.go:123.16,124.13 1 0 +auth/ent/token_create.go:126.2,126.10 1 0 +auth/ent/token_create.go:130.56,133.2 2 0 +auth/ent/token_create.go:136.51,137.37 1 0 +auth/ent/token_create.go:137.37,138.13 1 0 +auth/ent/token_create.go:143.35,144.41 1 13 +auth/ent/token_create.go:144.41,147.3 2 13 +auth/ent/token_create.go:148.2,148.43 1 13 +auth/ent/token_create.go:148.43,151.3 2 13 +auth/ent/token_create.go:152.2,152.43 1 13 +auth/ent/token_create.go:152.43,155.3 2 13 +auth/ent/token_create.go:156.2,156.36 1 13 +auth/ent/token_create.go:156.36,159.3 2 13 +auth/ent/token_create.go:163.38,164.39 1 13 +auth/ent/token_create.go:164.39,166.3 1 0 +auth/ent/token_create.go:167.2,167.41 1 13 +auth/ent/token_create.go:167.41,169.3 1 0 +auth/ent/token_create.go:170.2,170.40 1 13 +auth/ent/token_create.go:170.40,171.48 1 13 +auth/ent/token_create.go:171.48,173.4 1 0 +auth/ent/token_create.go:175.2,175.43 1 13 +auth/ent/token_create.go:175.43,177.3 1 0 +auth/ent/token_create.go:178.2,178.41 1 13 +auth/ent/token_create.go:178.41,180.3 1 0 +auth/ent/token_create.go:181.2,181.43 1 13 +auth/ent/token_create.go:181.43,183.3 1 0 +auth/ent/token_create.go:184.2,184.43 1 13 +auth/ent/token_create.go:184.43,186.3 1 0 +auth/ent/token_create.go:187.2,187.40 1 13 +auth/ent/token_create.go:187.40,189.3 1 0 +auth/ent/token_create.go:190.2,190.12 1 13 +auth/ent/token_create.go:193.69,194.35 1 13 +auth/ent/token_create.go:194.35,196.3 1 0 +auth/ent/token_create.go:197.2,198.67 2 13 +auth/ent/token_create.go:198.67,199.38 1 1 +auth/ent/token_create.go:199.38,201.4 1 1 +auth/ent/token_create.go:202.3,202.18 1 1 +auth/ent/token_create.go:204.2,204.27 1 12 +auth/ent/token_create.go:204.27,205.44 1 12 +auth/ent/token_create.go:205.44,207.4 1 12 +auth/ent/token_create.go:207.9,209.4 1 0 +auth/ent/token_create.go:211.2,213.19 3 12 +auth/ent/token_create.go:216.68,221.36 2 13 +auth/ent/token_create.go:221.36,224.3 2 13 +auth/ent/token_create.go:225.2,225.42 1 13 +auth/ent/token_create.go:225.42,228.3 2 13 +auth/ent/token_create.go:229.2,229.44 1 13 +auth/ent/token_create.go:229.44,232.3 2 13 +auth/ent/token_create.go:233.2,233.46 1 13 +auth/ent/token_create.go:233.46,236.3 2 13 +auth/ent/token_create.go:237.2,237.44 1 13 +auth/ent/token_create.go:237.44,240.3 2 13 +auth/ent/token_create.go:241.2,241.46 1 13 +auth/ent/token_create.go:241.46,244.3 2 13 +auth/ent/token_create.go:245.2,245.46 1 13 +auth/ent/token_create.go:245.46,248.3 2 13 +auth/ent/token_create.go:249.2,249.52 1 13 +auth/ent/token_create.go:249.52,260.27 2 13 +auth/ent/token_create.go:260.27,262.4 1 13 +auth/ent/token_create.go:263.3,264.42 2 13 +auth/ent/token_create.go:266.2,266.21 1 13 +auth/ent/token_create.go:277.73,278.20 1 0 +auth/ent/token_create.go:278.20,280.3 1 0 +auth/ent/token_create.go:281.2,284.30 4 0 +auth/ent/token_create.go:284.30,285.37 1 0 +auth/ent/token_create.go:285.37,288.86 3 0 +auth/ent/token_create.go:288.86,290.12 2 0 +auth/ent/token_create.go:290.12,292.6 1 0 +auth/ent/token_create.go:293.5,293.43 1 0 +auth/ent/token_create.go:293.43,295.6 1 0 +auth/ent/token_create.go:296.5,299.28 4 0 +auth/ent/token_create.go:299.28,301.6 1 0 +auth/ent/token_create.go:301.11,304.71 2 0 +auth/ent/token_create.go:304.71,305.42 1 0 +auth/ent/token_create.go:305.42,307.8 1 0 +auth/ent/token_create.go:310.5,310.19 1 0 +auth/ent/token_create.go:310.19,312.6 1 0 +auth/ent/token_create.go:313.5,315.25 3 0 +auth/ent/token_create.go:317.4,317.49 1 0 +auth/ent/token_create.go:317.49,319.5 1 0 +auth/ent/token_create.go:320.4,320.21 1 0 +auth/ent/token_create.go:323.2,323.23 1 0 +auth/ent/token_create.go:323.23,324.78 1 0 +auth/ent/token_create.go:324.78,326.4 1 0 +auth/ent/token_create.go:328.2,328.19 1 0 +auth/ent/token_create.go:332.65,334.16 2 0 +auth/ent/token_create.go:334.16,335.13 1 0 +auth/ent/token_create.go:337.2,337.10 1 0 +auth/ent/token_create.go:341.61,344.2 2 0 +auth/ent/token_create.go:347.56,348.38 1 0 +auth/ent/token_create.go:348.38,349.13 1 0 +auth/ent/token_delete.go:23.66,26.2 2 1 +auth/ent/token_delete.go:29.63,31.2 1 1 +auth/ent/token_delete.go:34.55,36.16 2 0 +auth/ent/token_delete.go:36.16,37.13 1 0 +auth/ent/token_delete.go:39.2,39.10 1 0 +auth/ent/token_delete.go:42.66,44.47 2 1 +auth/ent/token_delete.go:44.47,45.50 1 1 +auth/ent/token_delete.go:45.50,46.22 1 1 +auth/ent/token_delete.go:46.22,48.5 1 1 +auth/ent/token_delete.go:51.2,52.51 2 1 +auth/ent/token_delete.go:52.51,54.3 1 0 +auth/ent/token_delete.go:55.2,56.22 2 1 +auth/ent/token_delete.go:65.73,68.2 2 0 +auth/ent/token_delete.go:71.60,73.9 2 0 +auth/ent/token_delete.go:74.18,75.13 1 0 +auth/ent/token_delete.go:76.14,77.37 1 0 +auth/ent/token_delete.go:78.10,79.13 1 0 +auth/ent/token_delete.go:84.55,85.38 1 0 +auth/ent/token_delete.go:85.38,86.13 1 0 +auth/ent/token_query.go:33.64,36.2 2 9 +auth/ent/token_query.go:39.52,42.2 2 7 +auth/ent/token_query.go:45.54,48.2 2 0 +auth/ent/token_query.go:52.55,55.2 2 0 +auth/ent/token_query.go:58.65,61.2 2 0 +auth/ent/token_query.go:64.46,66.74 2 0 +auth/ent/token_query.go:66.74,67.46 1 0 +auth/ent/token_query.go:67.46,69.4 1 0 +auth/ent/token_query.go:70.3,71.40 2 0 +auth/ent/token_query.go:71.40,73.4 1 0 +auth/ent/token_query.go:74.3,80.20 3 0 +auth/ent/token_query.go:82.2,82.14 1 0 +auth/ent/token_query.go:87.66,89.16 2 0 +auth/ent/token_query.go:89.16,91.3 1 0 +auth/ent/token_query.go:92.2,92.21 1 0 +auth/ent/token_query.go:92.21,94.3 1 0 +auth/ent/token_query.go:95.2,95.22 1 0 +auth/ent/token_query.go:99.58,101.36 2 0 +auth/ent/token_query.go:101.36,102.13 1 0 +auth/ent/token_query.go:104.2,104.13 1 0 +auth/ent/token_query.go:109.75,111.82 2 0 +auth/ent/token_query.go:111.82,113.3 1 0 +auth/ent/token_query.go:114.2,114.19 1 0 +auth/ent/token_query.go:114.19,117.3 2 0 +auth/ent/token_query.go:118.2,118.20 1 0 +auth/ent/token_query.go:122.60,124.36 2 0 +auth/ent/token_query.go:124.36,125.13 1 0 +auth/ent/token_query.go:127.2,127.11 1 0 +auth/ent/token_query.go:133.65,135.16 2 7 +auth/ent/token_query.go:135.16,137.3 1 0 +auth/ent/token_query.go:138.2,138.20 1 7 +auth/ent/token_query.go:139.9,140.23 1 5 +auth/ent/token_query.go:141.9,142.42 1 2 +auth/ent/token_query.go:143.10,144.45 1 0 +auth/ent/token_query.go:149.57,151.16 2 0 +auth/ent/token_query.go:151.16,152.13 1 0 +auth/ent/token_query.go:154.2,154.13 1 0 +auth/ent/token_query.go:160.74,162.81 2 0 +auth/ent/token_query.go:162.81,164.3 1 0 +auth/ent/token_query.go:165.2,165.18 1 0 +auth/ent/token_query.go:166.9,167.14 1 0 +auth/ent/token_query.go:168.9,169.36 1 0 +auth/ent/token_query.go:170.10,171.39 1 0 +auth/ent/token_query.go:173.2,173.8 1 0 +auth/ent/token_query.go:177.59,179.16 2 0 +auth/ent/token_query.go:179.16,180.13 1 0 +auth/ent/token_query.go:182.2,182.11 1 0 +auth/ent/token_query.go:186.66,188.45 2 10 +auth/ent/token_query.go:188.45,190.3 1 0 +auth/ent/token_query.go:191.2,192.59 2 10 +auth/ent/token_query.go:196.58,198.16 2 0 +auth/ent/token_query.go:198.16,199.13 1 0 +auth/ent/token_query.go:201.2,201.14 1 0 +auth/ent/token_query.go:205.74,206.44 1 0 +auth/ent/token_query.go:206.44,208.3 1 0 +auth/ent/token_query.go:209.2,210.64 2 0 +auth/ent/token_query.go:210.64,212.3 1 0 +auth/ent/token_query.go:213.2,213.17 1 0 +auth/ent/token_query.go:217.58,219.16 2 0 +auth/ent/token_query.go:219.16,220.13 1 0 +auth/ent/token_query.go:222.2,222.12 1 0 +auth/ent/token_query.go:226.63,228.45 2 0 +auth/ent/token_query.go:228.45,230.3 1 0 +auth/ent/token_query.go:231.2,231.79 1 0 +auth/ent/token_query.go:235.55,237.16 2 0 +auth/ent/token_query.go:237.16,238.13 1 0 +auth/ent/token_query.go:240.2,240.14 1 0 +auth/ent/token_query.go:244.64,246.36 2 0 +auth/ent/token_query.go:247.23,248.20 1 0 +auth/ent/token_query.go:249.18,250.60 1 0 +auth/ent/token_query.go:251.10,252.19 1 0 +auth/ent/token_query.go:257.56,259.16 2 0 +auth/ent/token_query.go:259.16,260.13 1 0 +auth/ent/token_query.go:262.2,262.14 1 0 +auth/ent/token_query.go:267.43,268.15 1 0 +auth/ent/token_query.go:268.15,270.3 1 0 +auth/ent/token_query.go:271.2,281.3 1 0 +auth/ent/token_query.go:286.70,288.27 2 0 +auth/ent/token_query.go:288.27,290.3 1 0 +auth/ent/token_query.go:291.2,292.11 2 0 +auth/ent/token_query.go:309.77,316.2 6 0 +auth/ent/token_query.go:330.61,336.2 5 0 +auth/ent/token_query.go:339.68,341.2 1 0 +auth/ent/token_query.go:343.63,344.34 1 10 +auth/ent/token_query.go:344.34,345.19 1 0 +auth/ent/token_query.go:345.19,347.4 1 0 +auth/ent/token_query.go:348.3,348.39 1 0 +auth/ent/token_query.go:348.39,349.48 1 0 +auth/ent/token_query.go:349.48,351.5 1 0 +auth/ent/token_query.go:354.2,354.34 1 10 +auth/ent/token_query.go:354.34,355.28 1 0 +auth/ent/token_query.go:355.28,357.4 1 0 +auth/ent/token_query.go:359.2,359.20 1 10 +auth/ent/token_query.go:359.20,361.17 2 1 +auth/ent/token_query.go:361.17,363.4 1 0 +auth/ent/token_query.go:364.3,364.16 1 1 +auth/ent/token_query.go:366.2,366.12 1 10 +auth/ent/token_query.go:369.89,378.24 2 10 +auth/ent/token_query.go:378.24,380.3 1 0 +auth/ent/token_query.go:381.2,381.13 1 10 +auth/ent/token_query.go:381.13,383.3 1 0 +auth/ent/token_query.go:384.2,384.59 1 10 +auth/ent/token_query.go:384.59,386.3 1 7 +auth/ent/token_query.go:387.2,387.60 1 10 +auth/ent/token_query.go:387.60,392.3 4 7 +auth/ent/token_query.go:393.2,393.23 1 10 +auth/ent/token_query.go:393.23,395.3 1 0 +auth/ent/token_query.go:396.2,396.67 1 10 +auth/ent/token_query.go:396.67,398.3 1 0 +auth/ent/token_query.go:399.2,399.21 1 10 +auth/ent/token_query.go:399.21,401.3 1 3 +auth/ent/token_query.go:402.2,402.40 1 7 +auth/ent/token_query.go:402.40,404.28 1 0 +auth/ent/token_query.go:404.28,404.48 1 0 +auth/ent/token_query.go:404.62,406.4 1 0 +auth/ent/token_query.go:408.2,408.19 1 7 +auth/ent/token_query.go:411.140,414.23 3 0 +auth/ent/token_query.go:414.23,415.34 1 0 +auth/ent/token_query.go:415.34,416.12 1 0 +auth/ent/token_query.go:418.3,419.32 2 0 +auth/ent/token_query.go:419.32,421.4 1 0 +auth/ent/token_query.go:422.3,422.46 1 0 +auth/ent/token_query.go:424.2,424.19 1 0 +auth/ent/token_query.go:424.19,426.3 1 0 +auth/ent/token_query.go:427.2,429.16 3 0 +auth/ent/token_query.go:429.16,431.3 1 0 +auth/ent/token_query.go:432.2,432.30 1 0 +auth/ent/token_query.go:432.30,434.10 2 0 +auth/ent/token_query.go:434.10,436.4 1 0 +auth/ent/token_query.go:437.3,437.24 1 0 +auth/ent/token_query.go:437.24,439.4 1 0 +auth/ent/token_query.go:441.2,441.12 1 0 +auth/ent/token_query.go:444.66,447.28 3 0 +auth/ent/token_query.go:447.28,449.3 1 0 +auth/ent/token_query.go:450.2,450.51 1 0 +auth/ent/token_query.go:453.55,456.44 3 10 +auth/ent/token_query.go:456.44,458.3 1 0 +auth/ent/token_query.go:458.8,458.27 1 10 +auth/ent/token_query.go:458.27,460.3 1 1 +auth/ent/token_query.go:461.2,461.46 1 10 +auth/ent/token_query.go:461.46,464.25 3 0 +auth/ent/token_query.go:464.25,465.34 1 0 +auth/ent/token_query.go:465.34,467.5 1 0 +auth/ent/token_query.go:470.2,470.38 1 10 +auth/ent/token_query.go:470.38,471.50 1 9 +auth/ent/token_query.go:471.50,472.22 1 9 +auth/ent/token_query.go:472.22,474.5 1 13 +auth/ent/token_query.go:477.2,477.41 1 10 +auth/ent/token_query.go:477.41,479.3 1 7 +auth/ent/token_query.go:480.2,480.44 1 10 +auth/ent/token_query.go:480.44,482.3 1 0 +auth/ent/token_query.go:483.2,483.33 1 10 +auth/ent/token_query.go:483.33,484.46 1 0 +auth/ent/token_query.go:484.46,485.22 1 0 +auth/ent/token_query.go:485.22,487.5 1 0 +auth/ent/token_query.go:490.2,490.14 1 10 +auth/ent/token_query.go:493.67,497.23 4 0 +auth/ent/token_query.go:497.23,499.3 1 0 +auth/ent/token_query.go:500.2,501.19 2 0 +auth/ent/token_query.go:501.19,504.3 2 0 +auth/ent/token_query.go:505.2,505.44 1 0 +auth/ent/token_query.go:505.44,507.3 1 0 +auth/ent/token_query.go:508.2,508.34 1 0 +auth/ent/token_query.go:508.34,510.3 1 0 +auth/ent/token_query.go:511.2,511.29 1 0 +auth/ent/token_query.go:511.29,513.3 1 0 +auth/ent/token_query.go:514.2,514.44 1 0 +auth/ent/token_query.go:514.44,518.3 1 0 +auth/ent/token_query.go:519.2,519.41 1 0 +auth/ent/token_query.go:519.41,521.3 1 0 +auth/ent/token_query.go:522.2,522.17 1 0 +auth/ent/token_query.go:532.72,535.2 2 0 +auth/ent/token_query.go:538.65,540.52 2 0 +auth/ent/token_query.go:540.52,542.3 1 0 +auth/ent/token_query.go:543.2,543.99 1 0 +auth/ent/token_query.go:546.86,549.29 3 0 +auth/ent/token_query.go:549.29,551.3 1 0 +auth/ent/token_query.go:552.2,552.42 1 0 +auth/ent/token_query.go:552.42,554.31 2 0 +auth/ent/token_query.go:554.31,556.4 1 0 +auth/ent/token_query.go:557.3,558.30 2 0 +auth/ent/token_query.go:560.2,561.39 2 0 +auth/ent/token_query.go:561.39,563.3 1 0 +auth/ent/token_query.go:564.2,566.71 3 0 +auth/ent/token_query.go:566.71,568.3 1 0 +auth/ent/token_query.go:569.2,570.31 2 0 +auth/ent/token_query.go:580.69,583.2 2 0 +auth/ent/token_query.go:586.63,588.45 2 0 +auth/ent/token_query.go:588.45,590.3 1 0 +auth/ent/token_query.go:591.2,591.94 1 0 +auth/ent/token_query.go:594.84,597.28 3 0 +auth/ent/token_query.go:597.28,599.3 1 0 +auth/ent/token_query.go:600.2,600.38 1 0 +auth/ent/token_query.go:601.38,602.34 1 0 +auth/ent/token_query.go:603.38,604.40 1 0 +auth/ent/token_query.go:606.2,608.64 3 0 +auth/ent/token_query.go:608.64,610.3 1 0 +auth/ent/token_query.go:611.2,612.31 2 0 +auth/ent/token_update.go:27.66,30.2 2 4 +auth/ent/token_update.go:33.56,36.2 2 0 +auth/ent/token_update.go:39.65,40.14 1 0 +auth/ent/token_update.go:40.14,42.3 1 0 +auth/ent/token_update.go:43.2,43.11 1 0 +auth/ent/token_update.go:47.59,50.2 2 0 +auth/ent/token_update.go:53.68,54.14 1 0 +auth/ent/token_update.go:54.14,56.3 1 0 +auth/ent/token_update.go:57.2,57.11 1 0 +auth/ent/token_update.go:61.63,64.2 2 0 +auth/ent/token_update.go:67.72,68.14 1 0 +auth/ent/token_update.go:68.14,70.3 1 0 +auth/ent/token_update.go:71.2,71.11 1 0 +auth/ent/token_update.go:75.56,78.2 2 4 +auth/ent/token_update.go:81.65,82.14 1 0 +auth/ent/token_update.go:82.14,84.3 1 0 +auth/ent/token_update.go:85.2,85.11 1 0 +auth/ent/token_update.go:89.63,92.2 2 0 +auth/ent/token_update.go:95.72,96.14 1 0 +auth/ent/token_update.go:96.14,98.3 1 0 +auth/ent/token_update.go:99.2,99.11 1 0 +auth/ent/token_update.go:103.63,106.2 2 0 +auth/ent/token_update.go:109.58,112.2 2 0 +auth/ent/token_update.go:115.54,117.2 1 0 +auth/ent/token_update.go:120.50,122.2 1 0 +auth/ent/token_update.go:125.49,128.2 2 0 +auth/ent/token_update.go:131.63,134.2 2 4 +auth/ent/token_update.go:137.55,139.16 2 0 +auth/ent/token_update.go:139.16,140.13 1 0 +auth/ent/token_update.go:142.2,142.17 1 0 +auth/ent/token_update.go:146.56,149.2 2 0 +auth/ent/token_update.go:152.51,153.37 1 0 +auth/ent/token_update.go:153.37,154.13 1 0 +auth/ent/token_update.go:159.35,160.43 1 4 +auth/ent/token_update.go:160.43,163.3 2 4 +auth/ent/token_update.go:167.38,168.40 1 4 +auth/ent/token_update.go:168.40,169.48 1 0 +auth/ent/token_update.go:169.48,171.4 1 0 +auth/ent/token_update.go:173.2,173.69 1 4 +auth/ent/token_update.go:173.69,175.3 1 0 +auth/ent/token_update.go:176.2,176.12 1 4 +auth/ent/token_update.go:179.72,180.35 1 4 +auth/ent/token_update.go:180.35,182.3 1 0 +auth/ent/token_update.go:183.2,184.47 2 4 +auth/ent/token_update.go:184.47,185.50 1 4 +auth/ent/token_update.go:185.50,186.22 1 4 +auth/ent/token_update.go:186.22,188.5 1 8 +auth/ent/token_update.go:191.2,191.42 1 4 +auth/ent/token_update.go:191.42,193.3 1 0 +auth/ent/token_update.go:194.2,194.44 1 4 +auth/ent/token_update.go:194.44,196.3 1 0 +auth/ent/token_update.go:197.2,197.46 1 4 +auth/ent/token_update.go:197.46,199.3 1 0 +auth/ent/token_update.go:200.2,200.44 1 4 +auth/ent/token_update.go:200.44,202.3 1 4 +auth/ent/token_update.go:203.2,203.46 1 4 +auth/ent/token_update.go:203.46,205.3 1 0 +auth/ent/token_update.go:206.2,206.46 1 4 +auth/ent/token_update.go:206.46,208.3 1 4 +auth/ent/token_update.go:209.2,209.31 1 4 +auth/ent/token_update.go:209.31,221.3 2 0 +auth/ent/token_update.go:222.2,222.52 1 4 +auth/ent/token_update.go:222.52,233.27 2 0 +auth/ent/token_update.go:233.27,235.4 1 0 +auth/ent/token_update.go:236.3,236.50 1 0 +auth/ent/token_update.go:238.2,238.70 1 4 +auth/ent/token_update.go:238.70,239.49 1 0 +auth/ent/token_update.go:239.49,241.4 1 0 +auth/ent/token_update.go:241.9,241.45 1 0 +auth/ent/token_update.go:241.45,243.4 1 0 +auth/ent/token_update.go:244.3,244.16 1 0 +auth/ent/token_update.go:246.2,247.15 2 4 +auth/ent/token_update.go:259.63,262.2 2 0 +auth/ent/token_update.go:265.72,266.14 1 0 +auth/ent/token_update.go:266.14,268.3 1 0 +auth/ent/token_update.go:269.2,269.12 1 0 +auth/ent/token_update.go:273.66,276.2 2 0 +auth/ent/token_update.go:279.75,280.14 1 0 +auth/ent/token_update.go:280.14,282.3 1 0 +auth/ent/token_update.go:283.2,283.12 1 0 +auth/ent/token_update.go:287.70,290.2 2 0 +auth/ent/token_update.go:293.79,294.14 1 0 +auth/ent/token_update.go:294.14,296.3 1 0 +auth/ent/token_update.go:297.2,297.12 1 0 +auth/ent/token_update.go:301.63,304.2 2 1 +auth/ent/token_update.go:307.72,308.14 1 0 +auth/ent/token_update.go:308.14,310.3 1 0 +auth/ent/token_update.go:311.2,311.12 1 0 +auth/ent/token_update.go:315.70,318.2 2 0 +auth/ent/token_update.go:321.79,322.14 1 0 +auth/ent/token_update.go:322.14,324.3 1 0 +auth/ent/token_update.go:325.2,325.12 1 0 +auth/ent/token_update.go:329.70,332.2 2 0 +auth/ent/token_update.go:335.65,338.2 2 0 +auth/ent/token_update.go:341.61,343.2 1 0 +auth/ent/token_update.go:346.54,348.2 1 0 +auth/ent/token_update.go:351.56,354.2 2 0 +auth/ent/token_update.go:357.73,360.2 2 0 +auth/ent/token_update.go:364.83,367.2 2 0 +auth/ent/token_update.go:370.70,373.2 2 1 +auth/ent/token_update.go:376.62,378.16 2 0 +auth/ent/token_update.go:378.16,379.13 1 0 +auth/ent/token_update.go:381.2,381.13 1 0 +auth/ent/token_update.go:385.60,388.2 2 0 +auth/ent/token_update.go:391.55,392.38 1 0 +auth/ent/token_update.go:392.38,393.13 1 0 +auth/ent/token_update.go:398.39,399.44 1 1 +auth/ent/token_update.go:399.44,402.3 2 1 +auth/ent/token_update.go:406.42,407.41 1 1 +auth/ent/token_update.go:407.41,408.48 1 0 +auth/ent/token_update.go:408.48,410.4 1 0 +auth/ent/token_update.go:412.2,412.71 1 1 +auth/ent/token_update.go:412.71,414.3 1 0 +auth/ent/token_update.go:415.2,415.12 1 1 +auth/ent/token_update.go:418.83,419.36 1 1 +auth/ent/token_update.go:419.36,421.3 1 0 +auth/ent/token_update.go:422.2,424.9 3 1 +auth/ent/token_update.go:424.9,426.3 1 0 +auth/ent/token_update.go:427.2,428.43 2 1 +auth/ent/token_update.go:428.43,431.28 3 0 +auth/ent/token_update.go:431.28,432.29 1 0 +auth/ent/token_update.go:432.29,434.5 1 0 +auth/ent/token_update.go:435.4,435.26 1 0 +auth/ent/token_update.go:435.26,437.5 1 0 +auth/ent/token_update.go:440.2,440.48 1 1 +auth/ent/token_update.go:440.48,441.50 1 0 +auth/ent/token_update.go:441.50,442.22 1 0 +auth/ent/token_update.go:442.22,444.5 1 0 +auth/ent/token_update.go:447.2,447.43 1 1 +auth/ent/token_update.go:447.43,449.3 1 0 +auth/ent/token_update.go:450.2,450.45 1 1 +auth/ent/token_update.go:450.45,452.3 1 0 +auth/ent/token_update.go:453.2,453.47 1 1 +auth/ent/token_update.go:453.47,455.3 1 0 +auth/ent/token_update.go:456.2,456.45 1 1 +auth/ent/token_update.go:456.45,458.3 1 1 +auth/ent/token_update.go:459.2,459.47 1 1 +auth/ent/token_update.go:459.47,461.3 1 0 +auth/ent/token_update.go:462.2,462.47 1 1 +auth/ent/token_update.go:462.47,464.3 1 1 +auth/ent/token_update.go:465.2,465.32 1 1 +auth/ent/token_update.go:465.32,477.3 2 0 +auth/ent/token_update.go:478.2,478.53 1 1 +auth/ent/token_update.go:478.53,489.27 2 0 +auth/ent/token_update.go:489.27,491.4 1 0 +auth/ent/token_update.go:492.3,492.50 1 0 +auth/ent/token_update.go:494.2,497.67 4 1 +auth/ent/token_update.go:497.67,498.49 1 0 +auth/ent/token_update.go:498.49,500.4 1 0 +auth/ent/token_update.go:500.9,500.45 1 0 +auth/ent/token_update.go:500.45,502.4 1 0 +auth/ent/token_update.go:503.3,503.18 1 0 +auth/ent/token_update.go:505.2,506.19 2 1 +auth/ent/tx.go:59.63,61.2 1 0 +auth/ent/tx.go:64.30,66.65 2 0 +auth/ent/tx.go:66.65,68.3 1 0 +auth/ent/tx.go:69.2,72.39 4 0 +auth/ent/tx.go:72.39,74.3 1 0 +auth/ent/tx.go:75.2,75.30 1 0 +auth/ent/tx.go:79.38,84.2 4 0 +auth/ent/tx.go:115.67,117.2 1 0 +auth/ent/tx.go:120.32,122.68 2 0 +auth/ent/tx.go:122.68,124.3 1 0 +auth/ent/tx.go:125.2,128.39 4 0 +auth/ent/tx.go:128.39,130.3 1 0 +auth/ent/tx.go:131.2,131.32 1 0 +auth/ent/tx.go:135.42,140.2 4 0 +auth/ent/tx.go:143.32,144.26 1 0 +auth/ent/tx.go:144.26,147.3 2 0 +auth/ent/tx.go:148.2,148.18 1 0 +auth/ent/tx.go:151.22,155.2 3 0 +auth/ent/tx.go:180.72,182.16 2 0 +auth/ent/tx.go:182.16,184.3 1 0 +auth/ent/tx.go:185.2,185.41 1 0 +auth/ent/tx.go:190.61,190.79 1 0 +auth/ent/tx.go:193.38,193.65 1 0 +auth/ent/tx.go:196.32,196.46 1 0 +auth/ent/tx.go:200.33,200.47 1 0 +auth/ent/tx.go:204.35,204.49 1 0 +auth/ent/tx.go:207.80,209.2 1 0 +auth/ent/tx.go:212.81,214.2 1 0 +auth/ent/user.go:49.50,50.22 1 0 +auth/ent/user.go:50.22,52.3 1 0 +auth/ent/user.go:53.2,53.44 1 0 +auth/ent/user.go:58.52,59.22 1 0 +auth/ent/user.go:59.22,61.3 1 0 +auth/ent/user.go:62.2,62.45 1 0 +auth/ent/user.go:66.58,68.25 2 40 +auth/ent/user.go:68.25,69.21 1 240 +auth/ent/user.go:70.78,71.35 1 160 +auth/ent/user.go:72.49,73.33 1 80 +auth/ent/user.go:74.11,75.36 1 0 +auth/ent/user.go:78.2,78.20 1 40 +auth/ent/user.go:83.67,84.46 1 40 +auth/ent/user.go:84.46,86.3 1 0 +auth/ent/user.go:87.2,87.25 1 40 +auth/ent/user.go:87.25,88.21 1 240 +auth/ent/user.go:89.21,90.53 1 40 +auth/ent/user.go:90.53,92.5 1 0 +auth/ent/user.go:92.10,92.26 1 40 +auth/ent/user.go:92.26,94.5 1 40 +auth/ent/user.go:95.27,96.53 1 40 +auth/ent/user.go:96.53,98.5 1 0 +auth/ent/user.go:98.10,98.26 1 40 +auth/ent/user.go:98.26,100.5 1 40 +auth/ent/user.go:101.24,102.53 1 40 +auth/ent/user.go:102.53,104.5 1 0 +auth/ent/user.go:104.10,104.26 1 40 +auth/ent/user.go:104.26,106.5 1 40 +auth/ent/user.go:107.27,108.53 1 40 +auth/ent/user.go:108.53,110.5 1 0 +auth/ent/user.go:110.10,110.26 1 40 +auth/ent/user.go:110.26,112.5 1 40 +auth/ent/user.go:113.28,114.51 1 40 +auth/ent/user.go:114.51,116.5 1 0 +auth/ent/user.go:116.10,116.26 1 40 +auth/ent/user.go:116.26,118.5 1 40 +auth/ent/user.go:119.28,120.51 1 40 +auth/ent/user.go:120.51,122.5 1 0 +auth/ent/user.go:122.10,122.26 1 40 +auth/ent/user.go:122.26,124.5 1 40 +auth/ent/user.go:125.11,126.45 1 0 +auth/ent/user.go:129.2,129.12 1 40 +auth/ent/user.go:134.54,136.2 1 0 +auth/ent/user.go:139.40,141.2 1 1 +auth/ent/user.go:144.42,146.2 1 1 +auth/ent/user.go:151.40,153.2 1 0 +auth/ent/user.go:157.31,159.9 2 0 +auth/ent/user.go:159.9,160.51 1 0 +auth/ent/user.go:162.2,163.10 2 0 +auth/ent/user.go:167.32,187.2 19 1 +auth/ent/user_create.go:26.57,29.2 2 44 +auth/ent/user_create.go:32.54,35.2 2 44 +auth/ent/user_create.go:38.57,41.2 2 44 +auth/ent/user_create.go:44.61,47.2 2 0 +auth/ent/user_create.go:50.70,51.14 1 0 +auth/ent/user_create.go:51.14,53.3 1 0 +auth/ent/user_create.go:54.2,54.11 1 0 +auth/ent/user_create.go:58.61,61.2 2 0 +auth/ent/user_create.go:64.70,65.14 1 0 +auth/ent/user_create.go:65.14,67.3 1 0 +auth/ent/user_create.go:68.2,68.11 1 0 +auth/ent/user_create.go:72.51,75.2 2 6 +auth/ent/user_create.go:78.60,79.14 1 0 +auth/ent/user_create.go:79.14,81.3 1 0 +auth/ent/user_create.go:82.2,82.11 1 0 +auth/ent/user_create.go:86.61,89.2 2 0 +auth/ent/user_create.go:92.56,94.19 2 0 +auth/ent/user_create.go:94.19,96.3 1 0 +auth/ent/user_create.go:97.2,97.30 1 0 +auth/ent/user_create.go:101.62,104.2 2 0 +auth/ent/user_create.go:107.58,109.19 2 0 +auth/ent/user_create.go:109.19,111.3 1 0 +auth/ent/user_create.go:112.2,112.31 1 0 +auth/ent/user_create.go:116.48,118.2 1 0 +auth/ent/user_create.go:121.64,122.38 1 44 +auth/ent/user_create.go:122.38,124.3 1 0 +auth/ent/user_create.go:125.2,125.58 1 44 +auth/ent/user_create.go:129.56,131.16 2 1 +auth/ent/user_create.go:131.16,132.13 1 0 +auth/ent/user_create.go:134.2,134.10 1 1 +auth/ent/user_create.go:138.55,141.2 2 0 +auth/ent/user_create.go:144.50,145.37 1 0 +auth/ent/user_create.go:145.37,146.13 1 0 +auth/ent/user_create.go:151.40,152.43 1 44 +auth/ent/user_create.go:152.43,153.35 1 44 +auth/ent/user_create.go:153.35,155.4 1 0 +auth/ent/user_create.go:156.3,157.30 2 44 +auth/ent/user_create.go:159.2,159.43 1 44 +auth/ent/user_create.go:159.43,160.35 1 44 +auth/ent/user_create.go:160.35,162.4 1 0 +auth/ent/user_create.go:163.3,164.30 2 44 +auth/ent/user_create.go:166.2,166.36 1 44 +auth/ent/user_create.go:166.36,167.28 1 38 +auth/ent/user_create.go:167.28,169.4 1 0 +auth/ent/user_create.go:170.3,171.23 2 38 +auth/ent/user_create.go:173.2,173.12 1 44 +auth/ent/user_create.go:177.37,178.42 1 44 +auth/ent/user_create.go:178.42,180.3 1 0 +auth/ent/user_create.go:181.2,181.39 1 44 +auth/ent/user_create.go:181.39,183.3 1 0 +auth/ent/user_create.go:184.2,184.42 1 44 +auth/ent/user_create.go:184.42,186.3 1 0 +auth/ent/user_create.go:187.2,187.43 1 44 +auth/ent/user_create.go:187.43,189.3 1 0 +auth/ent/user_create.go:190.2,190.43 1 44 +auth/ent/user_create.go:190.43,192.3 1 0 +auth/ent/user_create.go:193.2,193.12 1 44 +auth/ent/user_create.go:196.67,197.35 1 44 +auth/ent/user_create.go:197.35,199.3 1 0 +auth/ent/user_create.go:200.2,201.67 2 44 +auth/ent/user_create.go:201.67,202.38 1 2 +auth/ent/user_create.go:202.38,204.4 1 2 +auth/ent/user_create.go:205.3,205.18 1 2 +auth/ent/user_create.go:207.2,207.27 1 42 +auth/ent/user_create.go:207.27,208.44 1 42 +auth/ent/user_create.go:208.44,210.4 1 42 +auth/ent/user_create.go:210.9,212.4 1 0 +auth/ent/user_create.go:214.2,216.19 3 42 +auth/ent/user_create.go:219.66,224.36 2 44 +auth/ent/user_create.go:224.36,227.3 2 44 +auth/ent/user_create.go:228.2,228.45 1 44 +auth/ent/user_create.go:228.45,231.3 2 44 +auth/ent/user_create.go:232.2,232.42 1 44 +auth/ent/user_create.go:232.42,235.3 2 44 +auth/ent/user_create.go:236.2,236.45 1 44 +auth/ent/user_create.go:236.45,239.3 2 44 +auth/ent/user_create.go:240.2,240.46 1 44 +auth/ent/user_create.go:240.46,243.3 2 44 +auth/ent/user_create.go:244.2,244.46 1 44 +auth/ent/user_create.go:244.46,247.3 2 44 +auth/ent/user_create.go:248.2,248.53 1 44 +auth/ent/user_create.go:248.53,259.27 2 0 +auth/ent/user_create.go:259.27,261.4 1 0 +auth/ent/user_create.go:262.3,262.42 1 0 +auth/ent/user_create.go:264.2,264.54 1 44 +auth/ent/user_create.go:264.54,275.27 2 0 +auth/ent/user_create.go:275.27,277.4 1 0 +auth/ent/user_create.go:278.3,278.42 1 0 +auth/ent/user_create.go:280.2,280.21 1 44 +auth/ent/user_create.go:291.71,292.20 1 0 +auth/ent/user_create.go:292.20,294.3 1 0 +auth/ent/user_create.go:295.2,298.30 4 0 +auth/ent/user_create.go:298.30,299.37 1 0 +auth/ent/user_create.go:299.37,302.86 3 0 +auth/ent/user_create.go:302.86,304.12 2 0 +auth/ent/user_create.go:304.12,306.6 1 0 +auth/ent/user_create.go:307.5,307.43 1 0 +auth/ent/user_create.go:307.43,309.6 1 0 +auth/ent/user_create.go:310.5,313.28 4 0 +auth/ent/user_create.go:313.28,315.6 1 0 +auth/ent/user_create.go:315.11,318.71 2 0 +auth/ent/user_create.go:318.71,319.42 1 0 +auth/ent/user_create.go:319.42,321.8 1 0 +auth/ent/user_create.go:324.5,324.19 1 0 +auth/ent/user_create.go:324.19,326.6 1 0 +auth/ent/user_create.go:327.5,329.25 3 0 +auth/ent/user_create.go:331.4,331.49 1 0 +auth/ent/user_create.go:331.49,333.5 1 0 +auth/ent/user_create.go:334.4,334.21 1 0 +auth/ent/user_create.go:337.2,337.23 1 0 +auth/ent/user_create.go:337.23,338.78 1 0 +auth/ent/user_create.go:338.78,340.4 1 0 +auth/ent/user_create.go:342.2,342.19 1 0 +auth/ent/user_create.go:346.63,348.16 2 0 +auth/ent/user_create.go:348.16,349.13 1 0 +auth/ent/user_create.go:351.2,351.10 1 0 +auth/ent/user_create.go:355.60,358.2 2 0 +auth/ent/user_create.go:361.55,362.38 1 0 +auth/ent/user_create.go:362.38,363.13 1 0 +auth/ent/user_delete.go:23.63,26.2 2 2 +auth/ent/user_delete.go:29.62,31.2 1 3 +auth/ent/user_delete.go:34.54,36.16 2 0 +auth/ent/user_delete.go:36.16,37.13 1 0 +auth/ent/user_delete.go:39.2,39.10 1 0 +auth/ent/user_delete.go:42.65,44.47 2 3 +auth/ent/user_delete.go:44.47,45.50 1 2 +auth/ent/user_delete.go:45.50,46.22 1 2 +auth/ent/user_delete.go:46.22,48.5 1 2 +auth/ent/user_delete.go:51.2,52.51 2 3 +auth/ent/user_delete.go:52.51,54.3 1 0 +auth/ent/user_delete.go:55.2,56.22 2 3 +auth/ent/user_delete.go:65.70,68.2 2 0 +auth/ent/user_delete.go:71.59,73.9 2 2 +auth/ent/user_delete.go:74.18,75.13 1 0 +auth/ent/user_delete.go:76.14,77.36 1 1 +auth/ent/user_delete.go:78.10,79.13 1 1 +auth/ent/user_delete.go:84.54,85.38 1 0 +auth/ent/user_delete.go:85.38,86.13 1 0 +auth/ent/user_query.go:35.61,38.2 2 24 +auth/ent/user_query.go:41.50,44.2 2 24 +auth/ent/user_query.go:47.52,50.2 2 2 +auth/ent/user_query.go:54.53,57.2 2 0 +auth/ent/user_query.go:60.62,63.2 2 0 +auth/ent/user_query.go:66.46,68.74 2 0 +auth/ent/user_query.go:68.74,69.46 1 0 +auth/ent/user_query.go:69.46,71.4 1 0 +auth/ent/user_query.go:72.3,73.40 2 0 +auth/ent/user_query.go:73.40,75.4 1 0 +auth/ent/user_query.go:76.3,82.20 3 0 +auth/ent/user_query.go:84.2,84.14 1 0 +auth/ent/user_query.go:88.48,90.74 2 0 +auth/ent/user_query.go:90.74,91.46 1 0 +auth/ent/user_query.go:91.46,93.4 1 0 +auth/ent/user_query.go:94.3,95.40 2 0 +auth/ent/user_query.go:95.40,97.4 1 0 +auth/ent/user_query.go:98.3,104.20 3 0 +auth/ent/user_query.go:106.2,106.14 1 0 +auth/ent/user_query.go:111.64,113.16 2 0 +auth/ent/user_query.go:113.16,115.3 1 0 +auth/ent/user_query.go:116.2,116.21 1 0 +auth/ent/user_query.go:116.21,118.3 1 0 +auth/ent/user_query.go:119.2,119.22 1 0 +auth/ent/user_query.go:123.56,125.36 2 0 +auth/ent/user_query.go:125.36,126.13 1 0 +auth/ent/user_query.go:128.2,128.13 1 0 +auth/ent/user_query.go:133.74,135.82 2 0 +auth/ent/user_query.go:135.82,137.3 1 0 +auth/ent/user_query.go:138.2,138.19 1 0 +auth/ent/user_query.go:138.19,141.3 2 0 +auth/ent/user_query.go:142.2,142.20 1 0 +auth/ent/user_query.go:146.59,148.36 2 0 +auth/ent/user_query.go:148.36,149.13 1 0 +auth/ent/user_query.go:151.2,151.11 1 0 +auth/ent/user_query.go:157.63,159.16 2 22 +auth/ent/user_query.go:159.16,161.3 1 0 +auth/ent/user_query.go:162.2,162.20 1 22 +auth/ent/user_query.go:163.9,164.23 1 17 +auth/ent/user_query.go:165.9,166.41 1 5 +auth/ent/user_query.go:167.10,168.44 1 0 +auth/ent/user_query.go:173.55,175.16 2 0 +auth/ent/user_query.go:175.16,176.13 1 0 +auth/ent/user_query.go:178.2,178.13 1 0 +auth/ent/user_query.go:184.73,186.81 2 0 +auth/ent/user_query.go:186.81,188.3 1 0 +auth/ent/user_query.go:189.2,189.18 1 0 +auth/ent/user_query.go:190.9,191.14 1 0 +auth/ent/user_query.go:192.9,193.35 1 0 +auth/ent/user_query.go:194.10,195.38 1 0 +auth/ent/user_query.go:197.2,197.8 1 0 +auth/ent/user_query.go:201.58,203.16 2 0 +auth/ent/user_query.go:203.16,204.13 1 0 +auth/ent/user_query.go:206.2,206.11 1 0 +auth/ent/user_query.go:210.64,212.45 2 27 +auth/ent/user_query.go:212.45,214.3 1 0 +auth/ent/user_query.go:215.2,216.58 2 27 +auth/ent/user_query.go:220.56,222.16 2 0 +auth/ent/user_query.go:222.16,223.13 1 0 +auth/ent/user_query.go:225.2,225.14 1 0 +auth/ent/user_query.go:229.73,230.44 1 0 +auth/ent/user_query.go:230.44,232.3 1 0 +auth/ent/user_query.go:233.2,234.63 2 0 +auth/ent/user_query.go:234.63,236.3 1 0 +auth/ent/user_query.go:237.2,237.17 1 0 +auth/ent/user_query.go:241.57,243.16 2 0 +auth/ent/user_query.go:243.16,244.13 1 0 +auth/ent/user_query.go:246.2,246.12 1 0 +auth/ent/user_query.go:250.62,252.45 2 2 +auth/ent/user_query.go:252.45,254.3 1 0 +auth/ent/user_query.go:255.2,255.78 1 2 +auth/ent/user_query.go:259.54,261.16 2 0 +auth/ent/user_query.go:261.16,262.13 1 0 +auth/ent/user_query.go:264.2,264.14 1 0 +auth/ent/user_query.go:268.63,270.36 2 0 +auth/ent/user_query.go:271.23,272.20 1 0 +auth/ent/user_query.go:273.18,274.60 1 0 +auth/ent/user_query.go:275.10,276.19 1 0 +auth/ent/user_query.go:281.55,283.16 2 0 +auth/ent/user_query.go:283.16,284.13 1 0 +auth/ent/user_query.go:286.2,286.14 1 0 +auth/ent/user_query.go:291.41,292.15 1 0 +auth/ent/user_query.go:292.15,294.3 1 0 +auth/ent/user_query.go:295.2,306.3 1 0 +auth/ent/user_query.go:311.69,313.27 2 3 +auth/ent/user_query.go:313.27,315.3 1 0 +auth/ent/user_query.go:316.2,317.11 2 3 +auth/ent/user_query.go:322.71,324.27 2 0 +auth/ent/user_query.go:324.27,326.3 1 0 +auth/ent/user_query.go:327.2,328.11 2 0 +auth/ent/user_query.go:345.75,352.2 6 0 +auth/ent/user_query.go:366.59,372.2 5 0 +auth/ent/user_query.go:375.66,377.2 1 0 +auth/ent/user_query.go:379.62,380.34 1 30 +auth/ent/user_query.go:380.34,381.19 1 0 +auth/ent/user_query.go:381.19,383.4 1 0 +auth/ent/user_query.go:384.3,384.39 1 0 +auth/ent/user_query.go:384.39,385.48 1 0 +auth/ent/user_query.go:385.48,387.5 1 0 +auth/ent/user_query.go:390.2,390.34 1 30 +auth/ent/user_query.go:390.34,391.27 1 0 +auth/ent/user_query.go:391.27,393.4 1 0 +auth/ent/user_query.go:395.2,395.20 1 30 +auth/ent/user_query.go:395.20,397.17 2 2 +auth/ent/user_query.go:397.17,399.4 1 0 +auth/ent/user_query.go:400.3,400.16 1 2 +auth/ent/user_query.go:402.2,402.12 1 30 +auth/ent/user_query.go:405.87,414.59 2 28 +auth/ent/user_query.go:414.59,416.3 1 27 +auth/ent/user_query.go:417.2,417.60 1 28 +auth/ent/user_query.go:417.60,422.3 4 27 +auth/ent/user_query.go:423.2,423.23 1 28 +auth/ent/user_query.go:423.23,425.3 1 1 +auth/ent/user_query.go:426.2,426.67 1 28 +auth/ent/user_query.go:426.67,428.3 1 0 +auth/ent/user_query.go:429.2,429.21 1 28 +auth/ent/user_query.go:429.21,431.3 1 5 +auth/ent/user_query.go:432.2,432.41 1 23 +auth/ent/user_query.go:432.41,434.18 1 3 +auth/ent/user_query.go:434.18,434.47 1 3 +auth/ent/user_query.go:435.27,435.71 1 2 +auth/ent/user_query.go:435.85,437.4 1 0 +auth/ent/user_query.go:439.2,439.42 1 23 +auth/ent/user_query.go:439.42,441.18 1 0 +auth/ent/user_query.go:441.18,441.49 1 0 +auth/ent/user_query.go:442.28,442.74 1 0 +auth/ent/user_query.go:442.88,444.4 1 0 +auth/ent/user_query.go:446.2,446.19 1 23 +auth/ent/user_query.go:449.137,453.29 4 3 +auth/ent/user_query.go:453.29,456.18 3 3 +auth/ent/user_query.go:456.18,458.4 1 3 +auth/ent/user_query.go:460.2,460.36 1 3 +auth/ent/user_query.go:460.36,468.3 7 3 +auth/ent/user_query.go:469.2,469.48 1 3 +auth/ent/user_query.go:469.48,471.3 1 0 +auth/ent/user_query.go:472.2,472.70 1 3 +auth/ent/user_query.go:472.70,473.78 1 3 +auth/ent/user_query.go:473.78,476.60 3 3 +auth/ent/user_query.go:476.60,478.19 2 2 +auth/ent/user_query.go:478.19,480.6 1 0 +auth/ent/user_query.go:481.5,481.62 1 2 +auth/ent/user_query.go:483.4,483.61 1 3 +auth/ent/user_query.go:483.61,486.29 3 2 +auth/ent/user_query.go:486.29,489.6 2 2 +auth/ent/user_query.go:490.5,491.15 2 0 +auth/ent/user_query.go:495.2,496.16 2 3 +auth/ent/user_query.go:496.16,498.3 1 0 +auth/ent/user_query.go:499.2,499.30 1 3 +auth/ent/user_query.go:499.30,501.10 2 2 +auth/ent/user_query.go:501.10,503.4 1 0 +auth/ent/user_query.go:504.3,504.25 1 2 +auth/ent/user_query.go:504.25,506.4 1 2 +auth/ent/user_query.go:508.2,508.12 1 3 +auth/ent/user_query.go:510.140,513.23 3 0 +auth/ent/user_query.go:513.23,516.18 3 0 +auth/ent/user_query.go:516.18,518.4 1 0 +auth/ent/user_query.go:520.2,521.52 2 0 +auth/ent/user_query.go:521.52,523.3 1 0 +auth/ent/user_query.go:524.2,525.16 2 0 +auth/ent/user_query.go:525.16,527.3 1 0 +auth/ent/user_query.go:528.2,528.30 1 0 +auth/ent/user_query.go:528.30,530.16 2 0 +auth/ent/user_query.go:530.16,532.4 1 0 +auth/ent/user_query.go:533.3,534.10 2 0 +auth/ent/user_query.go:534.10,536.4 1 0 +auth/ent/user_query.go:537.3,537.18 1 0 +auth/ent/user_query.go:539.2,539.12 1 0 +auth/ent/user_query.go:542.65,545.28 3 2 +auth/ent/user_query.go:545.28,547.3 1 0 +auth/ent/user_query.go:548.2,548.51 1 2 +auth/ent/user_query.go:551.54,554.44 3 30 +auth/ent/user_query.go:554.44,556.3 1 0 +auth/ent/user_query.go:556.8,556.27 1 30 +auth/ent/user_query.go:556.27,558.3 1 2 +auth/ent/user_query.go:559.2,559.46 1 30 +auth/ent/user_query.go:559.46,562.25 3 0 +auth/ent/user_query.go:562.25,563.33 1 0 +auth/ent/user_query.go:563.33,565.5 1 0 +auth/ent/user_query.go:568.2,568.38 1 30 +auth/ent/user_query.go:568.38,569.50 1 24 +auth/ent/user_query.go:569.50,570.22 1 24 +auth/ent/user_query.go:570.22,572.5 1 24 +auth/ent/user_query.go:575.2,575.41 1 30 +auth/ent/user_query.go:575.41,577.3 1 24 +auth/ent/user_query.go:578.2,578.44 1 30 +auth/ent/user_query.go:578.44,580.3 1 2 +auth/ent/user_query.go:581.2,581.33 1 30 +auth/ent/user_query.go:581.33,582.46 1 0 +auth/ent/user_query.go:582.46,583.22 1 0 +auth/ent/user_query.go:583.22,585.5 1 0 +auth/ent/user_query.go:588.2,588.14 1 30 +auth/ent/user_query.go:591.66,595.23 4 0 +auth/ent/user_query.go:595.23,597.3 1 0 +auth/ent/user_query.go:598.2,599.19 2 0 +auth/ent/user_query.go:599.19,602.3 2 0 +auth/ent/user_query.go:603.2,603.44 1 0 +auth/ent/user_query.go:603.44,605.3 1 0 +auth/ent/user_query.go:606.2,606.34 1 0 +auth/ent/user_query.go:606.34,608.3 1 0 +auth/ent/user_query.go:609.2,609.29 1 0 +auth/ent/user_query.go:609.29,611.3 1 0 +auth/ent/user_query.go:612.2,612.44 1 0 +auth/ent/user_query.go:612.44,616.3 1 0 +auth/ent/user_query.go:617.2,617.41 1 0 +auth/ent/user_query.go:617.41,619.3 1 0 +auth/ent/user_query.go:620.2,620.17 1 0 +auth/ent/user_query.go:630.70,633.2 2 0 +auth/ent/user_query.go:636.64,638.52 2 0 +auth/ent/user_query.go:638.52,640.3 1 0 +auth/ent/user_query.go:641.2,641.97 1 0 +auth/ent/user_query.go:644.84,647.29 3 0 +auth/ent/user_query.go:647.29,649.3 1 0 +auth/ent/user_query.go:650.2,650.42 1 0 +auth/ent/user_query.go:650.42,652.31 2 0 +auth/ent/user_query.go:652.31,654.4 1 0 +auth/ent/user_query.go:655.3,656.30 2 0 +auth/ent/user_query.go:658.2,659.39 2 0 +auth/ent/user_query.go:659.39,661.3 1 0 +auth/ent/user_query.go:662.2,664.71 3 0 +auth/ent/user_query.go:664.71,666.3 1 0 +auth/ent/user_query.go:667.2,668.31 2 0 +auth/ent/user_query.go:678.67,681.2 2 0 +auth/ent/user_query.go:684.62,686.45 2 0 +auth/ent/user_query.go:686.45,688.3 1 0 +auth/ent/user_query.go:689.2,689.91 1 0 +auth/ent/user_query.go:692.82,695.28 3 0 +auth/ent/user_query.go:695.28,697.3 1 0 +auth/ent/user_query.go:698.2,698.38 1 0 +auth/ent/user_query.go:699.38,700.34 1 0 +auth/ent/user_query.go:701.38,702.40 1 0 +auth/ent/user_query.go:704.2,706.64 3 0 +auth/ent/user_query.go:706.64,708.3 1 0 +auth/ent/user_query.go:709.2,710.31 2 0 +auth/ent/user_update.go:28.63,31.2 2 0 +auth/ent/user_update.go:34.57,37.2 2 0 +auth/ent/user_update.go:40.66,41.14 1 0 +auth/ent/user_update.go:41.14,43.3 1 0 +auth/ent/user_update.go:44.2,44.11 1 0 +auth/ent/user_update.go:48.54,51.2 2 0 +auth/ent/user_update.go:54.63,55.14 1 0 +auth/ent/user_update.go:55.14,57.3 1 0 +auth/ent/user_update.go:58.2,58.11 1 0 +auth/ent/user_update.go:62.57,65.2 2 0 +auth/ent/user_update.go:68.66,69.14 1 0 +auth/ent/user_update.go:69.14,71.3 1 0 +auth/ent/user_update.go:72.2,72.11 1 0 +auth/ent/user_update.go:76.61,79.2 2 0 +auth/ent/user_update.go:82.70,83.14 1 0 +auth/ent/user_update.go:83.14,85.3 1 0 +auth/ent/user_update.go:86.2,86.11 1 0 +auth/ent/user_update.go:90.61,93.2 2 0 +auth/ent/user_update.go:96.61,99.2 2 0 +auth/ent/user_update.go:102.56,104.19 2 0 +auth/ent/user_update.go:104.19,106.3 1 0 +auth/ent/user_update.go:107.2,107.30 1 0 +auth/ent/user_update.go:111.62,114.2 2 0 +auth/ent/user_update.go:117.58,119.19 2 0 +auth/ent/user_update.go:119.19,121.3 1 0 +auth/ent/user_update.go:122.2,122.31 1 0 +auth/ent/user_update.go:126.48,128.2 1 0 +auth/ent/user_update.go:131.48,134.2 2 0 +auth/ent/user_update.go:137.64,140.2 2 0 +auth/ent/user_update.go:143.59,145.19 2 0 +auth/ent/user_update.go:145.19,147.3 1 0 +auth/ent/user_update.go:148.2,148.33 1 0 +auth/ent/user_update.go:152.49,155.2 2 0 +auth/ent/user_update.go:158.65,161.2 2 0 +auth/ent/user_update.go:164.61,166.19 2 0 +auth/ent/user_update.go:166.19,168.3 1 0 +auth/ent/user_update.go:169.2,169.34 1 0 +auth/ent/user_update.go:173.62,174.38 1 0 +auth/ent/user_update.go:174.38,176.3 1 0 +auth/ent/user_update.go:177.2,177.58 1 0 +auth/ent/user_update.go:181.54,183.16 2 0 +auth/ent/user_update.go:183.16,184.13 1 0 +auth/ent/user_update.go:186.2,186.17 1 0 +auth/ent/user_update.go:190.55,193.2 2 0 +auth/ent/user_update.go:196.50,197.37 1 0 +auth/ent/user_update.go:197.37,198.13 1 0 +auth/ent/user_update.go:203.40,204.43 1 0 +auth/ent/user_update.go:204.43,205.41 1 0 +auth/ent/user_update.go:205.41,207.4 1 0 +auth/ent/user_update.go:208.3,209.30 2 0 +auth/ent/user_update.go:211.2,211.12 1 0 +auth/ent/user_update.go:214.71,216.47 2 0 +auth/ent/user_update.go:216.47,217.50 1 0 +auth/ent/user_update.go:217.50,218.22 1 0 +auth/ent/user_update.go:218.22,220.5 1 0 +auth/ent/user_update.go:223.2,223.45 1 0 +auth/ent/user_update.go:223.45,225.3 1 0 +auth/ent/user_update.go:226.2,226.42 1 0 +auth/ent/user_update.go:226.42,228.3 1 0 +auth/ent/user_update.go:229.2,229.45 1 0 +auth/ent/user_update.go:229.45,231.3 1 0 +auth/ent/user_update.go:232.2,232.46 1 0 +auth/ent/user_update.go:232.46,234.3 1 0 +auth/ent/user_update.go:235.2,235.46 1 0 +auth/ent/user_update.go:235.46,237.3 1 0 +auth/ent/user_update.go:238.2,238.32 1 0 +auth/ent/user_update.go:238.32,250.3 2 0 +auth/ent/user_update.go:251.2,251.91 1 0 +auth/ent/user_update.go:251.91,262.27 2 0 +auth/ent/user_update.go:262.27,264.4 1 0 +auth/ent/user_update.go:265.3,265.54 1 0 +auth/ent/user_update.go:267.2,267.53 1 0 +auth/ent/user_update.go:267.53,278.27 2 0 +auth/ent/user_update.go:278.27,280.4 1 0 +auth/ent/user_update.go:281.3,281.50 1 0 +auth/ent/user_update.go:283.2,283.33 1 0 +auth/ent/user_update.go:283.33,295.3 2 0 +auth/ent/user_update.go:296.2,296.93 1 0 +auth/ent/user_update.go:296.93,307.27 2 0 +auth/ent/user_update.go:307.27,309.4 1 0 +auth/ent/user_update.go:310.3,310.54 1 0 +auth/ent/user_update.go:312.2,312.54 1 0 +auth/ent/user_update.go:312.54,323.27 2 0 +auth/ent/user_update.go:323.27,325.4 1 0 +auth/ent/user_update.go:326.3,326.50 1 0 +auth/ent/user_update.go:328.2,328.70 1 0 +auth/ent/user_update.go:328.70,329.49 1 0 +auth/ent/user_update.go:329.49,331.4 1 0 +auth/ent/user_update.go:331.9,331.45 1 0 +auth/ent/user_update.go:331.45,333.4 1 0 +auth/ent/user_update.go:334.3,334.16 1 0 +auth/ent/user_update.go:336.2,337.15 2 0 +auth/ent/user_update.go:349.64,352.2 2 1 +auth/ent/user_update.go:355.73,356.14 1 0 +auth/ent/user_update.go:356.14,358.3 1 0 +auth/ent/user_update.go:359.2,359.12 1 0 +auth/ent/user_update.go:363.61,366.2 2 1 +auth/ent/user_update.go:369.70,370.14 1 0 +auth/ent/user_update.go:370.14,372.3 1 0 +auth/ent/user_update.go:373.2,373.12 1 0 +auth/ent/user_update.go:377.64,380.2 2 3 +auth/ent/user_update.go:383.73,384.14 1 0 +auth/ent/user_update.go:384.14,386.3 1 0 +auth/ent/user_update.go:387.2,387.12 1 0 +auth/ent/user_update.go:391.68,394.2 2 0 +auth/ent/user_update.go:397.77,398.14 1 0 +auth/ent/user_update.go:398.14,400.3 1 0 +auth/ent/user_update.go:401.2,401.12 1 0 +auth/ent/user_update.go:405.68,408.2 2 2 +auth/ent/user_update.go:411.68,414.2 2 8 +auth/ent/user_update.go:417.63,419.19 2 0 +auth/ent/user_update.go:419.19,421.3 1 0 +auth/ent/user_update.go:422.2,422.31 1 0 +auth/ent/user_update.go:426.69,429.2 2 0 +auth/ent/user_update.go:432.65,434.19 2 0 +auth/ent/user_update.go:434.19,436.3 1 0 +auth/ent/user_update.go:437.2,437.32 1 0 +auth/ent/user_update.go:441.52,443.2 1 0 +auth/ent/user_update.go:446.55,449.2 2 0 +auth/ent/user_update.go:452.71,455.2 2 2 +auth/ent/user_update.go:458.66,460.19 2 0 +auth/ent/user_update.go:460.19,462.3 1 0 +auth/ent/user_update.go:463.2,463.34 1 0 +auth/ent/user_update.go:467.56,470.2 2 0 +auth/ent/user_update.go:473.72,476.2 2 0 +auth/ent/user_update.go:479.68,481.19 2 0 +auth/ent/user_update.go:481.19,483.3 1 0 +auth/ent/user_update.go:484.2,484.35 1 0 +auth/ent/user_update.go:488.70,491.2 2 0 +auth/ent/user_update.go:495.81,498.2 2 0 +auth/ent/user_update.go:501.68,502.39 1 13 +auth/ent/user_update.go:502.39,504.3 1 0 +auth/ent/user_update.go:505.2,505.61 1 13 +auth/ent/user_update.go:509.60,511.16 2 0 +auth/ent/user_update.go:511.16,512.13 1 0 +auth/ent/user_update.go:514.2,514.13 1 0 +auth/ent/user_update.go:518.59,521.2 2 12 +auth/ent/user_update.go:524.54,525.38 1 0 +auth/ent/user_update.go:525.38,526.13 1 0 +auth/ent/user_update.go:531.44,532.44 1 13 +auth/ent/user_update.go:532.44,533.41 1 11 +auth/ent/user_update.go:533.41,535.4 1 0 +auth/ent/user_update.go:536.3,537.31 2 11 +auth/ent/user_update.go:539.2,539.12 1 13 +auth/ent/user_update.go:542.81,545.9 3 13 +auth/ent/user_update.go:545.9,547.3 1 0 +auth/ent/user_update.go:548.2,549.43 2 13 +auth/ent/user_update.go:549.43,552.28 3 0 +auth/ent/user_update.go:552.28,553.28 1 0 +auth/ent/user_update.go:553.28,555.5 1 0 +auth/ent/user_update.go:556.4,556.25 1 0 +auth/ent/user_update.go:556.25,558.5 1 0 +auth/ent/user_update.go:561.2,561.48 1 13 +auth/ent/user_update.go:561.48,562.50 1 0 +auth/ent/user_update.go:562.50,563.22 1 0 +auth/ent/user_update.go:563.22,565.5 1 0 +auth/ent/user_update.go:568.2,568.46 1 13 +auth/ent/user_update.go:568.46,570.3 1 1 +auth/ent/user_update.go:571.2,571.43 1 13 +auth/ent/user_update.go:571.43,573.3 1 1 +auth/ent/user_update.go:574.2,574.46 1 13 +auth/ent/user_update.go:574.46,576.3 1 3 +auth/ent/user_update.go:577.2,577.47 1 13 +auth/ent/user_update.go:577.47,579.3 1 0 +auth/ent/user_update.go:580.2,580.47 1 13 +auth/ent/user_update.go:580.47,582.3 1 13 +auth/ent/user_update.go:583.2,583.33 1 13 +auth/ent/user_update.go:583.33,595.3 2 0 +auth/ent/user_update.go:596.2,596.93 1 13 +auth/ent/user_update.go:596.93,607.27 2 2 +auth/ent/user_update.go:607.27,609.4 1 2 +auth/ent/user_update.go:610.3,610.54 1 2 +auth/ent/user_update.go:612.2,612.54 1 13 +auth/ent/user_update.go:612.54,623.27 2 8 +auth/ent/user_update.go:623.27,625.4 1 8 +auth/ent/user_update.go:626.3,626.50 1 8 +auth/ent/user_update.go:628.2,628.34 1 13 +auth/ent/user_update.go:628.34,640.3 2 0 +auth/ent/user_update.go:641.2,641.95 1 13 +auth/ent/user_update.go:641.95,652.27 2 0 +auth/ent/user_update.go:652.27,654.4 1 0 +auth/ent/user_update.go:655.3,655.54 1 0 +auth/ent/user_update.go:657.2,657.55 1 13 +auth/ent/user_update.go:657.55,668.27 2 0 +auth/ent/user_update.go:668.27,670.4 1 0 +auth/ent/user_update.go:671.3,671.50 1 0 +auth/ent/user_update.go:673.2,676.67 4 13 +auth/ent/user_update.go:676.67,677.49 1 0 +auth/ent/user_update.go:677.49,679.4 1 0 +auth/ent/user_update.go:679.9,679.45 1 0 +auth/ent/user_update.go:679.45,681.4 1 0 +auth/ent/user_update.go:682.3,682.18 1 0 +auth/ent/user_update.go:684.2,685.19 2 13 +auth/ent/enttest/enttest.go:35.45,36.26 1 0 +auth/ent/enttest/enttest.go:36.26,38.3 1 0 +auth/ent/enttest/enttest.go:42.62,43.26 1 0 +auth/ent/enttest/enttest.go:43.26,45.3 1 0 +auth/ent/enttest/enttest.go:48.41,50.27 2 6 +auth/ent/enttest/enttest.go:50.27,52.3 1 0 +auth/ent/enttest/enttest.go:53.2,53.10 1 6 +auth/ent/enttest/enttest.go:57.86,60.16 3 6 +auth/ent/enttest/enttest.go:60.16,63.3 2 0 +auth/ent/enttest/enttest.go:64.2,65.10 2 6 +auth/ent/enttest/enttest.go:69.56,74.2 4 0 +auth/ent/enttest/enttest.go:75.59,77.16 2 6 +auth/ent/enttest/enttest.go:77.16,80.3 2 0 +auth/ent/enttest/enttest.go:81.2,81.97 1 6 +auth/ent/enttest/enttest.go:81.97,84.3 2 0 +auth/ent/migrate/migrate.go:41.44,41.72 1 6 +auth/ent/migrate/migrate.go:44.82,46.2 1 0 +auth/ent/migrate/migrate.go:49.105,51.16 2 6 +auth/ent/migrate/migrate.go:51.16,53.3 1 0 +auth/ent/migrate/migrate.go:54.2,54.39 1 6 +auth/ent/migrate/migrate.go:62.96,64.2 1 0 +auth/ent/migrate/schema.go:99.13,103.2 3 1 +auth/ent/role/role.go:52.38,53.25 1 0 +auth/ent/role/role.go:53.25,54.27 1 0 +auth/ent/role/role.go:54.27,56.4 1 0 +auth/ent/role/role.go:58.2,58.14 1 0 +auth/ent/role/role.go:76.52,78.2 1 0 +auth/ent/role/role.go:81.54,83.2 1 0 +auth/ent/role/role.go:86.59,88.2 1 0 +auth/ent/role/role.go:91.59,93.2 1 0 +auth/ent/role/role.go:96.60,97.31 1 0 +auth/ent/role/role.go:97.31,99.3 1 0 +auth/ent/role/role.go:103.70,104.31 1 0 +auth/ent/role/role.go:104.31,106.3 1 0 +auth/ent/role/role.go:108.36,114.2 1 3 +auth/ent/role/where.go:14.35,16.2 1 8 +auth/ent/role/where.go:19.37,21.2 1 0 +auth/ent/role/where.go:24.38,26.2 1 0 +auth/ent/role/where.go:29.41,31.2 1 0 +auth/ent/role/where.go:34.44,36.2 1 0 +auth/ent/role/where.go:39.37,41.2 1 0 +auth/ent/role/where.go:44.38,46.2 1 0 +auth/ent/role/where.go:49.37,51.2 1 0 +auth/ent/role/where.go:54.38,56.2 1 0 +auth/ent/role/where.go:59.44,61.2 1 0 +auth/ent/role/where.go:64.47,66.2 1 0 +auth/ent/role/where.go:69.36,71.2 1 1 +auth/ent/role/where.go:74.44,76.2 1 0 +auth/ent/role/where.go:79.44,81.2 1 0 +auth/ent/role/where.go:84.38,86.2 1 0 +auth/ent/role/where.go:89.39,91.2 1 0 +auth/ent/role/where.go:94.42,96.2 1 0 +auth/ent/role/where.go:99.45,101.2 1 0 +auth/ent/role/where.go:104.38,106.2 1 0 +auth/ent/role/where.go:109.39,111.2 1 0 +auth/ent/role/where.go:114.38,116.2 1 0 +auth/ent/role/where.go:119.39,121.2 1 0 +auth/ent/role/where.go:124.44,126.2 1 0 +auth/ent/role/where.go:129.45,131.2 1 1 +auth/ent/role/where.go:134.45,136.2 1 0 +auth/ent/role/where.go:139.45,141.2 1 0 +auth/ent/role/where.go:144.48,146.2 1 0 +auth/ent/role/where.go:149.46,151.2 1 0 +auth/ent/role/where.go:154.47,156.2 1 0 +auth/ent/role/where.go:159.50,161.2 1 0 +auth/ent/role/where.go:164.53,166.2 1 0 +auth/ent/role/where.go:169.46,171.2 1 0 +auth/ent/role/where.go:174.47,176.2 1 0 +auth/ent/role/where.go:179.46,181.2 1 0 +auth/ent/role/where.go:184.47,186.2 1 0 +auth/ent/role/where.go:189.46,191.2 1 0 +auth/ent/role/where.go:194.47,196.2 1 0 +auth/ent/role/where.go:199.50,201.2 1 0 +auth/ent/role/where.go:204.53,206.2 1 0 +auth/ent/role/where.go:209.46,211.2 1 0 +auth/ent/role/where.go:214.47,216.2 1 0 +auth/ent/role/where.go:219.46,221.2 1 0 +auth/ent/role/where.go:224.47,226.2 1 0 +auth/ent/role/where.go:229.32,230.46 1 0 +auth/ent/role/where.go:230.46,236.3 2 0 +auth/ent/role/where.go:240.59,241.46 1 3 +auth/ent/role/where.go:241.46,243.60 2 3 +auth/ent/role/where.go:243.60,244.28 1 3 +auth/ent/role/where.go:244.28,246.5 1 3 +auth/ent/role/where.go:252.55,254.2 1 0 +auth/ent/role/where.go:257.54,259.2 1 0 +auth/ent/role/where.go:262.43,264.2 1 0 +auth/ent/runtime/runtime.go:16.13,71.2 31 1 +auth/ent/schema/role.go:18.34,21.30 1 1 +auth/ent/schema/role.go:21.30,23.5 1 34 +auth/ent/schema/role.go:35.32,40.2 1 0 +auth/ent/schema/token.go:18.35,21.30 1 1 +auth/ent/schema/token.go:21.30,23.5 1 13 +auth/ent/schema/token.go:39.33,46.2 1 0 +auth/ent/schema/user.go:20.34,23.30 1 1 +auth/ent/schema/user.go:23.30,25.5 1 38 +auth/ent/schema/user.go:38.32,43.2 1 0 +auth/ent/schema/user.go:46.32,50.2 1 1 +auth/ent/schema/user.go:53.30,54.44 1 1 +auth/ent/schema/user.go:54.44,55.86 1 60 +auth/ent/schema/user.go:55.86,56.47 1 60 +auth/ent/schema/user.go:56.47,58.19 2 47 +auth/ent/schema/user.go:58.19,60.6 1 0 +auth/ent/schema/user.go:61.5,61.41 1 47 +auth/ent/schema/user.go:63.4,63.30 1 60 +auth/ent/token/token.go:61.38,62.25 1 0 +auth/ent/token/token.go:62.25,63.27 1 0 +auth/ent/token/token.go:63.27,65.4 1 0 +auth/ent/token/token.go:67.2,67.29 1 0 +auth/ent/token/token.go:67.29,68.31 1 0 +auth/ent/token/token.go:68.31,70.4 1 0 +auth/ent/token/token.go:72.2,72.14 1 0 +auth/ent/token/token.go:97.35,99.2 1 2 +auth/ent/token/token.go:102.38,103.15 1 13 +auth/ent/token/token.go:104.31,105.13 1 13 +auth/ent/token/token.go:106.10,107.75 1 0 +auth/ent/token/token.go:115.52,117.2 1 0 +auth/ent/token/token.go:120.55,122.2 1 0 +auth/ent/token/token.go:125.54,127.2 1 0 +auth/ent/token/token.go:130.59,132.2 1 0 +auth/ent/token/token.go:135.57,137.2 1 0 +auth/ent/token/token.go:140.59,142.2 1 0 +auth/ent/token/token.go:145.59,147.2 1 0 +auth/ent/token/token.go:150.73,151.31 1 0 +auth/ent/token/token.go:151.31,153.3 1 0 +auth/ent/token/token.go:155.35,161.2 1 3 +auth/ent/token/where.go:14.36,16.2 1 4 +auth/ent/token/where.go:19.38,21.2 1 0 +auth/ent/token/where.go:24.39,26.2 1 0 +auth/ent/token/where.go:29.42,31.2 1 0 +auth/ent/token/where.go:34.45,36.2 1 0 +auth/ent/token/where.go:39.38,41.2 1 0 +auth/ent/token/where.go:44.39,46.2 1 0 +auth/ent/token/where.go:49.38,51.2 1 0 +auth/ent/token/where.go:54.39,56.2 1 0 +auth/ent/token/where.go:59.45,61.2 1 0 +auth/ent/token/where.go:64.48,66.2 1 0 +auth/ent/token/where.go:69.38,71.2 1 6 +auth/ent/token/where.go:74.45,76.2 1 0 +auth/ent/token/where.go:79.38,81.2 1 4 +auth/ent/token/where.go:84.45,86.2 1 0 +auth/ent/token/where.go:89.45,91.2 1 0 +auth/ent/token/where.go:94.40,96.2 1 0 +auth/ent/token/where.go:99.41,101.2 1 0 +auth/ent/token/where.go:104.44,106.2 1 0 +auth/ent/token/where.go:109.47,111.2 1 0 +auth/ent/token/where.go:114.40,116.2 1 0 +auth/ent/token/where.go:119.41,121.2 1 0 +auth/ent/token/where.go:124.40,126.2 1 0 +auth/ent/token/where.go:129.41,131.2 1 0 +auth/ent/token/where.go:134.46,136.2 1 0 +auth/ent/token/where.go:139.47,141.2 1 0 +auth/ent/token/where.go:144.47,146.2 1 0 +auth/ent/token/where.go:149.47,151.2 1 0 +auth/ent/token/where.go:154.50,156.2 1 0 +auth/ent/token/where.go:159.37,161.2 1 0 +auth/ent/token/where.go:164.38,166.2 1 0 +auth/ent/token/where.go:169.41,171.2 1 0 +auth/ent/token/where.go:174.44,176.2 1 0 +auth/ent/token/where.go:179.47,181.2 1 0 +auth/ent/token/where.go:184.48,186.2 1 0 +auth/ent/token/where.go:189.51,191.2 1 0 +auth/ent/token/where.go:194.54,196.2 1 0 +auth/ent/token/where.go:199.47,201.2 1 2 +auth/ent/token/where.go:204.48,206.2 1 0 +auth/ent/token/where.go:209.47,211.2 1 1 +auth/ent/token/where.go:214.48,216.2 1 0 +auth/ent/token/where.go:219.40,221.2 1 3 +auth/ent/token/where.go:224.41,226.2 1 0 +auth/ent/token/where.go:229.47,231.2 1 0 +auth/ent/token/where.go:234.48,236.2 1 0 +auth/ent/token/where.go:239.51,241.2 1 0 +auth/ent/token/where.go:244.54,246.2 1 0 +auth/ent/token/where.go:249.47,251.2 1 0 +auth/ent/token/where.go:254.48,256.2 1 0 +auth/ent/token/where.go:259.47,261.2 1 0 +auth/ent/token/where.go:264.48,266.2 1 0 +auth/ent/token/where.go:269.47,271.2 1 0 +auth/ent/token/where.go:274.48,276.2 1 0 +auth/ent/token/where.go:279.51,281.2 1 0 +auth/ent/token/where.go:284.54,286.2 1 0 +auth/ent/token/where.go:289.47,291.2 1 0 +auth/ent/token/where.go:294.48,296.2 1 0 +auth/ent/token/where.go:299.47,301.2 1 0 +auth/ent/token/where.go:304.48,306.2 1 0 +auth/ent/token/where.go:309.32,310.47 1 0 +auth/ent/token/where.go:310.47,316.3 2 0 +auth/ent/token/where.go:320.59,321.47 1 3 +auth/ent/token/where.go:321.47,323.60 2 3 +auth/ent/token/where.go:323.60,324.28 1 3 +auth/ent/token/where.go:324.28,326.5 1 3 +auth/ent/token/where.go:332.57,334.2 1 0 +auth/ent/token/where.go:337.56,339.2 1 1 +auth/ent/token/where.go:342.45,344.2 1 0 +auth/ent/user/user.go:65.38,66.25 1 0 +auth/ent/user/user.go:66.25,67.27 1 0 +auth/ent/user/user.go:67.27,69.4 1 0 +auth/ent/user/user.go:71.2,71.14 1 0 +auth/ent/user/user.go:95.52,97.2 1 0 +auth/ent/user/user.go:100.58,102.2 1 0 +auth/ent/user/user.go:105.55,107.2 1 0 +auth/ent/user/user.go:110.58,112.2 1 0 +auth/ent/user/user.go:115.59,117.2 1 0 +auth/ent/user/user.go:120.59,122.2 1 0 +auth/ent/user/user.go:125.60,126.31 1 0 +auth/ent/user/user.go:126.31,128.3 1 0 +auth/ent/user/user.go:132.70,133.31 1 0 +auth/ent/user/user.go:133.31,135.3 1 0 +auth/ent/user/user.go:139.61,140.31 1 0 +auth/ent/user/user.go:140.31,142.3 1 0 +auth/ent/user/user.go:146.71,147.31 1 0 +auth/ent/user/user.go:147.31,149.3 1 0 +auth/ent/user/user.go:151.36,157.2 1 1 +auth/ent/user/user.go:158.37,164.2 1 0 +auth/ent/user/where.go:14.35,16.2 1 18 +auth/ent/user/where.go:19.37,21.2 1 0 +auth/ent/user/where.go:24.38,26.2 1 0 +auth/ent/user/where.go:29.41,31.2 1 0 +auth/ent/user/where.go:34.44,36.2 1 0 +auth/ent/user/where.go:39.37,41.2 1 0 +auth/ent/user/where.go:44.38,46.2 1 0 +auth/ent/user/where.go:49.37,51.2 1 0 +auth/ent/user/where.go:54.38,56.2 1 0 +auth/ent/user/where.go:59.44,61.2 1 0 +auth/ent/user/where.go:64.47,66.2 1 0 +auth/ent/user/where.go:69.40,71.2 1 9 +auth/ent/user/where.go:74.37,76.2 1 2 +auth/ent/user/where.go:79.40,81.2 1 0 +auth/ent/user/where.go:84.44,86.2 1 0 +auth/ent/user/where.go:89.44,91.2 1 0 +auth/ent/user/where.go:94.42,96.2 1 0 +auth/ent/user/where.go:99.43,101.2 1 0 +auth/ent/user/where.go:104.46,106.2 1 0 +auth/ent/user/where.go:109.49,111.2 1 0 +auth/ent/user/where.go:114.42,116.2 1 0 +auth/ent/user/where.go:119.43,121.2 1 0 +auth/ent/user/where.go:124.42,126.2 1 0 +auth/ent/user/where.go:129.43,131.2 1 0 +auth/ent/user/where.go:134.48,136.2 1 1 +auth/ent/user/where.go:139.49,141.2 1 0 +auth/ent/user/where.go:144.49,146.2 1 0 +auth/ent/user/where.go:149.49,151.2 1 0 +auth/ent/user/where.go:154.52,156.2 1 0 +auth/ent/user/where.go:159.39,161.2 1 0 +auth/ent/user/where.go:164.40,166.2 1 0 +auth/ent/user/where.go:169.43,171.2 1 0 +auth/ent/user/where.go:174.46,176.2 1 0 +auth/ent/user/where.go:179.39,181.2 1 0 +auth/ent/user/where.go:184.40,186.2 1 0 +auth/ent/user/where.go:189.39,191.2 1 0 +auth/ent/user/where.go:194.40,196.2 1 0 +auth/ent/user/where.go:199.45,201.2 1 1 +auth/ent/user/where.go:204.46,206.2 1 0 +auth/ent/user/where.go:209.46,211.2 1 0 +auth/ent/user/where.go:214.46,216.2 1 0 +auth/ent/user/where.go:219.49,221.2 1 0 +auth/ent/user/where.go:224.42,226.2 1 0 +auth/ent/user/where.go:229.43,231.2 1 0 +auth/ent/user/where.go:234.46,236.2 1 0 +auth/ent/user/where.go:239.49,241.2 1 0 +auth/ent/user/where.go:244.42,246.2 1 0 +auth/ent/user/where.go:249.43,251.2 1 0 +auth/ent/user/where.go:254.42,256.2 1 0 +auth/ent/user/where.go:259.43,261.2 1 0 +auth/ent/user/where.go:264.48,266.2 1 0 +auth/ent/user/where.go:269.49,271.2 1 0 +auth/ent/user/where.go:274.49,276.2 1 0 +auth/ent/user/where.go:279.49,281.2 1 0 +auth/ent/user/where.go:284.52,286.2 1 0 +auth/ent/user/where.go:289.46,291.2 1 0 +auth/ent/user/where.go:294.47,296.2 1 0 +auth/ent/user/where.go:299.50,301.2 1 0 +auth/ent/user/where.go:304.53,306.2 1 0 +auth/ent/user/where.go:309.46,311.2 1 0 +auth/ent/user/where.go:314.47,316.2 1 0 +auth/ent/user/where.go:319.46,321.2 1 0 +auth/ent/user/where.go:324.47,326.2 1 0 +auth/ent/user/where.go:329.46,331.2 1 0 +auth/ent/user/where.go:334.47,336.2 1 0 +auth/ent/user/where.go:339.50,341.2 1 0 +auth/ent/user/where.go:344.53,346.2 1 0 +auth/ent/user/where.go:349.46,351.2 1 0 +auth/ent/user/where.go:354.47,356.2 1 0 +auth/ent/user/where.go:359.46,361.2 1 0 +auth/ent/user/where.go:364.47,366.2 1 0 +auth/ent/user/where.go:369.32,370.46 1 0 +auth/ent/user/where.go:370.46,376.3 2 0 +auth/ent/user/where.go:380.59,381.46 1 1 +auth/ent/user/where.go:381.46,383.60 2 1 +auth/ent/user/where.go:383.60,384.28 1 1 +auth/ent/user/where.go:384.28,386.5 1 1 +auth/ent/user/where.go:392.33,393.46 1 0 +auth/ent/user/where.go:393.46,399.3 2 0 +auth/ent/user/where.go:403.61,404.46 1 0 +auth/ent/user/where.go:404.46,406.60 2 0 +auth/ent/user/where.go:406.60,407.28 1 0 +auth/ent/user/where.go:407.28,409.5 1 0 +auth/ent/user/where.go:415.55,417.2 1 0 +auth/ent/user/where.go:420.54,422.2 1 1 +auth/ent/user/where.go:425.43,427.2 1 0 +auth/internal/repository/role.go:375.60,377.2 1 1 +auth/internal/repository/role.go:379.89,385.2 1 27 +auth/internal/repository/role.go:387.85,389.2 1 5 +auth/internal/repository/role.go:391.89,393.2 1 1 +auth/internal/repository/role.go:395.89,401.2 1 1 +auth/internal/repository/role.go:403.71,405.2 1 1 +auth/internal/repository/role.go:407.92,412.2 1 1 +auth/internal/repository/role.go:414.66,416.2 1 2 +auth/internal/repository/role.go:418.94,422.2 1 1 +auth/internal/repository/role.go:424.97,426.16 2 1 +auth/internal/repository/role.go:426.16,428.3 1 0 +auth/internal/repository/role.go:430.2,431.41 2 1 +auth/internal/repository/role.go:431.41,432.22 1 2 +auth/internal/repository/role.go:432.22,434.4 1 1 +auth/internal/repository/role.go:437.2,443.12 3 1 +auth/internal/repository/role.go:446.95,448.16 2 0 +auth/internal/repository/role.go:448.16,450.3 1 0 +auth/internal/repository/role.go:451.2,451.34 1 0 +auth/internal/repository/role.go:454.90,458.2 1 1 +auth/internal/repository/role.go:460.95,464.2 1 0 +auth/internal/repository/role.go:466.98,471.16 2 1 +auth/internal/repository/role.go:471.16,473.3 1 0 +auth/internal/repository/role.go:474.2,474.34 1 1 +auth/internal/repository/role.go:477.89,481.2 1 1 +auth/internal/repository/role.go:483.100,487.2 1 3 +auth/internal/repository/role.go:489.93,493.2 1 3 +auth/internal/repository/role.go:495.95,499.2 1 1 +auth/internal/repository/token.go:93.62,95.2 1 1 +auth/internal/repository/token.go:98.142,106.2 1 9 +auth/internal/repository/token.go:109.99,114.2 1 3 +auth/internal/repository/token.go:117.86,127.16 2 3 +auth/internal/repository/token.go:127.16,129.3 1 0 +auth/internal/repository/token.go:131.2,131.19 1 3 +auth/internal/repository/token.go:131.19,133.3 1 2 +auth/internal/repository/token.go:135.2,135.12 1 1 +auth/internal/repository/token.go:139.74,150.2 2 1 +auth/internal/repository/token.go:153.108,162.2 1 2 +auth/internal/repository/token.go:165.89,175.2 2 1 +auth/internal/repository/user.go:354.60,356.2 1 1 +auth/internal/repository/user.go:359.86,366.2 1 24 +auth/internal/repository/user.go:369.85,371.2 1 5 +auth/internal/repository/user.go:374.97,376.2 1 2 +auth/internal/repository/user.go:379.91,381.2 1 2 +auth/internal/repository/user.go:384.86,391.2 1 1 +auth/internal/repository/user.go:394.71,396.2 1 2 +auth/internal/repository/user.go:398.92,403.2 1 2 +auth/internal/repository/user.go:406.66,408.2 1 2 +auth/internal/repository/user.go:411.84,415.2 1 5 +auth/internal/repository/user.go:418.87,422.2 1 1 +auth/internal/repository/user.go:425.92,430.16 2 3 +auth/internal/repository/user.go:430.16,432.3 1 0 +auth/internal/repository/user.go:433.2,433.27 1 3 +auth/internal/repository/user.go:437.89,446.2 1 1 +auth/internal/repository/user.go:449.96,451.16 2 1 +auth/internal/repository/user.go:451.16,453.3 1 0 +auth/internal/repository/user.go:455.2,458.12 1 1 +auth/internal/repository/user.go:463.98,467.2 1 1 +auth/internal/repository/user.go:470.93,472.16 2 5 +auth/internal/repository/user.go:472.16,474.3 1 0 +auth/internal/repository/user.go:475.2,477.28 2 5 +auth/internal/repository/user.go:481.92,483.16 2 2 +auth/internal/repository/user.go:483.16,484.26 1 1 +auth/internal/repository/user.go:484.26,486.4 1 1 +auth/internal/repository/user.go:487.3,487.13 1 0 +auth/internal/repository/user.go:490.2,490.70 1 1 diff --git a/pkg/go.mod b/pkg/go.mod index 563f14c..ee20eb3 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -2,14 +2,20 @@ module pkg go 1.21 -require github.com/spf13/viper v1.19.0 +require ( + github.com/spf13/viper v1.19.0 + github.com/stretchr/testify v1.9.0 +) require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -20,8 +26,9 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/go.sum b/pkg/go.sum index 2b668ad..0c89791 100644 --- a/pkg/go.sum +++ b/pkg/go.sum @@ -1,9 +1,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -11,6 +16,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -33,6 +40,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -42,11 +50,10 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/qodana.yaml b/qodana.yaml new file mode 100644 index 0000000..215d808 --- /dev/null +++ b/qodana.yaml @@ -0,0 +1,29 @@ +#-------------------------------------------------------------------------------# +# Qodana analysis is configured by qodana.yaml file # +# https://www.jetbrains.com/help/qodana/qodana-yaml.html # +#-------------------------------------------------------------------------------# +version: "1.0" + +#Specify inspection profile for code analysis +profile: + name: qodana.starter + +#Enable inspections +#include: +# - name: + +#Disable inspections +#exclude: +# - name: +# paths: +# - + +#Execute shell command before Qodana execution (Applied in CI/CD pipeline) +#bootstrap: sh ./prepare-qodana.sh + +#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline) +#plugins: +# - id: #(plugin id can be found at https://plugins.jetbrains.com) + +#Specify Qodana linter for analysis (Applied in CI/CD pipeline) +linter: jetbrains/qodana-go:latest diff --git a/scripts/generate_certs.sh b/scripts/generate_certs.sh index 4463be8..d37211a 100644 --- a/scripts/generate_certs.sh +++ b/scripts/generate_certs.sh @@ -30,4 +30,4 @@ openssl x509 -req -in $CERT_DIR/client-req.pem -days 360 -CA $CERT_DIR/ca-cert.p echo "Client's signed certificate generated" -echo "All certificates have been generated in $CERT_DIR" \ No newline at end of file +echo "All certificates have been generated in $CERT_DIR" diff --git a/web/.eslintrc.js b/web/.eslintrc.js new file mode 100644 index 0000000..0cff6df --- /dev/null +++ b/web/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + root: true, + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "next/core-web-vitals", + ], + env: { + browser: true, + node: true, + es6: true, + }, + rules: {}, +}; diff --git a/web/.eslintrc.json b/web/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/web/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/web/components.json b/web/components.json index b0af43f..e5972ab 100644 --- a/web/components.json +++ b/web/components.json @@ -13,4 +13,4 @@ "utils": "@/lib/utils", "components": "@/components" } -} \ No newline at end of file +} diff --git a/web/components/ui/avatar.tsx b/web/components/ui/avatar.tsx index 51e507b..09cd14d 100644 --- a/web/components/ui/avatar.tsx +++ b/web/components/ui/avatar.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import * as React from "react"; +import * as AvatarPrimitive from "@radix-ui/react-avatar"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Avatar = React.forwardRef< React.ElementRef, @@ -13,12 +13,12 @@ const Avatar = React.forwardRef< ref={ref} className={cn( "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", - className + className, )} {...props} /> -)) -Avatar.displayName = AvatarPrimitive.Root.displayName +)); +Avatar.displayName = AvatarPrimitive.Root.displayName; const AvatarImage = React.forwardRef< React.ElementRef, @@ -29,8 +29,8 @@ const AvatarImage = React.forwardRef< className={cn("aspect-square h-full w-full", className)} {...props} /> -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName +)); +AvatarImage.displayName = AvatarPrimitive.Image.displayName; const AvatarFallback = React.forwardRef< React.ElementRef, @@ -40,11 +40,11 @@ const AvatarFallback = React.forwardRef< ref={ref} className={cn( "flex h-full w-full items-center justify-center rounded-full bg-muted", - className + className, )} {...props} /> -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName +)); +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; -export { Avatar, AvatarImage, AvatarFallback } +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/web/components/ui/badge.tsx b/web/components/ui/badge.tsx index f000e3e..d3d5d60 100644 --- a/web/components/ui/badge.tsx +++ b/web/components/ui/badge.tsx @@ -1,7 +1,7 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const badgeVariants = cva( "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", @@ -20,8 +20,8 @@ const badgeVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); export interface BadgeProps extends React.HTMLAttributes, @@ -30,7 +30,7 @@ export interface BadgeProps function Badge({ className, variant, ...props }: BadgeProps) { return (
- ) + ); } -export { Badge, badgeVariants } +export { Badge, badgeVariants }; diff --git a/web/components/ui/breadcrumb.tsx b/web/components/ui/breadcrumb.tsx index 71a5c32..6934f83 100644 --- a/web/components/ui/breadcrumb.tsx +++ b/web/components/ui/breadcrumb.tsx @@ -1,16 +1,16 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { ChevronRight, MoreHorizontal } from "lucide-react" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Breadcrumb = React.forwardRef< HTMLElement, React.ComponentPropsWithoutRef<"nav"> & { - separator?: React.ReactNode + separator?: React.ReactNode; } ->(({ ...props }, ref) =>