From 7de26a1b8afb6efb111d327eac897e004471fc84 Mon Sep 17 00:00:00 2001 From: XuLinrui <504645946@qq.com> Date: Wed, 6 Sep 2023 02:44:28 +0800 Subject: [PATCH] feat: add user and jwt authentication and sample code - add casbin permission and sample code --- README.md | 4 +- Taskfile.yaml | 26 +- cmd/main.go | 4 +- dbconfig.yml.example | 4 + etc/config.yaml.example | 9 +- etc/rbac_model.conf | 6 +- go.mod | 78 +- go.sum | 265 +- internal/app/adapter/adapter.go | 4 +- internal/app/adapter/cron/cron.go | 8 +- internal/app/adapter/cron/job/example.go | 2 +- .../app/adapter/cron/scheduler/scheduler.go | 4 +- .../app/adapter/kafka/consumer/example.go | 10 +- internal/app/adapter/kafka/handler/example.go | 2 +- internal/app/adapter/kafka/kafka.go | 6 +- .../app/adapter/server/grpc/api/generate.go | 13 +- .../server/grpc/api/v1/permission.proto | 54 + .../adapter/server/grpc/api/v1/product.proto | 51 + .../app/adapter/server/grpc/api/v1/role.proto | 62 + .../app/adapter/server/grpc/api/v1/user.proto | 56 +- internal/app/adapter/server/grpc/grpc.go | 13 +- .../adapter/server/grpc/handler/v1/greet.go | 13 +- .../server/grpc/handler/v1/permission.go | 119 + .../adapter/server/grpc/handler/v1/product.go | 115 + .../adapter/server/grpc/handler/v1/role.go | 138 + .../adapter/server/grpc/handler/v1/user.go | 120 +- .../adapter/server/grpc/pkg/errors/errors.go | 20 +- .../app/adapter/server/grpc/router/router.go | 24 +- .../app/adapter/server/http/api/docs/docs.go | 2645 +++++++++++++++-- .../adapter/server/http/api/docs/swagger.json | 2642 ++++++++++++++-- .../adapter/server/http/api/docs/swagger.yaml | 1579 +++++++++- .../adapter/server/http/handler/v1/account.go | 272 ++ .../adapter/server/http/handler/v1/greet.go | 9 +- .../server/http/handler/v1/permission.go | 248 ++ .../server/http/handler/v1/producer.go | 9 +- .../adapter/server/http/handler/v1/product.go | 241 ++ .../adapter/server/http/handler/v1/role.go | 314 ++ .../adapter/server/http/handler/v1/trace.go | 20 +- .../adapter/server/http/handler/v1/user.go | 242 +- internal/app/adapter/server/http/http.go | 12 +- .../adapter/server/http/middleware/auth.go | 117 + .../adapter/server/http/middleware/body.go | 10 +- .../adapter/server/http/middleware/context.go | 23 + .../server/http/middleware/error_handler.go | 77 +- .../adapter/server/http/middleware/logger.go | 3 +- .../server/http/middleware/permission.go | 63 + .../adapter/server/http/middleware/recover.go | 8 +- .../adapter/server/http/pkg/errors/errors.go | 24 + .../adapter/server/http/router/api_group.go | 39 +- .../server/http/router/api_v1_group.go | 94 +- .../app/adapter/server/http/router/router.go | 8 +- internal/app/adapter/server/server.go | 8 +- internal/app/app.go | 4 +- internal/app/controller/account.go | 202 ++ internal/app/controller/account_permission.go | 45 + internal/app/controller/account_token.go | 83 + internal/app/controller/controller.go | 8 +- internal/app/controller/greet.go | 18 +- internal/app/controller/permission.go | 175 ++ internal/app/controller/producer.go | 19 +- internal/app/controller/product.go | 142 + internal/app/controller/role.go | 201 ++ internal/app/controller/user.go | 221 +- internal/app/domain/id.go | 23 - internal/app/domain/permission.go | 9 + internal/app/domain/product.go | 8 + internal/app/domain/role.go | 6 + internal/app/domain/scene.go | 28 - internal/app/domain/token.go | 8 + internal/app/domain/user.go | 90 +- internal/app/pkg/casbin/adapter/adapter.go | 27 +- internal/app/pkg/casbin/adapter/ent.go | 35 + internal/app/pkg/casbin/adapter/file.go | 6 +- internal/app/pkg/casbin/adapter/gorm.go | 24 +- internal/app/pkg/casbin/casbin.go | 20 +- internal/app/pkg/casbin/model/model.go | 4 +- internal/app/pkg/casbin/provide.go | 16 +- internal/app/pkg/client/grpc.go | 4 +- internal/app/pkg/db/db.go | 4 +- internal/app/pkg/discovery/consul.go | 4 +- internal/app/pkg/discovery/discovery.go | 4 +- internal/app/pkg/discovery/etcd.go | 4 +- internal/app/pkg/ent/ent.go | 16 +- internal/app/pkg/ent/ent/client.go | 492 ++- internal/app/pkg/ent/ent/config.go | 94 - internal/app/pkg/ent/ent/context.go | 33 - internal/app/pkg/ent/ent/ent.go | 88 +- internal/app/pkg/ent/ent/hook/hook.go | 36 + .../app/pkg/ent/ent/intercept/intercept.go | 117 +- internal/app/pkg/ent/ent/migrate/schema.go | 86 +- internal/app/pkg/ent/ent/mutation.go | 2136 ++++++++++++- internal/app/pkg/ent/ent/permission.go | 172 ++ .../app/pkg/ent/ent/permission/permission.go | 126 + internal/app/pkg/ent/ent/permission/where.go | 487 +++ internal/app/pkg/ent/ent/permission_create.go | 365 +++ internal/app/pkg/ent/ent/permission_delete.go | 88 + internal/app/pkg/ent/ent/permission_query.go | 548 ++++ internal/app/pkg/ent/ent/permission_update.go | 466 +++ .../app/pkg/ent/ent/predicate/predicate.go | 9 + internal/app/pkg/ent/ent/product.go | 161 + internal/app/pkg/ent/ent/product/product.go | 112 + internal/app/pkg/ent/ent/product/where.go | 417 +++ internal/app/pkg/ent/ent/product_create.go | 337 +++ internal/app/pkg/ent/ent/product_delete.go | 88 + internal/app/pkg/ent/ent/product_query.go | 548 ++++ internal/app/pkg/ent/ent/product_update.go | 402 +++ internal/app/pkg/ent/ent/role.go | 139 + internal/app/pkg/ent/ent/role/role.go | 92 + internal/app/pkg/ent/ent/role/where.go | 302 ++ internal/app/pkg/ent/ent/role_create.go | 280 ++ internal/app/pkg/ent/ent/role_delete.go | 88 + internal/app/pkg/ent/ent/role_query.go | 548 ++++ internal/app/pkg/ent/ent/role_update.go | 324 ++ internal/app/pkg/ent/ent/runtime/runtime.go | 128 +- internal/app/pkg/ent/ent/tx.go | 11 +- internal/app/pkg/ent/ent/user.go | 74 +- internal/app/pkg/ent/ent/user/user.go | 81 +- internal/app/pkg/ent/ent/user/where.go | 303 +- internal/app/pkg/ent/ent/user_create.go | 123 +- internal/app/pkg/ent/ent/user_delete.go | 12 +- internal/app/pkg/ent/ent/user_query.go | 30 +- internal/app/pkg/ent/ent/user_update.go | 198 +- internal/app/pkg/ent/provide.go | 9 +- internal/app/pkg/errors/errors.go | 37 +- internal/app/pkg/gorm/dialector.go | 6 +- internal/app/pkg/gorm/gorm.go | 10 +- internal/app/pkg/gorm/provide.go | 6 +- internal/app/pkg/pkg.go | 4 +- internal/app/pkg/redis/provide.go | 4 +- internal/app/pkg/redis/redis.go | 4 +- internal/app/repository/casbin_rule.go | 17 - internal/app/repository/permission.go | 172 ++ internal/app/repository/policy.go | 35 + internal/app/repository/product.go | 114 + internal/app/repository/repository.go | 46 +- internal/app/repository/role.go | 193 ++ .../repository/schema/mixin/soft_delete.go | 10 +- internal/app/repository/schema/mixin/time.go | 4 +- internal/app/repository/schema/permission.go | 55 + internal/app/repository/schema/product.go | 54 + internal/app/repository/schema/role.go | 45 + internal/app/repository/schema/user.go | 12 +- internal/app/repository/user.go | 241 +- internal/app/service/token.go | 67 + internal/app/tests/db.go | 16 +- internal/app/tests/logger.go | 3 +- internal/app/tests/redis.go | 5 +- internal/app/tests/tests.go | 2 +- internal/app/usecase/account.go | 47 + internal/app/usecase/permission.go | 56 + internal/app/usecase/product.go | 56 + internal/app/usecase/role.go | 66 + internal/app/usecase/usecase.go | 8 +- internal/app/usecase/user.go | 75 +- internal/command/base.go | 14 +- internal/command/flag.go | 4 +- internal/command/migrate.go | 20 +- internal/command/server.go | 3 +- internal/command/wire.go | 6 +- internal/command/wire_gen.go | 88 +- internal/config/config.go | 9 - internal/config/server.go | 24 +- internal/config/watch.go | 5 +- .../20230510004346-create_users_table.sql | 10 +- ...0230510004740-create_casbin_rule_table.sql | 20 - .../20230728103932-create_products_table.sql | 20 + ...0230822175206-create_permissions_table.sql | 21 + .../20230822182128-create_roles_table.sql | 18 + ...05134244-insert_permissions_table_data.sql | 45 + pkg/log/cron/logger.go | 3 +- pkg/log/ent/logger.go | 3 +- pkg/log/gorm/logger.go | 6 +- pkg/log/kratos/logger.go | 6 +- pkg/log/log.go | 67 +- pkg/trace/trace.go | 9 +- pkg/validator/validator.go | 40 + 176 files changed, 21446 insertions(+), 2010 deletions(-) create mode 100644 dbconfig.yml.example create mode 100644 internal/app/adapter/server/grpc/api/v1/permission.proto create mode 100644 internal/app/adapter/server/grpc/api/v1/product.proto create mode 100644 internal/app/adapter/server/grpc/api/v1/role.proto create mode 100644 internal/app/adapter/server/grpc/handler/v1/permission.go create mode 100644 internal/app/adapter/server/grpc/handler/v1/product.go create mode 100644 internal/app/adapter/server/grpc/handler/v1/role.go create mode 100644 internal/app/adapter/server/http/handler/v1/account.go create mode 100644 internal/app/adapter/server/http/handler/v1/permission.go create mode 100644 internal/app/adapter/server/http/handler/v1/product.go create mode 100644 internal/app/adapter/server/http/handler/v1/role.go create mode 100644 internal/app/adapter/server/http/middleware/auth.go create mode 100644 internal/app/adapter/server/http/middleware/context.go create mode 100644 internal/app/adapter/server/http/middleware/permission.go create mode 100644 internal/app/adapter/server/http/pkg/errors/errors.go create mode 100644 internal/app/controller/account.go create mode 100644 internal/app/controller/account_permission.go create mode 100644 internal/app/controller/account_token.go create mode 100644 internal/app/controller/permission.go create mode 100644 internal/app/controller/product.go create mode 100644 internal/app/controller/role.go delete mode 100644 internal/app/domain/id.go create mode 100644 internal/app/domain/permission.go create mode 100644 internal/app/domain/product.go create mode 100644 internal/app/domain/role.go delete mode 100644 internal/app/domain/scene.go create mode 100644 internal/app/domain/token.go create mode 100644 internal/app/pkg/casbin/adapter/ent.go delete mode 100644 internal/app/pkg/ent/ent/config.go delete mode 100644 internal/app/pkg/ent/ent/context.go create mode 100644 internal/app/pkg/ent/ent/permission.go create mode 100644 internal/app/pkg/ent/ent/permission/permission.go create mode 100644 internal/app/pkg/ent/ent/permission/where.go create mode 100644 internal/app/pkg/ent/ent/permission_create.go create mode 100644 internal/app/pkg/ent/ent/permission_delete.go create mode 100644 internal/app/pkg/ent/ent/permission_query.go create mode 100644 internal/app/pkg/ent/ent/permission_update.go create mode 100644 internal/app/pkg/ent/ent/product.go create mode 100644 internal/app/pkg/ent/ent/product/product.go create mode 100644 internal/app/pkg/ent/ent/product/where.go create mode 100644 internal/app/pkg/ent/ent/product_create.go create mode 100644 internal/app/pkg/ent/ent/product_delete.go create mode 100644 internal/app/pkg/ent/ent/product_query.go create mode 100644 internal/app/pkg/ent/ent/product_update.go create mode 100644 internal/app/pkg/ent/ent/role.go create mode 100644 internal/app/pkg/ent/ent/role/role.go create mode 100644 internal/app/pkg/ent/ent/role/where.go create mode 100644 internal/app/pkg/ent/ent/role_create.go create mode 100644 internal/app/pkg/ent/ent/role_delete.go create mode 100644 internal/app/pkg/ent/ent/role_query.go create mode 100644 internal/app/pkg/ent/ent/role_update.go delete mode 100644 internal/app/repository/casbin_rule.go create mode 100644 internal/app/repository/permission.go create mode 100644 internal/app/repository/policy.go create mode 100644 internal/app/repository/product.go create mode 100644 internal/app/repository/role.go create mode 100644 internal/app/repository/schema/permission.go create mode 100644 internal/app/repository/schema/product.go create mode 100644 internal/app/repository/schema/role.go create mode 100644 internal/app/service/token.go create mode 100644 internal/app/usecase/account.go create mode 100644 internal/app/usecase/permission.go create mode 100644 internal/app/usecase/product.go create mode 100644 internal/app/usecase/role.go delete mode 100644 migrations/20230510004740-create_casbin_rule_table.sql create mode 100644 migrations/20230728103932-create_products_table.sql create mode 100644 migrations/20230822175206-create_permissions_table.sql create mode 100644 migrations/20230822182128-create_roles_table.sql create mode 100644 migrations/20230905134244-insert_permissions_table_data.sql diff --git a/README.md b/README.md index 0e9920ac..8dff004b 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ var watchKeys = []string{ # 日志 -日志基于 [slog](https://pkg.go.dev/golang.org/x/exp/slog),日志的切割基于 [file-rotatelogs](https://github.com/lestrrat-go/file-rotatelogs) +日志基于 [slog](https://pkg.go.dev/log/slog),日志的切割基于 [file-rotatelogs](https://github.com/lestrrat-go/file-rotatelogs) 日志内容默认输出到 `logs` 目录中,并且根据每天的日期进行分割 @@ -198,7 +198,7 @@ var watchKeys = []string{ ```go package v1 -import "golang.org/x/exp/slog" +import "log/slog" type Handler struct { logger *slog.Logger diff --git a/Taskfile.yaml b/Taskfile.yaml index 3fc50d8e..6d046b0a 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -3,13 +3,14 @@ version: '3' vars: APP_BIN_PATH: bin/app APP_MAIN_DIR: cmd + # wire + WIRE_ENTRY_DIR: ./internal/command # swagger API_SWAGGER_SCAN_DIR: internal/app/adapter/server/http API_SWAGGER_SCAN_ENTRY: http.go API_SWAGGER_OUT_DIR: internal/app/adapter/server/http/api/docs # proto - API_PROTO_DIR: internal/app/adapter/server/grpc/api - API_PROTO_PB_DIR: internal/app/adapter/server/grpc/api + API_PROTO_GENERATE_FILE: internal/app/adapter/server/grpc/api/generate.go tasks: build: @@ -45,6 +46,10 @@ tasks: desc: build the files required for the application cmd: go generate ./... + wire: + desc: automatically inject dependencies + cmd: wire {{.WIRE_ENTRY_DIR}} + download: desc: download the dependencies required for compilation run: once @@ -88,20 +93,11 @@ tasks: proto: desc: generate the proto file silent: true - cmds: - - | - for f in $(find {{.API_PROTO_DIR}} -name *.proto) - do - kratos proto client --proto_path=./proto ${f} - done - # inject tag - - | - for f in $(find {{.API_PROTO_PB_DIR}} -name *.pb.go) - do - protoc-go-inject-tag -input=${f} - done + cmd: go generate {{.API_PROTO_GENERATE_FILE}} format: desc: format all go files silent: true - cmd: goimports-reviser -imports-order std,project,company,general -format -recursive ./... + cmds: + - gofmt -w . + - goimports-reviser -imports-order std,company,general,project -format -recursive ./... diff --git a/cmd/main.go b/cmd/main.go index 416b6da3..4bc87838 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,12 +1,12 @@ package main import ( + klog "github.com/go-kratos/kratos/v2/log" + "go-scaffold/internal/command" _ "go-scaffold/pkg/dump" "go-scaffold/pkg/log" iklog "go-scaffold/pkg/log/kratos" - - klog "github.com/go-kratos/kratos/v2/log" ) func main() { diff --git a/dbconfig.yml.example b/dbconfig.yml.example new file mode 100644 index 00000000..b06f3f54 --- /dev/null +++ b/dbconfig.yml.example @@ -0,0 +1,4 @@ +development: + dialect: mysql + datasource: host=${DB_HOST} dbname=${DB_NAME} user=${DB_USER} password=${DB_PASSWORD} sslmode=required + dir: migrations diff --git a/etc/config.yaml.example b/etc/config.yaml.example index 63c4f665..3402955b 100644 --- a/etc/config.yaml.example +++ b/etc/config.yaml.example @@ -14,16 +14,13 @@ http: addr: "0.0.0.0:9527" timeout: 5 externalAddr: "" # external access address, such as reverse proxy - # jwt: - # key: "" # casbin: # model: # path: "etc/rbac_model.conf" # adapter: - # file: - # path: "etc/rbac_policy.csv" - # gorm: - # tableName: "" + # file: "etc/rbac_policy.csv" + # gorm: {} + # ent: {} grpc: server: diff --git a/etc/rbac_model.conf b/etc/rbac_model.conf index 9f8f6df4..84886bfb 100644 --- a/etc/rbac_model.conf +++ b/etc/rbac_model.conf @@ -1,8 +1,8 @@ [request_definition] -r = sub, obj, act +r = sub, obj [policy_definition] -p = sub, obj, act +p = sub, obj [role_definition] g = _, _ @@ -11,4 +11,4 @@ g = _, _ e = some(where (p.eft == allow)) [matchers] -m = g(r.sub, p.sub) && keyMatch3(r.obj, p.obj) && r.act == p.act \ No newline at end of file +m = r.sub == 'user_1' || g(r.sub, p.sub) && r.obj == p.obj \ No newline at end of file diff --git a/go.mod b/go.mod index 588ce344..5393edc4 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,14 @@ module go-scaffold -go 1.20 +go 1.21 require ( - entgo.io/ent v0.11.7 + entgo.io/ent v0.12.3 github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/bwmarrin/snowflake v0.3.0 - github.com/casbin/casbin/v2 v2.66.1 - github.com/casbin/gorm-adapter/v3 v3.15.0 + github.com/casbin/casbin/v2 v2.77.1 + github.com/casbin/ent-adapter v0.3.0 + github.com/casbin/gorm-adapter/v3 v3.18.1 github.com/davecgh/go-spew v1.1.1 github.com/fatih/color v1.14.1 github.com/go-kratos/consul v0.1.5 @@ -17,7 +18,9 @@ require ( github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/go-redis/redis/v8 v8.11.5 github.com/go-redis/redismock/v8 v8.11.5 - github.com/go-sql-driver/mysql v1.7.0 + github.com/go-sql-driver/mysql v1.7.1 + github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/google/uuid v1.3.1 github.com/google/wire v0.5.1-0.20220620021424-0675cdc9191c github.com/hashicorp/consul/api v1.18.0 github.com/jackc/pgx v3.6.2+incompatible @@ -30,7 +33,7 @@ require ( github.com/rubenv/sql-migrate v1.4.0 github.com/samber/lo v1.37.0 github.com/segmentio/kafka-go v0.4.39 - github.com/spf13/cobra v1.6.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/swaggo/echo-swagger v1.3.5 github.com/swaggo/swag v1.16.1 @@ -40,24 +43,22 @@ require ( go.opentelemetry.io/otel/exporters/jaeger v1.12.0 go.opentelemetry.io/otel/sdk v1.12.0 go.opentelemetry.io/otel/trace v1.14.0 - golang.org/x/exp v0.0.0-20230307190834-24139beb5833 google.golang.org/grpc v1.53.0 - google.golang.org/protobuf v1.28.1 - gorm.io/driver/mysql v1.4.7 - gorm.io/driver/postgres v1.5.0 - gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 - gorm.io/plugin/dbresolver v1.4.1 + gorm.io/driver/mysql v1.5.1 + gorm.io/driver/postgres v1.5.2 + gorm.io/gorm v1.25.4 + gorm.io/plugin/dbresolver v1.4.7 gorm.io/plugin/soft_delete v1.2.0 ) require ( - ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb // indirect + ariga.io/atlas v0.13.3 // indirect github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apolloconfig/agollo/v4 v4.3.0 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/armon/go-metrics v0.4.1 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/armon/go-metrics v0.4.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -65,8 +66,8 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/glebarez/go-sqlite v1.21.1 // indirect - github.com/glebarez/sqlite v1.7.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/glebarez/sqlite v1.9.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -84,22 +85,27 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.4.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/hcl/v2 v2.16.0 // indirect + github.com/hashicorp/hcl/v2 v2.18.0 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect + github.com/jackc/pgconn v1.14.1 // indirect + github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.3.1 // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect @@ -107,12 +113,13 @@ require ( github.com/klauspost/compress v1.15.9 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/microsoft/go-mssqldb v0.21.0 // indirect + github.com/microsoft/go-mssqldb v1.5.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -126,29 +133,34 @@ require ( github.com/spf13/viper v1.15.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/swaggo/files v1.0.0 // indirect + github.com/tidwall/gjson v1.16.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/zclconf/go-cty v1.12.1 // indirect + github.com/zclconf/go-cty v1.14.0 // indirect go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/goleak v1.1.12 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.2.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.9.1 // indirect google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/driver/sqlserver v1.4.2 // indirect - modernc.org/libc v1.22.3 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.5.0 // indirect - modernc.org/sqlite v1.21.1 // indirect + gorm.io/driver/sqlserver v1.5.1 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.1 // indirect + modernc.org/sqlite v1.25.0 // indirect ) diff --git a/go.sum b/go.sum index fc5aeff3..dbfff210 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb h1:mbsFtavDqGdYwdDpP50LGOOZ2hgyGoJcZeOpbgKMyu4= -ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb/go.mod h1:T230JFcENj4ZZzMkZrXFDSkv+2kXkUgpJ5FQQ5hMcKU= +ariga.io/atlas v0.13.3 h1:L6Zz/0/yo86flQclZwIqJEKrHoJxQOkj3Z2JPvzZEHE= +ariga.io/atlas v0.13.3/go.mod h1:+TR129FJZ5Lvzms6dvCeGWh1yR6hMvmXBhug4hrNIGk= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -55,17 +55,13 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -entgo.io/ent v0.11.7 h1:V+wKFh0jhAbY/FoU+PPbdMOf2Ma5vh07R/IdF+N/nFg= -entgo.io/ent v0.11.7/go.mod h1:ericBi6Q8l3wBH1wEIDfKxw7rcQEuRPyBfbIzjtxJ18= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= +entgo.io/ent v0.8.0/go.mod h1:KNjsukat/NJi6zJh1utwRadsbGOZsBbAZNDxkW7tMCc= +entgo.io/ent v0.12.3 h1:N5lO2EOrHpCH5HYfiMOCHYbo+oh5M8GjT0/cx5x6xkk= +entgo.io/ent v0.12.3/go.mod h1:AigGGx+tbrBBYHAzGOg8ND661E5cxx1Uiu5o/otJ6Yg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= @@ -77,6 +73,7 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= @@ -96,20 +93,21 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apolloconfig/agollo/v4 v4.3.0 h1:AarIBtpDE76jIevHUOzzgT9eLB5HPvIQ8oL+OpScOPU= github.com/apolloconfig/agollo/v4 v4.3.0/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs= -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/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -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/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= +github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -118,13 +116,16 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= -github.com/casbin/casbin/v2 v2.55.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= -github.com/casbin/casbin/v2 v2.66.1 h1:HOFlZYTUYx8ktgv5fLNFo6hr4K18ogGFq/lnYXv1OfA= -github.com/casbin/casbin/v2 v2.66.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= -github.com/casbin/gorm-adapter/v3 v3.15.0 h1:SLGhY5d/jN+zWLGmHlS8x/2zxYXVWf/d201aGv5EIyc= -github.com/casbin/gorm-adapter/v3 v3.15.0/go.mod h1:jqaf4bUITbCyMPUellaTd8IQJ77JfVAbe77gZZnx98w= +github.com/casbin/casbin/v2 v2.29.2/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= +github.com/casbin/casbin/v2 v2.77.1 h1:+H46VamJCTlmCPcb0N99Zaj4tSorfuvBh3v5lyGopeU= +github.com/casbin/casbin/v2 v2.77.1/go.mod h1:mzGx0hYW9/ksOSpw3wNjk3NRAroq5VMFYUQ6G43iGPk= +github.com/casbin/ent-adapter v0.3.0 h1:4lkhB/BwXAhj84iSrZG/gQ4avkO4uPwz4kdDP1VEnww= +github.com/casbin/ent-adapter v0.3.0/go.mod h1:U6saAFuVDEOWLCtrgx35d95M12FC0uh5GtJL82QunRM= +github.com/casbin/gorm-adapter/v3 v3.18.1 h1:M+l2EbmUkfvXc7ptbM+Bz+Jo3OZu4qNUmOYLp7KiNUM= +github.com/casbin/gorm-adapter/v3 v3.18.1/go.mod h1:ekufPNBgVIQvv9JffVGsg7KUv4DjnevTh6AQnBNkoK8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -146,6 +147,7 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b h1:ACGZRIr7HsgBKHsueQ1yM4WaVaXh21ynwqsF8M8tXhA= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -189,8 +191,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3 h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= @@ -207,12 +211,11 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/glebarez/go-sqlite v1.19.1/go.mod h1:9AykawGIyIcxoSfpYWiX1SgTNHTNsa/FVc75cDkbp4M= -github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= -github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= -github.com/glebarez/sqlite v1.5.0/go.mod h1:0wzXzTvfVJIN2GqRhCdMbnYd+m+aH5/QV7B30rM6NgY= -github.com/glebarez/sqlite v1.7.0 h1:A7Xj/KN2Lvie4Z4rrgQHY8MsbebX3NyWsL3n2i82MVI= -github.com/glebarez/sqlite v1.7.0/go.mod h1:PkeevrRlF/1BhQBCnzcMWzgrIk7IOop+qS2jUYLfHhk= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.9.0 h1:Aj6bPA12ZEx5GbSF6XADmCkYXlljPNUY+Zf1EQxynXs= +github.com/glebarez/sqlite v1.9.0/go.mod h1:YBYCoyupOao60lzp1MVBLEjZfgkq0tdB1voAQ09K9zw= +github.com/go-bindata/go-bindata v1.0.1-0.20190711162640-ee3c2418e368/go.mod h1:7xCgX1lzlrXPHkfvn3EhumqHkmSlzt8at9q7v0ax19c= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -271,12 +274,15 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redismock/v8 v8.11.5 h1:RJFIiua58hrBrSpXhnGX3on79AU3S271H4ZhRI1wyVo= github.com/go-redis/redismock/v8 v8.11.5/go.mod h1:UaAU9dEe1C+eGr+FHV5prCWIt0hafyPWbGMEWE0UWdA= +github.com/go-sql-driver/mysql v1.5.1-0.20200311113236-681ffa848bae/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= @@ -291,12 +297,13 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -378,13 +385,16 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.1-0.20220620021424-0675cdc9191c h1:En+uJjqzEi/dqlxu65GhlbkbjyNdBTaJAktsDXfeXNc= github.com/google/wire v0.5.1-0.20220620021424-0675cdc9191c/go.mod h1:+Sd/FRHahkNYWBxsUXYuWzWEFnIvrOOb/n7uDNINUtY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -445,19 +455,21 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/hashicorp/hcl/v2 v2.16.0 h1:MPq1q615H+9wBAdE3EbwEd6imSohElrIguuasbQruB0= -github.com/hashicorp/hcl/v2 v2.16.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= +github.com/hashicorp/hcl/v2 v2.18.0 h1:wYnG7Lt31t2zYkcquwgKo6MWXzRUDIeIVU5naZwHLl8= +github.com/hashicorp/hcl/v2 v2.18.0/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= @@ -485,11 +497,11 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= @@ -499,10 +511,14 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4= +github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= @@ -513,7 +529,8 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= @@ -521,28 +538,29 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= -github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= +github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -567,8 +585,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= @@ -607,9 +625,11 @@ github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -648,19 +668,20 @@ github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= 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/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= -github.com/microsoft/go-mssqldb v0.19.0/go.mod h1:ukJCBnnzLzpVF0qYRT+eg1e+eSwjeQ7IvenUv8QPook= -github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8= -github.com/microsoft/go-mssqldb v0.21.0/go.mod h1:+4wZTUnz/SV6nffv+RRRB/ss8jPng5Sho2SmM1l2ts4= +github.com/microsoft/go-mssqldb v1.1.0/go.mod h1:LzkFdl4z2Ck+Hi+ycGOTbL56VEfgoyA2DvYejrNGbRk= +github.com/microsoft/go-mssqldb v1.5.0 h1:CgENxkwtOBNj3Jg6T1X209y2blCfTTcwuOlznd2k9fk= +github.com/microsoft/go-mssqldb v1.5.0/go.mod h1:lmWsjHD8XX/Txr0f8ZqgbEZSC+BZjmEQy/Ms+rLrvho= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -693,7 +714,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= @@ -734,7 +755,6 @@ github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvI github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -773,7 +793,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -803,6 +822,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/segmentio/kafka-go v0.4.39 h1:75smaomhvkYRwtuOwqLsdhgCG30B82NsbdkdDfFbvrw= github.com/segmentio/kafka-go v0.4.39/go.mod h1:T0MLgygYvmqmBvC+s8aCcbVNfJN4znVne5j0Pzowp/Q= 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/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -831,9 +851,10 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -841,6 +862,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.11.0/go.mod h1:djo0X/bA5+tYVoCn+C7cAYJGcVn/qYLFTG8gdUsX7Zk= @@ -863,6 +885,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -876,6 +899,14 @@ github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg= github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto= github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0= github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= +github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -901,8 +932,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= -github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= +github.com/zclconf/go-cty v1.14.0 h1:/Xrd39K7DXbHzlisFP9c4pHao4yyf+/Ug9LEz+Y/yhc= +github.com/zclconf/go-cty v1.14.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -930,6 +961,7 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.40.0 h1:uieC4MjrlpHeEtapTOpix710ykBLqXQqZqN6DpnvOvw= go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.40.0/go.mod h1:9jOfbttH75jtbNJR3xGi1Bs+gN9IcQzj2iDqN9zi8Jg= go.opentelemetry.io/contrib/propagators/b3 v1.15.0 h1:bMaonPyFcAvZ4EVzkUNkfnUHP5Zi63CIDlA3dRsEg8Q= +go.opentelemetry.io/contrib/propagators/b3 v1.15.0/go.mod h1:VjU0g2v6HSQ+NwfifambSLAeBgevjIcqmceaKWEzl0c= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= @@ -981,7 +1013,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -990,15 +1021,14 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1038,8 +1068,9 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1076,7 +1107,6 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1105,6 +1135,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1234,7 +1266,6 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1251,15 +1282,19 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1272,8 +1307,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1282,6 +1319,7 @@ golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1333,7 +1371,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1349,6 +1386,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1545,7 +1583,6 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -1566,31 +1603,24 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= -gorm.io/driver/mysql v1.4.1/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= -gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= -gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= -gorm.io/driver/postgres v1.4.4/go.mod h1:whNfh5WhhHs96honoLjBAMwJGYEuA3m1hvgUbNXhPCw= -gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= -gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= +gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= +gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= +gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.1.3 h1:BYfdVuZB5He/u9dt4qDpZqiqDJ6KhPqs5QUqsr/Eeuc= gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c= -gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= -gorm.io/driver/sqlserver v1.4.2 h1:nMtEeKqv2R/vv9FoHUFWfXfP6SskAgRar0TPlZV1stk= -gorm.io/driver/sqlserver v1.4.2/go.mod h1:XHwBuB4Tlh7DqO0x7Ema8dmyWsQW7wi38VQOAFkrbXY= +gorm.io/driver/sqlserver v1.5.1 h1:wpyW/pR26U94uaujltiFGXY7fd2Jw5hC9PB1ZF/Y5s4= +gorm.io/driver/sqlserver v1.5.1/go.mod h1:AYHzzte2msKTmYBYsSIq8ZUsznLJwBdkB2wpI+kt0nM= gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g= -gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/plugin/dbresolver v1.3.0/go.mod h1:Pr7p5+JFlgDaiM6sOrli5olekJD16YRunMyA2S7ZfKk= -gorm.io/plugin/dbresolver v1.4.1 h1:Ug4LcoPhrvqq71UhxtF346f+skTYoCa/nEsdjvHwEzk= -gorm.io/plugin/dbresolver v1.4.1/go.mod h1:CTbCtMWhsjXSiJqiW2R8POvJ2cq18RVOl4WGyT5nhNc= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= +gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/dbresolver v1.4.7 h1:ZwtwmJQxTx9us7o6zEHFvH1q4OeEo1pooU7efmnunJA= +gorm.io/plugin/dbresolver v1.4.7/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0= gorm.io/plugin/soft_delete v1.2.0 h1:txWHRMqLPqfXUFytXCdxb/jthRe3CrG4R5XOdagut6Q= gorm.io/plugin/soft_delete v1.2.0/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1600,41 +1630,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= -modernc.org/cc/v3 v3.38.1/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= -modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= -modernc.org/ccgo/v3 v3.0.0-20220910160915-348f15de615a/go.mod h1:8p47QxPkdugex9J4n9P2tLZ9bK01yngIVp00g4nomW0= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= -modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= -modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= -modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY= -modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.19.1/go.mod h1:UfQ83woKMaPW/ZBruK0T7YaFCrI+IE0LeWVY6pmnVms= -modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= -modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.14.0/go.mod h1:gQ7c1YPMvryCHCcmf8acB6VPabE59QBeuRQLL7cTUlM= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.6.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= +modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.1 h1:9J+2/GKTlV503mk3yv8QJ6oEpRCUrRy0ad8TXEPoV8M= +modernc.org/memory v1.7.1/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA= +modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/app/adapter/adapter.go b/internal/app/adapter/adapter.go index eb7b42c7..6b61ed9a 100644 --- a/internal/app/adapter/adapter.go +++ b/internal/app/adapter/adapter.go @@ -1,11 +1,11 @@ package adapter import ( + "github.com/google/wire" + "go-scaffold/internal/app/adapter/cron" "go-scaffold/internal/app/adapter/kafka" "go-scaffold/internal/app/adapter/server" - - "github.com/google/wire" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/adapter/cron/cron.go b/internal/app/adapter/cron/cron.go index 6da2c22f..8807c1e4 100644 --- a/internal/app/adapter/cron/cron.go +++ b/internal/app/adapter/cron/cron.go @@ -2,14 +2,14 @@ package cron import ( "context" + "log/slog" + + "github.com/google/wire" + "github.com/robfig/cron/v3" "go-scaffold/internal/app/adapter/cron/job" "go-scaffold/internal/app/adapter/cron/scheduler" clog "go-scaffold/pkg/log/cron" - - "github.com/google/wire" - "github.com/robfig/cron/v3" - "golang.org/x/exp/slog" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/adapter/cron/job/example.go b/internal/app/adapter/cron/job/example.go index ca1dd432..1b0b0c96 100644 --- a/internal/app/adapter/cron/job/example.go +++ b/internal/app/adapter/cron/job/example.go @@ -1,6 +1,6 @@ package job -import "golang.org/x/exp/slog" +import "log/slog" // ExampleJob example job type ExampleJob struct { diff --git a/internal/app/adapter/cron/scheduler/scheduler.go b/internal/app/adapter/cron/scheduler/scheduler.go index 555e220c..333d5aa4 100644 --- a/internal/app/adapter/cron/scheduler/scheduler.go +++ b/internal/app/adapter/cron/scheduler/scheduler.go @@ -1,10 +1,10 @@ package scheduler import ( + "github.com/robfig/cron/v3" + "go-scaffold/internal/app/adapter/cron/job" "go-scaffold/internal/config" - - "github.com/robfig/cron/v3" ) // Scheduler job scheduler diff --git a/internal/app/adapter/kafka/consumer/example.go b/internal/app/adapter/kafka/consumer/example.go index 7f3826da..418b5113 100644 --- a/internal/app/adapter/kafka/consumer/example.go +++ b/internal/app/adapter/kafka/consumer/example.go @@ -5,13 +5,13 @@ import ( "encoding/json" "errors" "io" + "log/slog" "strings" + "github.com/segmentio/kafka-go" + "go-scaffold/internal/app/adapter/kafka/handler" "go-scaffold/internal/config" - - "github.com/segmentio/kafka-go" - "golang.org/x/exp/slog" ) type ExampleConsumer struct { @@ -61,7 +61,7 @@ func (c *ExampleConsumer) Consume(ctx context.Context) { } else if errors.Is(err, io.EOF) { continue } else if err != nil { - c.logger.Error("read message error", err) + c.logger.Error("read message error", slog.Any("error", err)) continue } @@ -72,7 +72,7 @@ func (c *ExampleConsumer) Consume(ctx context.Context) { } if err := c.handler.Handle(msg); err != nil { - c.logger.Error("handle message error", err) + c.logger.Error("handle message error", slog.Any("error", err)) continue } } diff --git a/internal/app/adapter/kafka/handler/example.go b/internal/app/adapter/kafka/handler/example.go index 6bedc04d..5fa6630e 100644 --- a/internal/app/adapter/kafka/handler/example.go +++ b/internal/app/adapter/kafka/handler/example.go @@ -1,6 +1,6 @@ package handler -import "golang.org/x/exp/slog" +import "log/slog" type ExampleMessage struct { Msg string `json:"msg"` diff --git a/internal/app/adapter/kafka/kafka.go b/internal/app/adapter/kafka/kafka.go index c95c3ae8..20065156 100644 --- a/internal/app/adapter/kafka/kafka.go +++ b/internal/app/adapter/kafka/kafka.go @@ -2,12 +2,12 @@ package kafka import ( "context" + "log/slog" + + "github.com/google/wire" "go-scaffold/internal/app/adapter/kafka/consumer" "go-scaffold/internal/app/adapter/kafka/handler" - - "github.com/google/wire" - "golang.org/x/exp/slog" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/adapter/server/grpc/api/generate.go b/internal/app/adapter/server/grpc/api/generate.go index ca078100..8a3b997e 100644 --- a/internal/app/adapter/server/grpc/api/generate.go +++ b/internal/app/adapter/server/grpc/api/generate.go @@ -1,7 +1,16 @@ package api -//go:generate kratos proto client --proto_path=../../../../../proto v1/greet.proto +//go:generate kratos proto client --proto_path=../api --proto_path=../../../../../proto v1/greet.proto //go:generate protoc-go-inject-tag -input=./v1/greet.pb.go -//go:generate kratos proto client --proto_path=../../../../../proto v1/user.proto +//go:generate kratos proto client --proto_path=../api --proto_path=../../../../../proto v1/user.proto //go:generate protoc-go-inject-tag -input=./v1/user.pb.go + +//go:generate kratos proto client --proto_path=../api --proto_path=../../../../../proto v1/role.proto +//go:generate protoc-go-inject-tag -input=./v1/role.pb.go + +//go:generate kratos proto client --proto_path=../api --proto_path=../../../../../proto v1/permission.proto +//go:generate protoc-go-inject-tag -input=./v1/permission.pb.go + +//go:generate kratos proto client --proto_path=../api --proto_path=../../../../../proto v1/product.proto +//go:generate protoc-go-inject-tag -input=./v1/product.pb.go diff --git a/internal/app/adapter/server/grpc/api/v1/permission.proto b/internal/app/adapter/server/grpc/api/v1/permission.proto new file mode 100644 index 00000000..21252170 --- /dev/null +++ b/internal/app/adapter/server/grpc/api/v1/permission.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; + +package internal.app.adapter.grpc.api.v1.permission; + +option go_package = "go-scaffold/internal/app/adapter/grpc/api/v1;v1"; + +service Permission { + rpc Create (PermissionCreateRequest) returns (PermissionCreateResponse) {}; + rpc Update (PermissionUpdateRequest) returns (PermissionUpdateResponse) {}; + rpc Delete (PermissionDeleteRequest) returns (PermissionDeleteResponse) {}; + rpc Detail (PermissionDetailRequest) returns (PermissionInfo) {}; + rpc List (PermissionListRequest) returns (PermissionListResponse) {}; +} + +message PermissionInfo { + int64 id = 1; // @gotags: json:"id" + string key = 2; // @gotags: json:"key" + string name = 3; // @gotags: json:"name" + string desc = 4; // @gotags: json:"desc" + int64 parentID = 5; // @gotags: json:"parentID" +} + +message PermissionCreateRequest { + string key = 1; // @gotags: json:"key" + string name = 2; // @gotags: json:"name" + string desc = 3; // @gotags: json:"desc" + int64 parentID = 4; // @gotags: json:"parentID" +} +message PermissionCreateResponse {} + +message PermissionUpdateRequest { + int64 id = 1; // @gotags: json:"id" + string key = 2; // @gotags: json:"key" + string name = 3; // @gotags: json:"name" + string desc = 4; // @gotags: json:"desc" + int64 parentID = 5; // @gotags: json:"parentID" +} +message PermissionUpdateResponse {} + +message PermissionDeleteRequest { + int64 id = 1; // @gotags: json:"id" +} +message PermissionDeleteResponse {} + +message PermissionDetailRequest { + int64 id = 1; // @gotags: json:"id" +} + +message PermissionListRequest { + string keyword = 1; // @gotags: json:"keyword" +} +message PermissionListResponse { + repeated PermissionInfo items = 1; // @gotags: json:"items" +} \ No newline at end of file diff --git a/internal/app/adapter/server/grpc/api/v1/product.proto b/internal/app/adapter/server/grpc/api/v1/product.proto new file mode 100644 index 00000000..bb0335c7 --- /dev/null +++ b/internal/app/adapter/server/grpc/api/v1/product.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; + +package internal.app.adapter.grpc.api.v1.product; + +option go_package = "go-scaffold/internal/app/adapter/grpc/api/v1;v1"; + +service Product { + rpc Create (ProductCreateRequest) returns (ProductCreateResponse) {}; + rpc Update (ProductUpdateRequest) returns (ProductUpdateResponse) {}; + rpc Delete (ProductDeleteRequest) returns (ProductDeleteResponse) {}; + rpc Detail (ProductDetailRequest) returns (ProductInfo) {}; + rpc List (ProductListRequest) returns (ProductListResponse) {}; +} + +message ProductInfo { + int64 id = 1; // @gotags: json:"id" + string name = 2; // @gotags: json:"name" + string desc = 3; // @gotags: json:"desc" + int64 price = 4; // @gotags: json:"price" +} + +message ProductCreateRequest { + string name = 1; // @gotags: json:"name" + string desc = 2; // @gotags: json:"desc" + int64 price = 3; // @gotags: json:"price" +} +message ProductCreateResponse {} + +message ProductUpdateRequest { + int64 id = 1; // @gotags: json:"id" + string name = 2; // @gotags: json:"name" + string desc = 3; // @gotags: json:"desc" + int64 price = 4; // @gotags: json:"price" +} +message ProductUpdateResponse {} + +message ProductDeleteRequest { + int64 id = 1; // @gotags: json:"id" +} +message ProductDeleteResponse {} + +message ProductDetailRequest { + int64 id = 1; // @gotags: json:"id" +} + +message ProductListRequest { + string keyword = 1; // @gotags: json:"keyword" +} +message ProductListResponse { + repeated ProductInfo items = 1; // @gotags: json:"items" +} \ No newline at end of file diff --git a/internal/app/adapter/server/grpc/api/v1/role.proto b/internal/app/adapter/server/grpc/api/v1/role.proto new file mode 100644 index 00000000..e2115b28 --- /dev/null +++ b/internal/app/adapter/server/grpc/api/v1/role.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; + +package internal.app.adapter.grpc.api.v1.role; + +option go_package = "go-scaffold/internal/app/adapter/grpc/api/v1;v1"; + +import "v1/permission.proto"; + +service Role { + rpc Create (RoleCreateRequest) returns (RoleCreateResponse) {}; + rpc Update (RoleUpdateRequest) returns (RoleUpdateResponse) {}; + rpc Delete (RoleDeleteRequest) returns (RoleDeleteResponse) {}; + rpc Detail (RoleDetailRequest) returns (RoleInfo) {}; + rpc List (RoleListRequest) returns (RoleListResponse) {}; + rpc GrantPermissions (RoleGrantPermissionsRequest) returns (RoleGrantPermissionsResponse) {}; + rpc GetPermissions (RoleGetPermissionsRequest) returns (RoleGetPermissionsResponse) {}; +} + +message RoleInfo { + int64 id = 1; // @gotags: json:"id" + string name = 2; // @gotags: json:"name" +} + +message RoleCreateRequest { + string name = 1; // @gotags: json:"name" +} +message RoleCreateResponse {} + +message RoleUpdateRequest { + int64 id = 1; // @gotags: json:"id" + string name = 2; // @gotags: json:"name" +} +message RoleUpdateResponse {} + +message RoleDeleteRequest { + int64 id = 1; // @gotags: json:"id" +} +message RoleDeleteResponse {} + +message RoleDetailRequest { + int64 id = 1; // @gotags: json:"id" +} + +message RoleListRequest { + string keyword = 1; // @gotags: json:"keyword" +} +message RoleListResponse { + repeated RoleInfo items = 1; // @gotags: json:"items" +} + +message RoleGrantPermissionsRequest { + int64 role = 1; // @gotags: json:"role" + repeated int64 permissions = 2; // @gotags: json:"permissions" +} +message RoleGrantPermissionsResponse {} + +message RoleGetPermissionsRequest { + int64 id = 1; // @gotags: json:"id" +} +message RoleGetPermissionsResponse { + repeated permission.PermissionInfo items = 1; // @gotags: json:"items" +} diff --git a/internal/app/adapter/server/grpc/api/v1/user.proto b/internal/app/adapter/server/grpc/api/v1/user.proto index a91bb625..c3b04c96 100644 --- a/internal/app/adapter/server/grpc/api/v1/user.proto +++ b/internal/app/adapter/server/grpc/api/v1/user.proto @@ -4,26 +4,39 @@ package internal.app.adapter.grpc.api.v1.user; option go_package = "go-scaffold/internal/app/adapter/grpc/api/v1;v1"; +import "v1/role.proto"; + service User { rpc Create (UserCreateRequest) returns (UserCreateResponse) {}; rpc Update (UserUpdateRequest) returns (UserUpdateResponse) {}; rpc Delete (UserDeleteRequest) returns (UserDeleteResponse) {}; - rpc Detail (UserDetailRequest) returns (UserDetailResponse) {}; + rpc Detail (UserDetailRequest) returns (UserInfo) {}; rpc List (UserListRequest) returns (UserListResponse) {}; + rpc AssignRoles (UserAssignRolesRequest) returns (UserAssignRolesResponse) {}; + rpc GetRoles (UserGetRolesRequest) returns (UserGetRolesResponse) {}; +} + +message UserInfo { + int64 id = 1; // @gotags: json:"id" + string username = 2; // @gotags: json:"username" + string nickname = 3; // @gotags: json:"nickname" + string phone = 4; // @gotags: json:"phone" } message UserCreateRequest { - string name = 1; // @gotags: json:"name" - int32 age = 2; // @gotags: json:"age" - string phone = 3; // @gotags: json:"phone" + string username = 1; // @gotags: json:"username" + string password = 2; // @gotags: json:"password" + string nickname = 3; // @gotags: json:"nickname" + string phone = 4; // @gotags: json:"phone" } message UserCreateResponse {} message UserUpdateRequest { - int64 id = 1; // @gotags: json:"id" - string name = 2; // @gotags: json:"name" - int32 age = 3; // @gotags: json:"age" - string phone = 4; // @gotags: json:"phone" + int64 id = 1; // @gotags: json:"id" + string username = 2; // @gotags: json:"username" + string password = 3; // @gotags: json:"password" + string nickname = 4; // @gotags: json:"nickname" + string phone = 5; // @gotags: json:"phone" } message UserUpdateResponse {} @@ -35,24 +48,23 @@ message UserDeleteResponse {} message UserDetailRequest { int64 id = 1; // @gotags: json:"id" } -message UserDetailResponse { - int64 id = 1; // @gotags: json:"id" - string name = 2; // @gotags: json:"name" - int32 age = 3; // @gotags: json:"age" - string phone = 4; // @gotags: json:"phone" -} message UserListRequest { string keyword = 1; // @gotags: json:"keyword" } +message UserListResponse { + repeated UserInfo items = 1; // @gotags: json:"items" +} -message ListItem { - int64 id = 1; // @gotags: json:"id" - string name = 2; // @gotags: json:"name" - int32 age = 3; // @gotags: json:"age" - string phone = 4; // @gotags: json:"phone" +message UserAssignRolesRequest { + int64 user = 1; // @gotags: json:"user" + repeated int64 roles = 2; // @gotags: json:"roles" } +message UserAssignRolesResponse {} -message UserListResponse { - repeated ListItem items = 1; // @gotags: json:"items" -} \ No newline at end of file +message UserGetRolesRequest { + int64 id = 1; // @gotags: json:"id" +} +message UserGetRolesResponse { + repeated role.RoleInfo items = 1; // @gotags: json:"items" +} diff --git a/internal/app/adapter/server/grpc/grpc.go b/internal/app/adapter/server/grpc/grpc.go index 2a823eca..d7c2e2e4 100644 --- a/internal/app/adapter/server/grpc/grpc.go +++ b/internal/app/adapter/server/grpc/grpc.go @@ -3,11 +3,6 @@ package grpc import ( "time" - v1api "go-scaffold/internal/app/adapter/server/grpc/api/v1" - v1handler "go-scaffold/internal/app/adapter/server/grpc/handler/v1" - "go-scaffold/internal/app/adapter/server/grpc/router" - "go-scaffold/internal/config" - "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware/logging" "github.com/go-kratos/kratos/v2/middleware/metadata" @@ -15,12 +10,20 @@ import ( "github.com/go-kratos/kratos/v2/middleware/tracing" "github.com/go-kratos/kratos/v2/transport/grpc" "github.com/google/wire" + + v1api "go-scaffold/internal/app/adapter/server/grpc/api/v1" + v1handler "go-scaffold/internal/app/adapter/server/grpc/handler/v1" + "go-scaffold/internal/app/adapter/server/grpc/router" + "go-scaffold/internal/config" ) var ProviderSet = wire.NewSet( // handler wire.NewSet(wire.Bind(new(v1api.GreetServer), new(*v1handler.GreetHandler)), v1handler.NewGreetHandler), wire.NewSet(wire.Bind(new(v1api.UserServer), new(*v1handler.UserHandler)), v1handler.NewUserHandler), + wire.NewSet(wire.Bind(new(v1api.RoleServer), new(*v1handler.RoleHandler)), v1handler.NewRoleHandler), + wire.NewSet(wire.Bind(new(v1api.PermissionServer), new(*v1handler.PermissionHandler)), v1handler.NewPermissionHandler), + wire.NewSet(wire.Bind(new(v1api.ProductServer), new(*v1handler.ProductHandler)), v1handler.NewProductHandler), // register router.New, // gRPC server diff --git a/internal/app/adapter/server/grpc/handler/v1/greet.go b/internal/app/adapter/server/grpc/handler/v1/greet.go index e2ac4159..8255323b 100644 --- a/internal/app/adapter/server/grpc/handler/v1/greet.go +++ b/internal/app/adapter/server/grpc/handler/v1/greet.go @@ -2,22 +2,19 @@ package v1 import ( "context" + "log/slog" v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" "go-scaffold/internal/app/adapter/server/grpc/pkg/errors" "go-scaffold/internal/app/controller" - - "golang.org/x/exp/slog" ) -// GreetHandler 示例处理器 type GreetHandler struct { v1.UnimplementedGreetServer logger *slog.Logger controller *controller.GreetController } -// NewGreetHandler 构造示例处理器 func NewGreetHandler( logger *slog.Logger, controller *controller.GreetController, @@ -34,13 +31,11 @@ func (h *GreetHandler) Hello(ctx context.Context, req *v1.GreetHelloRequest) (*v ret, err := h.controller.Hello(ctx, controllerReq) if err != nil { - h.logger.Error("call controller.GreetController.Hello method error", err) + h.logger.Error("call GreetController.Hello method error", slog.Any("error", err)) return nil, errors.Wrap(err) } - resp := &v1.GreetHelloResponse{ + return &v1.GreetHelloResponse{ Msg: ret.Msg, - } - - return resp, nil + }, nil } diff --git a/internal/app/adapter/server/grpc/handler/v1/permission.go b/internal/app/adapter/server/grpc/handler/v1/permission.go new file mode 100644 index 00000000..baed2524 --- /dev/null +++ b/internal/app/adapter/server/grpc/handler/v1/permission.go @@ -0,0 +1,119 @@ +package v1 + +import ( + "context" + "log/slog" + + v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" + "go-scaffold/internal/app/adapter/server/grpc/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type PermissionHandler struct { + v1.UnimplementedPermissionServer + logger *slog.Logger + permissionController *controller.PermissionController +} + +func NewPermissionHandler( + logger *slog.Logger, + permissionController *controller.PermissionController, +) *PermissionHandler { + return &PermissionHandler{ + logger: logger, + permissionController: permissionController, + } +} + +// List 权限列表 +func (h *PermissionHandler) List(ctx context.Context, req *v1.PermissionListRequest) (*v1.PermissionListResponse, error) { + r := controller.PermissionListRequest{ + Keyword: req.Keyword, + } + + list, err := h.permissionController.List(ctx, r) + if err != nil { + h.logger.Error("call PermissionController.List method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + items := make([]*v1.PermissionInfo, 0, len(list)) + + for _, item := range list { + items = append(items, &v1.PermissionInfo{ + Id: item.ID, + Key: item.Key, + Name: item.Name, + Desc: item.Desc, + ParentID: item.ParentID, + }) + } + + return &v1.PermissionListResponse{Items: items}, nil +} + +// Create 权限创建 +func (h *PermissionHandler) Create(ctx context.Context, req *v1.PermissionCreateRequest) (*v1.PermissionCreateResponse, error) { + r := controller.PermissionCreateRequest{ + PermissionAttr: controller.PermissionAttr{ + Key: req.Key, + Name: req.Name, + Desc: req.Desc, + ParentID: req.ParentID, + }, + } + + if err := h.permissionController.Create(ctx, r); err != nil { + h.logger.Error("call PermissionController.Create method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.PermissionCreateResponse{}, nil +} + +// Update 权限更新 +func (h *PermissionHandler) Update(ctx context.Context, req *v1.PermissionUpdateRequest) (*v1.PermissionUpdateResponse, error) { + r := controller.PermissionUpdateRequest{ + ID: req.Id, + PermissionAttr: controller.PermissionAttr{ + Key: req.Key, + Name: req.Name, + Desc: req.Desc, + ParentID: req.ParentID, + }, + } + + if err := h.permissionController.Update(ctx, r); err != nil { + h.logger.Error("call PermissionController.Update method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.PermissionUpdateResponse{}, nil +} + +// Detail 权限详情 +func (h *PermissionHandler) Detail(ctx context.Context, req *v1.PermissionDetailRequest) (*v1.PermissionInfo, error) { + ret, err := h.permissionController.Detail(ctx, req.Id) + if err != nil { + h.logger.Error("call PermissionController.Detail method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.PermissionInfo{ + Id: ret.ID, + Key: ret.Key, + Name: ret.Name, + Desc: ret.Desc, + ParentID: ret.ParentID, + }, nil +} + +// Delete 权限删除 +func (h *PermissionHandler) Delete(ctx context.Context, req *v1.PermissionDeleteRequest) (*v1.PermissionDeleteResponse, error) { + if err := h.permissionController.Delete(ctx, req.Id); err != nil { + h.logger.Error("call PermissionController.Delete method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.PermissionDeleteResponse{}, nil +} diff --git a/internal/app/adapter/server/grpc/handler/v1/product.go b/internal/app/adapter/server/grpc/handler/v1/product.go new file mode 100644 index 00000000..8cafc8f3 --- /dev/null +++ b/internal/app/adapter/server/grpc/handler/v1/product.go @@ -0,0 +1,115 @@ +package v1 + +import ( + "context" + "log/slog" + + v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" + "go-scaffold/internal/app/adapter/server/grpc/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type ProductHandler struct { + v1.UnimplementedProductServer + logger *slog.Logger + productController *controller.ProductController +} + +func NewProductHandler( + logger *slog.Logger, + productController *controller.ProductController, +) *ProductHandler { + return &ProductHandler{ + logger: logger, + productController: productController, + } +} + +// List 产品列表 +func (h *ProductHandler) List(ctx context.Context, req *v1.ProductListRequest) (*v1.ProductListResponse, error) { + r := controller.ProductListRequest{ + Keyword: req.Keyword, + } + + list, err := h.productController.List(ctx, r) + if err != nil { + h.logger.Error("call ProductController.List method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + items := make([]*v1.ProductInfo, 0, len(list)) + + for _, item := range list { + items = append(items, &v1.ProductInfo{ + Id: item.ID, + Name: item.Name, + Desc: item.Desc, + Price: int64(item.Price), + }) + } + + return &v1.ProductListResponse{Items: items}, nil +} + +// Create 产品创建 +func (h *ProductHandler) Create(ctx context.Context, req *v1.ProductCreateRequest) (*v1.ProductCreateResponse, error) { + r := controller.ProductCreateRequest{ + ProductAttr: controller.ProductAttr{ + Name: req.Name, + Desc: req.Desc, + Price: int(req.Price), + }, + } + + if err := h.productController.Create(ctx, r); err != nil { + h.logger.Error("call ProductController.Create method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.ProductCreateResponse{}, nil +} + +// Update 产品更新 +func (h *ProductHandler) Update(ctx context.Context, req *v1.ProductUpdateRequest) (*v1.ProductUpdateResponse, error) { + r := controller.ProductUpdateRequest{ + ID: req.Id, + ProductAttr: controller.ProductAttr{ + Name: req.Name, + Desc: req.Desc, + Price: int(req.Price), + }, + } + + if err := h.productController.Update(ctx, r); err != nil { + h.logger.Error("call ProductController.Update method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.ProductUpdateResponse{}, nil +} + +// Detail 产品详情 +func (h *ProductHandler) Detail(ctx context.Context, req *v1.ProductDetailRequest) (*v1.ProductInfo, error) { + ret, err := h.productController.Detail(ctx, req.Id) + if err != nil { + h.logger.Error("call ProductController.Detail method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.ProductInfo{ + Id: ret.ID, + Name: ret.Name, + Desc: ret.Desc, + Price: int64(ret.Price), + }, nil +} + +// Delete 产品删除 +func (h *ProductHandler) Delete(ctx context.Context, req *v1.ProductDeleteRequest) (*v1.ProductDeleteResponse, error) { + if err := h.productController.Delete(ctx, req.Id); err != nil { + h.logger.Error("call ProductController.Delete method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.ProductDeleteResponse{}, nil +} diff --git a/internal/app/adapter/server/grpc/handler/v1/role.go b/internal/app/adapter/server/grpc/handler/v1/role.go new file mode 100644 index 00000000..7ad71bd8 --- /dev/null +++ b/internal/app/adapter/server/grpc/handler/v1/role.go @@ -0,0 +1,138 @@ +package v1 + +import ( + "context" + "log/slog" + + v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" + "go-scaffold/internal/app/adapter/server/grpc/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type RoleHandler struct { + v1.UnimplementedRoleServer + logger *slog.Logger + roleController *controller.RoleController +} + +func NewRoleHandler( + logger *slog.Logger, + roleController *controller.RoleController, +) *RoleHandler { + return &RoleHandler{ + logger: logger, + roleController: roleController, + } +} + +func (h *RoleHandler) List(ctx context.Context, req *v1.RoleListRequest) (*v1.RoleListResponse, error) { + r := controller.RoleListRequest{ + Keyword: req.Keyword, + } + + list, err := h.roleController.List(ctx, r) + if err != nil { + h.logger.Error("call RoleController.List method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + items := make([]*v1.RoleInfo, 0, len(list)) + + for _, item := range list { + items = append(items, &v1.RoleInfo{ + Id: item.ID, + Name: item.Name, + }) + } + + return &v1.RoleListResponse{Items: items}, nil +} + +func (h *RoleHandler) Create(ctx context.Context, req *v1.RoleCreateRequest) (*v1.RoleCreateResponse, error) { + r := controller.RoleCreateRequest{ + RoleAttr: controller.RoleAttr{ + Name: req.Name, + }, + } + + if err := h.roleController.Create(ctx, r); err != nil { + h.logger.Error("call RoleController.Create method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.RoleCreateResponse{}, nil +} + +func (h *RoleHandler) Update(ctx context.Context, req *v1.RoleUpdateRequest) (*v1.RoleUpdateResponse, error) { + r := controller.RoleUpdateRequest{ + ID: req.Id, + RoleAttr: controller.RoleAttr{ + Name: req.Name, + }, + } + + if err := h.roleController.Update(ctx, r); err != nil { + h.logger.Error("call RoleController.Update method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.RoleUpdateResponse{}, nil +} + +func (h *RoleHandler) Detail(ctx context.Context, req *v1.RoleDetailRequest) (*v1.RoleInfo, error) { + ret, err := h.roleController.Detail(ctx, req.Id) + if err != nil { + h.logger.Error("call RoleController.Detail method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.RoleInfo{ + Id: ret.ID, + Name: ret.Name, + }, nil +} + +func (h *RoleHandler) Delete(ctx context.Context, req *v1.RoleDeleteRequest) (*v1.RoleDeleteResponse, error) { + if err := h.roleController.Delete(ctx, req.Id); err != nil { + h.logger.Error("call RoleController.Delete method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.RoleDeleteResponse{}, nil +} + +func (h *RoleHandler) GrantPermissions(ctx context.Context, req *v1.RoleGrantPermissionsRequest) (*v1.RoleGrantPermissionsResponse, error) { + r := controller.RoleGrantPermissionsRequest{ + Role: req.Role, + Permissions: req.Permissions, + } + + if err := h.roleController.GrantPermissions(ctx, r); err != nil { + h.logger.Error("call RoleController.GrantPermissions method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.RoleGrantPermissionsResponse{}, nil +} + +func (h *RoleHandler) GetPermissions(ctx context.Context, req *v1.RoleGetPermissionsRequest) (*v1.RoleGetPermissionsResponse, error) { + list, err := h.roleController.GetPermissions(ctx, req.Id) + if err != nil { + h.logger.Error("call RoleController.GetPermissions method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + items := make([]*v1.PermissionInfo, 0, len(list)) + + for _, item := range list { + items = append(items, &v1.PermissionInfo{ + Id: item.ID, + Key: item.Key, + Name: item.Name, + Desc: item.Desc, + ParentID: item.ParentID, + }) + } + + return &v1.RoleGetPermissionsResponse{Items: items}, nil +} diff --git a/internal/app/adapter/server/grpc/handler/v1/user.go b/internal/app/adapter/server/grpc/handler/v1/user.go index d8d78124..921abdfd 100644 --- a/internal/app/adapter/server/grpc/handler/v1/user.go +++ b/internal/app/adapter/server/grpc/handler/v1/user.go @@ -2,13 +2,11 @@ package v1 import ( "context" + "log/slog" v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" "go-scaffold/internal/app/adapter/server/grpc/pkg/errors" "go-scaffold/internal/app/controller" - "go-scaffold/internal/app/domain" - - "golang.org/x/exp/slog" ) type UserHandler struct { @@ -27,91 +25,121 @@ func NewUserHandler( } } -// List 用户列表 func (h *UserHandler) List(ctx context.Context, req *v1.UserListRequest) (*v1.UserListResponse, error) { - param := domain.UserListParam{ + r := controller.UserListRequest{ Keyword: req.Keyword, } - list, err := h.userController.List(ctx, param) + list, err := h.userController.List(ctx, r) if err != nil { - h.logger.Error("call controller.UserController.List method error", err) + h.logger.Error("call UserController.List method error", slog.Any("error", err)) return nil, errors.Wrap(err) } - items := make([]*v1.ListItem, 0, len(list)) + items := make([]*v1.UserInfo, 0, len(list)) for _, item := range list { - items = append(items, &v1.ListItem{ - Id: item.ID.Int64(), - Name: item.Name, - Age: int32(item.Age), - Phone: item.Phone, + items = append(items, &v1.UserInfo{ + Id: item.ID, + Username: item.Username, + Nickname: item.Nickname, + Phone: item.Phone, }) } - resp := &v1.UserListResponse{Items: items} - - return resp, nil + return &v1.UserListResponse{Items: items}, nil } -// Create 创建用户 func (h *UserHandler) Create(ctx context.Context, req *v1.UserCreateRequest) (*v1.UserCreateResponse, error) { - p := domain.User{ - Name: req.Name, - Age: int8(req.Age), - Phone: req.Phone, + r := controller.UserCreateRequest{ + UserAttr: controller.UserAttr{ + Username: req.Username, + Password: req.Password, + Nickname: req.Nickname, + Phone: req.Phone, + }, } - if err := h.userController.Create(ctx, p); err != nil { - h.logger.Error("call controller.UserController.Create method error", err) + if err := h.userController.Create(ctx, r); err != nil { + h.logger.Error("call UserController.Create method error", slog.Any("error", err)) return nil, errors.Wrap(err) } return &v1.UserCreateResponse{}, nil } -// Update 更新用户 func (h *UserHandler) Update(ctx context.Context, req *v1.UserUpdateRequest) (*v1.UserUpdateResponse, error) { - p := domain.User{ - ID: domain.ID(req.Id), - Name: req.Name, - Age: int8(req.Age), - Phone: req.Phone, + r := controller.UserUpdateRequest{ + ID: req.Id, + UserAttr: controller.UserAttr{ + Username: req.Username, + Password: req.Password, + Nickname: req.Nickname, + Phone: req.Phone, + }, } - if err := h.userController.Update(ctx, p); err != nil { - h.logger.Error("call controller.UserController.Update method error", err) + if err := h.userController.Update(ctx, r); err != nil { + h.logger.Error("call UserController.Update method error", slog.Any("error", err)) return nil, errors.Wrap(err) } return &v1.UserUpdateResponse{}, nil } -// Detail 用户详情 -func (h *UserHandler) Detail(ctx context.Context, req *v1.UserDetailRequest) (*v1.UserDetailResponse, error) { - ret, err := h.userController.Detail(ctx, domain.ID(req.Id)) +func (h *UserHandler) Detail(ctx context.Context, req *v1.UserDetailRequest) (*v1.UserInfo, error) { + ret, err := h.userController.Detail(ctx, req.Id) if err != nil { - h.logger.Error("call controller.UserController.Detail method error", err) + h.logger.Error("call UserController.Detail method error", slog.Any("error", err)) return nil, errors.Wrap(err) } - resp := &v1.UserDetailResponse{ - Id: ret.ID.Int64(), - Name: ret.Name, - Age: int32(ret.Age), - Phone: ret.Phone, - } - - return resp, nil + return &v1.UserInfo{ + Id: ret.ID, + Username: ret.Username, + Nickname: ret.Nickname, + Phone: ret.Phone, + }, nil } -// Delete 删除用户 func (h *UserHandler) Delete(ctx context.Context, req *v1.UserDeleteRequest) (*v1.UserDeleteResponse, error) { - if err := h.userController.Delete(ctx, domain.ID(req.Id)); err != nil { - h.logger.Error("call controller.UserController.Delete method error", err) + if err := h.userController.Delete(ctx, req.Id); err != nil { + h.logger.Error("call UserController.Delete method error", slog.Any("error", err)) return nil, errors.Wrap(err) } return &v1.UserDeleteResponse{}, nil } + +func (h *UserHandler) AssignRoles(ctx context.Context, req *v1.UserAssignRolesRequest) (*v1.UserAssignRolesResponse, error) { + r := controller.UserAssignRoleRequest{ + User: req.User, + Roles: req.Roles, + } + + if err := h.userController.AssignRoles(ctx, r); err != nil { + h.logger.Error("call UserController.AssignRoles method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + return &v1.UserAssignRolesResponse{}, nil +} + +func (h *UserHandler) GetRoles(ctx context.Context, req *v1.UserGetRolesRequest) (*v1.UserGetRolesResponse, error) { + list, err := h.userController.GetRoles(ctx, req.Id) + if err != nil { + h.logger.Error("call UserController.GetRoles method error", slog.Any("error", err)) + return nil, errors.Wrap(err) + } + + items := make([]*v1.RoleInfo, 0, len(list)) + + for _, item := range list { + items = append(items, &v1.RoleInfo{ + Id: item.ID, + Name: item.Name, + }) + } + + return &v1.UserGetRolesResponse{Items: items}, nil +} diff --git a/internal/app/adapter/server/grpc/pkg/errors/errors.go b/internal/app/adapter/server/grpc/pkg/errors/errors.go index 1dc68edc..9dfbf421 100644 --- a/internal/app/adapter/server/grpc/pkg/errors/errors.go +++ b/internal/app/adapter/server/grpc/pkg/errors/errors.go @@ -1,19 +1,19 @@ package errors import ( - berr "go-scaffold/internal/app/pkg/errors" - kerr "github.com/go-kratos/kratos/v2/errors" + + berr "go-scaffold/internal/app/pkg/errors" ) var errMsg = map[error]string{ - berr.ErrServerError: "服务器出错", - berr.ErrBadRequest: "客户端请求错误", - berr.ErrValidateError: "参数校验错误", - berr.ErrUnauthorized: "未经授权", - berr.ErrPermissionDenied: "暂无权限", - berr.ErrResourceNotFound: "资源不存在", - berr.ErrTooManyRequest: "请求过于频繁", + berr.ErrInternalError: "服务器出错", + berr.ErrBadCall: "客户端请求错误", + berr.ErrValidateError: "参数校验错误", + berr.ErrInvalidAuthorized: "未经授权", + berr.ErrAccessDenied: "暂无权限", + berr.ErrResourceNotFound: "资源不存在", + berr.ErrCallsTooFrequently: "请求过于频繁", } func Message(err error) string { @@ -27,6 +27,6 @@ func Wrap(err error) error { return kerr.New(se.Code(), se.Label(), Message(se)) } - e := berr.ErrServerError + e := berr.ErrInternalError return kerr.New(e.Code(), e.Label(), err.Error()) } diff --git a/internal/app/adapter/server/grpc/router/router.go b/internal/app/adapter/server/grpc/router/router.go index 33ad1fc2..5868d64e 100644 --- a/internal/app/adapter/server/grpc/router/router.go +++ b/internal/app/adapter/server/grpc/router/router.go @@ -1,25 +1,34 @@ package router import ( - v1api "go-scaffold/internal/app/adapter/server/grpc/api/v1" - "github.com/go-kratos/kratos/v2/transport/grpc" + + v1api "go-scaffold/internal/app/adapter/server/grpc/api/v1" ) // Router 注册器 type Router struct { - greetServer v1api.GreetServer - userServer v1api.UserServer + greetServer v1api.GreetServer + userServer v1api.UserServer + roleServer v1api.RoleServer + permissionServer v1api.PermissionServer + productServer v1api.ProductServer } // New 构造注册器 func New( greetServer v1api.GreetServer, userServer v1api.UserServer, + roleServer v1api.RoleServer, + permissionServer v1api.PermissionServer, + productServer v1api.ProductServer, ) *Router { return &Router{ - greetServer: greetServer, - userServer: userServer, + greetServer: greetServer, + userServer: userServer, + roleServer: roleServer, + permissionServer: permissionServer, + productServer: productServer, } } @@ -27,4 +36,7 @@ func New( func (r *Router) Register(server *grpc.Server) { v1api.RegisterGreetServer(server, r.greetServer) v1api.RegisterUserServer(server, r.userServer) + v1api.RegisterRoleServer(server, r.roleServer) + v1api.RegisterPermissionServer(server, r.permissionServer) + v1api.RegisterProductServer(server, r.productServer) } diff --git a/internal/app/adapter/server/http/api/docs/docs.go b/internal/app/adapter/server/http/api/docs/docs.go index 7b149043..8d098602 100644 --- a/internal/app/adapter/server/http/api/docs/docs.go +++ b/internal/app/adapter/server/http/api/docs/docs.go @@ -1,5 +1,4 @@ -// Code generated by swaggo/swag. DO NOT EDIT. - +// Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -23,35 +22,103 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/v1/greet": { + "/v1/account/permissions": { "get": { "security": [ { "Authorization": [] } ], - "description": "示例接口", + "description": "获取账号权限", "consumes": [ - "application/x-www-form-urlencoded" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "示例" + "账号" ], - "summary": "示例接口", - "parameters": [ + "summary": "获取账号权限", + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.PermissionInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/account/profile": { + "get": { + "security": [ { - "type": "string", - "format": "string", - "default": "Tom", - "description": "名称", - "name": "name", - "in": "query", - "required": true + "Authorization": [] } ], + "description": "获取账号信息", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "账号" + ], + "summary": "获取账号信息", "responses": { "200": { "description": "成功响应", @@ -64,7 +131,7 @@ const docTemplate = `{ "type": "object", "properties": { "data": { - "$ref": "#/definitions/v1.GreetHelloResponse" + "$ref": "#/definitions/v1.AccountProfileResponse" } } } @@ -108,16 +175,14 @@ const docTemplate = `{ } } } - } - }, - "/v1/producer/example": { - "post": { + }, + "put": { "security": [ { "Authorization": [] } ], - "description": "示例接口", + "description": "更新账号信息", "consumes": [ "application/json" ], @@ -125,18 +190,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "示例" + "账号" ], - "summary": "示例接口", + "summary": "更新账号信息", "parameters": [ { "format": "string", - "description": "生产者消息", + "description": "请求体", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.ProducerExampleRequest" + "$ref": "#/definitions/v1.AccountUpdateProfileRequest" } } ], @@ -186,8 +251,8 @@ const docTemplate = `{ } } }, - "/v1/trace/example": { - "post": { + "/v1/greet": { + "get": { "security": [ { "Authorization": [] @@ -195,7 +260,7 @@ const docTemplate = `{ ], "description": "示例接口", "consumes": [ - "application/json" + "application/x-www-form-urlencoded" ], "produces": [ "application/json" @@ -204,11 +269,34 @@ const docTemplate = `{ "示例" ], "summary": "示例接口", + "parameters": [ + { + "type": "string", + "format": "string", + "default": "Tom", + "description": "名称", + "name": "name", + "in": "query", + "required": true + } + ], "responses": { "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.GreetHelloResponse" + } + } + } + ] } }, "400": { @@ -250,14 +338,14 @@ const docTemplate = `{ } } }, - "/v1/user": { + "/v1/login": { "post": { "security": [ { "Authorization": [] } ], - "description": "创建用户", + "description": "登录", "consumes": [ "application/json" ], @@ -265,18 +353,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "用户" + "账号" ], - "summary": "创建用户", + "summary": "登录", "parameters": [ { "format": "string", - "description": "用户信息", + "description": "请求体", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.UserCreateRequest" + "$ref": "#/definitions/v1.AccountLoginRequest" } } ], @@ -284,7 +372,19 @@ const docTemplate = `{ "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.AccountLoginResponse" + } + } + } + ] } }, "400": { @@ -326,14 +426,14 @@ const docTemplate = `{ } } }, - "/v1/user/{id}": { - "get": { + "/v1/logout": { + "delete": { "security": [ { "Authorization": [] } ], - "description": "用户详情", + "description": "登出", "consumes": [ "text/plain" ], @@ -341,37 +441,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "用户" - ], - "summary": "用户详情", - "parameters": [ - { - "minimum": 1, - "type": "integer", - "format": "uint", - "description": "用户 id", - "name": "id", - "in": "path", - "required": true - } + "账号" ], + "summary": "登出", "responses": { "200": { "description": "成功响应", "schema": { - "allOf": [ - { - "$ref": "#/definitions/example.Success" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/v1.UserDetailResponse" - } - } - } - ] + "$ref": "#/definitions/example.Success" } }, "400": { @@ -411,50 +488,54 @@ const docTemplate = `{ } } } - }, - "put": { + } + }, + "/v1/permission": { + "get": { "security": [ { "Authorization": [] } ], - "description": "更新用户", + "description": "权限详情", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "更新用户", + "summary": "权限详情", "parameters": [ { "minimum": 1, "type": "integer", "format": "uint", - "description": "用户 id", + "description": "权限 id", "name": "id", - "in": "path", + "in": "query", "required": true - }, - { - "format": "string", - "description": "用户信息", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1.UserCreateRequest" - } } ], "responses": { "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.PermissionDetailResponse" + } + } + } + ] } }, "400": { @@ -495,32 +576,33 @@ const docTemplate = `{ } } }, - "delete": { + "put": { "security": [ { "Authorization": [] } ], - "description": "删除用户", + "description": "权限更新", "consumes": [ - "text/plain" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "删除用户", + "summary": "权限更新", "parameters": [ { - "minimum": 1, - "type": "integer", - "format": "uint", - "description": "用户 id", - "name": "id", - "in": "path", - "required": true + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PermissionUpdateRequest" + } } ], "responses": { @@ -567,55 +649,1933 @@ const docTemplate = `{ } } } - } - }, - "/v1/users": { - "get": { + }, + "post": { "security": [ { "Authorization": [] } ], - "description": "用户列表", + "description": "权限创建", "consumes": [ - "application/x-www-form-urlencoded" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "用户列表", + "summary": "权限创建", "parameters": [ { - "type": "string", "format": "string", - "description": "查询字符串", - "name": "keyword", - "in": "query" + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PermissionCreateRequest" + } } ], "responses": { "200": { "description": "成功响应", "schema": { - "allOf": [ - { - "$ref": "#/definitions/example.Success" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/v1.UserListItem" - } - } - } - } - ] + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "权限删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限" + ], + "summary": "权限删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/permissions": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "权限列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限" + ], + "summary": "权限列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.PermissionInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/producer/example": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "示例接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "示例" + ], + "summary": "示例接口", + "parameters": [ + { + "format": "string", + "description": "生产者消息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProducerExampleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/product": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "产品 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.ProductDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品更新", + "parameters": [ + { + "format": "string", + "description": "产品信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProductUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品创建", + "parameters": [ + { + "format": "string", + "description": "产品信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProductCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "产品 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/products": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.ProductInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/register": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "注册", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "账号" + ], + "summary": "注册", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.AccountRegisterRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.AccountRegisterResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/role": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.RoleDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色更新", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色创建", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/role/permissions": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "获取角色权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "获取角色权限", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleGetPermissionsRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "授权角色权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "授权角色权限", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleGrantPermissionsRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/roles": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/trace/example": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "示例接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "示例" + ], + "summary": "示例接口", + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/user": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.UserDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户更新", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户创建", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/user/roles": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "获取用户角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "获取用户角色", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserGetRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "分配用户角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "分配用户角色", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserAssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/users": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.UserInfo" + } + } + } + } + ] } }, "400": { @@ -662,93 +2622,245 @@ const docTemplate = `{ "example.ClientError": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "客户端请求错误|参数校验错误" + "errMsg": { + "type": "string", + "example": "客户端请求错误|参数校验错误" + }, + "errNo": { + "description": "errNo 类型应为 int,string 仅为了表达多个错误码", + "type": "string", + "example": "10002|10003" + } + } + }, + "example.PermissionDenied": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "暂无权限" + }, + "errNo": { + "type": "integer", + "example": 10005 + } + } + }, + "example.ResourceNotFound": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "资源不存在" + }, + "errNo": { + "type": "integer", + "example": 10006 + } + } + }, + "example.ServerError": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "服务器出错" + }, + "errNo": { + "type": "integer", + "example": 10001 + } + } + }, + "example.Success": { + "type": "object", + "properties": { + "data": {} + } + }, + "example.TooManyRequest": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "请求过于频繁" + }, + "errNo": { + "type": "integer", + "example": 10007 + } + } + }, + "example.Unauthorized": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "未经授权" + }, + "errNo": { + "type": "integer", + "example": 10004 + } + } + }, + "v1.AccountLoginRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.AccountLoginResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/v1.UserInfo" + } + } + }, + "v1.AccountProfileResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" }, - "errNo": { - "description": "errNo 类型应为 int,string 仅为了表达多个错误码", - "type": "string", - "example": "10002|10003" + "nickname": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" } } }, - "example.PermissionDenied": { + "v1.AccountRegisterRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "暂无权限" + "nickname": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10005 + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" } } }, - "example.ResourceNotFound": { + "v1.AccountRegisterResponse": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "资源不存在" + "token": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10006 + "user": { + "$ref": "#/definitions/v1.UserInfo" } } }, - "example.ServerError": { + "v1.AccountUpdateProfileRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "服务器出错" - }, - "errNo": { - "type": "integer", - "example": 10001 + "nickname": { + "type": "string" } } }, - "example.Success": { + "v1.GreetHelloResponse": { "type": "object", "properties": { - "data": {} + "msg": { + "type": "string" + } } }, - "example.TooManyRequest": { + "v1.PermissionCreateRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "请求过于频繁" + "desc": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10007 + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, - "example.Unauthorized": { + "v1.PermissionDetailResponse": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "未经授权" + "desc": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10004 + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, - "v1.GreetHelloResponse": { + "v1.PermissionInfo": { "type": "object", "properties": { - "msg": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" + } + } + }, + "v1.PermissionUpdateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "key": { "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, @@ -760,51 +2872,224 @@ const docTemplate = `{ } } }, - "v1.UserCreateRequest": { + "v1.ProductCreateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + } + } + }, + "v1.ProductDetailResponse": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + } + } + }, + "v1.ProductInfo": { "type": "object", "properties": { - "age": { + "desc": { + "type": "string" + }, + "id": { "type": "integer" }, "name": { "type": "string" }, - "phone": { + "price": { + "type": "integer" + } + } + }, + "v1.ProductUpdateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { "type": "string" + }, + "price": { + "type": "integer" } } }, - "v1.UserDetailResponse": { + "v1.RoleCreateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + }, + "v1.RoleDetailResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "v1.RoleGetPermissionsRequest": { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + }, + "v1.RoleGrantPermissionsRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "type": "integer" + } + }, + "role": { + "type": "integer" + } + } + }, + "v1.RoleInfo": { "type": "object", "properties": { - "age": { + "id": { "type": "integer" }, + "name": { + "type": "string" + } + } + }, + "v1.RoleUpdateRequest": { + "type": "object", + "properties": { "id": { "type": "integer" }, "name": { "type": "string" + } + } + }, + "v1.UserAssignRoleRequest": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "type": "integer" + } + }, + "user": { + "type": "integer" + } + } + }, + "v1.UserCreateRequest": { + "type": "object", + "properties": { + "nickname": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.UserDetailResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "nickname": { + "type": "string" }, "phone": { "type": "string" + }, + "username": { + "type": "string" } } }, - "v1.UserListItem": { + "v1.UserGetRoleRequest": { "type": "object", "properties": { - "age": { + "id": { + "type": "integer" + } + } + }, + "v1.UserInfo": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "nickname": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.UserUpdateRequest": { + "type": "object", + "properties": { "id": { "type": "integer" }, - "name": { + "nickname": { + "type": "string" + }, + "password": { "type": "string" }, "phone": { "type": "string" + }, + "username": { + "type": "string" } } } @@ -828,8 +3113,6 @@ var SwaggerInfo = &swag.Spec{ Description: "API 接口文档", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, - LeftDelim: "{{", - RightDelim: "}}", } func init() { diff --git a/internal/app/adapter/server/http/api/docs/swagger.json b/internal/app/adapter/server/http/api/docs/swagger.json index d6f4e3a0..5afa39cb 100644 --- a/internal/app/adapter/server/http/api/docs/swagger.json +++ b/internal/app/adapter/server/http/api/docs/swagger.json @@ -20,35 +20,103 @@ "host": "localhost", "basePath": "/api", "paths": { - "/v1/greet": { + "/v1/account/permissions": { "get": { "security": [ { "Authorization": [] } ], - "description": "示例接口", + "description": "获取账号权限", "consumes": [ - "application/x-www-form-urlencoded" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "示例" + "账号" ], - "summary": "示例接口", - "parameters": [ + "summary": "获取账号权限", + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.PermissionInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/account/profile": { + "get": { + "security": [ { - "type": "string", - "format": "string", - "default": "Tom", - "description": "名称", - "name": "name", - "in": "query", - "required": true + "Authorization": [] } ], + "description": "获取账号信息", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "账号" + ], + "summary": "获取账号信息", "responses": { "200": { "description": "成功响应", @@ -61,7 +129,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/definitions/v1.GreetHelloResponse" + "$ref": "#/definitions/v1.AccountProfileResponse" } } } @@ -105,16 +173,14 @@ } } } - } - }, - "/v1/producer/example": { - "post": { + }, + "put": { "security": [ { "Authorization": [] } ], - "description": "示例接口", + "description": "更新账号信息", "consumes": [ "application/json" ], @@ -122,18 +188,18 @@ "application/json" ], "tags": [ - "示例" + "账号" ], - "summary": "示例接口", + "summary": "更新账号信息", "parameters": [ { "format": "string", - "description": "生产者消息", + "description": "请求体", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.ProducerExampleRequest" + "$ref": "#/definitions/v1.AccountUpdateProfileRequest" } } ], @@ -183,8 +249,8 @@ } } }, - "/v1/trace/example": { - "post": { + "/v1/greet": { + "get": { "security": [ { "Authorization": [] @@ -192,7 +258,7 @@ ], "description": "示例接口", "consumes": [ - "application/json" + "application/x-www-form-urlencoded" ], "produces": [ "application/json" @@ -201,11 +267,34 @@ "示例" ], "summary": "示例接口", + "parameters": [ + { + "type": "string", + "format": "string", + "default": "Tom", + "description": "名称", + "name": "name", + "in": "query", + "required": true + } + ], "responses": { "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.GreetHelloResponse" + } + } + } + ] } }, "400": { @@ -247,14 +336,14 @@ } } }, - "/v1/user": { + "/v1/login": { "post": { "security": [ { "Authorization": [] } ], - "description": "创建用户", + "description": "登录", "consumes": [ "application/json" ], @@ -262,18 +351,18 @@ "application/json" ], "tags": [ - "用户" + "账号" ], - "summary": "创建用户", + "summary": "登录", "parameters": [ { "format": "string", - "description": "用户信息", + "description": "请求体", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.UserCreateRequest" + "$ref": "#/definitions/v1.AccountLoginRequest" } } ], @@ -281,7 +370,19 @@ "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.AccountLoginResponse" + } + } + } + ] } }, "400": { @@ -323,14 +424,14 @@ } } }, - "/v1/user/{id}": { - "get": { + "/v1/logout": { + "delete": { "security": [ { "Authorization": [] } ], - "description": "用户详情", + "description": "登出", "consumes": [ "text/plain" ], @@ -338,37 +439,14 @@ "application/json" ], "tags": [ - "用户" - ], - "summary": "用户详情", - "parameters": [ - { - "minimum": 1, - "type": "integer", - "format": "uint", - "description": "用户 id", - "name": "id", - "in": "path", - "required": true - } + "账号" ], + "summary": "登出", "responses": { "200": { "description": "成功响应", "schema": { - "allOf": [ - { - "$ref": "#/definitions/example.Success" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/v1.UserDetailResponse" - } - } - } - ] + "$ref": "#/definitions/example.Success" } }, "400": { @@ -408,50 +486,54 @@ } } } - }, - "put": { + } + }, + "/v1/permission": { + "get": { "security": [ { "Authorization": [] } ], - "description": "更新用户", + "description": "权限详情", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "更新用户", + "summary": "权限详情", "parameters": [ { "minimum": 1, "type": "integer", "format": "uint", - "description": "用户 id", + "description": "权限 id", "name": "id", - "in": "path", + "in": "query", "required": true - }, - { - "format": "string", - "description": "用户信息", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1.UserCreateRequest" - } } ], "responses": { "200": { "description": "成功响应", "schema": { - "$ref": "#/definitions/example.Success" + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.PermissionDetailResponse" + } + } + } + ] } }, "400": { @@ -492,32 +574,33 @@ } } }, - "delete": { + "put": { "security": [ { "Authorization": [] } ], - "description": "删除用户", + "description": "权限更新", "consumes": [ - "text/plain" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "删除用户", + "summary": "权限更新", "parameters": [ { - "minimum": 1, - "type": "integer", - "format": "uint", - "description": "用户 id", - "name": "id", - "in": "path", - "required": true + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PermissionUpdateRequest" + } } ], "responses": { @@ -564,55 +647,41 @@ } } } - } - }, - "/v1/users": { - "get": { + }, + "post": { "security": [ { "Authorization": [] } ], - "description": "用户列表", + "description": "权限创建", "consumes": [ - "application/x-www-form-urlencoded" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "用户" + "权限" ], - "summary": "用户列表", + "summary": "权限创建", "parameters": [ { - "type": "string", "format": "string", - "description": "查询字符串", - "name": "keyword", - "in": "query" + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PermissionCreateRequest" + } } ], "responses": { "200": { "description": "成功响应", "schema": { - "allOf": [ - { - "$ref": "#/definitions/example.Success" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/v1.UserListItem" - } - } - } - } - ] + "$ref": "#/definitions/example.Success" } }, "400": { @@ -652,100 +721,2144 @@ } } } - } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "权限删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限" + ], + "summary": "权限删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/permissions": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "权限列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限" + ], + "summary": "权限列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.PermissionInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/producer/example": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "示例接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "示例" + ], + "summary": "示例接口", + "parameters": [ + { + "format": "string", + "description": "生产者消息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProducerExampleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/product": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "产品 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.ProductDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品更新", + "parameters": [ + { + "format": "string", + "description": "产品信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProductUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品创建", + "parameters": [ + { + "format": "string", + "description": "产品信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProductCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "产品 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/products": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "产品列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "产品" + ], + "summary": "产品列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.ProductInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/register": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "注册", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "账号" + ], + "summary": "注册", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.AccountRegisterRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.AccountRegisterResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/role": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.RoleDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色更新", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色创建", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "角色删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/role/permissions": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "获取角色权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "获取角色权限", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleGetPermissionsRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "授权角色权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "授权角色权限", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.RoleGrantPermissionsRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/roles": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "角色列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/trace/example": { + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "示例接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "示例" + ], + "summary": "示例接口", + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/user": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户详情", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户详情", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/v1.UserDetailResponse" + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "put": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户更新", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户创建", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户创建", + "parameters": [ + { + "format": "string", + "description": "权限信息", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户删除", + "consumes": [ + "text/plain" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户删除", + "parameters": [ + { + "minimum": 1, + "type": "integer", + "format": "uint", + "description": "权限 id", + "name": "id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/user/roles": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "获取用户角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "获取用户角色", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserGetRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + }, + "post": { + "security": [ + { + "Authorization": [] + } + ], + "description": "分配用户角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "分配用户角色", + "parameters": [ + { + "format": "string", + "description": "请求体", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UserAssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "$ref": "#/definitions/example.Success" + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } + }, + "/v1/users": { + "get": { + "security": [ + { + "Authorization": [] + } + ], + "description": "用户列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "用户列表", + "parameters": [ + { + "type": "string", + "format": "string", + "description": "查询字符串", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/example.Success" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.UserInfo" + } + } + } + } + ] + } + }, + "400": { + "description": "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)", + "schema": { + "$ref": "#/definitions/example.ClientError" + } + }, + "401": { + "description": "登陆失效", + "schema": { + "$ref": "#/definitions/example.Unauthorized" + } + }, + "403": { + "description": "没有权限", + "schema": { + "$ref": "#/definitions/example.PermissionDenied" + } + }, + "404": { + "description": "资源不存在", + "schema": { + "$ref": "#/definitions/example.ResourceNotFound" + } + }, + "429": { + "description": "请求过于频繁", + "schema": { + "$ref": "#/definitions/example.TooManyRequest" + } + }, + "500": { + "description": "服务器出错", + "schema": { + "$ref": "#/definitions/example.ServerError" + } + } + } + } } }, "definitions": { "example.ClientError": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "客户端请求错误|参数校验错误" + "errMsg": { + "type": "string", + "example": "客户端请求错误|参数校验错误" + }, + "errNo": { + "description": "errNo 类型应为 int,string 仅为了表达多个错误码", + "type": "string", + "example": "10002|10003" + } + } + }, + "example.PermissionDenied": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "暂无权限" + }, + "errNo": { + "type": "integer", + "example": 10005 + } + } + }, + "example.ResourceNotFound": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "资源不存在" + }, + "errNo": { + "type": "integer", + "example": 10006 + } + } + }, + "example.ServerError": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "服务器出错" + }, + "errNo": { + "type": "integer", + "example": 10001 + } + } + }, + "example.Success": { + "type": "object", + "properties": { + "data": {} + } + }, + "example.TooManyRequest": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "请求过于频繁" + }, + "errNo": { + "type": "integer", + "example": 10007 + } + } + }, + "example.Unauthorized": { + "type": "object", + "properties": { + "errMsg": { + "type": "string", + "example": "未经授权" + }, + "errNo": { + "type": "integer", + "example": 10004 + } + } + }, + "v1.AccountLoginRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.AccountLoginResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/v1.UserInfo" + } + } + }, + "v1.AccountProfileResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" }, - "errNo": { - "description": "errNo 类型应为 int,string 仅为了表达多个错误码", - "type": "string", - "example": "10002|10003" + "nickname": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" } } }, - "example.PermissionDenied": { + "v1.AccountRegisterRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "暂无权限" + "nickname": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10005 + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" } } }, - "example.ResourceNotFound": { + "v1.AccountRegisterResponse": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "资源不存在" + "token": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10006 + "user": { + "$ref": "#/definitions/v1.UserInfo" } } }, - "example.ServerError": { + "v1.AccountUpdateProfileRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "服务器出错" - }, - "errNo": { - "type": "integer", - "example": 10001 + "nickname": { + "type": "string" } } }, - "example.Success": { + "v1.GreetHelloResponse": { "type": "object", "properties": { - "data": {} + "msg": { + "type": "string" + } } }, - "example.TooManyRequest": { + "v1.PermissionCreateRequest": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "请求过于频繁" + "desc": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10007 + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, - "example.Unauthorized": { + "v1.PermissionDetailResponse": { "type": "object", "properties": { - "errMsg": { - "type": "string", - "example": "未经授权" + "desc": { + "type": "string" }, - "errNo": { - "type": "integer", - "example": 10004 + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, - "v1.GreetHelloResponse": { + "v1.PermissionInfo": { "type": "object", "properties": { - "msg": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" + } + } + }, + "v1.PermissionUpdateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "key": { "type": "string" + }, + "name": { + "type": "string" + }, + "parentID": { + "type": "integer" } } }, @@ -757,51 +2870,224 @@ } } }, - "v1.UserCreateRequest": { + "v1.ProductCreateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + } + } + }, + "v1.ProductDetailResponse": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + } + } + }, + "v1.ProductInfo": { "type": "object", "properties": { - "age": { + "desc": { + "type": "string" + }, + "id": { "type": "integer" }, "name": { "type": "string" }, - "phone": { + "price": { + "type": "integer" + } + } + }, + "v1.ProductUpdateRequest": { + "type": "object", + "properties": { + "desc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { "type": "string" + }, + "price": { + "type": "integer" } } }, - "v1.UserDetailResponse": { + "v1.RoleCreateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + }, + "v1.RoleDetailResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "v1.RoleGetPermissionsRequest": { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + }, + "v1.RoleGrantPermissionsRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "type": "integer" + } + }, + "role": { + "type": "integer" + } + } + }, + "v1.RoleInfo": { "type": "object", "properties": { - "age": { + "id": { "type": "integer" }, + "name": { + "type": "string" + } + } + }, + "v1.RoleUpdateRequest": { + "type": "object", + "properties": { "id": { "type": "integer" }, "name": { "type": "string" + } + } + }, + "v1.UserAssignRoleRequest": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "type": "integer" + } + }, + "user": { + "type": "integer" + } + } + }, + "v1.UserCreateRequest": { + "type": "object", + "properties": { + "nickname": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.UserDetailResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "nickname": { + "type": "string" }, "phone": { "type": "string" + }, + "username": { + "type": "string" } } }, - "v1.UserListItem": { + "v1.UserGetRoleRequest": { "type": "object", "properties": { - "age": { + "id": { + "type": "integer" + } + } + }, + "v1.UserInfo": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "nickname": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "v1.UserUpdateRequest": { + "type": "object", + "properties": { "id": { "type": "integer" }, - "name": { + "nickname": { + "type": "string" + }, + "password": { "type": "string" }, "phone": { "type": "string" + }, + "username": { + "type": "string" } } } diff --git a/internal/app/adapter/server/http/api/docs/swagger.yaml b/internal/app/adapter/server/http/api/docs/swagger.yaml index aa527ccc..3c04052a 100644 --- a/internal/app/adapter/server/http/api/docs/swagger.yaml +++ b/internal/app/adapter/server/http/api/docs/swagger.yaml @@ -62,46 +62,255 @@ definitions: example: 10004 type: integer type: object + v1.AccountLoginRequest: + properties: + password: + type: string + username: + type: string + type: object + v1.AccountLoginResponse: + properties: + token: + type: string + user: + $ref: '#/definitions/v1.UserInfo' + type: object + v1.AccountProfileResponse: + properties: + id: + type: integer + nickname: + type: string + phone: + type: string + username: + type: string + type: object + v1.AccountRegisterRequest: + properties: + nickname: + type: string + password: + type: string + phone: + type: string + username: + type: string + type: object + v1.AccountRegisterResponse: + properties: + token: + type: string + user: + $ref: '#/definitions/v1.UserInfo' + type: object + v1.AccountUpdateProfileRequest: + properties: + nickname: + type: string + type: object v1.GreetHelloResponse: properties: msg: type: string type: object + v1.PermissionCreateRequest: + properties: + desc: + type: string + key: + type: string + name: + type: string + parentID: + type: integer + type: object + v1.PermissionDetailResponse: + properties: + desc: + type: string + id: + type: integer + key: + type: string + name: + type: string + parentID: + type: integer + type: object + v1.PermissionInfo: + properties: + desc: + type: string + id: + type: integer + key: + type: string + name: + type: string + parentID: + type: integer + type: object + v1.PermissionUpdateRequest: + properties: + desc: + type: string + id: + type: integer + key: + type: string + name: + type: string + parentID: + type: integer + type: object v1.ProducerExampleRequest: properties: msg: type: string type: object - v1.UserCreateRequest: + v1.ProductCreateRequest: + properties: + desc: + type: string + name: + type: string + price: + type: integer + type: object + v1.ProductDetailResponse: properties: - age: + desc: + type: string + id: type: integer name: type: string - phone: + price: + type: integer + type: object + v1.ProductInfo: + properties: + desc: + type: string + id: + type: integer + name: + type: string + price: + type: integer + type: object + v1.ProductUpdateRequest: + properties: + desc: + type: string + id: + type: integer + name: + type: string + price: + type: integer + type: object + v1.RoleCreateRequest: + properties: + name: type: string type: object - v1.UserDetailResponse: + v1.RoleDetailResponse: + properties: + id: + type: integer + name: + type: string + type: object + v1.RoleGetPermissionsRequest: + properties: + id: + type: integer + type: object + v1.RoleGrantPermissionsRequest: + properties: + permissions: + items: + type: integer + type: array + role: + type: integer + type: object + v1.RoleInfo: properties: - age: + id: type: integer + name: + type: string + type: object + v1.RoleUpdateRequest: + properties: id: type: integer name: type: string + type: object + v1.UserAssignRoleRequest: + properties: + roles: + items: + type: integer + type: array + user: + type: integer + type: object + v1.UserCreateRequest: + properties: + nickname: + type: string + password: + type: string + phone: + type: string + username: + type: string + type: object + v1.UserDetailResponse: + properties: + id: + type: integer + nickname: + type: string phone: type: string + username: + type: string type: object - v1.UserListItem: + v1.UserGetRoleRequest: properties: - age: + id: type: integer + type: object + v1.UserInfo: + properties: id: type: integer - name: + nickname: + type: string + phone: + type: string + username: + type: string + type: object + v1.UserUpdateRequest: + properties: + id: + type: integer + nickname: + type: string + password: type: string phone: type: string + username: + type: string type: object host: localhost info: @@ -110,31 +319,1073 @@ info: title: API 接口文档 version: 0.0.0 paths: - /v1/greet: + /v1/account/permissions: + get: + consumes: + - text/plain + description: 获取账号权限 + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + items: + $ref: '#/definitions/v1.PermissionInfo' + type: array + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 获取账号权限 + tags: + - 账号 + /v1/account/profile: get: consumes: - - application/x-www-form-urlencoded - description: 示例接口 + - text/plain + description: 获取账号信息 + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.AccountProfileResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 获取账号信息 + tags: + - 账号 + put: + consumes: + - application/json + description: 更新账号信息 + parameters: + - description: 请求体 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.AccountUpdateProfileRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 更新账号信息 + tags: + - 账号 + /v1/greet: + get: + consumes: + - application/x-www-form-urlencoded + description: 示例接口 + parameters: + - default: Tom + description: 名称 + format: string + in: query + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.GreetHelloResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 示例接口 + tags: + - 示例 + /v1/login: + post: + consumes: + - application/json + description: 登录 + parameters: + - description: 请求体 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.AccountLoginRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.AccountLoginResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 登录 + tags: + - 账号 + /v1/logout: + delete: + consumes: + - text/plain + description: 登出 + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 登出 + tags: + - 账号 + /v1/permission: + delete: + consumes: + - text/plain + description: 权限删除 + parameters: + - description: 权限 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 权限删除 + tags: + - 权限 + get: + consumes: + - text/plain + description: 权限详情 + parameters: + - description: 权限 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.PermissionDetailResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 权限详情 + tags: + - 权限 + post: + consumes: + - application/json + description: 权限创建 + parameters: + - description: 权限信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.PermissionCreateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 权限创建 + tags: + - 权限 + put: + consumes: + - application/json + description: 权限更新 + parameters: + - description: 权限信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.PermissionUpdateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 权限更新 + tags: + - 权限 + /v1/permissions: + get: + consumes: + - application/x-www-form-urlencoded + description: 权限列表 + parameters: + - description: 查询字符串 + format: string + in: query + name: keyword + type: string + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + items: + $ref: '#/definitions/v1.PermissionInfo' + type: array + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 权限列表 + tags: + - 权限 + /v1/producer/example: + post: + consumes: + - application/json + description: 示例接口 + parameters: + - description: 生产者消息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.ProducerExampleRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 示例接口 + tags: + - 示例 + /v1/product: + delete: + consumes: + - text/plain + description: 产品删除 + parameters: + - description: 产品 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 产品删除 + tags: + - 产品 + get: + consumes: + - text/plain + description: 产品详情 + parameters: + - description: 产品 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.ProductDetailResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 产品详情 + tags: + - 产品 + post: + consumes: + - application/json + description: 产品创建 + parameters: + - description: 产品信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.ProductCreateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 产品创建 + tags: + - 产品 + put: + consumes: + - application/json + description: 产品更新 + parameters: + - description: 产品信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.ProductUpdateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 产品更新 + tags: + - 产品 + /v1/products: + get: + consumes: + - application/x-www-form-urlencoded + description: 产品列表 + parameters: + - description: 查询字符串 + format: string + in: query + name: keyword + type: string + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + items: + $ref: '#/definitions/v1.ProductInfo' + type: array + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 产品列表 + tags: + - 产品 + /v1/register: + post: + consumes: + - application/json + description: 注册 + parameters: + - description: 请求体 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.AccountRegisterRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.AccountRegisterResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 注册 + tags: + - 账号 + /v1/role: + delete: + consumes: + - text/plain + description: 角色删除 + parameters: + - description: 权限 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 角色删除 + tags: + - 角色 + get: + consumes: + - text/plain + description: 角色详情 + parameters: + - description: 权限 id + format: uint + in: query + minimum: 1 + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + $ref: '#/definitions/v1.RoleDetailResponse' + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 角色详情 + tags: + - 角色 + post: + consumes: + - application/json + description: 角色创建 + parameters: + - description: 权限信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.RoleCreateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 角色创建 + tags: + - 角色 + put: + consumes: + - application/json + description: 角色更新 parameters: - - default: Tom - description: 名称 + - description: 权限信息 format: string - in: query - name: name + in: body + name: data required: true - type: string + schema: + $ref: '#/definitions/v1.RoleUpdateRequest' produces: - application/json responses: "200": description: 成功响应 schema: - allOf: - - $ref: '#/definitions/example.Success' - - properties: - data: - $ref: '#/definitions/v1.GreetHelloResponse' - type: object + $ref: '#/definitions/example.Success' "400": description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) schema: @@ -161,22 +1412,22 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 示例接口 + summary: 角色更新 tags: - - 示例 - /v1/producer/example: - post: + - 角色 + /v1/role/permissions: + get: consumes: - application/json - description: 示例接口 + description: 获取角色权限 parameters: - - description: 生产者消息 + - description: 请求体 format: string in: body name: data required: true schema: - $ref: '#/definitions/v1.ProducerExampleRequest' + $ref: '#/definitions/v1.RoleGetPermissionsRequest' produces: - application/json responses: @@ -210,14 +1461,21 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 示例接口 + summary: 获取角色权限 tags: - - 示例 - /v1/trace/example: + - 角色 post: consumes: - application/json - description: 示例接口 + description: 授权角色权限 + parameters: + - description: 请求体 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.RoleGrantPermissionsRequest' produces: - application/json responses: @@ -251,22 +1509,68 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 示例接口 + summary: 授权角色权限 tags: - - 示例 - /v1/user: - post: + - 角色 + /v1/roles: + get: consumes: - - application/json - description: 创建用户 + - application/x-www-form-urlencoded + description: 角色列表 parameters: - - description: 用户信息 + - description: 查询字符串 format: string - in: body - name: data - required: true - schema: - $ref: '#/definitions/v1.UserCreateRequest' + in: query + name: keyword + type: string + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + items: + $ref: '#/definitions/v1.RoleInfo' + type: array + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 列表 + tags: + - 角色 + /v1/trace/example: + post: + consumes: + - application/json + description: 示例接口 produces: - application/json responses: @@ -300,18 +1604,18 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 创建用户 + summary: 示例接口 tags: - - 用户 - /v1/user/{id}: + - 示例 + /v1/user: delete: consumes: - text/plain - description: 删除用户 + description: 用户删除 parameters: - - description: 用户 id + - description: 权限 id format: uint - in: path + in: query minimum: 1 name: id required: true @@ -349,7 +1653,7 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 删除用户 + summary: 用户删除 tags: - 用户 get: @@ -357,9 +1661,9 @@ paths: - text/plain description: 用户详情 parameters: - - description: 用户 id + - description: 权限 id format: uint - in: path + in: query minimum: 1 name: id required: true @@ -405,25 +1709,170 @@ paths: summary: 用户详情 tags: - 用户 + post: + consumes: + - application/json + description: 用户创建 + parameters: + - description: 权限信息 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.UserCreateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 用户创建 + tags: + - 用户 put: consumes: - application/json - description: 更新用户 + description: 用户更新 parameters: - - description: 用户 id - format: uint - in: path - minimum: 1 - name: id + - description: 权限信息 + format: string + in: body + name: data required: true - type: integer - - description: 用户信息 + schema: + $ref: '#/definitions/v1.UserUpdateRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + $ref: '#/definitions/example.Success' + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 用户更新 + tags: + - 用户 + /v1/user/roles: + get: + consumes: + - application/json + description: 获取用户角色 + parameters: + - description: 请求体 format: string in: body name: data required: true schema: - $ref: '#/definitions/v1.UserCreateRequest' + $ref: '#/definitions/v1.UserGetRoleRequest' + produces: + - application/json + responses: + "200": + description: 成功响应 + schema: + allOf: + - $ref: '#/definitions/example.Success' + - properties: + data: + items: + $ref: '#/definitions/v1.RoleInfo' + type: array + type: object + "400": + description: 客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码) + schema: + $ref: '#/definitions/example.ClientError' + "401": + description: 登陆失效 + schema: + $ref: '#/definitions/example.Unauthorized' + "403": + description: 没有权限 + schema: + $ref: '#/definitions/example.PermissionDenied' + "404": + description: 资源不存在 + schema: + $ref: '#/definitions/example.ResourceNotFound' + "429": + description: 请求过于频繁 + schema: + $ref: '#/definitions/example.TooManyRequest' + "500": + description: 服务器出错 + schema: + $ref: '#/definitions/example.ServerError' + security: + - Authorization: [] + summary: 获取用户角色 + tags: + - 用户 + post: + consumes: + - application/json + description: 分配用户角色 + parameters: + - description: 请求体 + format: string + in: body + name: data + required: true + schema: + $ref: '#/definitions/v1.UserAssignRoleRequest' produces: - application/json responses: @@ -457,7 +1906,7 @@ paths: $ref: '#/definitions/example.ServerError' security: - Authorization: [] - summary: 更新用户 + summary: 分配用户角色 tags: - 用户 /v1/users: @@ -482,7 +1931,7 @@ paths: - properties: data: items: - $ref: '#/definitions/v1.UserListItem' + $ref: '#/definitions/v1.UserInfo' type: array type: object "400": diff --git a/internal/app/adapter/server/http/handler/v1/account.go b/internal/app/adapter/server/http/handler/v1/account.go new file mode 100644 index 00000000..7e835e05 --- /dev/null +++ b/internal/app/adapter/server/http/handler/v1/account.go @@ -0,0 +1,272 @@ +package v1 + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "go-scaffold/internal/app/adapter/server/http/middleware" + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type AccountHandler struct { + controller *controller.AccountController +} + +func NewAccountHandler(controller *controller.AccountController) *AccountHandler { + return &AccountHandler{controller} +} + +type AccountRegisterRequest UserCreateRequest + +type AccountRegisterResponse struct { + User *UserInfo `json:"user"` + Token string `json:"token"` +} + +// Register 注册 +// +// @Router /v1/register [post] +// @Summary 注册 +// @Description 注册 +// @Tags 账号 +// @Accept json +// @Produce json +// @Param data body AccountRegisterRequest true "请求体" format(string) +// @Success 200 {object} example.Success{data=AccountRegisterResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) Register(ctx echo.Context) error { + req := new(AccountRegisterRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.AccountRegisterRequest{ + UserAttr: controller.UserAttr{ + Username: req.Username, + Password: req.Password, + Nickname: req.Nickname, + Phone: req.Phone, + }, + } + ret, err := h.controller.Register(ctx.Request().Context(), r) + if err != nil { + return err + } + + data := AccountRegisterResponse{ + User: &UserInfo{ + ID: ret.User.ID, + Username: ret.User.Username, + Nickname: ret.User.Nickname, + Phone: ret.User.Phone, + }, + Token: ret.Token, + } + + return ctx.JSON(http.StatusOK, data) +} + +type AccountLoginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type AccountLoginResponse struct { + User *UserInfo `json:"user"` + Token string `json:"token"` +} + +// Login 登录 +// +// @Router /v1/login [post] +// @Summary 登录 +// @Description 登录 +// @Tags 账号 +// @Accept json +// @Produce json +// @Param data body AccountLoginRequest true "请求体" format(string) +// @Success 200 {object} example.Success{data=AccountLoginResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) Login(ctx echo.Context) error { + req := new(AccountLoginRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.AccountLoginRequest{ + Username: req.Username, + Password: req.Password, + } + ret, err := h.controller.Login(ctx.Request().Context(), r) + if err != nil { + return err + } + + data := AccountLoginResponse{ + User: &UserInfo{ + ID: ret.User.ID, + Username: ret.User.Username, + Nickname: ret.User.Nickname, + Phone: ret.User.Phone, + }, + Token: ret.Token, + } + + return ctx.JSON(http.StatusOK, data) +} + +// Logout 登出 +// +// @Router /v1/logout [delete] +// @Summary 登出 +// @Description 登出 +// @Tags 账号 +// @Accept plain +// @Produce json +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) Logout(ctx echo.Context) error { + user := ctx.(*middleware.Context).GetUser() + + if err := h.controller.Logout(ctx.Request().Context(), user.ID); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type AccountUpdateProfileRequest struct { + Nickname string `json:"nickname"` +} + +// UpdateProfile 更新账号信息 +// +// @Router /v1/account/profile [put] +// @Summary 更新账号信息 +// @Description 更新账号信息 +// @Tags 账号 +// @Accept json +// @Produce json +// @Param data body AccountUpdateProfileRequest true "请求体" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) UpdateProfile(ctx echo.Context) error { + req := new(AccountUpdateProfileRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + user := ctx.(*middleware.Context).GetUser() + + r := controller.AccountUpdateProfileRequest{ + ID: user.ID, + Nickname: req.Nickname, + } + if err := h.controller.UpdateProfile(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type AccountProfileResponse UserInfo + +// GetProfile 获取账号信息 +// +// @Router /v1/account/profile [get] +// @Summary 获取账号信息 +// @Description 获取账号信息 +// @Tags 账号 +// @Accept plain +// @Produce json +// @Success 200 {object} example.Success{data=AccountProfileResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) GetProfile(ctx echo.Context) error { + user := ctx.(*middleware.Context).GetUser() + + ret, err := h.controller.GetProfile(ctx.Request().Context(), user.ID) + if err != nil { + return err + } + + data := &AccountProfileResponse{ + ID: ret.ID, + Username: ret.Username, + Nickname: ret.Nickname, + Phone: ret.Phone, + } + + return ctx.JSON(http.StatusOK, data) +} + +type AccountGetPermissionsResponse []*PermissionInfo + +// GetPermissions 获取账号权限 +// +// @Router /v1/account/permissions [get] +// @Summary 获取账号权限 +// @Description 获取账号权限 +// @Tags 账号 +// @Accept plain +// @Produce json +// @Success 200 {object} example.Success{data=AccountGetPermissionsResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *AccountHandler) GetPermissions(ctx echo.Context) error { + user := ctx.(*middleware.Context).GetUser() + + ret, err := h.controller.GetPermissions(ctx.Request().Context(), user.ID) + if err != nil { + return err + } + + data := make(AccountGetPermissionsResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &PermissionInfo{ + ID: item.ID, + Key: item.Key, + Name: item.Name, + Desc: item.Desc, + ParentID: item.ParentID, + }) + } + + return ctx.JSON(http.StatusOK, data) +} diff --git a/internal/app/adapter/server/http/handler/v1/greet.go b/internal/app/adapter/server/http/handler/v1/greet.go index def3d14b..5777e17d 100644 --- a/internal/app/adapter/server/http/handler/v1/greet.go +++ b/internal/app/adapter/server/http/handler/v1/greet.go @@ -3,11 +3,10 @@ package v1 import ( "net/http" - "go-scaffold/internal/app/controller" - berr "go-scaffold/internal/app/pkg/errors" - "github.com/labstack/echo/v4" - "github.com/pkg/errors" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" ) type GreetHandler struct { @@ -42,7 +41,7 @@ type GreetHelloResponse struct { func (h *GreetHandler) Hello(ctx echo.Context) error { req := new(controller.GreetHelloRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } ret, err := h.controller.Hello(ctx.Request().Context(), *req) diff --git a/internal/app/adapter/server/http/handler/v1/permission.go b/internal/app/adapter/server/http/handler/v1/permission.go new file mode 100644 index 00000000..ea19cf85 --- /dev/null +++ b/internal/app/adapter/server/http/handler/v1/permission.go @@ -0,0 +1,248 @@ +package v1 + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type PermissionHandler struct { + controller *controller.PermissionController +} + +func NewPermissionHandler(controller *controller.PermissionController) *PermissionHandler { + return &PermissionHandler{controller} +} + +type PermissionInfo struct { + ID int64 `json:"id"` + Key string `json:"key"` + Name string `json:"name"` + Desc string `json:"desc"` + ParentID int64 `json:"parentID"` +} + +type PermissionListRequest struct { + Keyword string `json:"keyword" query:"keyword"` +} + +type PermissionListResponse []*PermissionInfo + +// List 权限列表 +// +// @Router /v1/permissions [get] +// @Summary 权限列表 +// @Description 权限列表 +// @Tags 权限 +// @Accept x-www-form-urlencoded +// @Produce json +// @Param keyword query string false "查询字符串" format(string) +// @Success 200 {object} example.Success{data=PermissionListResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *PermissionHandler) List(ctx echo.Context) error { + req := new(PermissionListRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.PermissionListRequest{ + Keyword: req.Keyword, + } + ret, err := h.controller.List(ctx.Request().Context(), r) + if err != nil { + return err + } + + data := make(PermissionListResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &PermissionInfo{ + ID: item.ID, + Key: item.Key, + Name: item.Name, + Desc: item.Desc, + ParentID: item.ParentID, + }) + } + + return ctx.JSON(http.StatusOK, data) +} + +type PermissionCreateRequest struct { + Key string `json:"key"` + Name string `json:"name"` + Desc string `json:"desc"` + ParentID int64 `json:"parentID"` +} + +// Create 权限创建 +// +// @Router /v1/permission [post] +// @Summary 权限创建 +// @Description 权限创建 +// @Tags 权限 +// @Accept json +// @Produce json +// @Param data body PermissionCreateRequest true "权限信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *PermissionHandler) Create(ctx echo.Context) error { + req := new(PermissionCreateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.PermissionCreateRequest{ + PermissionAttr: controller.PermissionAttr{ + Key: req.Key, + Name: req.Name, + Desc: req.Desc, + ParentID: req.ParentID, + }, + } + if err := h.controller.Create(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type PermissionUpdateRequest struct { + ID int64 `json:"id"` + Key string `json:"key"` + Name string `json:"name"` + Desc string `json:"desc"` + ParentID int64 `json:"parentID"` +} + +// Update 权限更新 +// +// @Router /v1/permission [put] +// @Summary 权限更新 +// @Description 权限更新 +// @Tags 权限 +// @Accept json +// @Produce json +// @Param data body PermissionUpdateRequest true "权限信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *PermissionHandler) Update(ctx echo.Context) error { + req := new(PermissionUpdateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + p := controller.PermissionUpdateRequest{ + ID: req.ID, + PermissionAttr: controller.PermissionAttr{ + Key: req.Key, + Name: req.Name, + Desc: req.Desc, + ParentID: req.ParentID, + }, + } + if err := h.controller.Update(ctx.Request().Context(), p); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type PermissionDetailRequest struct { + ID int64 `query:"id"` +} + +type PermissionDetailResponse = PermissionInfo + +// Detail 权限详情 +// +// @Router /v1/permission [get] +// @Summary 权限详情 +// @Description 权限详情 +// @Tags 权限 +// @Accept plain +// @Produce json +// @Param id query integer true "权限 id" format(uint) minimum(1) +// @Success 200 {object} example.Success{data=PermissionDetailResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *PermissionHandler) Detail(ctx echo.Context) error { + req := new(PermissionDetailRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + ret, err := h.controller.Detail(ctx.Request().Context(), req.ID) + if err != nil { + return err + } + + data := &PermissionDetailResponse{ + ID: ret.ID, + Key: ret.Key, + Name: ret.Name, + Desc: ret.Desc, + ParentID: ret.ParentID, + } + + return ctx.JSON(http.StatusOK, data) +} + +type PermissionDeleteRequest struct { + ID int64 `query:"id"` +} + +// Delete 权限删除 +// +// @Router /v1/permission [delete] +// @Summary 权限删除 +// @Description 权限删除 +// @Tags 权限 +// @Accept plain +// @Produce json +// @Param id query integer true "权限 id" format(uint) minimum(1) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *PermissionHandler) Delete(ctx echo.Context) error { + req := new(PermissionDeleteRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + if err := h.controller.Delete(ctx.Request().Context(), req.ID); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} diff --git a/internal/app/adapter/server/http/handler/v1/producer.go b/internal/app/adapter/server/http/handler/v1/producer.go index 7ebec71c..310dc041 100644 --- a/internal/app/adapter/server/http/handler/v1/producer.go +++ b/internal/app/adapter/server/http/handler/v1/producer.go @@ -3,11 +3,10 @@ package v1 import ( "net/http" - "go-scaffold/internal/app/controller" - berr "go-scaffold/internal/app/pkg/errors" - "github.com/labstack/echo/v4" - "github.com/pkg/errors" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" ) type ProducerHandler struct { @@ -42,7 +41,7 @@ type ProducerExampleRequest struct { func (h *ProducerHandler) Example(ctx echo.Context) error { req := new(controller.ProducerExampleRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } if err := h.controller.Example(ctx.Request().Context(), *req); err != nil { diff --git a/internal/app/adapter/server/http/handler/v1/product.go b/internal/app/adapter/server/http/handler/v1/product.go new file mode 100644 index 00000000..316627c8 --- /dev/null +++ b/internal/app/adapter/server/http/handler/v1/product.go @@ -0,0 +1,241 @@ +package v1 + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type ProductHandler struct { + controller *controller.ProductController +} + +func NewProductHandler(controller *controller.ProductController) *ProductHandler { + return &ProductHandler{controller} +} + +type ProductInfo struct { + ID int64 `json:"id"` + Name string `json:"name"` + Desc string `json:"desc"` + Price int `json:"price"` +} + +type ProductListRequest struct { + Keyword string `json:"keyword" query:"keyword"` +} + +type ProductListResponse []*ProductInfo + +// List 产品列表 +// +// @Router /v1/products [get] +// @Summary 产品列表 +// @Description 产品列表 +// @Tags 产品 +// @Accept x-www-form-urlencoded +// @Produce json +// @Param keyword query string false "查询字符串" format(string) +// @Success 200 {object} example.Success{data=ProductListResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *ProductHandler) List(ctx echo.Context) error { + req := new(ProductListRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.ProductListRequest{ + Keyword: req.Keyword, + } + ret, err := h.controller.List(ctx.Request().Context(), r) + if err != nil { + return err + } + + data := make(ProductListResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &ProductInfo{ + ID: item.ID, + Name: item.Name, + Desc: item.Desc, + Price: item.Price, + }) + } + + return ctx.JSON(http.StatusOK, data) +} + +type ProductCreateRequest struct { + Name string `json:"name"` + Desc string `json:"desc"` + Price int `json:"price"` +} + +// Create 产品创建 +// +// @Router /v1/product [post] +// @Summary 产品创建 +// @Description 产品创建 +// @Tags 产品 +// @Accept json +// @Produce json +// @Param data body ProductCreateRequest true "产品信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *ProductHandler) Create(ctx echo.Context) error { + req := new(ProductCreateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.ProductCreateRequest{ + ProductAttr: controller.ProductAttr{ + Name: req.Name, + Desc: req.Desc, + Price: req.Price, + }, + } + if err := h.controller.Create(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type ProductUpdateRequest struct { + ID int64 `json:"id"` + Name string `json:"name"` + Desc string `json:"desc"` + Price int `json:"price"` +} + +// Update 产品更新 +// +// @Router /v1/product [put] +// @Summary 产品更新 +// @Description 产品更新 +// @Tags 产品 +// @Accept json +// @Produce json +// @Param data body ProductUpdateRequest true "产品信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *ProductHandler) Update(ctx echo.Context) error { + req := new(ProductUpdateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + p := controller.ProductUpdateRequest{ + ID: req.ID, + ProductAttr: controller.ProductAttr{ + Name: req.Name, + Desc: req.Desc, + Price: req.Price, + }, + } + if err := h.controller.Update(ctx.Request().Context(), p); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type ProductDetailRequest struct { + ID int64 `query:"id"` +} + +type ProductDetailResponse = ProductInfo + +// Detail 产品详情 +// +// @Router /v1/product [get] +// @Summary 产品详情 +// @Description 产品详情 +// @Tags 产品 +// @Accept plain +// @Produce json +// @Param id query integer true "产品 id" format(uint) minimum(1) +// @Success 200 {object} example.Success{data=ProductDetailResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *ProductHandler) Detail(ctx echo.Context) error { + req := new(ProductDetailRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + ret, err := h.controller.Detail(ctx.Request().Context(), req.ID) + if err != nil { + return err + } + + data := &ProductDetailResponse{ + ID: ret.ID, + Name: ret.Name, + Desc: ret.Desc, + Price: ret.Price, + } + + return ctx.JSON(http.StatusOK, data) +} + +type ProductDeleteRequest struct { + ID int64 `query:"id"` +} + +// Delete 产品删除 +// +// @Router /v1/product [delete] +// @Summary 产品删除 +// @Description 产品删除 +// @Tags 产品 +// @Accept plain +// @Produce json +// @Param id query integer true "产品 id" format(uint) minimum(1) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *ProductHandler) Delete(ctx echo.Context) error { + req := new(ProductDeleteRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + if err := h.controller.Delete(ctx.Request().Context(), req.ID); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} diff --git a/internal/app/adapter/server/http/handler/v1/role.go b/internal/app/adapter/server/http/handler/v1/role.go new file mode 100644 index 00000000..a70be6eb --- /dev/null +++ b/internal/app/adapter/server/http/handler/v1/role.go @@ -0,0 +1,314 @@ +package v1 + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" +) + +type RoleHandler struct { + controller *controller.RoleController +} + +func NewRoleHandler(controller *controller.RoleController) *RoleHandler { + return &RoleHandler{controller} +} + +type RoleInfo struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + +type RoleListRequest struct { + Keyword string `json:"keyword" query:"keyword"` +} + +type RoleListResponse []*RoleInfo + +// List 角色列表 +// +// @Router /v1/roles [get] +// @Summary 列表 +// @Description 角色列表 +// @Tags 角色 +// @Accept x-www-form-urlencoded +// @Produce json +// @Param keyword query string false "查询字符串" format(string) +// @Success 200 {object} example.Success{data=RoleListResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) List(ctx echo.Context) error { + req := new(RoleListRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.RoleListRequest{ + Keyword: req.Keyword, + } + ret, err := h.controller.List(ctx.Request().Context(), r) + if err != nil { + return err + } + + data := make(RoleListResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &RoleInfo{ + ID: item.ID, + Name: item.Name, + }) + } + + return ctx.JSON(http.StatusOK, data) +} + +type RoleCreateRequest struct { + Name string `json:"name"` +} + +// Create 角色创建 +// +// @Router /v1/role [post] +// @Summary 角色创建 +// @Description 角色创建 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param data body RoleCreateRequest true "权限信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) Create(ctx echo.Context) error { + req := new(RoleCreateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.RoleCreateRequest{ + RoleAttr: controller.RoleAttr{ + Name: req.Name, + }, + } + if err := h.controller.Create(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type RoleUpdateRequest struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + +// Update 角色更新 +// +// @Router /v1/role [put] +// @Summary 角色更新 +// @Description 角色更新 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param data body RoleUpdateRequest true "权限信息" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) Update(ctx echo.Context) error { + req := new(RoleUpdateRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + p := controller.RoleUpdateRequest{ + ID: req.ID, + RoleAttr: controller.RoleAttr{ + Name: req.Name, + }, + } + if err := h.controller.Update(ctx.Request().Context(), p); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type RoleDetailRequest struct { + ID int64 `query:"id"` +} + +type RoleDetailResponse = RoleInfo + +// Detail 角色详情 +// +// @Router /v1/role [get] +// @Summary 角色详情 +// @Description 角色详情 +// @Tags 角色 +// @Accept plain +// @Produce json +// @Param id query integer true "权限 id" format(uint) minimum(1) +// @Success 200 {object} example.Success{data=RoleDetailResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) Detail(ctx echo.Context) error { + req := new(RoleDetailRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + ret, err := h.controller.Detail(ctx.Request().Context(), req.ID) + if err != nil { + return err + } + + data := &RoleDetailResponse{ + ID: ret.ID, + Name: ret.Name, + } + + return ctx.JSON(http.StatusOK, data) +} + +type RoleDeleteRequest struct { + ID int64 `query:"id"` +} + +// Delete 角色删除 +// +// @Router /v1/role [delete] +// @Summary 角色删除 +// @Description 角色删除 +// @Tags 角色 +// @Accept plain +// @Produce json +// @Param id query integer true "权限 id" format(uint) minimum(1) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) Delete(ctx echo.Context) error { + req := new(RoleDeleteRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + if err := h.controller.Delete(ctx.Request().Context(), req.ID); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type RoleGrantPermissionsRequest struct { + Role int64 `json:"role"` + Permissions []int64 `json:"permissions"` +} + +// GrantPermissions 授权角色权限 +// +// @Router /v1/role/permissions [post] +// @Summary 授权角色权限 +// @Description 授权角色权限 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param data body RoleGrantPermissionsRequest true "请求体" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) GrantPermissions(ctx echo.Context) error { + req := new(RoleGrantPermissionsRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.RoleGrantPermissionsRequest{ + Role: req.Role, + Permissions: req.Permissions, + } + if err := h.controller.GrantPermissions(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type RoleGetPermissionsRequest struct { + ID int64 `query:"id"` +} + +type RoleGetPermissionsResponse []*PermissionInfo + +// GetPermissions 获取角色权限 +// +// @Router /v1/role/permissions [get] +// @Summary 获取角色权限 +// @Description 获取角色权限 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param data body RoleGetPermissionsRequest true "请求体" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *RoleHandler) GetPermissions(ctx echo.Context) error { + req := new(RoleGetPermissionsRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + ret, err := h.controller.GetPermissions(ctx.Request().Context(), req.ID) + if err != nil { + return err + } + + data := make(RoleGetPermissionsResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &PermissionInfo{ + ID: item.ID, + Key: item.Key, + Name: item.Name, + Desc: item.Desc, + ParentID: item.ParentID, + }) + } + + return ctx.JSON(http.StatusOK, data) +} diff --git a/internal/app/adapter/server/http/handler/v1/trace.go b/internal/app/adapter/server/http/handler/v1/trace.go index 7b9281c4..bb6e7e56 100644 --- a/internal/app/adapter/server/http/handler/v1/trace.go +++ b/internal/app/adapter/server/http/handler/v1/trace.go @@ -3,15 +3,10 @@ package v1 import ( "context" "fmt" + "log/slog" "math/rand" "net/http" - v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" - "go-scaffold/internal/app/pkg/client" - berr "go-scaffold/internal/app/pkg/errors" - "go-scaffold/internal/config" - "go-scaffold/pkg/trace" - kerr "github.com/go-kratos/kratos/v2/errors" "github.com/labstack/echo/v4" "github.com/pkg/errors" @@ -21,7 +16,12 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/trace" - "golang.org/x/exp/slog" + + v1 "go-scaffold/internal/app/adapter/server/grpc/api/v1" + "go-scaffold/internal/app/pkg/client" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/config" + "go-scaffold/pkg/trace" ) type TraceHandler struct { @@ -91,7 +91,7 @@ func (h *TraceHandler) Example(ctx echo.Context) error { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) - return errors.WithStack(berr.ErrServerError) + return berr.ErrInternalError.WithError(errors.WithStack(err)) } // 携带 baggage 信息 @@ -99,14 +99,14 @@ func (h *TraceHandler) Example(ctx echo.Context) error { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) - return errors.WithStack(berr.ErrServerError) + return berr.ErrInternalError.WithError(errors.WithStack(err)) } bag, err := baggage.New(mem) if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) - return errors.WithStack(berr.ErrServerError) + return berr.ErrInternalError.WithError(errors.WithStack(err)) } reqCtx = baggage.ContextWithBaggage(reqCtx, bag) diff --git a/internal/app/adapter/server/http/handler/v1/user.go b/internal/app/adapter/server/http/handler/v1/user.go index 4824fa59..902ce02b 100644 --- a/internal/app/adapter/server/http/handler/v1/user.go +++ b/internal/app/adapter/server/http/handler/v1/user.go @@ -3,39 +3,32 @@ package v1 import ( "net/http" - "go-scaffold/internal/app/controller" - "go-scaffold/internal/app/domain" - berr "go-scaffold/internal/app/pkg/errors" - "github.com/labstack/echo/v4" - "github.com/pkg/errors" + + "go-scaffold/internal/app/adapter/server/http/pkg/errors" + "go-scaffold/internal/app/controller" ) -// UserHandler 用户处理器 type UserHandler struct { controller *controller.UserController } -// NewUserHandler 构造用户处理器 func NewUserHandler(controller *controller.UserController) *UserHandler { return &UserHandler{controller} } -// UserListRequest 用户列表请求参数 -type UserListRequest struct { - Keyword string `json:"keyword" query:"keyword"` +type UserInfo struct { + ID int64 `json:"id"` + Username string `json:"username"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` } -// UserListItem 用户列表项 -type UserListItem struct { - ID int64 `json:"id"` - Name string `json:"name"` - Age int8 `json:"age"` - Phone string `json:"phone"` +type UserListRequest struct { + Keyword string `json:"keyword" query:"keyword"` } -// UserListResponse 用户列表响应数据 -type UserListResponse []*UserListItem +type UserListResponse []*UserInfo // List 用户列表 // @@ -57,46 +50,46 @@ type UserListResponse []*UserListItem func (h *UserHandler) List(ctx echo.Context) error { req := new(UserListRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } - p := domain.UserListParam{ + r := controller.UserListRequest{ Keyword: req.Keyword, } - ret, err := h.controller.List(ctx.Request().Context(), p) + ret, err := h.controller.List(ctx.Request().Context(), r) if err != nil { return err } data := make(UserListResponse, 0, len(ret)) for _, item := range ret { - data = append(data, &UserListItem{ - ID: item.ID.Int64(), - Name: item.Name, - Age: item.Age, - Phone: item.Phone, + data = append(data, &UserInfo{ + ID: item.ID, + Username: item.Username, + Nickname: item.Nickname, + Phone: item.Phone, }) } return ctx.JSON(http.StatusOK, data) } -// UserCreateRequest 创建用户请求参数 type UserCreateRequest struct { - Name string `json:"name"` - Age int8 `json:"age"` - Phone string `json:"phone"` + Username string `json:"username"` + Password string `json:"password"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` } -// Create 创建用户 +// Create 用户创建 // // @Router /v1/user [post] -// @Summary 创建用户 -// @Description 创建用户 +// @Summary 用户创建 +// @Description 用户创建 // @Tags 用户 // @Accept json // @Produce json -// @Param data body UserCreateRequest true "用户信息" format(string) +// @Param data body UserCreateRequest true "权限信息" format(string) // @Success 200 {object} example.Success "成功响应" // @Failure 500 {object} example.ServerError "服务器出错" // @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" @@ -108,39 +101,41 @@ type UserCreateRequest struct { func (h *UserHandler) Create(ctx echo.Context) error { req := new(UserCreateRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } - p := domain.User{ - Name: req.Name, - Age: req.Age, - Phone: req.Phone, + r := controller.UserCreateRequest{ + UserAttr: controller.UserAttr{ + Username: req.Username, + Password: req.Password, + Nickname: req.Nickname, + Phone: req.Phone, + }, } - if err := h.controller.Create(ctx.Request().Context(), p); err != nil { + if err := h.controller.Create(ctx.Request().Context(), r); err != nil { return err } return ctx.NoContent(http.StatusOK) } -// UserUpdateRequest 更新用户请求参数 type UserUpdateRequest struct { - ID int64 `json:"id" param:"id"` - Name string `json:"name"` - Age int8 `json:"age"` - Phone string `json:"phone"` + ID int64 `json:"id"` + Username string `json:"username"` + Password string `json:"password"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` } -// Update 更新用户 +// Update 用户更新 // -// @Router /v1/user/{id} [put] -// @Summary 更新用户 -// @Description 更新用户 +// @Router /v1/user [put] +// @Summary 用户更新 +// @Description 用户更新 // @Tags 用户 // @Accept json // @Produce json -// @Param id path integer true "用户 id" format(uint) minimum(1) -// @Param data body UserCreateRequest true "用户信息" format(string) +// @Param data body UserUpdateRequest true "权限信息" format(string) // @Success 200 {object} example.Success "成功响应" // @Failure 500 {object} example.ServerError "服务器出错" // @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" @@ -152,14 +147,17 @@ type UserUpdateRequest struct { func (h *UserHandler) Update(ctx echo.Context) error { req := new(UserUpdateRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } - p := domain.User{ - ID: domain.ID(req.ID), - Name: req.Name, - Age: req.Age, - Phone: req.Phone, + p := controller.UserUpdateRequest{ + ID: req.ID, + UserAttr: controller.UserAttr{ + Username: req.Username, + Password: req.Password, + Nickname: req.Nickname, + Phone: req.Phone, + }, } if err := h.controller.Update(ctx.Request().Context(), p); err != nil { return err @@ -168,28 +166,21 @@ func (h *UserHandler) Update(ctx echo.Context) error { return ctx.NoContent(http.StatusOK) } -// UserDetailRequest 用户详情请求参数 type UserDetailRequest struct { - ID int64 `json:"id" param:"id"` + ID int64 `query:"id"` } -// UserDetailResponse 用户详情响应数据 -type UserDetailResponse struct { - ID int64 `json:"id"` - Name string `json:"name"` - Age int8 `json:"age"` - Phone string `json:"phone"` -} +type UserDetailResponse = UserInfo // Detail 用户详情 // -// @Router /v1/user/{id} [get] +// @Router /v1/user [get] // @Summary 用户详情 // @Description 用户详情 // @Tags 用户 // @Accept plain // @Produce json -// @Param id path integer true "用户 id" format(uint) minimum(1) +// @Param id query integer true "权限 id" format(uint) minimum(1) // @Success 200 {object} example.Success{data=UserDetailResponse} "成功响应" // @Failure 500 {object} example.ServerError "服务器出错" // @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" @@ -201,38 +192,37 @@ type UserDetailResponse struct { func (h *UserHandler) Detail(ctx echo.Context) error { req := new(UserDetailRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } - ret, err := h.controller.Detail(ctx.Request().Context(), domain.ID(req.ID)) + ret, err := h.controller.Detail(ctx.Request().Context(), req.ID) if err != nil { return err } data := &UserDetailResponse{ - ID: ret.ID.Int64(), - Name: ret.Name, - Age: ret.Age, - Phone: ret.Phone, + ID: ret.ID, + Username: ret.Username, + Nickname: ret.Nickname, + Phone: ret.Phone, } return ctx.JSON(http.StatusOK, data) } -// UserDeleteRequest 删除用户请求参数 type UserDeleteRequest struct { - ID int64 `json:"id" param:"id"` + ID int64 `query:"id"` } -// Delete 删除用户 +// Delete 用户删除 // -// @Router /v1/user/{id} [delete] -// @Summary 删除用户 -// @Description 删除用户 +// @Router /v1/user [delete] +// @Summary 用户删除 +// @Description 用户删除 // @Tags 用户 // @Accept plain // @Produce json -// @Param id path integer true "用户 id" format(uint) minimum(1) +// @Param id query integer true "权限 id" format(uint) minimum(1) // @Success 200 {object} example.Success "成功响应" // @Failure 500 {object} example.ServerError "服务器出错" // @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" @@ -242,14 +232,98 @@ type UserDeleteRequest struct { // @Failure 429 {object} example.TooManyRequest "请求过于频繁" // @Security Authorization func (h *UserHandler) Delete(ctx echo.Context) error { - req := new(UserDeleteRequest) + req := new(PermissionDeleteRequest) if err := ctx.Bind(req); err != nil { - return errors.Wrap(err, berr.ErrBadRequest.Error()) + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() } - if err := h.controller.Delete(ctx.Request().Context(), domain.ID(req.ID)); err != nil { + if err := h.controller.Delete(ctx.Request().Context(), req.ID); err != nil { return err } return ctx.NoContent(http.StatusOK) } + +type UserAssignRoleRequest struct { + User int64 `json:"user"` + Roles []int64 `json:"roles"` +} + +// AssignRoles 分配用户角色 +// +// @Router /v1/user/roles [post] +// @Summary 分配用户角色 +// @Description 分配用户角色 +// @Tags 用户 +// @Accept json +// @Produce json +// @Param data body UserAssignRoleRequest true "请求体" format(string) +// @Success 200 {object} example.Success "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *UserHandler) AssignRoles(ctx echo.Context) error { + req := new(UserAssignRoleRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + r := controller.UserAssignRoleRequest{ + User: req.User, + Roles: req.Roles, + } + if err := h.controller.AssignRoles(ctx.Request().Context(), r); err != nil { + return err + } + + return ctx.NoContent(http.StatusOK) +} + +type UserGetRoleRequest struct { + ID int64 `query:"id"` +} + +type UserGetRoleResponse []*RoleInfo + +// GetRoles 获取用户角色 +// +// @Router /v1/user/roles [get] +// @Summary 获取用户角色 +// @Description 获取用户角色 +// @Tags 用户 +// @Accept json +// @Produce json +// @Param data body UserGetRoleRequest true "请求体" format(string) +// @Success 200 {object} example.Success{data=UserGetRoleResponse} "成功响应" +// @Failure 500 {object} example.ServerError "服务器出错" +// @Failure 400 {object} example.ClientError "客户端请求错误(code 类型应为 int,string 仅为了表达多个错误码)" +// @Failure 401 {object} example.Unauthorized "登陆失效" +// @Failure 403 {object} example.PermissionDenied "没有权限" +// @Failure 404 {object} example.ResourceNotFound "资源不存在" +// @Failure 429 {object} example.TooManyRequest "请求过于频繁" +// @Security Authorization +func (h *UserHandler) GetRoles(ctx echo.Context) error { + req := new(UserGetRoleRequest) + if err := ctx.Bind(req); err != nil { + return errors.WrapHTTTPError(err.(*echo.HTTPError)).SetMessage("request parameter parsing error").Unwrap() + } + + ret, err := h.controller.GetRoles(ctx.Request().Context(), req.ID) + if err != nil { + return err + } + + data := make(UserGetRoleResponse, 0, len(ret)) + for _, item := range ret { + data = append(data, &RoleInfo{ + ID: item.ID, + Name: item.Name, + }) + } + + return ctx.JSON(http.StatusOK, data) +} diff --git a/internal/app/adapter/server/http/http.go b/internal/app/adapter/server/http/http.go index 3ea3a3b6..1af07c8d 100644 --- a/internal/app/adapter/server/http/http.go +++ b/internal/app/adapter/server/http/http.go @@ -7,12 +7,12 @@ import ( "net/http" "time" + khttp "github.com/go-kratos/kratos/v2/transport/http" + "github.com/google/wire" + v1 "go-scaffold/internal/app/adapter/server/http/handler/v1" "go-scaffold/internal/app/adapter/server/http/router" "go-scaffold/internal/config" - - khttp "github.com/go-kratos/kratos/v2/transport/http" - "github.com/google/wire" ) // @title API 接口文档 @@ -32,8 +32,12 @@ var ProviderSet = wire.NewSet( // handler v1.NewGreetHandler, v1.NewTraceHandler, - v1.NewUserHandler, v1.NewProducerHandler, + v1.NewAccountHandler, + v1.NewUserHandler, + v1.NewRoleHandler, + v1.NewPermissionHandler, + v1.NewProductHandler, // router router.New, router.NewAPIGroup, diff --git a/internal/app/adapter/server/http/middleware/auth.go b/internal/app/adapter/server/http/middleware/auth.go new file mode 100644 index 00000000..3f0c331d --- /dev/null +++ b/internal/app/adapter/server/http/middleware/auth.go @@ -0,0 +1,117 @@ +package middleware + +import ( + "context" + "net/http" + "strings" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + + "go-scaffold/internal/app/domain" +) + +const ( + defaultTokenHeaderKey = "Authorization" + defaultTokenHeaderValuePrefix = "Bearer " +) + +type TokenValidator interface { + ValidateToken(ctx context.Context, token string) (*domain.UserProfile, error) +} + +type TokenRefresher interface { + RefreshToken(ctx context.Context, userProfile domain.UserProfile, token string) (string, error) +} + +type AuthConfig struct { + // Skipper defines a function to skip middleware. + Skipper middleware.Skipper + + // HeaderKey key that get the token from header + // if not specified,default: "Authorization" + HeaderKey string + + // HeaderValuePrefix header value prefix of token + // if not specified,default: "Bearer " + HeaderValuePrefix string + + // TokenValidator handle the validate of token + TokenValidator TokenValidator + + // TokenRefresher handle the refresh of token + TokenRefresher TokenRefresher +} + +func (c *AuthConfig) WithSkipper(skipper middleware.Skipper) *AuthConfig { + c.Skipper = skipper + return c +} + +func (c *AuthConfig) WithHeaderKey(key string) *AuthConfig { + c.HeaderKey = key + return c +} + +func (c *AuthConfig) WithHeaderValuePrefix(prefix string) *AuthConfig { + c.HeaderValuePrefix = prefix + return c +} + +func (c *AuthConfig) WithTokenValidator(handler TokenValidator) *AuthConfig { + c.TokenValidator = handler + return c +} + +func (c *AuthConfig) WithTokenRefresher(handler TokenRefresher) *AuthConfig { + c.TokenRefresher = handler + return c +} + +func NewDefaultAuthConfig() *AuthConfig { + return &AuthConfig{ + Skipper: middleware.DefaultSkipper, + HeaderKey: defaultTokenHeaderKey, + HeaderValuePrefix: defaultTokenHeaderValuePrefix, + } +} + +func Auth(config AuthConfig) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if config.Skipper(c) { + return next(c) + } + + token := c.Request().Header.Get(config.HeaderKey) + + if token == "" { + return echo.NewHTTPError(http.StatusUnauthorized, "missing token") + } + + if config.HeaderValuePrefix != "" { + token = strings.TrimPrefix(token, config.HeaderValuePrefix) + } + + if config.TokenValidator == nil { + return next(c) + } + + user, err := config.TokenValidator.ValidateToken(c.Request().Context(), token) + if err != nil { + return echo.NewHTTPError(http.StatusUnauthorized, "malformed token").SetInternal(err) + } + + if config.TokenRefresher != nil { + refreshedToken, err := config.TokenRefresher.RefreshToken(c.Request().Context(), *user, token) + if err != nil { + return err + } + + c.Response().Header().Set(config.HeaderKey, refreshedToken) + } + + return next(&Context{c, *user}) + } + } +} diff --git a/internal/app/adapter/server/http/middleware/body.go b/internal/app/adapter/server/http/middleware/body.go index 1a816c75..7bac9696 100644 --- a/internal/app/adapter/server/http/middleware/body.go +++ b/internal/app/adapter/server/http/middleware/body.go @@ -2,10 +2,10 @@ package middleware // Body formatted json response type Body struct { - ErrNo int `json:"errNo,omitempty"` - ErrMsg any `json:"errMsg,omitempty"` - Stack any `json:"stack,omitempty"` - Data any `json:"data,omitempty"` + ErrNo int `json:"errNo,omitempty"` + ErrMsg string `json:"errMsg,omitempty"` + Stack any `json:"stack,omitempty"` + Data any `json:"data,omitempty"` } // NewDefaultBody return json response body @@ -18,7 +18,7 @@ func (b *Body) WithErrNo(code int) *Body { return b } -func (b *Body) WithErrMsg(msg any) *Body { +func (b *Body) WithErrMsg(msg string) *Body { b.ErrMsg = msg return b } diff --git a/internal/app/adapter/server/http/middleware/context.go b/internal/app/adapter/server/http/middleware/context.go new file mode 100644 index 00000000..9f9d5714 --- /dev/null +++ b/internal/app/adapter/server/http/middleware/context.go @@ -0,0 +1,23 @@ +package middleware + +import ( + "github.com/labstack/echo/v4" + + "go-scaffold/internal/app/domain" +) + +// Context user profile context +type Context struct { + echo.Context + user domain.UserProfile +} + +// GetUser get user profile from context +func (u *Context) GetUser() domain.UserProfile { + return u.user +} + +// SetUser set user profile to context +func (u *Context) SetUser(user domain.UserProfile) { + u.user = user +} diff --git a/internal/app/adapter/server/http/middleware/error_handler.go b/internal/app/adapter/server/http/middleware/error_handler.go index 227f1033..c0a87748 100644 --- a/internal/app/adapter/server/http/middleware/error_handler.go +++ b/internal/app/adapter/server/http/middleware/error_handler.go @@ -1,21 +1,21 @@ package middleware import ( + "fmt" + "log/slog" "net/http" - berr "go-scaffold/internal/app/pkg/errors" - uerr "go-scaffold/pkg/errors" - "github.com/labstack/echo/v4" - "github.com/pkg/errors" "github.com/samber/lo" - "golang.org/x/exp/slog" + + berr "go-scaffold/internal/app/pkg/errors" + uerr "go-scaffold/pkg/errors" ) // ErrorHandler is HTTP error handler. It sends a JSON response func ErrorHandler(debug bool, logger *slog.Logger) echo.HTTPErrorHandler { return func(err error, ctx echo.Context) { - logger.Error("handle request error", err) + logger.Error("handle request error", slog.Any("error", err)) if ctx.Response().Committed { return @@ -23,26 +23,35 @@ func ErrorHandler(debug bool, logger *slog.Logger) echo.HTTPErrorHandler { var ( bc int - hintMsg any + hintMsg string statusCode int ) - ce := errors.Cause(err) - - switch er := ce.(type) { + switch ae := err.(type) { case *echo.HTTPError: - statusCode = er.Code - bc = berr.ErrServerError.Code() + statusCode = ae.Code + bc = berr.ErrInternalError.Code() if c, ok := lo.Invert(errHttpStatusCode)[statusCode]; ok { bc = c } - hintMsg = er.Message + hintMsg = fmt.Sprintf("%v", ae.Message) + if une := ae.Unwrap(); une != nil { + err = une + if ce, ok := une.(*berr.Error); ok { + if ce.Unwrap() != nil { + err = ce.Unwrap() + } + } + } case *berr.Error: - bc = er.Code() - hintMsg = hintMessage(er.Label()) + bc = ae.Code() + hintMsg = ae.Msg() statusCode = httpStatusCode(bc) + if ae.Unwrap() != nil { + err = ae.Unwrap() + } default: - de := berr.ErrServerError + de := berr.ErrInternalError bc = de.Code() hintMsg = hintMessage(de.Label()) statusCode = httpStatusCode(bc) @@ -53,7 +62,11 @@ func ErrorHandler(debug bool, logger *slog.Logger) echo.HTTPErrorHandler { WithErrMsg(hintMsg) if debug { - responseBody.WithErrMsg(err.Error()) + wrapMsg := err.Error() + if hintMsg != "" { + wrapMsg = fmt.Sprintf("%s: %s", hintMsg, err) + } + responseBody.WithErrMsg(wrapMsg) stack := uerr.ErrorStackTrace(err) if stack != nil { @@ -67,19 +80,19 @@ func ErrorHandler(debug bool, logger *slog.Logger) echo.HTTPErrorHandler { err = ctx.JSON(statusCode, responseBody) } if err != nil { - logger.Error("send error response error", err) + logger.Error("send error response error", slog.Any("error", err)) } } } var errHttpStatusCode = map[int]int{ - berr.ErrServerError.Code(): http.StatusInternalServerError, - berr.ErrBadRequest.Code(): http.StatusBadRequest, - berr.ErrValidateError.Code(): http.StatusBadRequest, - berr.ErrUnauthorized.Code(): http.StatusUnauthorized, - berr.ErrPermissionDenied.Code(): http.StatusForbidden, - berr.ErrResourceNotFound.Code(): http.StatusNotFound, - berr.ErrTooManyRequest.Code(): http.StatusTooManyRequests, + berr.ErrInternalError.Code(): http.StatusInternalServerError, + berr.ErrBadCall.Code(): http.StatusBadRequest, + berr.ErrValidateError.Code(): http.StatusBadRequest, + berr.ErrInvalidAuthorized.Code(): http.StatusUnauthorized, + berr.ErrAccessDenied.Code(): http.StatusForbidden, + berr.ErrResourceNotFound.Code(): http.StatusNotFound, + berr.ErrCallsTooFrequently.Code(): http.StatusTooManyRequests, } func httpStatusCode(c int) int { @@ -87,13 +100,13 @@ func httpStatusCode(c int) int { } var errHintMsg = map[string]string{ - berr.ErrServerError.Label(): "服务器出错", - berr.ErrBadRequest.Label(): "客户端请求错误", - berr.ErrValidateError.Label(): "参数校验错误", - berr.ErrUnauthorized.Label(): "未经授权", - berr.ErrPermissionDenied.Label(): "暂无权限", - berr.ErrResourceNotFound.Label(): "资源不存在", - berr.ErrTooManyRequest.Label(): "请求过于频繁", + berr.ErrInternalError.Label(): "服务器出错", + berr.ErrBadCall.Label(): "客户端请求错误", + berr.ErrValidateError.Label(): "参数校验错误", + berr.ErrInvalidAuthorized.Label(): "未经授权", + berr.ErrAccessDenied.Label(): "暂无权限", + berr.ErrResourceNotFound.Label(): "资源不存在", + berr.ErrCallsTooFrequently.Label(): "请求太频繁", } func hintMessage(l string) string { diff --git a/internal/app/adapter/server/http/middleware/logger.go b/internal/app/adapter/server/http/middleware/logger.go index 5913012c..efe5b477 100644 --- a/internal/app/adapter/server/http/middleware/logger.go +++ b/internal/app/adapter/server/http/middleware/logger.go @@ -1,9 +1,10 @@ package middleware import ( + "log/slog" + "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" - "golang.org/x/exp/slog" ) // Logger request logger middleware diff --git a/internal/app/adapter/server/http/middleware/permission.go b/internal/app/adapter/server/http/middleware/permission.go new file mode 100644 index 00000000..e26e6d7a --- /dev/null +++ b/internal/app/adapter/server/http/middleware/permission.go @@ -0,0 +1,63 @@ +package middleware + +import ( + "context" + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +type PermissionValidator interface { + ValidatePermission(ctx context.Context, user int64, permissionKey string) (bool, error) +} + +type PermissionConfig struct { + // Skipper defines a function to skip middleware. + Skipper middleware.Skipper + + // PermissionValidator handle the validate of permission + PermissionValidator PermissionValidator +} + +func (c *PermissionConfig) WithSkipper(skipper middleware.Skipper) *PermissionConfig { + c.Skipper = skipper + return c +} + +func (c *PermissionConfig) WithValidator(handler PermissionValidator) *PermissionConfig { + c.PermissionValidator = handler + return c +} + +func NewDefaultPermissionConfig() *PermissionConfig { + return &PermissionConfig{ + Skipper: middleware.DefaultSkipper, + } +} + +func Permission(config PermissionConfig) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if config.Skipper(c) { + return next(c) + } + + if config.PermissionValidator != nil { + user := c.(*Context).GetUser() + permissionKey := fmt.Sprintf("%s %s", c.Request().Method, c.Path()) + + result, err := config.PermissionValidator.ValidatePermission(c.Request().Context(), user.ID, permissionKey) + if err != nil { + return err + } + if !result { + return echo.NewHTTPError(http.StatusForbidden, "access denied") + } + } + + return next(c) + } + } +} diff --git a/internal/app/adapter/server/http/middleware/recover.go b/internal/app/adapter/server/http/middleware/recover.go index ace6c3cd..9df1b624 100644 --- a/internal/app/adapter/server/http/middleware/recover.go +++ b/internal/app/adapter/server/http/middleware/recover.go @@ -2,13 +2,13 @@ package middleware import ( "fmt" + "log/slog" "net/http" - uerr "go-scaffold/pkg/errors" - "github.com/labstack/echo/v4" "github.com/pkg/errors" - "golang.org/x/exp/slog" + + uerr "go-scaffold/pkg/errors" ) // Recover returns a recover middleware @@ -30,7 +30,7 @@ func Recover(logger *slog.Logger) echo.MiddlewareFunc { err = errors.WithStack(err) } - logger.Error("panic recover", err) + logger.Error("panic recover", slog.Any("error", err)) c.Error(err) } diff --git a/internal/app/adapter/server/http/pkg/errors/errors.go b/internal/app/adapter/server/http/pkg/errors/errors.go new file mode 100644 index 00000000..7b60a547 --- /dev/null +++ b/internal/app/adapter/server/http/pkg/errors/errors.go @@ -0,0 +1,24 @@ +package errors + +import ( + "github.com/labstack/echo/v4" + "github.com/pkg/errors" +) + +type HTTPError struct { + *echo.HTTPError +} + +func WrapHTTTPError(err *echo.HTTPError) *HTTPError { + err.Internal = errors.WithStack(err.Internal) + return &HTTPError{err} +} + +func (e *HTTPError) SetMessage(message string) *HTTPError { + e.Message = message + return e +} + +func (e *HTTPError) Unwrap() *echo.HTTPError { + return e.HTTPError +} diff --git a/internal/app/adapter/server/http/router/api_group.go b/internal/app/adapter/server/http/router/api_group.go index 74d5233d..4df9256d 100644 --- a/internal/app/adapter/server/http/router/api_group.go +++ b/internal/app/adapter/server/http/router/api_group.go @@ -1,29 +1,22 @@ package router import ( + "log/slog" "net/http" - "go-scaffold/internal/app/adapter/server/http/api/docs" - "go-scaffold/internal/config" - "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" echoSwagger "github.com/swaggo/echo-swagger" - "golang.org/x/exp/slog" -) -// optional middleware (prevent deletion by formatters) -// "github.com/casbin/casbin/v2" -// casbinmw "github.com/labstack/echo-contrib/casbin" -// jwtmw "github.com/labstack/echo-jwt/v4" + "go-scaffold/internal/app/adapter/server/http/api/docs" + "go-scaffold/internal/config" +) // ApiGroup api routing group type ApiGroup struct { - env config.Env - logger *slog.Logger - hsConf config.HTTPServer - // jwtConf config.JWT // optional jwt middleware - // enforcer *casbin.Enforcer // optional casbin middleware + env config.Env + logger *slog.Logger + hsConf config.HTTPServer apiV1Group *ApiV1Group group *echo.Group @@ -35,16 +28,12 @@ func NewAPIGroup( env config.Env, logger *slog.Logger, hsConf config.HTTPServer, - // jwtConf config.JWT, // optional jwt middleware - // enforcer *casbin.Enforcer, // optional casbin middleware apiV1Group *ApiV1Group, ) *ApiGroup { return &ApiGroup{ - env: env, - logger: logger, - hsConf: hsConf, - // jwtConf: jwtConf, // optional jwt middleware - // enforcer: enforcer, // optional casbin middleware + env: env, + logger: logger, + hsConf: hsConf, apiV1Group: apiV1Group, } } @@ -58,14 +47,6 @@ func (g *ApiGroup) setup(prefix string, rg *echo.Group) { func (g *ApiGroup) useMiddlewares() { // allowed to cross g.group.Use(middleware.CORS()) - - // g.group.Use(jwtmw.JWT([]byte(g.jwtConf.Key))) // optional jwt middleware - // optional casbin middleware - // if err := g.enforcer.LoadPolicy(); err != nil { - // g.logger.Error("load casbin policy error", err) - // } else { - // g.group.Use(casbinmw.Middleware(g.enforcer)) - // } } func (g *ApiGroup) useRoutes(e *echo.Echo) { diff --git a/internal/app/adapter/server/http/router/api_v1_group.go b/internal/app/adapter/server/http/router/api_v1_group.go index 737134fc..926fc70a 100644 --- a/internal/app/adapter/server/http/router/api_v1_group.go +++ b/internal/app/adapter/server/http/router/api_v1_group.go @@ -1,34 +1,56 @@ package router import ( - v1 "go-scaffold/internal/app/adapter/server/http/handler/v1" - "github.com/labstack/echo/v4" + + v1 "go-scaffold/internal/app/adapter/server/http/handler/v1" + imiddleware "go-scaffold/internal/app/adapter/server/http/middleware" + "go-scaffold/internal/app/controller" ) // ApiV1Group v1 API routing group type ApiV1Group struct { - greetHandler *v1.GreetHandler - traceHandler *v1.TraceHandler - producerHandler *v1.ProducerHandler - userHandler *v1.UserHandler - group *echo.Group + accountTokenController *controller.AccountTokenController + accountPermissionController *controller.AccountPermissionController + + greetHandler *v1.GreetHandler + traceHandler *v1.TraceHandler + producerHandler *v1.ProducerHandler + accountHandler *v1.AccountHandler + userHandler *v1.UserHandler + roleHandler *v1.RoleHandler + permissionHandler *v1.PermissionHandler + productHandler *v1.ProductHandler + + group *echo.Group basePath string } // NewAPIV1Group return *ApiV1Group func NewAPIV1Group( + accountTokenController *controller.AccountTokenController, + accountPermissionController *controller.AccountPermissionController, greetHandler *v1.GreetHandler, traceHandler *v1.TraceHandler, producerHandler *v1.ProducerHandler, + accountHandler *v1.AccountHandler, userHandler *v1.UserHandler, + roleHandler *v1.RoleHandler, + permissionHandler *v1.PermissionHandler, + productHandler *v1.ProductHandler, ) *ApiV1Group { return &ApiV1Group{ - greetHandler: greetHandler, - traceHandler: traceHandler, - producerHandler: producerHandler, - userHandler: userHandler, + accountTokenController: accountTokenController, + accountPermissionController: accountPermissionController, + greetHandler: greetHandler, + traceHandler: traceHandler, + productHandler: productHandler, + accountHandler: accountHandler, + userHandler: userHandler, + roleHandler: roleHandler, + permissionHandler: permissionHandler, + producerHandler: producerHandler, } } @@ -43,9 +65,49 @@ func (g *ApiV1Group) useRoutes() { g.group.POST("/trace/example", g.traceHandler.Example) g.group.POST("/producer/example", g.producerHandler.Example) - g.group.GET("/users", g.userHandler.List) - g.group.GET("/user/:id", g.userHandler.Detail) - g.group.POST("/user", g.userHandler.Create) - g.group.PUT("/user/:id", g.userHandler.Update) - g.group.DELETE("/user/:id", g.userHandler.Delete) + g.group.POST("/register", g.accountHandler.Register) + g.group.POST("/login", g.accountHandler.Login) + + g.group.Use(imiddleware.Auth(*imiddleware.NewDefaultAuthConfig(). + WithTokenValidator(g.accountTokenController). + WithTokenRefresher(g.accountTokenController), + )) + { + g.group.DELETE("/logout", g.accountHandler.Logout) + g.group.PUT("/account/profile", g.accountHandler.UpdateProfile) + g.group.GET("/account/profile", g.accountHandler.GetProfile) + g.group.GET("/account/permissions", g.accountHandler.GetPermissions) + + g.group.Use(imiddleware.Permission(*imiddleware.NewDefaultPermissionConfig(). + WithValidator(g.accountPermissionController), + )) + + g.group.GET("/users", g.userHandler.List) + g.group.GET("/user", g.userHandler.Detail) + g.group.POST("/user", g.userHandler.Create) + g.group.PUT("/user", g.userHandler.Update) + g.group.DELETE("/user", g.userHandler.Delete) + g.group.GET("/user/roles", g.userHandler.GetRoles) + g.group.POST("/user/roles", g.userHandler.AssignRoles) + + g.group.GET("/roles", g.roleHandler.List) + g.group.GET("/role", g.roleHandler.Detail) + g.group.POST("/role", g.roleHandler.Create) + g.group.PUT("/role", g.roleHandler.Update) + g.group.DELETE("/role", g.roleHandler.Delete) + g.group.GET("/role/permissions", g.roleHandler.GetPermissions) + g.group.POST("/role/permissions", g.roleHandler.GrantPermissions) + + g.group.GET("/permissions", g.permissionHandler.List) + g.group.GET("/permission", g.permissionHandler.Detail) + g.group.POST("/permission", g.permissionHandler.Create) + g.group.PUT("/permission", g.permissionHandler.Update) + g.group.DELETE("/permission", g.permissionHandler.Delete) + + g.group.GET("/products", g.productHandler.List) + g.group.GET("/product", g.productHandler.Detail) + g.group.POST("/product", g.productHandler.Create) + g.group.PUT("/product", g.productHandler.Update) + g.group.DELETE("/product", g.productHandler.Delete) + } } diff --git a/internal/app/adapter/server/http/router/router.go b/internal/app/adapter/server/http/router/router.go index b9b254ad..81ff9877 100644 --- a/internal/app/adapter/server/http/router/router.go +++ b/internal/app/adapter/server/http/router/router.go @@ -1,16 +1,16 @@ package router import ( + "log/slog" "net/http" "strings" - imiddleware "go-scaffold/internal/app/adapter/server/http/middleware" - "go-scaffold/internal/config" - "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" - "golang.org/x/exp/slog" + + imiddleware "go-scaffold/internal/app/adapter/server/http/middleware" + "go-scaffold/internal/config" ) type router struct { diff --git a/internal/app/adapter/server/server.go b/internal/app/adapter/server/server.go index 6f93e374..f8e25763 100644 --- a/internal/app/adapter/server/server.go +++ b/internal/app/adapter/server/server.go @@ -4,15 +4,15 @@ import ( "context" "os" - gserv "go-scaffold/internal/app/adapter/server/grpc" - hserv "go-scaffold/internal/app/adapter/server/http" - "go-scaffold/internal/config" - "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/transport" "github.com/go-kratos/kratos/v2/transport/grpc" "github.com/go-kratos/kratos/v2/transport/http" "github.com/google/wire" + + gserv "go-scaffold/internal/app/adapter/server/grpc" + hserv "go-scaffold/internal/app/adapter/server/http" + "go-scaffold/internal/config" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/app.go b/internal/app/app.go index 3d7a9a9d..c1aede69 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -1,13 +1,13 @@ package app import ( + "github.com/google/wire" + "go-scaffold/internal/app/adapter" "go-scaffold/internal/app/controller" "go-scaffold/internal/app/pkg" "go-scaffold/internal/app/repository" "go-scaffold/internal/app/usecase" - - "github.com/google/wire" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/controller/account.go b/internal/app/controller/account.go new file mode 100644 index 00000000..9c050b18 --- /dev/null +++ b/internal/app/controller/account.go @@ -0,0 +1,202 @@ +package controller + +import ( + "context" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/google/uuid" + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/usecase" + "go-scaffold/pkg/validator" +) + +type AccountController struct { + auc usecase.AccountUseCaseInterface + uuc usecase.UserUseCaseInterface + userRepo repository.UserRepositoryInterface +} + +func NewAccountController( + auc usecase.AccountUseCaseInterface, + uuc usecase.UserUseCaseInterface, + userRepo repository.UserRepositoryInterface, +) *AccountController { + return &AccountController{ + auc: auc, + uuc: uuc, + userRepo: userRepo, + } +} + +type AccountRegisterRequest struct { + UserAttr +} + +func (r AccountRegisterRequest) toEntity() domain.User { + return domain.User{ + Username: r.Username, + Password: domain.Plaintext(r.Password).Encrypt(), + Nickname: r.Nickname, + Phone: r.Phone, + Salt: uuid.New().String(), + } +} + +type AccountRegisterResponse struct { + User *domain.UserProfile `json:"user"` + Token string `json:"token"` +} + +func (c *AccountController) Register(ctx context.Context, req AccountRegisterRequest) (*AccountRegisterResponse, error) { + if err := req.Validate(); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + exist, err := c.userRepo.UsernameExist(ctx, req.Username) + if err != nil { + return nil, err + } + if exist { + return nil, berr.ErrBadCall.WithMsg("username already exist").WithError(errors.New("username already exist")) + } + + user, err := c.uuc.Create(ctx, req.toEntity()) + if err != nil { + return nil, err + } + + token, err := c.auc.Login(ctx, *user) + if err != nil { + return nil, err + } + + return &AccountRegisterResponse{ + user.ToProfile(), + token, + }, nil +} + +type AccountLoginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func (r AccountLoginRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Username, + validation.Required.Error("username is required"), + validation.Length(8, 16).Error("username must be 8 ~ 16 characters"), + ), + validation.Field(&r.Password, + validation.Required.Error("password is required"), + validation.Length(8, 18).Error("password must be 8 ~ 18 characters"), + validation.By(validator.PasswordComplexity), + ), + ) +} + +type AccountLoginResponse struct { + User *domain.UserProfile `json:"user"` + Token string `json:"token"` +} + +func (c *AccountController) Login(ctx context.Context, req AccountLoginRequest) (*AccountLoginResponse, error) { + if err := req.Validate(); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + user, err := c.userRepo.FindOneByUsername(ctx, req.Username) + if repository.IsNotFound(err) { + return nil, berr.ErrBadCall.WithMsg("username or password is incorrect").WithError(errors.New("username not exist")) + } else if err != nil { + return nil, err + } + + if !user.Password.Verify(domain.Plaintext(req.Password)) { + return nil, berr.ErrBadCall.WithMsg("username or password is incorrect").WithError(errors.New("password incorrect")) + } + + token, err := c.auc.Login(ctx, *user) + if err != nil { + return nil, err + } + + return &AccountLoginResponse{ + user.ToProfile(), + token, + }, nil +} + +func (c *AccountController) Logout(ctx context.Context, id int64) error { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + user, err := c.userRepo.FindOne(ctx, id) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithMsg("user not exist").WithError(err) + } else if err != nil { + return err + } + + return c.auc.Logout(ctx, *user) +} + +type AccountUpdateProfileRequest struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` +} + +func (r AccountUpdateProfileRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.ID, validation.Required.Error("id is required")), + validation.Field(&r.Nickname, + validation.Required.Error("nickname is required"), + validation.Length(8, 16).Error("nickname must be 8 ~ 16 characters"), + ), + ) +} + +func (c *AccountController) UpdateProfile(ctx context.Context, req AccountUpdateProfileRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + e, err := c.userRepo.FindOne(ctx, req.ID) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + e.Nickname = req.Nickname + + _, err = c.uuc.Update(ctx, *e) + return err +} + +func (c *AccountController) GetProfile(ctx context.Context, id int64) (*domain.UserProfile, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + user, err := c.uuc.Detail(ctx, id) + if repository.IsNotFound(err) { + return nil, berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return nil, err + } + + return user.ToProfile(), nil +} + +func (c *AccountController) GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + return c.uuc.GetPermissions(ctx, id) +} diff --git a/internal/app/controller/account_permission.go b/internal/app/controller/account_permission.go new file mode 100644 index 00000000..dd5ba296 --- /dev/null +++ b/internal/app/controller/account_permission.go @@ -0,0 +1,45 @@ +package controller + +import ( + "context" + "fmt" + + "github.com/casbin/casbin/v2" + "github.com/pkg/errors" + + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" +) + +type AccountPermissionController struct { + roleRepo repository.RoleRepositoryInterface + permissionRepo repository.PermissionRepositoryInterface + enforcer *casbin.Enforcer +} + +func NewAccountPermissionController( + roleRepo repository.RoleRepositoryInterface, + permissionRepo repository.PermissionRepositoryInterface, + enforcer *casbin.Enforcer, +) *AccountPermissionController { + return &AccountPermissionController{ + roleRepo: roleRepo, + permissionRepo: permissionRepo, + enforcer: enforcer, + } +} + +func (c *AccountPermissionController) ValidatePermission(ctx context.Context, user int64, permissionKey string) (bool, error) { + permission, err := c.permissionRepo.FindOneByKey(ctx, permissionKey) + if repository.IsNotFound(err) { + return false, berr.ErrAccessDenied.WithError(err) + } else if err != nil { + return false, err + } + result, err := c.enforcer.Enforce(repository.GetPolicyUser(user), fmt.Sprintf("%d", permission.ID)) + if err != nil { + return false, berr.ErrAccessDenied.WithError(errors.WithStack(err)) + } + + return result, nil +} diff --git a/internal/app/controller/account_token.go b/internal/app/controller/account_token.go new file mode 100644 index 00000000..71c666ca --- /dev/null +++ b/internal/app/controller/account_token.go @@ -0,0 +1,83 @@ +package controller + +import ( + "context" + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/service" + "go-scaffold/internal/app/usecase" +) + +type AccountTokenController struct { + uc usecase.AccountUseCaseInterface + repo repository.UserRepositoryInterface +} + +func NewAccountTokenController( + uc usecase.AccountUseCaseInterface, + repo repository.UserRepositoryInterface, +) *AccountTokenController { + return &AccountTokenController{ + uc: uc, + repo: repo, + } +} + +func (c *AccountTokenController) ValidateToken(ctx context.Context, token string) (*domain.UserProfile, error) { + claims, err := service.ParseAccountTokenUnverified(token) + if err != nil { + return nil, err + } + + user, err := c.repo.FindOne(ctx, claims.Data.UserID) + if repository.IsNotFound(err) { + return nil, berr.ErrInvalidAuthorized.WithError(err) + } else if err != nil { + return nil, err + } + + tokenService := service.NewAccountTokenService(user.Salt) + _, err = tokenService.ValidateToken(token) + if err != nil { + return nil, err + } + + return user.ToProfile(), nil +} + +func (c *AccountTokenController) RefreshToken(ctx context.Context, userProfile domain.UserProfile, token string) (string, error) { + claims, err := service.ParseAccountTokenUnverified(token) + if err != nil { + return "", err + } + + expireDuration := claims.ExpiresAt.Sub(time.Now()) + if expireDuration <= 0 { + return "", berr.ErrInvalidAuthorized.WithError(errors.WithStack(jwt.ErrTokenExpired)) + } + if expireDuration > domain.AccountTokenRefreshDuration { + return token, nil + } + + user := domain.User{ + ID: userProfile.ID, + Username: userProfile.Username, + Nickname: userProfile.Nickname, + Phone: userProfile.Phone, + Salt: uuid.New().String(), + } + + token, err = c.uc.Login(ctx, user) + if err != nil { + return "", err + } + + return token, nil +} diff --git a/internal/app/controller/controller.go b/internal/app/controller/controller.go index 0bd42d70..1e7b35b9 100644 --- a/internal/app/controller/controller.go +++ b/internal/app/controller/controller.go @@ -3,7 +3,13 @@ package controller import "github.com/google/wire" var ProviderSet = wire.NewSet( - NewUserController, NewGreetController, NewProducerController, + NewAccountTokenController, + NewAccountPermissionController, + NewAccountController, + NewUserController, + NewRoleController, + NewPermissionController, + NewProductController, ) diff --git a/internal/app/controller/greet.go b/internal/app/controller/greet.go index 90bf857f..4b78ab71 100644 --- a/internal/app/controller/greet.go +++ b/internal/app/controller/greet.go @@ -4,41 +4,35 @@ import ( "context" "fmt" - berr "go-scaffold/internal/app/pkg/errors" - validation "github.com/go-ozzo/ozzo-validation/v4" "github.com/pkg/errors" + + berr "go-scaffold/internal/app/pkg/errors" ) -// GreetController 示例控制器 type GreetController struct{} -// NewGreetController 构造示例控制器 func NewGreetController() *GreetController { return &GreetController{} } -// GreetHelloRequest 请求参数 type GreetHelloRequest struct { Name string `json:"name" query:"name"` } -// Validate 验证参数 func (r GreetHelloRequest) Validate() error { - return errors.WithStack(validation.ValidateStruct(&r, - validation.Field(&r.Name, validation.Required.Error("名称不能为空")), - )) + return validation.ValidateStruct(&r, + validation.Field(&r.Name, validation.Required.Error("name is required")), + ) } -// GreetHelloResponse 请求响应 type GreetHelloResponse struct { Msg string } -// Hello 示例方法 func (c *GreetController) Hello(ctx context.Context, req GreetHelloRequest) (*GreetHelloResponse, error) { if err := req.Validate(); err != nil { - return nil, errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) } return &GreetHelloResponse{ diff --git a/internal/app/controller/permission.go b/internal/app/controller/permission.go new file mode 100644 index 00000000..a2320eab --- /dev/null +++ b/internal/app/controller/permission.go @@ -0,0 +1,175 @@ +package controller + +import ( + "context" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/usecase" +) + +type PermissionController struct { + uc usecase.PermissionUseCaseInterface + repo repository.PermissionRepositoryInterface +} + +func NewPermissionController( + uc usecase.PermissionUseCaseInterface, + repo repository.PermissionRepositoryInterface, +) *PermissionController { + return &PermissionController{ + uc: uc, + repo: repo, + } +} + +type PermissionAttr struct { + Key string `json:"key"` // 权限标识 + Name string `json:"title"` // 权限 + Desc string `json:"desc"` // 权限描述 + ParentID int64 `json:"parentID"` // 父级权限 id +} + +func (r PermissionAttr) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Key, + validation.Required.Error("key is required"), + validation.Length(1, 128).Error("key must be 1 ~ 128 characters"), + ), + validation.Field(&r.Name, + validation.Length(0, 128).Error("name must be 0 ~ 128 characters"), + ), + validation.Field(&r.Desc, + validation.Length(0, 255).Error("description must be 0 ~ 255 characters"), + ), + ) +} + +type PermissionCreateRequest struct { + PermissionAttr +} + +func (r PermissionCreateRequest) toEntity() domain.Permission { + return domain.Permission{ + Key: r.Key, + Name: r.Name, + Desc: r.Desc, + ParentID: r.ParentID, + } +} + +func (c *PermissionController) Create(ctx context.Context, req PermissionCreateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + exist, err := c.repo.KeyExist(ctx, req.Key) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("permission key already exist").WithError(errors.New("key already exist")) + } + + return c.uc.Create(ctx, req.toEntity()) +} + +type PermissionUpdateRequest struct { + ID int64 `json:"id"` + PermissionAttr +} + +func (r PermissionUpdateRequest) toEntity() domain.Permission { + return domain.Permission{ + ID: r.ID, + Key: r.Key, + Name: r.Name, + Desc: r.Desc, + ParentID: r.ParentID, + } +} + +func (r PermissionUpdateRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.ID, validation.Required.Error("id is required")), + validation.Field(&r.PermissionAttr), + ) +} + +func (c *PermissionController) Update(ctx context.Context, req PermissionUpdateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + permission, err := c.repo.FindOne(ctx, req.ID) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + if req.ParentID == permission.ID { + return berr.ErrBadCall.WithMsg("parent cannot be self").WithError(errors.New("parent cannot be self")) + } + + exist, err := c.repo.KeyExistExcludeID(ctx, req.Key, req.ID) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("permission key already exist").WithError(errors.New("key already exist")) + } + + return c.uc.Update(ctx, req.toEntity()) +} + +func (c *PermissionController) Delete(ctx context.Context, id int64) error { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + permission, err := c.repo.FindOne(ctx, id) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + hasChild, err := c.repo.HasChild(ctx, permission.ID) + if err != nil { + return err + } + if hasChild { + return berr.ErrBadCall.WithMsg("permission has child").WithError(errors.New("permission has child")) + } + + return c.uc.Delete(ctx, *permission) +} + +func (c *PermissionController) Detail(ctx context.Context, id int64) (*domain.Permission, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + permission, err := c.uc.Detail(ctx, id) + if repository.IsNotFound(err) { + return nil, berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return nil, err + } + + return permission, nil +} + +type PermissionListRequest struct { + Keyword string +} + +func (c *PermissionController) List(ctx context.Context, req PermissionListRequest) ([]*domain.Permission, error) { + param := usecase.PermissionListParam{Keyword: req.Keyword} + return c.uc.List(ctx, param) +} diff --git a/internal/app/controller/producer.go b/internal/app/controller/producer.go index 7536ca13..1495dfcc 100644 --- a/internal/app/controller/producer.go +++ b/internal/app/controller/producer.go @@ -5,40 +5,35 @@ import ( "fmt" "time" - berr "go-scaffold/internal/app/pkg/errors" - "go-scaffold/internal/config" - validation "github.com/go-ozzo/ozzo-validation/v4" "github.com/pkg/errors" "github.com/segmentio/kafka-go" + + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/config" ) -// ProducerController 示例控制器 type ProducerController struct { kafkaConfig config.Kafka } -// NewProducerController 构造示例控制器 func NewProducerController(kafkaConfig config.Kafka) *ProducerController { return &ProducerController{kafkaConfig} } -// ProducerExampleRequest 请求参数 type ProducerExampleRequest struct { Msg string `json:"msg"` } -// Validate 验证参数 func (r ProducerExampleRequest) Validate() error { - return errors.WithStack(validation.ValidateStruct(&r, - validation.Field(&r.Msg, validation.Required.Error("消息不能为空")), - )) + return validation.ValidateStruct(&r, + validation.Field(&r.Msg, validation.Required.Error("message is required")), + ) } -// Example 示例方法 func (c *ProducerController) Example(ctx context.Context, req ProducerExampleRequest) error { if err := req.Validate(); err != nil { - return errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) + return berr.ErrValidateError.WithError(errors.WithStack(err)) } return c.sendMsg(ctx, req.Msg) diff --git a/internal/app/controller/product.go b/internal/app/controller/product.go new file mode 100644 index 00000000..7a6a11b7 --- /dev/null +++ b/internal/app/controller/product.go @@ -0,0 +1,142 @@ +package controller + +import ( + "context" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/usecase" +) + +type ProductController struct { + uc usecase.ProductUseCaseInterface + repo repository.ProductRepositoryInterface +} + +func NewProductController( + uc usecase.ProductUseCaseInterface, + repo repository.ProductRepositoryInterface, +) *ProductController { + return &ProductController{ + uc: uc, + repo: repo, + } +} + +type ProductAttr struct { + Name string `json:"name"` + Desc string `json:"desc"` + Price int `json:"price"` +} + +func (r ProductAttr) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Name, + validation.Required.Error("name is required"), + validation.Length(8, 128).Error("name must be 8 ~ 128 characters"), + ), + validation.Field(&r.Desc, + validation.Required.Error("description is required"), + validation.Length(0, 255).Error("description must be 0 ~ 255 characters"), + ), + validation.Field(&r.Price, validation.Required.Error("price is required")), + ) +} + +type ProductCreateRequest struct { + ProductAttr +} + +func (r ProductCreateRequest) toEntity() domain.Product { + return domain.Product{ + Name: r.Name, + Desc: r.Desc, + Price: r.Price, + } +} + +func (c *ProductController) Create(ctx context.Context, req ProductCreateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + return c.uc.Create(ctx, req.toEntity()) +} + +type ProductUpdateRequest struct { + ID int64 `json:"id"` + ProductAttr +} + +func (r ProductUpdateRequest) toEntity() domain.Product { + return domain.Product{ + ID: r.ID, + Name: r.Name, + Desc: r.Desc, + Price: r.Price, + } +} + +func (r ProductUpdateRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.ID, validation.Required.Error("id is required")), + validation.Field(&r.ProductAttr), + ) +} + +func (c *ProductController) Update(ctx context.Context, req ProductUpdateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + _, err := c.repo.FindOne(ctx, req.ID) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + return c.uc.Update(ctx, req.toEntity()) +} + +func (c *ProductController) Delete(ctx context.Context, id int64) error { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + product, err := c.repo.FindOne(ctx, id) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + return c.uc.Delete(ctx, *product) +} + +func (c *ProductController) Detail(ctx context.Context, id int64) (*domain.Product, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + product, err := c.uc.Detail(ctx, id) + if repository.IsNotFound(err) { + return nil, berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return nil, err + } + + return product, nil +} + +type ProductListRequest struct { + Keyword string +} + +func (c *ProductController) List(ctx context.Context, req ProductListRequest) ([]*domain.Product, error) { + param := usecase.ProductListParam{Keyword: req.Keyword} + return c.uc.List(ctx, param) +} diff --git a/internal/app/controller/role.go b/internal/app/controller/role.go new file mode 100644 index 00000000..0cad9275 --- /dev/null +++ b/internal/app/controller/role.go @@ -0,0 +1,201 @@ +package controller + +import ( + "context" + "fmt" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/pkg/errors" + "github.com/samber/lo" + + "go-scaffold/internal/app/domain" + berr "go-scaffold/internal/app/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/usecase" +) + +type RoleController struct { + uc usecase.RoleUseCaseInterface + roleRepo repository.RoleRepositoryInterface + permissionRepo repository.PermissionRepositoryInterface +} + +func NewRoleController( + uc usecase.RoleUseCaseInterface, + roleRepo repository.RoleRepositoryInterface, + permissionRepo repository.PermissionRepositoryInterface, +) *RoleController { + return &RoleController{ + uc: uc, + roleRepo: roleRepo, + permissionRepo: permissionRepo, + } +} + +type RoleAttr struct { + Name string `json:"name"` +} + +func (r RoleAttr) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Name, + validation.Required.Error("name is required"), + validation.Length(1, 32).Error("name must be 1 ~ 32 characters"), + ), + ) +} + +type RoleCreateRequest struct { + RoleAttr +} + +func (r RoleCreateRequest) toEntity() domain.Role { + return domain.Role{ + Name: r.Name, + } +} + +func (c *RoleController) Create(ctx context.Context, req RoleCreateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + exist, err := c.roleRepo.NameExist(ctx, req.Name) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("role name already exist").WithError(errors.New("name already exist")) + } + + return c.uc.Create(ctx, req.toEntity()) +} + +type RoleUpdateRequest struct { + ID int64 `json:"id"` + RoleAttr +} + +func (r RoleUpdateRequest) toEntity() domain.Role { + return domain.Role{ + ID: r.ID, + Name: r.Name, + } +} + +func (r RoleUpdateRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.ID, validation.Required.Error("id is required")), + validation.Field(&r.RoleAttr), + ) +} + +func (c *RoleController) Update(ctx context.Context, req RoleUpdateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + _, err := c.roleRepo.FindOne(ctx, req.ID) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + exist, err := c.roleRepo.NameExistExcludeID(ctx, req.Name, req.ID) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("role name already exist").WithError(errors.New("name already exist")) + } + + return c.uc.Update(ctx, req.toEntity()) +} + +func (c *RoleController) Delete(ctx context.Context, id int64) error { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + role, err := c.roleRepo.FindOne(ctx, id) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + return c.uc.Delete(ctx, *role) +} + +func (c *RoleController) Detail(ctx context.Context, id int64) (*domain.Role, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + role, err := c.uc.Detail(ctx, id) + if repository.IsNotFound(err) { + return nil, berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return nil, err + } + + return role, nil +} + +type RoleListRequest struct { + Keyword string +} + +func (c *RoleController) List(ctx context.Context, req RoleListRequest) ([]*domain.Role, error) { + param := usecase.RoleListParam{Keyword: req.Keyword} + return c.uc.List(ctx, param) +} + +type RoleGrantPermissionsRequest struct { + Role int64 + Permissions []int64 +} + +func (r RoleGrantPermissionsRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Role, validation.Required.Error("role is required")), + validation.Field(&r.Permissions, validation.Required.Error("no permissions that will be granted")), + ) +} + +func (c *RoleController) GrantPermissions(ctx context.Context, req RoleGrantPermissionsRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + if err := c.validatePermissionsExist(ctx, req.Permissions); err != nil { + return err + } + + return c.uc.GrantPermissions(ctx, req.Role, req.Permissions) +} + +func (c *RoleController) GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + return c.uc.GetPermissions(ctx, id) +} + +func (c *RoleController) validatePermissionsExist(ctx context.Context, permissions []int64) error { + list, err := c.permissionRepo.FindList(ctx, permissions) + if err != nil { + return err + } + permissionList := lo.Map(list, func(item *domain.Permission, index int) int64 { + return item.ID + }) + + diffs, _ := lo.Difference(permissions, permissionList) + if len(diffs) > 0 { + return berr.ErrBadCall.WithMsg(fmt.Sprintf("permissions %v not exist", diffs)).WithError(errors.New("permission not exist")) + } + return nil +} diff --git a/internal/app/controller/user.go b/internal/app/controller/user.go index 4c418275..74cc5982 100644 --- a/internal/app/controller/user.go +++ b/internal/app/controller/user.go @@ -2,64 +2,225 @@ package controller import ( "context" + "fmt" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/pkg/errors" + "github.com/samber/lo" "go-scaffold/internal/app/domain" berr "go-scaffold/internal/app/pkg/errors" - - "github.com/pkg/errors" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/usecase" + "go-scaffold/pkg/validator" ) -// UserController 用户控制器 type UserController struct { - uc domain.UserUseCase + uc usecase.UserUseCaseInterface + userRepo repository.UserRepositoryInterface + roleRepo repository.RoleRepositoryInterface } -// NewUserController 构造用户控制器 func NewUserController( - uc domain.UserUseCase, + uc usecase.UserUseCaseInterface, + userRepo repository.UserRepositoryInterface, + roleRepo repository.RoleRepositoryInterface, ) *UserController { return &UserController{ - uc: uc, + uc: uc, + userRepo: userRepo, + roleRepo: roleRepo, + } +} + +type UserAttr struct { + Username string `json:"username"` + Password string `json:"password"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` +} + +func (r UserAttr) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.Username, + validation.Required.Error("username is required"), + validation.Length(8, 16).Error("username must be 8 ~ 16 characters"), + ), + validation.Field(&r.Password, + validation.Required.Error("password is required"), + validation.Length(8, 18).Error("password must be 8 ~ 18 characters"), + validation.By(validator.PasswordComplexity), + ), + validation.Field(&r.Nickname, + validation.Required.Error("nickname is required"), + validation.Length(8, 16).Error("nickname must be 8 ~ 16 characters"), + ), + validation.Field(&r.Phone, + validation.Required.Error("phone is required"), + validation.By(validator.IsPhoneNumber), + ), + ) +} + +type UserCreateRequest struct { + UserAttr +} + +func (r UserCreateRequest) toEntity() domain.User { + return domain.User{ + Username: r.Username, + Password: domain.Plaintext(r.Password).Encrypt(), + Nickname: r.Nickname, + Phone: r.Phone, } } -// Create 新增用户 -func (c *UserController) Create(ctx context.Context, u domain.User) error { - if err := u.ValidateWithContext(domain.SetSceneWithContext(ctx, domain.Create)); err != nil { - return errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) +func (c *UserController) Create(ctx context.Context, req UserCreateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) } - return c.uc.Create(ctx, u) + exist, err := c.userRepo.UsernameExist(ctx, req.Username) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("username already exist").WithError(errors.New("username already exist")) + } + + _, err = c.uc.Create(ctx, req.toEntity()) + return err +} + +type UserUpdateRequest struct { + ID int64 `json:"id"` + UserAttr } -// Update 更新用户 -func (c *UserController) Update(ctx context.Context, u domain.User) error { - if err := u.ValidateWithContext(domain.SetSceneWithContext(ctx, domain.Update)); err != nil { - return errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) +func (r UserUpdateRequest) toEntity() domain.User { + return domain.User{ + ID: r.ID, + Username: r.Username, + Password: domain.Plaintext(r.Password).Encrypt(), + Nickname: r.Nickname, + Phone: r.Phone, } +} - return c.uc.Update(ctx, u) +func (r UserUpdateRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.ID, validation.Required.Error("id is required")), + validation.Field(&r.UserAttr), + ) } -// Delete 删除用户 -func (c *UserController) Delete(ctx context.Context, id domain.ID) error { - if err := id.ValidateWithContext(domain.SetSceneWithContext(ctx, domain.Delete)); err != nil { - return errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) +func (c *UserController) Update(ctx context.Context, req UserUpdateRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + _, err := c.userRepo.FindOne(ctx, req.ID) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err } - return c.uc.Delete(ctx, id) + exist, err := c.userRepo.UsernameExistExcludeID(ctx, req.Username, req.ID) + if err != nil { + return err + } + if exist { + return berr.ErrBadCall.WithMsg("User name already exist").WithError(errors.New("name already exist")) + } + + _, err = c.uc.Update(ctx, req.toEntity()) + return err } -// Detail 用户详情 -func (c *UserController) Detail(ctx context.Context, id domain.ID) (*domain.User, error) { - if err := id.ValidateWithContext(domain.SetSceneWithContext(ctx, domain.Detail)); err != nil { - return nil, errors.WithStack(berr.ErrValidateError.WithMsg(err.Error())) +func (c *UserController) Delete(ctx context.Context, id int64) error { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) } - return c.uc.Detail(ctx, id) + role, err := c.userRepo.FindOne(ctx, id) + if repository.IsNotFound(err) { + return berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return err + } + + return c.uc.Delete(ctx, *role) } -// List 用户列表 -func (c *UserController) List(ctx context.Context, req domain.UserListParam) ([]*domain.User, error) { - return c.uc.List(ctx, req) +func (c *UserController) Detail(ctx context.Context, id int64) (*domain.User, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + user, err := c.uc.Detail(ctx, id) + if repository.IsNotFound(err) { + return nil, berr.ErrResourceNotFound.WithError(err) + } else if err != nil { + return nil, err + } + + return user, nil +} + +type UserListRequest struct { + Keyword string +} + +func (c *UserController) List(ctx context.Context, req UserListRequest) ([]*domain.User, error) { + param := usecase.UserListParam{Keyword: req.Keyword} + return c.uc.List(ctx, param) +} + +type UserAssignRoleRequest struct { + User int64 + Roles []int64 +} + +func (r UserAssignRoleRequest) Validate() error { + return validation.ValidateStruct(&r, + validation.Field(&r.User, validation.Required.Error("user is required")), + validation.Field(&r.Roles, validation.Required.Error("no roles that will be assigned")), + ) +} + +func (c *UserController) AssignRoles(ctx context.Context, req UserAssignRoleRequest) error { + if err := req.Validate(); err != nil { + return berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + if err := c.validateRolesExist(ctx, req.Roles); err != nil { + return err + } + + return c.uc.AssignRoles(ctx, req.User, req.Roles) +} + +func (c *UserController) GetRoles(ctx context.Context, id int64) ([]*domain.Role, error) { + if err := validation.Validate(id, validation.Required.Error("id is required")); err != nil { + return nil, berr.ErrValidateError.WithError(errors.WithStack(err)) + } + + return c.uc.GetRoles(ctx, id) +} + +func (c *UserController) validateRolesExist(ctx context.Context, roles []int64) error { + list, err := c.roleRepo.FindList(ctx, roles) + if err != nil { + return err + } + roleList := lo.Map(list, func(item *domain.Role, index int) int64 { + return item.ID + }) + + diffs, _ := lo.Difference(roles, roleList) + if len(diffs) > 0 { + return berr.ErrBadCall.WithMsg(fmt.Sprintf("roles %v not exist", diffs)).WithError(errors.New("role not exist")) + } + return nil } diff --git a/internal/app/domain/id.go b/internal/app/domain/id.go deleted file mode 100644 index 8db2e1f6..00000000 --- a/internal/app/domain/id.go +++ /dev/null @@ -1,23 +0,0 @@ -package domain - -import ( - "context" - - validation "github.com/go-ozzo/ozzo-validation/v4" - "github.com/pkg/errors" -) - -type ID int64 - -func (i ID) ValidateWithContext(ctx context.Context) error { - scene := GetSceneFromContext(ctx) - return errors.WithStack(validation.Validate(int64(i), - validation.When( - scene == Detail || scene == Update || scene == Delete, - validation.Required.Error("id 不能为空"), - ))) -} - -func (i ID) Int64() int64 { - return int64(i) -} diff --git a/internal/app/domain/permission.go b/internal/app/domain/permission.go new file mode 100644 index 00000000..3efde1cf --- /dev/null +++ b/internal/app/domain/permission.go @@ -0,0 +1,9 @@ +package domain + +type Permission struct { + ID int64 `json:"id"` + Key string `json:"key"` + Name string `json:"name"` + Desc string `json:"desc"` + ParentID int64 `json:"parentID"` +} diff --git a/internal/app/domain/product.go b/internal/app/domain/product.go new file mode 100644 index 00000000..4e8f53f1 --- /dev/null +++ b/internal/app/domain/product.go @@ -0,0 +1,8 @@ +package domain + +type Product struct { + ID int64 `json:"id"` + Name string `json:"name"` + Desc string `json:"desc"` + Price int `json:"price"` +} diff --git a/internal/app/domain/role.go b/internal/app/domain/role.go new file mode 100644 index 00000000..a6e48be8 --- /dev/null +++ b/internal/app/domain/role.go @@ -0,0 +1,6 @@ +package domain + +type Role struct { + ID int64 `json:"id"` + Name string `json:"name"` +} diff --git a/internal/app/domain/scene.go b/internal/app/domain/scene.go deleted file mode 100644 index 1a875fe0..00000000 --- a/internal/app/domain/scene.go +++ /dev/null @@ -1,28 +0,0 @@ -package domain - -import "context" - -// Scene 场景 -type Scene string - -const ( - List Scene = "list" - Detail Scene = "detail" - Create Scene = "create" - Update Scene = "update" - Delete Scene = "delete" -) - -var sceneContextKey = Scene("scene") - -func SetSceneWithContext(ctx context.Context, value Scene) context.Context { - return context.WithValue(ctx, sceneContextKey, value) -} - -func GetSceneFromContext(ctx context.Context) Scene { - value := ctx.Value(sceneContextKey) - if value != nil { - return value.(Scene) - } - return "" -} diff --git a/internal/app/domain/token.go b/internal/app/domain/token.go new file mode 100644 index 00000000..e23467cd --- /dev/null +++ b/internal/app/domain/token.go @@ -0,0 +1,8 @@ +package domain + +import "time" + +const ( + AccountTokenExpireDuration = time.Hour * 24 * 30 + AccountTokenRefreshDuration = time.Hour * 24 * 7 +) diff --git a/internal/app/domain/user.go b/internal/app/domain/user.go index 87b4fc82..e8756fb4 100644 --- a/internal/app/domain/user.go +++ b/internal/app/domain/user.go @@ -1,70 +1,50 @@ package domain import ( - "context" + "crypto/md5" + "encoding/hex" - "go-scaffold/pkg/validator" - - validation "github.com/go-ozzo/ozzo-validation/v4" - "github.com/pkg/errors" + "github.com/google/uuid" ) -// User 用户实体 type User struct { - ID ID - Name string // 名称 - Age int8 // 年龄 - Phone string // 手机号码 + ID int64 `json:"id"` + Username string `json:"username"` + Password Password `json:"password"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` + Salt string `json:"salt"` } -func (u User) ValidateWithContext(ctx context.Context) error { - return errors.WithStack(validation.ValidateStruct(&u, - validation.Field(&u.ID), - validation.Field(&u.Name, validation.Required.Error("名称不能为空")), - validation.Field(&u.Phone, validation.By(validator.IsPhoneNumber)), - )) +func (u *User) RefreshSalt() { + u.Salt = uuid.New().String() } -type ( - // UserListParam 用户列表参数 - UserListParam struct { - Keyword string +func (u *User) ToProfile() *UserProfile { + return &UserProfile{ + ID: u.ID, + Username: u.Username, + Nickname: u.Nickname, + Phone: u.Phone, } +} - // UserUseCase 用例 - UserUseCase interface { - // Create 新增用户 - Create(ctx context.Context, user User) error - // Update 更新用户 - Update(ctx context.Context, user User) error - // Delete 删除用户 - Delete(ctx context.Context, id ID) error - // Detail 用户详情 - Detail(ctx context.Context, id ID) (*User, error) - // List 用户列表 - List(ctx context.Context, param UserListParam) ([]*User, error) - } -) +type Plaintext string -type ( - // FindUserListParam 列表查询参数 - FindUserListParam struct { - Keyword string - } +func (p Plaintext) Encrypt() Password { + sum := md5.Sum([]byte(p)) + return Password(hex.EncodeToString(sum[:])) +} - // UserRepository 仓储 - UserRepository interface { - // FindList 列表查询 - FindList(ctx context.Context, param FindUserListParam) ([]*User, error) - // FindOneByID 根据 ID 查询详情 - FindOneByID(ctx context.Context, id ID) (*User, error) - // Exist 数据是否存在 - Exist(ctx context.Context, id ID) (bool, error) - // Create 新增数据 - Create(ctx context.Context, user User) error - // Update 更新数据 - Update(ctx context.Context, user User) error - // Delete 删除数据 - Delete(ctx context.Context, user User) error - } -) +type Password string + +func (p Password) Verify(s Plaintext) bool { + return p == s.Encrypt() +} + +type UserProfile struct { + ID int64 `json:"id"` + Username string `json:"username"` + Nickname string `json:"nickname"` + Phone string `json:"phone"` +} diff --git a/internal/app/pkg/casbin/adapter/adapter.go b/internal/app/pkg/casbin/adapter/adapter.go index 140b3e47..b4b61d6c 100644 --- a/internal/app/pkg/casbin/adapter/adapter.go +++ b/internal/app/pkg/casbin/adapter/adapter.go @@ -1,10 +1,13 @@ package adapter import ( - "go-scaffold/internal/config" + "database/sql" + "log/slog" "github.com/casbin/casbin/v2/persist" "gorm.io/gorm" + + "go-scaffold/internal/config" ) // Adapter the interface that casbin adapter must implement @@ -16,16 +19,30 @@ type Adapter interface { } // New creates casin adapter -func New(conf config.CasbinAdapter, db *gorm.DB) (adp Adapter, err error) { +func New( + env config.Env, + conf config.CasbinAdapter, + dbConf config.DBConn, + logger *slog.Logger, + db *gorm.DB, + sdb *sql.DB, +) (adp Adapter, err error) { if conf.Gorm != nil { - adp, err = NewGormAdapter(*conf.Gorm, db) + adp, err = NewGormAdapter(db) + if err != nil { + return nil, err + } + } + + if conf.Ent != nil { + adp, err = NewEntAdapter(env, dbConf, logger, sdb) if err != nil { return nil, err } } - if conf.File != nil { - adp = NewFileAdapter(*conf.File) + if conf.File != "" { + adp = NewFileAdapter(conf.File) } return diff --git a/internal/app/pkg/casbin/adapter/ent.go b/internal/app/pkg/casbin/adapter/ent.go new file mode 100644 index 00000000..6db0a084 --- /dev/null +++ b/internal/app/pkg/casbin/adapter/ent.go @@ -0,0 +1,35 @@ +package adapter + +import ( + "database/sql" + "log/slog" + + entsql "entgo.io/ent/dialect/sql" + entadapter "github.com/casbin/ent-adapter" + "github.com/casbin/ent-adapter/ent" + + "go-scaffold/internal/config" + elog "go-scaffold/pkg/log/ent" +) + +// NewEntAdapter build casin ent adapter +func NewEntAdapter(env config.Env, dbConf config.DBConn, logger *slog.Logger, sdb *sql.DB) (*entadapter.Adapter, error) { + driver := entsql.OpenDB(dbConf.Driver.String(), sdb) + + options := []ent.Option{ + ent.Driver(driver), + ent.Log(elog.NewLogger(logger).Log), + } + if env.IsDebug() { + options = append(options, ent.Debug()) + } + + client := ent.NewClient(options...) + + adapter, err := entadapter.NewAdapterWithClient(client) + if err != nil { + return nil, err + } + + return adapter, nil +} diff --git a/internal/app/pkg/casbin/adapter/file.go b/internal/app/pkg/casbin/adapter/file.go index 4bd4754c..557f28de 100644 --- a/internal/app/pkg/casbin/adapter/file.go +++ b/internal/app/pkg/casbin/adapter/file.go @@ -1,12 +1,10 @@ package adapter import ( - "go-scaffold/internal/config" - fileadapter "github.com/casbin/casbin/v2/persist/file-adapter" ) // NewFileAdapter build casin file adapter -func NewFileAdapter(conf config.CasbinFileAdapter) *fileadapter.FilteredAdapter { - return fileadapter.NewFilteredAdapter(conf.Path) +func NewFileAdapter(fp string) *fileadapter.FilteredAdapter { + return fileadapter.NewFilteredAdapter(fp) } diff --git a/internal/app/pkg/casbin/adapter/gorm.go b/internal/app/pkg/casbin/adapter/gorm.go index 82a6661a..bcbe5287 100644 --- a/internal/app/pkg/casbin/adapter/gorm.go +++ b/internal/app/pkg/casbin/adapter/gorm.go @@ -1,26 +1,22 @@ package adapter import ( - "go-scaffold/internal/config" - gormadapter "github.com/casbin/gorm-adapter/v3" "gorm.io/gorm" ) +// casbinRuleTableName casbin rule's table name +// for consistency with the ent adapter +const casbinRuleTableName = "casbin_rules" + // NewGormAdapter build casin gorm adapter -func NewGormAdapter(conf config.CasbinGormAdapter, db *gorm.DB) (adp *gormadapter.Adapter, err error) { - gormadapter.TurnOffAutoMigrate(db) +func NewGormAdapter(db *gorm.DB) (adp *gormadapter.Adapter, err error) { + // turn on automatic migration for consistency with the ent adapter + // gormadapter.TurnOffAutoMigrate(db) - if conf.TableName == "" { - adp, err = gormadapter.NewAdapterByDB(db) - if err != nil { - return nil, err - } - } else { - adp, err = gormadapter.NewAdapterByDBUseTableName(db, "", conf.TableName) - if err != nil { - return nil, err - } + adp, err = gormadapter.NewAdapterByDBUseTableName(db, "", casbinRuleTableName) + if err != nil { + return nil, err } return diff --git a/internal/app/pkg/casbin/casbin.go b/internal/app/pkg/casbin/casbin.go index 1abb3f44..f4bc6df7 100644 --- a/internal/app/pkg/casbin/casbin.go +++ b/internal/app/pkg/casbin/casbin.go @@ -1,22 +1,32 @@ package casbin import ( - "go-scaffold/internal/app/pkg/casbin/adapter" - "go-scaffold/internal/app/pkg/casbin/model" - "go-scaffold/internal/config" + "database/sql" + "log/slog" "github.com/casbin/casbin/v2" "gorm.io/gorm" + + "go-scaffold/internal/app/pkg/casbin/adapter" + "go-scaffold/internal/app/pkg/casbin/model" + "go-scaffold/internal/config" ) // New build casbin -func New(conf config.Casbin, db *gorm.DB) (*casbin.Enforcer, error) { +func New( + env config.Env, + conf config.Casbin, + dbConf config.DBConn, + logger *slog.Logger, + gdb *gorm.DB, + sdb *sql.DB, +) (*casbin.Enforcer, error) { mod, err := model.New(conf.Model) if err != nil { return nil, err } - adp, err := adapter.New(conf.Adapter, db) + adp, err := adapter.New(env, conf.Adapter, dbConf, logger, gdb, sdb) if err != nil { return nil, err } diff --git a/internal/app/pkg/casbin/model/model.go b/internal/app/pkg/casbin/model/model.go index e32e8727..d2e47bb5 100644 --- a/internal/app/pkg/casbin/model/model.go +++ b/internal/app/pkg/casbin/model/model.go @@ -1,9 +1,9 @@ package model import ( - "go-scaffold/internal/config" - "github.com/casbin/casbin/v2/model" + + "go-scaffold/internal/config" ) // New creates model diff --git a/internal/app/pkg/casbin/provide.go b/internal/app/pkg/casbin/provide.go index c39f82c5..5bbde58e 100644 --- a/internal/app/pkg/casbin/provide.go +++ b/internal/app/pkg/casbin/provide.go @@ -1,13 +1,23 @@ package casbin import ( - "go-scaffold/internal/config" + "database/sql" + "log/slog" "github.com/casbin/casbin/v2" "gorm.io/gorm" + + "go-scaffold/internal/config" ) // Provide casbin -func Provide(conf config.Casbin, db *gorm.DB) (*casbin.Enforcer, error) { - return New(conf, db) +func Provide( + env config.Env, + conf config.Casbin, + dbConf config.DBConn, + logger *slog.Logger, + gdb *gorm.DB, + sdb *sql.DB, +) (*casbin.Enforcer, error) { + return New(env, conf, dbConf, logger, gdb, sdb) } diff --git a/internal/app/pkg/client/grpc.go b/internal/app/pkg/client/grpc.go index 8657710f..bd7fc01f 100644 --- a/internal/app/pkg/client/grpc.go +++ b/internal/app/pkg/client/grpc.go @@ -6,14 +6,14 @@ import ( "strings" "time" - "go-scaffold/internal/app/pkg/discovery" - "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware/logging" "github.com/go-kratos/kratos/v2/middleware/metadata" "github.com/go-kratos/kratos/v2/middleware/tracing" kgrpc "github.com/go-kratos/kratos/v2/transport/grpc" "google.golang.org/grpc" + + "go-scaffold/internal/app/pkg/discovery" ) // ErrDiscoveryIsNotSet discovery is not be set diff --git a/internal/app/pkg/db/db.go b/internal/app/pkg/db/db.go index 885f2e57..92e613a2 100644 --- a/internal/app/pkg/db/db.go +++ b/internal/app/pkg/db/db.go @@ -6,10 +6,10 @@ import ( "errors" "strings" - "go-scaffold/internal/config" - _ "github.com/go-sql-driver/mysql" _ "github.com/jackc/pgx" + + "go-scaffold/internal/config" ) // ErrUnsupportedDriver unsupported database driver diff --git a/internal/app/pkg/discovery/consul.go b/internal/app/pkg/discovery/consul.go index 2f8cb046..37ebe971 100644 --- a/internal/app/pkg/discovery/consul.go +++ b/internal/app/pkg/discovery/consul.go @@ -1,10 +1,10 @@ package discovery import ( - "go-scaffold/internal/config" - consul "github.com/go-kratos/consul/registry" "github.com/hashicorp/consul/api" + + "go-scaffold/internal/config" ) // NewConsul build consul discovery diff --git a/internal/app/pkg/discovery/discovery.go b/internal/app/pkg/discovery/discovery.go index 90714d59..e99382b4 100644 --- a/internal/app/pkg/discovery/discovery.go +++ b/internal/app/pkg/discovery/discovery.go @@ -3,9 +3,9 @@ package discovery import ( "context" - "go-scaffold/internal/config" - "github.com/go-kratos/kratos/v2/registry" + + "go-scaffold/internal/config" ) // Discovery the interface that discovery must implement diff --git a/internal/app/pkg/discovery/etcd.go b/internal/app/pkg/discovery/etcd.go index b97d3dfb..279ffc8c 100644 --- a/internal/app/pkg/discovery/etcd.go +++ b/internal/app/pkg/discovery/etcd.go @@ -3,10 +3,10 @@ package discovery import ( "context" - "go-scaffold/internal/config" - "github.com/go-kratos/kratos/contrib/registry/etcd/v2" etcdctl "go.etcd.io/etcd/client/v3" + + "go-scaffold/internal/config" ) // NewEtcd build etcd discovery diff --git a/internal/app/pkg/ent/ent.go b/internal/app/pkg/ent/ent.go index 436c718d..7c0543c4 100644 --- a/internal/app/pkg/ent/ent.go +++ b/internal/app/pkg/ent/ent.go @@ -3,25 +3,19 @@ package ent //go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/execquery --feature sql/modifier --feature intercept --target ./ent ../../repository/schema import ( - "context" + "database/sql" + "log/slog" + + entsql "entgo.io/ent/dialect/sql" - "go-scaffold/internal/app/pkg/db" "go-scaffold/internal/app/pkg/ent/ent" _ "go-scaffold/internal/app/pkg/ent/ent/runtime" "go-scaffold/internal/config" elog "go-scaffold/pkg/log/ent" - - entsql "entgo.io/ent/dialect/sql" - "golang.org/x/exp/slog" ) // New build db client -func New(ctx context.Context, env config.Env, dbConf config.DBConn, logger *slog.Logger) (*ent.Client, error) { - sdb, err := db.New(ctx, dbConf) - if err != nil { - return nil, err - } - +func New(env config.Env, dbConf config.DBConn, logger *slog.Logger, sdb *sql.DB) (*ent.Client, error) { driver := entsql.OpenDB(dbConf.Driver.String(), sdb) options := []ent.Option{ diff --git a/internal/app/pkg/ent/ent/client.go b/internal/app/pkg/ent/ent/client.go index 74d2f175..5e499880 100644 --- a/internal/app/pkg/ent/ent/client.go +++ b/internal/app/pkg/ent/ent/client.go @@ -10,10 +10,16 @@ import ( "go-scaffold/internal/app/pkg/ent/ent/migrate" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/pkg/ent/ent/role" "go-scaffold/internal/app/pkg/ent/ent/user" + "entgo.io/ent" "entgo.io/ent/dialect" "entgo.io/ent/dialect/sql" + + stdsql "database/sql" ) // Client is the client that holds all ent builders. @@ -21,6 +27,12 @@ type Client struct { config // Schema is the client for creating, migrating and dropping schema. Schema *migrate.Schema + // Permission is the client for interacting with the Permission builders. + Permission *PermissionClient + // Product is the client for interacting with the Product builders. + Product *ProductClient + // Role is the client for interacting with the Role builders. + Role *RoleClient // User is the client for interacting with the User builders. User *UserClient } @@ -36,9 +48,61 @@ func NewClient(opts ...Option) *Client { func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) + c.Permission = NewPermissionClient(c.config) + c.Product = NewProductClient(c.config) + c.Role = NewRoleClient(c.config) c.User = NewUserClient(c.config) } +type ( + // config is the configuration for the client and its builder. + config struct { + // driver used for executing database requests. + driver dialect.Driver + // debug enable a debug logging. + debug bool + // log used for logging on debug mode. + log func(...any) + // hooks to execute on mutations. + hooks *hooks + // interceptors to execute on queries. + inters *inters + } + // Option function to configure the client. + Option func(*config) +) + +// options applies the options on the config object. +func (c *config) options(opts ...Option) { + for _, opt := range opts { + opt(c) + } + if c.debug { + c.driver = dialect.Debug(c.driver, c.log) + } +} + +// Debug enables debug logging on the ent.Driver. +func Debug() Option { + return func(c *config) { + c.debug = true + } +} + +// Log sets the logging function for debug mode. +func Log(fn func(...any)) Option { + return func(c *config) { + c.log = fn + } +} + +// Driver configures the client driver. +func Driver(driver dialect.Driver) Option { + return func(c *config) { + c.driver = driver + } +} + // Open opens a database/sql.DB specified by the driver name and // the data source name, and returns a new client attached to it. // Optional parameters can be added for configuring the client. @@ -68,9 +132,12 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := c.config cfg.driver = tx return &Tx{ - ctx: ctx, - config: cfg, - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + Permission: NewPermissionClient(cfg), + Product: NewProductClient(cfg), + Role: NewRoleClient(cfg), + User: NewUserClient(cfg), }, nil } @@ -88,16 +155,19 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) cfg := c.config cfg.driver = &txDriver{tx: tx, drv: c.driver} return &Tx{ - ctx: ctx, - config: cfg, - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + Permission: NewPermissionClient(cfg), + Product: NewProductClient(cfg), + Role: NewRoleClient(cfg), + User: NewUserClient(cfg), }, nil } // Debug returns a new debug-client. It's used to get verbose logging on specific operations. // // client.Debug(). -// User. +// Permission. // Query(). // Count(ctx) func (c *Client) Debug() *Client { @@ -119,18 +189,30 @@ func (c *Client) Close() error { // Use adds the mutation hooks to all the entity clients. // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { + c.Permission.Use(hooks...) + c.Product.Use(hooks...) + c.Role.Use(hooks...) c.User.Use(hooks...) } // Intercept adds the query interceptors to all the entity clients. // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. func (c *Client) Intercept(interceptors ...Interceptor) { + c.Permission.Intercept(interceptors...) + c.Product.Intercept(interceptors...) + c.Role.Intercept(interceptors...) c.User.Intercept(interceptors...) } // Mutate implements the ent.Mutator interface. func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { switch m := m.(type) { + case *PermissionMutation: + return c.Permission.mutate(ctx, m) + case *ProductMutation: + return c.Product.mutate(ctx, m) + case *RoleMutation: + return c.Role.mutate(ctx, m) case *UserMutation: return c.User.mutate(ctx, m) default: @@ -138,6 +220,366 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { } } +// PermissionClient is a client for the Permission schema. +type PermissionClient struct { + config +} + +// NewPermissionClient returns a client for the Permission from the given config. +func NewPermissionClient(c config) *PermissionClient { + return &PermissionClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `permission.Hooks(f(g(h())))`. +func (c *PermissionClient) Use(hooks ...Hook) { + c.hooks.Permission = append(c.hooks.Permission, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `permission.Intercept(f(g(h())))`. +func (c *PermissionClient) Intercept(interceptors ...Interceptor) { + c.inters.Permission = append(c.inters.Permission, interceptors...) +} + +// Create returns a builder for creating a Permission entity. +func (c *PermissionClient) Create() *PermissionCreate { + mutation := newPermissionMutation(c.config, OpCreate) + return &PermissionCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Permission entities. +func (c *PermissionClient) CreateBulk(builders ...*PermissionCreate) *PermissionCreateBulk { + return &PermissionCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Permission. +func (c *PermissionClient) Update() *PermissionUpdate { + mutation := newPermissionMutation(c.config, OpUpdate) + return &PermissionUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *PermissionClient) UpdateOne(pe *Permission) *PermissionUpdateOne { + mutation := newPermissionMutation(c.config, OpUpdateOne, withPermission(pe)) + return &PermissionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *PermissionClient) UpdateOneID(id int64) *PermissionUpdateOne { + mutation := newPermissionMutation(c.config, OpUpdateOne, withPermissionID(id)) + return &PermissionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Permission. +func (c *PermissionClient) Delete() *PermissionDelete { + mutation := newPermissionMutation(c.config, OpDelete) + return &PermissionDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *PermissionClient) DeleteOne(pe *Permission) *PermissionDeleteOne { + return c.DeleteOneID(pe.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *PermissionClient) DeleteOneID(id int64) *PermissionDeleteOne { + builder := c.Delete().Where(permission.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &PermissionDeleteOne{builder} +} + +// Query returns a query builder for Permission. +func (c *PermissionClient) Query() *PermissionQuery { + return &PermissionQuery{ + config: c.config, + ctx: &QueryContext{Type: TypePermission}, + inters: c.Interceptors(), + } +} + +// Get returns a Permission entity by its id. +func (c *PermissionClient) Get(ctx context.Context, id int64) (*Permission, error) { + return c.Query().Where(permission.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *PermissionClient) GetX(ctx context.Context, id int64) *Permission { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *PermissionClient) Hooks() []Hook { + hooks := c.hooks.Permission + return append(hooks[:len(hooks):len(hooks)], permission.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *PermissionClient) Interceptors() []Interceptor { + inters := c.inters.Permission + return append(inters[:len(inters):len(inters)], permission.Interceptors[:]...) +} + +func (c *PermissionClient) mutate(ctx context.Context, m *PermissionMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&PermissionCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&PermissionUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&PermissionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&PermissionDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Permission mutation op: %q", m.Op()) + } +} + +// ProductClient is a client for the Product schema. +type ProductClient struct { + config +} + +// NewProductClient returns a client for the Product from the given config. +func NewProductClient(c config) *ProductClient { + return &ProductClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `product.Hooks(f(g(h())))`. +func (c *ProductClient) Use(hooks ...Hook) { + c.hooks.Product = append(c.hooks.Product, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `product.Intercept(f(g(h())))`. +func (c *ProductClient) Intercept(interceptors ...Interceptor) { + c.inters.Product = append(c.inters.Product, interceptors...) +} + +// Create returns a builder for creating a Product entity. +func (c *ProductClient) Create() *ProductCreate { + mutation := newProductMutation(c.config, OpCreate) + return &ProductCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Product entities. +func (c *ProductClient) CreateBulk(builders ...*ProductCreate) *ProductCreateBulk { + return &ProductCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Product. +func (c *ProductClient) Update() *ProductUpdate { + mutation := newProductMutation(c.config, OpUpdate) + return &ProductUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ProductClient) UpdateOne(pr *Product) *ProductUpdateOne { + mutation := newProductMutation(c.config, OpUpdateOne, withProduct(pr)) + return &ProductUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ProductClient) UpdateOneID(id int64) *ProductUpdateOne { + mutation := newProductMutation(c.config, OpUpdateOne, withProductID(id)) + return &ProductUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Product. +func (c *ProductClient) Delete() *ProductDelete { + mutation := newProductMutation(c.config, OpDelete) + return &ProductDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *ProductClient) DeleteOne(pr *Product) *ProductDeleteOne { + return c.DeleteOneID(pr.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *ProductClient) DeleteOneID(id int64) *ProductDeleteOne { + builder := c.Delete().Where(product.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ProductDeleteOne{builder} +} + +// Query returns a query builder for Product. +func (c *ProductClient) Query() *ProductQuery { + return &ProductQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeProduct}, + inters: c.Interceptors(), + } +} + +// Get returns a Product entity by its id. +func (c *ProductClient) Get(ctx context.Context, id int64) (*Product, error) { + return c.Query().Where(product.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ProductClient) GetX(ctx context.Context, id int64) *Product { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *ProductClient) Hooks() []Hook { + hooks := c.hooks.Product + return append(hooks[:len(hooks):len(hooks)], product.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *ProductClient) Interceptors() []Interceptor { + inters := c.inters.Product + return append(inters[:len(inters):len(inters)], product.Interceptors[:]...) +} + +func (c *ProductClient) mutate(ctx context.Context, m *ProductMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&ProductCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&ProductUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&ProductUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&ProductDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Product mutation op: %q", m.Op()) + } +} + +// RoleClient is a client for the Role schema. +type RoleClient struct { + config +} + +// NewRoleClient returns a client for the Role from the given config. +func NewRoleClient(c config) *RoleClient { + return &RoleClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `role.Hooks(f(g(h())))`. +func (c *RoleClient) Use(hooks ...Hook) { + c.hooks.Role = append(c.hooks.Role, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `role.Intercept(f(g(h())))`. +func (c *RoleClient) Intercept(interceptors ...Interceptor) { + c.inters.Role = append(c.inters.Role, interceptors...) +} + +// Create returns a builder for creating a Role entity. +func (c *RoleClient) Create() *RoleCreate { + mutation := newRoleMutation(c.config, OpCreate) + return &RoleCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Role entities. +func (c *RoleClient) CreateBulk(builders ...*RoleCreate) *RoleCreateBulk { + return &RoleCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Role. +func (c *RoleClient) Update() *RoleUpdate { + mutation := newRoleMutation(c.config, OpUpdate) + return &RoleUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *RoleClient) UpdateOne(r *Role) *RoleUpdateOne { + mutation := newRoleMutation(c.config, OpUpdateOne, withRole(r)) + return &RoleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *RoleClient) UpdateOneID(id int64) *RoleUpdateOne { + mutation := newRoleMutation(c.config, OpUpdateOne, withRoleID(id)) + return &RoleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Role. +func (c *RoleClient) Delete() *RoleDelete { + mutation := newRoleMutation(c.config, OpDelete) + return &RoleDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *RoleClient) DeleteOne(r *Role) *RoleDeleteOne { + return c.DeleteOneID(r.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *RoleClient) DeleteOneID(id int64) *RoleDeleteOne { + builder := c.Delete().Where(role.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &RoleDeleteOne{builder} +} + +// Query returns a query builder for Role. +func (c *RoleClient) Query() *RoleQuery { + return &RoleQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeRole}, + inters: c.Interceptors(), + } +} + +// Get returns a Role entity by its id. +func (c *RoleClient) Get(ctx context.Context, id int64) (*Role, error) { + return c.Query().Where(role.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *RoleClient) GetX(ctx context.Context, id int64) *Role { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *RoleClient) Hooks() []Hook { + hooks := c.hooks.Role + return append(hooks[:len(hooks):len(hooks)], role.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *RoleClient) Interceptors() []Interceptor { + inters := c.inters.Role + return append(inters[:len(inters):len(inters)], role.Interceptors[:]...) +} + +func (c *RoleClient) mutate(ctx context.Context, m *RoleMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&RoleCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&RoleUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&RoleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&RoleDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Role mutation op: %q", m.Op()) + } +} + // UserClient is a client for the User schema. type UserClient struct { config @@ -154,7 +596,7 @@ func (c *UserClient) Use(hooks ...Hook) { c.hooks.User = append(c.hooks.User, hooks...) } -// Use adds a list of query interceptors to the interceptors stack. +// Intercept adds a list of query interceptors to the interceptors stack. // A call to `Intercept(f, g, h)` equals to `user.Intercept(f(g(h())))`. func (c *UserClient) Intercept(interceptors ...Interceptor) { c.inters.User = append(c.inters.User, interceptors...) @@ -257,3 +699,37 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) return nil, fmt.Errorf("ent: unknown User mutation op: %q", m.Op()) } } + +// hooks and interceptors per client, for fast access. +type ( + hooks struct { + Permission, Product, Role, User []ent.Hook + } + inters struct { + Permission, Product, Role, User []ent.Interceptor + } +) + +// ExecContext allows calling the underlying ExecContext method of the driver if it is supported by it. +// See, database/sql#DB.ExecContext for more information. +func (c *config) ExecContext(ctx context.Context, query string, args ...any) (stdsql.Result, error) { + ex, ok := c.driver.(interface { + ExecContext(context.Context, string, ...any) (stdsql.Result, error) + }) + if !ok { + return nil, fmt.Errorf("Driver.ExecContext is not supported") + } + return ex.ExecContext(ctx, query, args...) +} + +// QueryContext allows calling the underlying QueryContext method of the driver if it is supported by it. +// See, database/sql#DB.QueryContext for more information. +func (c *config) QueryContext(ctx context.Context, query string, args ...any) (*stdsql.Rows, error) { + q, ok := c.driver.(interface { + QueryContext(context.Context, string, ...any) (*stdsql.Rows, error) + }) + if !ok { + return nil, fmt.Errorf("Driver.QueryContext is not supported") + } + return q.QueryContext(ctx, query, args...) +} diff --git a/internal/app/pkg/ent/ent/config.go b/internal/app/pkg/ent/ent/config.go deleted file mode 100644 index 875c00f4..00000000 --- a/internal/app/pkg/ent/ent/config.go +++ /dev/null @@ -1,94 +0,0 @@ -// Code generated by ent, DO NOT EDIT. - -package ent - -import ( - "context" - stdsql "database/sql" - "fmt" - - "entgo.io/ent" - "entgo.io/ent/dialect" -) - -// Option function to configure the client. -type Option func(*config) - -// Config is the configuration for the client and its builder. -type config struct { - // driver used for executing database requests. - driver dialect.Driver - // debug enable a debug logging. - debug bool - // log used for logging on debug mode. - log func(...any) - // hooks to execute on mutations. - hooks *hooks - // interceptors to execute on queries. - inters *inters -} - -// hooks and interceptors per client, for fast access. -type ( - hooks struct { - User []ent.Hook - } - inters struct { - User []ent.Interceptor - } -) - -// Options applies the options on the config object. -func (c *config) options(opts ...Option) { - for _, opt := range opts { - opt(c) - } - if c.debug { - c.driver = dialect.Debug(c.driver, c.log) - } -} - -// Debug enables debug logging on the ent.Driver. -func Debug() Option { - return func(c *config) { - c.debug = true - } -} - -// Log sets the logging function for debug mode. -func Log(fn func(...any)) Option { - return func(c *config) { - c.log = fn - } -} - -// Driver configures the client driver. -func Driver(driver dialect.Driver) Option { - return func(c *config) { - c.driver = driver - } -} - -// ExecContext allows calling the underlying ExecContext method of the driver if it is supported by it. -// See, database/sql#DB.ExecContext for more information. -func (c *config) ExecContext(ctx context.Context, query string, args ...any) (stdsql.Result, error) { - ex, ok := c.driver.(interface { - ExecContext(context.Context, string, ...any) (stdsql.Result, error) - }) - if !ok { - return nil, fmt.Errorf("Driver.ExecContext is not supported") - } - return ex.ExecContext(ctx, query, args...) -} - -// QueryContext allows calling the underlying QueryContext method of the driver if it is supported by it. -// See, database/sql#DB.QueryContext for more information. -func (c *config) QueryContext(ctx context.Context, query string, args ...any) (*stdsql.Rows, error) { - q, ok := c.driver.(interface { - QueryContext(context.Context, string, ...any) (*stdsql.Rows, error) - }) - if !ok { - return nil, fmt.Errorf("Driver.QueryContext is not supported") - } - return q.QueryContext(ctx, query, args...) -} diff --git a/internal/app/pkg/ent/ent/context.go b/internal/app/pkg/ent/ent/context.go deleted file mode 100644 index 7811bfa2..00000000 --- a/internal/app/pkg/ent/ent/context.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by ent, DO NOT EDIT. - -package ent - -import ( - "context" -) - -type clientCtxKey struct{} - -// FromContext returns a Client stored inside a context, or nil if there isn't one. -func FromContext(ctx context.Context) *Client { - c, _ := ctx.Value(clientCtxKey{}).(*Client) - return c -} - -// NewContext returns a new context with the given Client attached. -func NewContext(parent context.Context, c *Client) context.Context { - return context.WithValue(parent, clientCtxKey{}, c) -} - -type txCtxKey struct{} - -// TxFromContext returns a Tx stored inside a context, or nil if there isn't one. -func TxFromContext(ctx context.Context) *Tx { - tx, _ := ctx.Value(txCtxKey{}).(*Tx) - return tx -} - -// NewTxContext returns a new context with the given Tx attached. -func NewTxContext(parent context.Context, tx *Tx) context.Context { - return context.WithValue(parent, txCtxKey{}, tx) -} diff --git a/internal/app/pkg/ent/ent/ent.go b/internal/app/pkg/ent/ent/ent.go index 66183028..3aa2b11a 100644 --- a/internal/app/pkg/ent/ent/ent.go +++ b/internal/app/pkg/ent/ent/ent.go @@ -6,8 +6,12 @@ import ( "context" "errors" "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/pkg/ent/ent/role" "go-scaffold/internal/app/pkg/ent/ent/user" "reflect" + "sync" "entgo.io/ent" "entgo.io/ent/dialect/sql" @@ -33,34 +37,59 @@ type ( MutateFunc = ent.MutateFunc ) +type clientCtxKey struct{} + +// FromContext returns a Client stored inside a context, or nil if there isn't one. +func FromContext(ctx context.Context) *Client { + c, _ := ctx.Value(clientCtxKey{}).(*Client) + return c +} + +// NewContext returns a new context with the given Client attached. +func NewContext(parent context.Context, c *Client) context.Context { + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns a Tx stored inside a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Tx attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) +} + // OrderFunc applies an ordering on the sql selector. +// Deprecated: Use Asc/Desc functions or the package builders instead. type OrderFunc func(*sql.Selector) -// columnChecker returns a function indicates if the column exists in the given column. -func columnChecker(table string) func(string) error { - checks := map[string]func(string) bool{ - user.Table: user.ValidColumn, - } - check, ok := checks[table] - if !ok { - return func(string) error { - return fmt.Errorf("unknown table %q", table) - } - } - return func(column string) error { - if !check(column) { - return fmt.Errorf("unknown column %q for table %q", column, table) - } - return nil - } +var ( + initCheck sync.Once + columnCheck sql.ColumnCheck +) + +// columnChecker checks if the column exists in the given table. +func checkColumn(table, column string) error { + initCheck.Do(func() { + columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ + permission.Table: permission.ValidColumn, + product.Table: product.ValidColumn, + role.Table: role.ValidColumn, + user.Table: user.ValidColumn, + }) + }) + return columnCheck(table, column) } // Asc applies the given fields in ASC order. -func Asc(fields ...string) OrderFunc { +func Asc(fields ...string) func(*sql.Selector) { return func(s *sql.Selector) { - check := columnChecker(s.TableName()) for _, f := range fields { - if err := check(f); err != nil { + if err := checkColumn(s.TableName(), f); err != nil { s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) } s.OrderBy(sql.Asc(s.C(f))) @@ -69,11 +98,10 @@ func Asc(fields ...string) OrderFunc { } // Desc applies the given fields in DESC order. -func Desc(fields ...string) OrderFunc { +func Desc(fields ...string) func(*sql.Selector) { return func(s *sql.Selector) { - check := columnChecker(s.TableName()) for _, f := range fields { - if err := check(f); err != nil { + if err := checkColumn(s.TableName(), f); err != nil { s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) } s.OrderBy(sql.Desc(s.C(f))) @@ -105,8 +133,7 @@ func Count() AggregateFunc { // Max applies the "max" aggregation function on the given field of each group. func Max(field string) AggregateFunc { return func(s *sql.Selector) string { - check := columnChecker(s.TableName()) - if err := check(field); err != nil { + if err := checkColumn(s.TableName(), field); err != nil { s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) return "" } @@ -117,8 +144,7 @@ func Max(field string) AggregateFunc { // Mean applies the "mean" aggregation function on the given field of each group. func Mean(field string) AggregateFunc { return func(s *sql.Selector) string { - check := columnChecker(s.TableName()) - if err := check(field); err != nil { + if err := checkColumn(s.TableName(), field); err != nil { s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) return "" } @@ -129,8 +155,7 @@ func Mean(field string) AggregateFunc { // Min applies the "min" aggregation function on the given field of each group. func Min(field string) AggregateFunc { return func(s *sql.Selector) string { - check := columnChecker(s.TableName()) - if err := check(field); err != nil { + if err := checkColumn(s.TableName(), field); err != nil { s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) return "" } @@ -141,8 +166,7 @@ func Min(field string) AggregateFunc { // Sum applies the "sum" aggregation function on the given field of each group. func Sum(field string) AggregateFunc { return func(s *sql.Selector) string { - check := columnChecker(s.TableName()) - if err := check(field); err != nil { + if err := checkColumn(s.TableName(), field); err != nil { s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) return "" } @@ -479,7 +503,7 @@ func withHooks[V Value, M any, PM interface { return exec(ctx) } var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { - mutationT, ok := m.(PM) + mutationT, ok := any(m).(PM) if !ok { return nil, fmt.Errorf("unexpected mutation type %T", m) } diff --git a/internal/app/pkg/ent/ent/hook/hook.go b/internal/app/pkg/ent/ent/hook/hook.go index 4fbac550..122f1119 100644 --- a/internal/app/pkg/ent/ent/hook/hook.go +++ b/internal/app/pkg/ent/ent/hook/hook.go @@ -8,6 +8,42 @@ import ( "go-scaffold/internal/app/pkg/ent/ent" ) +// The PermissionFunc type is an adapter to allow the use of ordinary +// function as Permission mutator. +type PermissionFunc func(context.Context, *ent.PermissionMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f PermissionFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.PermissionMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PermissionMutation", m) +} + +// The ProductFunc type is an adapter to allow the use of ordinary +// function as Product mutator. +type ProductFunc func(context.Context, *ent.ProductMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ProductFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.ProductMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ProductMutation", m) +} + +// The RoleFunc type is an adapter to allow the use of ordinary +// function as Role mutator. +type RoleFunc func(context.Context, *ent.RoleMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f RoleFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.RoleMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.RoleMutation", m) +} + // The UserFunc type is an adapter to allow the use of ordinary // function as User mutator. type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error) diff --git a/internal/app/pkg/ent/ent/intercept/intercept.go b/internal/app/pkg/ent/ent/intercept/intercept.go index 38ea9bae..5007bb9a 100644 --- a/internal/app/pkg/ent/ent/intercept/intercept.go +++ b/internal/app/pkg/ent/ent/intercept/intercept.go @@ -6,7 +6,11 @@ import ( "context" "fmt" "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/permission" "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/pkg/ent/ent/role" + "go-scaffold/internal/app/pkg/ent/ent/user" "entgo.io/ent/dialect/sql" ) @@ -24,7 +28,7 @@ type Query interface { // Unique configures the query builder to filter duplicate records. Unique(bool) // Order specifies how the records should be ordered. - Order(...ent.OrderFunc) + Order(...func(*sql.Selector)) // WhereP appends storage-level predicates to the query builder. Using this method, users // can use type-assertion to append predicates that do not depend on any generated package. WhereP(...func(*sql.Selector)) @@ -67,6 +71,87 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error { return f(ctx, query) } +// The PermissionFunc type is an adapter to allow the use of ordinary function as a Querier. +type PermissionFunc func(context.Context, *ent.PermissionQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f PermissionFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.PermissionQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.PermissionQuery", q) +} + +// The TraversePermission type is an adapter to allow the use of ordinary function as Traverser. +type TraversePermission func(context.Context, *ent.PermissionQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraversePermission) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraversePermission) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.PermissionQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.PermissionQuery", q) +} + +// The ProductFunc type is an adapter to allow the use of ordinary function as a Querier. +type ProductFunc func(context.Context, *ent.ProductQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f ProductFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.ProductQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.ProductQuery", q) +} + +// The TraverseProduct type is an adapter to allow the use of ordinary function as Traverser. +type TraverseProduct func(context.Context, *ent.ProductQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseProduct) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseProduct) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ProductQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.ProductQuery", q) +} + +// The RoleFunc type is an adapter to allow the use of ordinary function as a Querier. +type RoleFunc func(context.Context, *ent.RoleQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f RoleFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.RoleQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.RoleQuery", q) +} + +// The TraverseRole type is an adapter to allow the use of ordinary function as Traverser. +type TraverseRole func(context.Context, *ent.RoleQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseRole) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseRole) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.RoleQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.RoleQuery", q) +} + // The UserFunc type is an adapter to allow the use of ordinary function as a Querier. type UserFunc func(context.Context, *ent.UserQuery) (ent.Value, error) @@ -97,45 +182,55 @@ func (f TraverseUser) Traverse(ctx context.Context, q ent.Query) error { // NewQuery returns the generic Query interface for the given typed query. func NewQuery(q ent.Query) (Query, error) { switch q := q.(type) { + case *ent.PermissionQuery: + return &query[*ent.PermissionQuery, predicate.Permission, permission.OrderOption]{typ: ent.TypePermission, tq: q}, nil + case *ent.ProductQuery: + return &query[*ent.ProductQuery, predicate.Product, product.OrderOption]{typ: ent.TypeProduct, tq: q}, nil + case *ent.RoleQuery: + return &query[*ent.RoleQuery, predicate.Role, role.OrderOption]{typ: ent.TypeRole, tq: q}, nil case *ent.UserQuery: - return &query[*ent.UserQuery, predicate.User]{typ: ent.TypeUser, tq: q}, nil + return &query[*ent.UserQuery, predicate.User, user.OrderOption]{typ: ent.TypeUser, tq: q}, nil default: return nil, fmt.Errorf("unknown query type %T", q) } } -type query[T any, P ~func(*sql.Selector)] struct { +type query[T any, P ~func(*sql.Selector), R ~func(*sql.Selector)] struct { typ string tq interface { Limit(int) T Offset(int) T Unique(bool) T - Order(...ent.OrderFunc) T + Order(...R) T Where(...P) T } } -func (q query[T, P]) Type() string { +func (q query[T, P, R]) Type() string { return q.typ } -func (q query[T, P]) Limit(limit int) { +func (q query[T, P, R]) Limit(limit int) { q.tq.Limit(limit) } -func (q query[T, P]) Offset(offset int) { +func (q query[T, P, R]) Offset(offset int) { q.tq.Offset(offset) } -func (q query[T, P]) Unique(unique bool) { +func (q query[T, P, R]) Unique(unique bool) { q.tq.Unique(unique) } -func (q query[T, P]) Order(orders ...ent.OrderFunc) { - q.tq.Order(orders...) +func (q query[T, P, R]) Order(orders ...func(*sql.Selector)) { + rs := make([]R, len(orders)) + for i := range orders { + rs[i] = orders[i] + } + q.tq.Order(rs...) } -func (q query[T, P]) WhereP(ps ...func(*sql.Selector)) { +func (q query[T, P, R]) WhereP(ps ...func(*sql.Selector)) { p := make([]P, len(ps)) for i := range ps { p[i] = ps[i] diff --git a/internal/app/pkg/ent/ent/migrate/schema.go b/internal/app/pkg/ent/ent/migrate/schema.go index 230c2c4d..954c3cf5 100644 --- a/internal/app/pkg/ent/ent/migrate/schema.go +++ b/internal/app/pkg/ent/ent/migrate/schema.go @@ -9,15 +9,78 @@ import ( ) var ( + // PermissionsColumns holds the columns for the "permissions" table. + PermissionsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt64, Increment: true}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "updated_at", Type: field.TypeTime}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, + {Name: "key", Type: field.TypeString, Unique: true, Size: 128, Comment: "权限标识"}, + {Name: "name", Type: field.TypeString, Size: 128, Comment: "权限名称", Default: ""}, + {Name: "desc", Type: field.TypeString, Size: 255, Comment: "权限描述", Default: ""}, + {Name: "parent_id", Type: field.TypeInt64, Comment: "父级权限 id", Default: 0}, + } + // PermissionsTable holds the schema information for the "permissions" table. + PermissionsTable = &schema.Table{ + Name: "permissions", + Columns: PermissionsColumns, + PrimaryKey: []*schema.Column{PermissionsColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "permission_key", + Unique: false, + Columns: []*schema.Column{PermissionsColumns[4]}, + }, + }, + } + // ProductsColumns holds the columns for the "products" table. + ProductsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt64, Increment: true}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "updated_at", Type: field.TypeTime}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, + {Name: "name", Type: field.TypeString, Comment: "名称", Default: ""}, + {Name: "desc", Type: field.TypeString, Comment: "描述", Default: ""}, + {Name: "price", Type: field.TypeInt, Comment: "价格", Default: 0}, + } + // ProductsTable holds the schema information for the "products" table. + ProductsTable = &schema.Table{ + Name: "products", + Columns: ProductsColumns, + PrimaryKey: []*schema.Column{ProductsColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "product_name", + Unique: false, + Columns: []*schema.Column{ProductsColumns[4]}, + }, + }, + } + // RolesColumns holds the columns for the "roles" table. + RolesColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt64, Increment: true}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "updated_at", Type: field.TypeTime}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, + {Name: "name", Type: field.TypeString, Unique: true, Size: 32, Comment: "角色名称"}, + } + // RolesTable holds the schema information for the "roles" table. + RolesTable = &schema.Table{ + Name: "roles", + Columns: RolesColumns, + PrimaryKey: []*schema.Column{RolesColumns[0]}, + } // UsersColumns holds the columns for the "users" table. UsersColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt64, Increment: true}, {Name: "created_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime}, {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, - {Name: "name", Type: field.TypeString, Comment: "名称", Default: ""}, - {Name: "age", Type: field.TypeInt8, Comment: "年龄", Default: 0}, + {Name: "username", Type: field.TypeString, Comment: "用户名", Default: ""}, + {Name: "password", Type: field.TypeString, Comment: "密码", Default: ""}, + {Name: "nickname", Type: field.TypeString, Comment: "用户名", Default: ""}, {Name: "phone", Type: field.TypeString, Comment: "电话", Default: ""}, + {Name: "salt", Type: field.TypeString, Comment: "盐值", Default: ""}, } // UsersTable holds the schema information for the "users" table. UsersTable = &schema.Table{ @@ -26,24 +89,39 @@ var ( PrimaryKey: []*schema.Column{UsersColumns[0]}, Indexes: []*schema.Index{ { - Name: "user_name", + Name: "user_username", Unique: false, Columns: []*schema.Column{UsersColumns[4]}, }, { Name: "user_phone", Unique: false, - Columns: []*schema.Column{UsersColumns[6]}, + Columns: []*schema.Column{UsersColumns[7]}, }, }, } // Tables holds all the tables in the schema. Tables = []*schema.Table{ + PermissionsTable, + ProductsTable, + RolesTable, UsersTable, } ) func init() { + PermissionsTable.Annotation = &entsql.Annotation{ + Table: "permissions", + Options: "COMMENT='权限表'", + } + ProductsTable.Annotation = &entsql.Annotation{ + Table: "products", + Options: "COMMENT='产品表'", + } + RolesTable.Annotation = &entsql.Annotation{ + Table: "roles", + Options: "COMMENT='角色表'", + } UsersTable.Annotation = &entsql.Annotation{ Table: "users", Options: "COMMENT='用户表'", diff --git a/internal/app/pkg/ent/ent/mutation.go b/internal/app/pkg/ent/ent/mutation.go index 6b8766d3..a6108fbf 100644 --- a/internal/app/pkg/ent/ent/mutation.go +++ b/internal/app/pkg/ent/ent/mutation.go @@ -6,7 +6,10 @@ import ( "context" "errors" "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/pkg/ent/ent/role" "go-scaffold/internal/app/pkg/ent/ent/user" "go-scaffold/internal/app/repository/schema/types" "sync" @@ -24,9 +27,1902 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. - TypeUser = "User" + TypePermission = "Permission" + TypeProduct = "Product" + TypeRole = "Role" + TypeUser = "User" ) +// PermissionMutation represents an operation that mutates the Permission nodes in the graph. +type PermissionMutation struct { + config + op Op + typ string + id *int64 + created_at *types.UnixTimestamp + updated_at *types.UnixTimestamp + deleted_at *types.UnixTimestamp + key *string + name *string + desc *string + parent_id *int64 + addparent_id *int64 + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*Permission, error) + predicates []predicate.Permission +} + +var _ ent.Mutation = (*PermissionMutation)(nil) + +// permissionOption allows management of the mutation configuration using functional options. +type permissionOption func(*PermissionMutation) + +// newPermissionMutation creates new mutation for the Permission entity. +func newPermissionMutation(c config, op Op, opts ...permissionOption) *PermissionMutation { + m := &PermissionMutation{ + config: c, + op: op, + typ: TypePermission, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withPermissionID sets the ID field of the mutation. +func withPermissionID(id int64) permissionOption { + return func(m *PermissionMutation) { + var ( + err error + once sync.Once + value *Permission + ) + m.oldValue = func(ctx context.Context) (*Permission, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Permission.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withPermission sets the old Permission of the mutation. +func withPermission(node *Permission) permissionOption { + return func(m *PermissionMutation) { + m.oldValue = func(context.Context) (*Permission, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m PermissionMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m PermissionMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Permission entities. +func (m *PermissionMutation) SetID(id int64) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *PermissionMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *PermissionMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Permission.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *PermissionMutation) SetCreatedAt(tt types.UnixTimestamp) { + m.created_at = &tt +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *PermissionMutation) CreatedAt() (r types.UnixTimestamp, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldCreatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *PermissionMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *PermissionMutation) SetUpdatedAt(tt types.UnixTimestamp) { + m.updated_at = &tt +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *PermissionMutation) UpdatedAt() (r types.UnixTimestamp, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldUpdatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *PermissionMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *PermissionMutation) SetDeletedAt(tt types.UnixTimestamp) { + m.deleted_at = &tt +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *PermissionMutation) DeletedAt() (r types.UnixTimestamp, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldDeletedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *PermissionMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[permission.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *PermissionMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[permission.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *PermissionMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, permission.FieldDeletedAt) +} + +// SetKey sets the "key" field. +func (m *PermissionMutation) SetKey(s string) { + m.key = &s +} + +// Key returns the value of the "key" field in the mutation. +func (m *PermissionMutation) Key() (r string, exists bool) { + v := m.key + if v == nil { + return + } + return *v, true +} + +// OldKey returns the old "key" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldKey(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldKey is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldKey requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldKey: %w", err) + } + return oldValue.Key, nil +} + +// ResetKey resets all changes to the "key" field. +func (m *PermissionMutation) ResetKey() { + m.key = nil +} + +// SetName sets the "name" field. +func (m *PermissionMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *PermissionMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *PermissionMutation) ResetName() { + m.name = nil +} + +// SetDesc sets the "desc" field. +func (m *PermissionMutation) SetDesc(s string) { + m.desc = &s +} + +// Desc returns the value of the "desc" field in the mutation. +func (m *PermissionMutation) Desc() (r string, exists bool) { + v := m.desc + if v == nil { + return + } + return *v, true +} + +// OldDesc returns the old "desc" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldDesc(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDesc is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDesc requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDesc: %w", err) + } + return oldValue.Desc, nil +} + +// ResetDesc resets all changes to the "desc" field. +func (m *PermissionMutation) ResetDesc() { + m.desc = nil +} + +// SetParentID sets the "parent_id" field. +func (m *PermissionMutation) SetParentID(i int64) { + m.parent_id = &i + m.addparent_id = nil +} + +// ParentID returns the value of the "parent_id" field in the mutation. +func (m *PermissionMutation) ParentID() (r int64, exists bool) { + v := m.parent_id + if v == nil { + return + } + return *v, true +} + +// OldParentID returns the old "parent_id" field's value of the Permission entity. +// If the Permission object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *PermissionMutation) OldParentID(ctx context.Context) (v int64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldParentID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldParentID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldParentID: %w", err) + } + return oldValue.ParentID, nil +} + +// AddParentID adds i to the "parent_id" field. +func (m *PermissionMutation) AddParentID(i int64) { + if m.addparent_id != nil { + *m.addparent_id += i + } else { + m.addparent_id = &i + } +} + +// AddedParentID returns the value that was added to the "parent_id" field in this mutation. +func (m *PermissionMutation) AddedParentID() (r int64, exists bool) { + v := m.addparent_id + if v == nil { + return + } + return *v, true +} + +// ResetParentID resets all changes to the "parent_id" field. +func (m *PermissionMutation) ResetParentID() { + m.parent_id = nil + m.addparent_id = nil +} + +// Where appends a list predicates to the PermissionMutation builder. +func (m *PermissionMutation) Where(ps ...predicate.Permission) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the PermissionMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *PermissionMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Permission, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *PermissionMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *PermissionMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Permission). +func (m *PermissionMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *PermissionMutation) Fields() []string { + fields := make([]string, 0, 7) + if m.created_at != nil { + fields = append(fields, permission.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, permission.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, permission.FieldDeletedAt) + } + if m.key != nil { + fields = append(fields, permission.FieldKey) + } + if m.name != nil { + fields = append(fields, permission.FieldName) + } + if m.desc != nil { + fields = append(fields, permission.FieldDesc) + } + if m.parent_id != nil { + fields = append(fields, permission.FieldParentID) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *PermissionMutation) Field(name string) (ent.Value, bool) { + switch name { + case permission.FieldCreatedAt: + return m.CreatedAt() + case permission.FieldUpdatedAt: + return m.UpdatedAt() + case permission.FieldDeletedAt: + return m.DeletedAt() + case permission.FieldKey: + return m.Key() + case permission.FieldName: + return m.Name() + case permission.FieldDesc: + return m.Desc() + case permission.FieldParentID: + return m.ParentID() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *PermissionMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case permission.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case permission.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case permission.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case permission.FieldKey: + return m.OldKey(ctx) + case permission.FieldName: + return m.OldName(ctx) + case permission.FieldDesc: + return m.OldDesc(ctx) + case permission.FieldParentID: + return m.OldParentID(ctx) + } + return nil, fmt.Errorf("unknown Permission field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PermissionMutation) SetField(name string, value ent.Value) error { + switch name { + case permission.FieldCreatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case permission.FieldUpdatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case permission.FieldDeletedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case permission.FieldKey: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetKey(v) + return nil + case permission.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case permission.FieldDesc: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDesc(v) + return nil + case permission.FieldParentID: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetParentID(v) + return nil + } + return fmt.Errorf("unknown Permission field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *PermissionMutation) AddedFields() []string { + var fields []string + if m.addparent_id != nil { + fields = append(fields, permission.FieldParentID) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *PermissionMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case permission.FieldParentID: + return m.AddedParentID() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *PermissionMutation) AddField(name string, value ent.Value) error { + switch name { + case permission.FieldParentID: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddParentID(v) + return nil + } + return fmt.Errorf("unknown Permission numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *PermissionMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(permission.FieldDeletedAt) { + fields = append(fields, permission.FieldDeletedAt) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *PermissionMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *PermissionMutation) ClearField(name string) error { + switch name { + case permission.FieldDeletedAt: + m.ClearDeletedAt() + return nil + } + return fmt.Errorf("unknown Permission nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *PermissionMutation) ResetField(name string) error { + switch name { + case permission.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case permission.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case permission.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case permission.FieldKey: + m.ResetKey() + return nil + case permission.FieldName: + m.ResetName() + return nil + case permission.FieldDesc: + m.ResetDesc() + return nil + case permission.FieldParentID: + m.ResetParentID() + return nil + } + return fmt.Errorf("unknown Permission field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *PermissionMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *PermissionMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *PermissionMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *PermissionMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *PermissionMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *PermissionMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *PermissionMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown Permission unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *PermissionMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown Permission edge %s", name) +} + +// ProductMutation represents an operation that mutates the Product nodes in the graph. +type ProductMutation struct { + config + op Op + typ string + id *int64 + created_at *types.UnixTimestamp + updated_at *types.UnixTimestamp + deleted_at *types.UnixTimestamp + name *string + desc *string + price *int + addprice *int + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*Product, error) + predicates []predicate.Product +} + +var _ ent.Mutation = (*ProductMutation)(nil) + +// productOption allows management of the mutation configuration using functional options. +type productOption func(*ProductMutation) + +// newProductMutation creates new mutation for the Product entity. +func newProductMutation(c config, op Op, opts ...productOption) *ProductMutation { + m := &ProductMutation{ + config: c, + op: op, + typ: TypeProduct, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withProductID sets the ID field of the mutation. +func withProductID(id int64) productOption { + return func(m *ProductMutation) { + var ( + err error + once sync.Once + value *Product + ) + m.oldValue = func(ctx context.Context) (*Product, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Product.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withProduct sets the old Product of the mutation. +func withProduct(node *Product) productOption { + return func(m *ProductMutation) { + m.oldValue = func(context.Context) (*Product, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ProductMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ProductMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Product entities. +func (m *ProductMutation) SetID(id int64) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ProductMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ProductMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Product.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *ProductMutation) SetCreatedAt(tt types.UnixTimestamp) { + m.created_at = &tt +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *ProductMutation) CreatedAt() (r types.UnixTimestamp, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldCreatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *ProductMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *ProductMutation) SetUpdatedAt(tt types.UnixTimestamp) { + m.updated_at = &tt +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *ProductMutation) UpdatedAt() (r types.UnixTimestamp, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldUpdatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *ProductMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *ProductMutation) SetDeletedAt(tt types.UnixTimestamp) { + m.deleted_at = &tt +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *ProductMutation) DeletedAt() (r types.UnixTimestamp, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldDeletedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *ProductMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[product.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *ProductMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[product.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *ProductMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, product.FieldDeletedAt) +} + +// SetName sets the "name" field. +func (m *ProductMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ProductMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ProductMutation) ResetName() { + m.name = nil +} + +// SetDesc sets the "desc" field. +func (m *ProductMutation) SetDesc(s string) { + m.desc = &s +} + +// Desc returns the value of the "desc" field in the mutation. +func (m *ProductMutation) Desc() (r string, exists bool) { + v := m.desc + if v == nil { + return + } + return *v, true +} + +// OldDesc returns the old "desc" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldDesc(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDesc is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDesc requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDesc: %w", err) + } + return oldValue.Desc, nil +} + +// ResetDesc resets all changes to the "desc" field. +func (m *ProductMutation) ResetDesc() { + m.desc = nil +} + +// SetPrice sets the "price" field. +func (m *ProductMutation) SetPrice(i int) { + m.price = &i + m.addprice = nil +} + +// Price returns the value of the "price" field in the mutation. +func (m *ProductMutation) Price() (r int, exists bool) { + v := m.price + if v == nil { + return + } + return *v, true +} + +// OldPrice returns the old "price" field's value of the Product entity. +// If the Product object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProductMutation) OldPrice(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPrice is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPrice requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPrice: %w", err) + } + return oldValue.Price, nil +} + +// AddPrice adds i to the "price" field. +func (m *ProductMutation) AddPrice(i int) { + if m.addprice != nil { + *m.addprice += i + } else { + m.addprice = &i + } +} + +// AddedPrice returns the value that was added to the "price" field in this mutation. +func (m *ProductMutation) AddedPrice() (r int, exists bool) { + v := m.addprice + if v == nil { + return + } + return *v, true +} + +// ResetPrice resets all changes to the "price" field. +func (m *ProductMutation) ResetPrice() { + m.price = nil + m.addprice = nil +} + +// Where appends a list predicates to the ProductMutation builder. +func (m *ProductMutation) Where(ps ...predicate.Product) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the ProductMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *ProductMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Product, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *ProductMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *ProductMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Product). +func (m *ProductMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ProductMutation) Fields() []string { + fields := make([]string, 0, 6) + if m.created_at != nil { + fields = append(fields, product.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, product.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, product.FieldDeletedAt) + } + if m.name != nil { + fields = append(fields, product.FieldName) + } + if m.desc != nil { + fields = append(fields, product.FieldDesc) + } + if m.price != nil { + fields = append(fields, product.FieldPrice) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ProductMutation) Field(name string) (ent.Value, bool) { + switch name { + case product.FieldCreatedAt: + return m.CreatedAt() + case product.FieldUpdatedAt: + return m.UpdatedAt() + case product.FieldDeletedAt: + return m.DeletedAt() + case product.FieldName: + return m.Name() + case product.FieldDesc: + return m.Desc() + case product.FieldPrice: + return m.Price() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ProductMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case product.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case product.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case product.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case product.FieldName: + return m.OldName(ctx) + case product.FieldDesc: + return m.OldDesc(ctx) + case product.FieldPrice: + return m.OldPrice(ctx) + } + return nil, fmt.Errorf("unknown Product field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ProductMutation) SetField(name string, value ent.Value) error { + switch name { + case product.FieldCreatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case product.FieldUpdatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case product.FieldDeletedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case product.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case product.FieldDesc: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDesc(v) + return nil + case product.FieldPrice: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPrice(v) + return nil + } + return fmt.Errorf("unknown Product field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ProductMutation) AddedFields() []string { + var fields []string + if m.addprice != nil { + fields = append(fields, product.FieldPrice) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ProductMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case product.FieldPrice: + return m.AddedPrice() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ProductMutation) AddField(name string, value ent.Value) error { + switch name { + case product.FieldPrice: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddPrice(v) + return nil + } + return fmt.Errorf("unknown Product numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ProductMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(product.FieldDeletedAt) { + fields = append(fields, product.FieldDeletedAt) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ProductMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ProductMutation) ClearField(name string) error { + switch name { + case product.FieldDeletedAt: + m.ClearDeletedAt() + return nil + } + return fmt.Errorf("unknown Product nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ProductMutation) ResetField(name string) error { + switch name { + case product.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case product.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case product.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case product.FieldName: + m.ResetName() + return nil + case product.FieldDesc: + m.ResetDesc() + return nil + case product.FieldPrice: + m.ResetPrice() + return nil + } + return fmt.Errorf("unknown Product field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ProductMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ProductMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ProductMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ProductMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ProductMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ProductMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ProductMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown Product unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ProductMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown Product edge %s", name) +} + +// RoleMutation represents an operation that mutates the Role nodes in the graph. +type RoleMutation struct { + config + op Op + typ string + id *int64 + created_at *types.UnixTimestamp + updated_at *types.UnixTimestamp + deleted_at *types.UnixTimestamp + name *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*Role, error) + predicates []predicate.Role +} + +var _ ent.Mutation = (*RoleMutation)(nil) + +// roleOption allows management of the mutation configuration using functional options. +type roleOption func(*RoleMutation) + +// newRoleMutation creates new mutation for the Role entity. +func newRoleMutation(c config, op Op, opts ...roleOption) *RoleMutation { + m := &RoleMutation{ + config: c, + op: op, + typ: TypeRole, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withRoleID sets the ID field of the mutation. +func withRoleID(id int64) roleOption { + return func(m *RoleMutation) { + var ( + err error + once sync.Once + value *Role + ) + m.oldValue = func(ctx context.Context) (*Role, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Role.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withRole sets the old Role of the mutation. +func withRole(node *Role) roleOption { + return func(m *RoleMutation) { + m.oldValue = func(context.Context) (*Role, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m RoleMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m RoleMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Role entities. +func (m *RoleMutation) SetID(id int64) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *RoleMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *RoleMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Role.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *RoleMutation) SetCreatedAt(tt types.UnixTimestamp) { + m.created_at = &tt +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *RoleMutation) CreatedAt() (r types.UnixTimestamp, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Role entity. +// If the Role object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *RoleMutation) OldCreatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *RoleMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *RoleMutation) SetUpdatedAt(tt types.UnixTimestamp) { + m.updated_at = &tt +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *RoleMutation) UpdatedAt() (r types.UnixTimestamp, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the Role entity. +// If the Role object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *RoleMutation) OldUpdatedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *RoleMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *RoleMutation) SetDeletedAt(tt types.UnixTimestamp) { + m.deleted_at = &tt +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *RoleMutation) DeletedAt() (r types.UnixTimestamp, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the Role entity. +// If the Role object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *RoleMutation) OldDeletedAt(ctx context.Context) (v types.UnixTimestamp, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *RoleMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[role.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *RoleMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[role.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *RoleMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, role.FieldDeletedAt) +} + +// SetName sets the "name" field. +func (m *RoleMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *RoleMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Role entity. +// If the Role object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *RoleMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *RoleMutation) ResetName() { + m.name = nil +} + +// Where appends a list predicates to the RoleMutation builder. +func (m *RoleMutation) Where(ps ...predicate.Role) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the RoleMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *RoleMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Role, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *RoleMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *RoleMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Role). +func (m *RoleMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *RoleMutation) Fields() []string { + fields := make([]string, 0, 4) + if m.created_at != nil { + fields = append(fields, role.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, role.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, role.FieldDeletedAt) + } + if m.name != nil { + fields = append(fields, role.FieldName) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *RoleMutation) Field(name string) (ent.Value, bool) { + switch name { + case role.FieldCreatedAt: + return m.CreatedAt() + case role.FieldUpdatedAt: + return m.UpdatedAt() + case role.FieldDeletedAt: + return m.DeletedAt() + case role.FieldName: + return m.Name() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *RoleMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case role.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case role.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case role.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case role.FieldName: + return m.OldName(ctx) + } + return nil, fmt.Errorf("unknown Role field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *RoleMutation) SetField(name string, value ent.Value) error { + switch name { + case role.FieldCreatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case role.FieldUpdatedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case role.FieldDeletedAt: + v, ok := value.(types.UnixTimestamp) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case role.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + } + return fmt.Errorf("unknown Role field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *RoleMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *RoleMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *RoleMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown Role numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *RoleMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(role.FieldDeletedAt) { + fields = append(fields, role.FieldDeletedAt) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *RoleMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *RoleMutation) ClearField(name string) error { + switch name { + case role.FieldDeletedAt: + m.ClearDeletedAt() + return nil + } + return fmt.Errorf("unknown Role nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *RoleMutation) ResetField(name string) error { + switch name { + case role.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case role.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case role.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case role.FieldName: + m.ResetName() + return nil + } + return fmt.Errorf("unknown Role field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *RoleMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *RoleMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *RoleMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *RoleMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *RoleMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *RoleMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *RoleMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown Role unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *RoleMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown Role edge %s", name) +} + // UserMutation represents an operation that mutates the User nodes in the graph. type UserMutation struct { config @@ -36,10 +1932,11 @@ type UserMutation struct { created_at *types.UnixTimestamp updated_at *types.UnixTimestamp deleted_at *types.UnixTimestamp - name *string - age *int8 - addage *int8 + username *string + password *string + nickname *string phone *string + salt *string clearedFields map[string]struct{} done bool oldValue func(context.Context) (*User, error) @@ -271,96 +2168,112 @@ func (m *UserMutation) ResetDeletedAt() { delete(m.clearedFields, user.FieldDeletedAt) } -// SetName sets the "name" field. -func (m *UserMutation) SetName(s string) { - m.name = &s +// SetUsername sets the "username" field. +func (m *UserMutation) SetUsername(s string) { + m.username = &s } -// Name returns the value of the "name" field in the mutation. -func (m *UserMutation) Name() (r string, exists bool) { - v := m.name +// Username returns the value of the "username" field in the mutation. +func (m *UserMutation) Username() (r string, exists bool) { + v := m.username if v == nil { return } return *v, true } -// OldName returns the old "name" field's value of the User entity. +// OldUsername returns the old "username" field's value of the User entity. // If the User object wasn't provided to the builder, the object is fetched from the database. // An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *UserMutation) OldName(ctx context.Context) (v string, err error) { +func (m *UserMutation) OldUsername(ctx context.Context) (v string, err error) { if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldName is only allowed on UpdateOne operations") + return v, errors.New("OldUsername is only allowed on UpdateOne operations") } if m.id == nil || m.oldValue == nil { - return v, errors.New("OldName requires an ID field in the mutation") + return v, errors.New("OldUsername requires an ID field in the mutation") } oldValue, err := m.oldValue(ctx) if err != nil { - return v, fmt.Errorf("querying old value for OldName: %w", err) + return v, fmt.Errorf("querying old value for OldUsername: %w", err) } - return oldValue.Name, nil + return oldValue.Username, nil } -// ResetName resets all changes to the "name" field. -func (m *UserMutation) ResetName() { - m.name = nil +// ResetUsername resets all changes to the "username" field. +func (m *UserMutation) ResetUsername() { + m.username = nil } -// SetAge sets the "age" field. -func (m *UserMutation) SetAge(i int8) { - m.age = &i - m.addage = nil +// SetPassword sets the "password" field. +func (m *UserMutation) SetPassword(s string) { + m.password = &s } -// Age returns the value of the "age" field in the mutation. -func (m *UserMutation) Age() (r int8, exists bool) { - v := m.age +// Password returns the value of the "password" field in the mutation. +func (m *UserMutation) Password() (r string, exists bool) { + v := m.password if v == nil { return } return *v, true } -// OldAge returns the old "age" field's value of the User entity. +// OldPassword returns the old "password" field's value of the User entity. // If the User object wasn't provided to the builder, the object is fetched from the database. // An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *UserMutation) OldAge(ctx context.Context) (v int8, err error) { +func (m *UserMutation) OldPassword(ctx context.Context) (v string, err error) { if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldAge is only allowed on UpdateOne operations") + return v, errors.New("OldPassword is only allowed on UpdateOne operations") } if m.id == nil || m.oldValue == nil { - return v, errors.New("OldAge requires an ID field in the mutation") + return v, errors.New("OldPassword requires an ID field in the mutation") } oldValue, err := m.oldValue(ctx) if err != nil { - return v, fmt.Errorf("querying old value for OldAge: %w", err) + return v, fmt.Errorf("querying old value for OldPassword: %w", err) } - return oldValue.Age, nil + return oldValue.Password, nil } -// AddAge adds i to the "age" field. -func (m *UserMutation) AddAge(i int8) { - if m.addage != nil { - *m.addage += i - } else { - m.addage = &i - } +// ResetPassword resets all changes to the "password" field. +func (m *UserMutation) ResetPassword() { + m.password = nil +} + +// SetNickname sets the "nickname" field. +func (m *UserMutation) SetNickname(s string) { + m.nickname = &s } -// AddedAge returns the value that was added to the "age" field in this mutation. -func (m *UserMutation) AddedAge() (r int8, exists bool) { - v := m.addage +// Nickname returns the value of the "nickname" field in the mutation. +func (m *UserMutation) Nickname() (r string, exists bool) { + v := m.nickname if v == nil { return } return *v, true } -// ResetAge resets all changes to the "age" field. -func (m *UserMutation) ResetAge() { - m.age = nil - m.addage = nil +// OldNickname returns the old "nickname" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldNickname(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldNickname is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldNickname requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldNickname: %w", err) + } + return oldValue.Nickname, nil +} + +// ResetNickname resets all changes to the "nickname" field. +func (m *UserMutation) ResetNickname() { + m.nickname = nil } // SetPhone sets the "phone" field. @@ -399,6 +2312,42 @@ func (m *UserMutation) ResetPhone() { m.phone = nil } +// SetSalt sets the "salt" field. +func (m *UserMutation) SetSalt(s string) { + m.salt = &s +} + +// Salt returns the value of the "salt" field in the mutation. +func (m *UserMutation) Salt() (r string, exists bool) { + v := m.salt + if v == nil { + return + } + return *v, true +} + +// OldSalt returns the old "salt" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldSalt(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSalt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSalt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSalt: %w", err) + } + return oldValue.Salt, nil +} + +// ResetSalt resets all changes to the "salt" field. +func (m *UserMutation) ResetSalt() { + m.salt = nil +} + // Where appends a list predicates to the UserMutation builder. func (m *UserMutation) Where(ps ...predicate.User) { m.predicates = append(m.predicates, ps...) @@ -433,7 +2382,7 @@ func (m *UserMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *UserMutation) Fields() []string { - fields := make([]string, 0, 6) + fields := make([]string, 0, 8) if m.created_at != nil { fields = append(fields, user.FieldCreatedAt) } @@ -443,15 +2392,21 @@ func (m *UserMutation) Fields() []string { if m.deleted_at != nil { fields = append(fields, user.FieldDeletedAt) } - if m.name != nil { - fields = append(fields, user.FieldName) + if m.username != nil { + fields = append(fields, user.FieldUsername) + } + if m.password != nil { + fields = append(fields, user.FieldPassword) } - if m.age != nil { - fields = append(fields, user.FieldAge) + if m.nickname != nil { + fields = append(fields, user.FieldNickname) } if m.phone != nil { fields = append(fields, user.FieldPhone) } + if m.salt != nil { + fields = append(fields, user.FieldSalt) + } return fields } @@ -466,12 +2421,16 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) { return m.UpdatedAt() case user.FieldDeletedAt: return m.DeletedAt() - case user.FieldName: - return m.Name() - case user.FieldAge: - return m.Age() + case user.FieldUsername: + return m.Username() + case user.FieldPassword: + return m.Password() + case user.FieldNickname: + return m.Nickname() case user.FieldPhone: return m.Phone() + case user.FieldSalt: + return m.Salt() } return nil, false } @@ -487,12 +2446,16 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er return m.OldUpdatedAt(ctx) case user.FieldDeletedAt: return m.OldDeletedAt(ctx) - case user.FieldName: - return m.OldName(ctx) - case user.FieldAge: - return m.OldAge(ctx) + case user.FieldUsername: + return m.OldUsername(ctx) + case user.FieldPassword: + return m.OldPassword(ctx) + case user.FieldNickname: + return m.OldNickname(ctx) case user.FieldPhone: return m.OldPhone(ctx) + case user.FieldSalt: + return m.OldSalt(ctx) } return nil, fmt.Errorf("unknown User field %s", name) } @@ -523,19 +2486,26 @@ func (m *UserMutation) SetField(name string, value ent.Value) error { } m.SetDeletedAt(v) return nil - case user.FieldName: + case user.FieldUsername: v, ok := value.(string) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } - m.SetName(v) + m.SetUsername(v) return nil - case user.FieldAge: - v, ok := value.(int8) + case user.FieldPassword: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPassword(v) + return nil + case user.FieldNickname: + v, ok := value.(string) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } - m.SetAge(v) + m.SetNickname(v) return nil case user.FieldPhone: v, ok := value.(string) @@ -544,6 +2514,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error { } m.SetPhone(v) return nil + case user.FieldSalt: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSalt(v) + return nil } return fmt.Errorf("unknown User field %s", name) } @@ -551,21 +2528,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error { // AddedFields returns all numeric fields that were incremented/decremented during // this mutation. func (m *UserMutation) AddedFields() []string { - var fields []string - if m.addage != nil { - fields = append(fields, user.FieldAge) - } - return fields + return nil } // AddedField returns the numeric value that was incremented/decremented on a field // with the given name. The second boolean return value indicates that this field // was not set, or was not defined in the schema. func (m *UserMutation) AddedField(name string) (ent.Value, bool) { - switch name { - case user.FieldAge: - return m.AddedAge() - } return nil, false } @@ -574,13 +2543,6 @@ func (m *UserMutation) AddedField(name string) (ent.Value, bool) { // type. func (m *UserMutation) AddField(name string, value ent.Value) error { switch name { - case user.FieldAge: - v, ok := value.(int8) - if !ok { - return fmt.Errorf("unexpected type %T for field %s", value, name) - } - m.AddAge(v) - return nil } return fmt.Errorf("unknown User numeric field %s", name) } @@ -626,15 +2588,21 @@ func (m *UserMutation) ResetField(name string) error { case user.FieldDeletedAt: m.ResetDeletedAt() return nil - case user.FieldName: - m.ResetName() + case user.FieldUsername: + m.ResetUsername() return nil - case user.FieldAge: - m.ResetAge() + case user.FieldPassword: + m.ResetPassword() + return nil + case user.FieldNickname: + m.ResetNickname() return nil case user.FieldPhone: m.ResetPhone() return nil + case user.FieldSalt: + m.ResetSalt() + return nil } return fmt.Errorf("unknown User field %s", name) } diff --git a/internal/app/pkg/ent/ent/permission.go b/internal/app/pkg/ent/ent/permission.go new file mode 100644 index 00000000..ef54f2d1 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission.go @@ -0,0 +1,172 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/repository/schema/types" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +// Permission is the model entity for the Permission schema. +type Permission struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt types.UnixTimestamp `json:"updated_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt types.UnixTimestamp `json:"deleted_at,omitempty"` + // 权限标识 + Key string `json:"key,omitempty"` + // 权限名称 + Name string `json:"name,omitempty"` + // 权限描述 + Desc string `json:"desc,omitempty"` + // 父级权限 id + ParentID int64 `json:"parent_id,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Permission) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case permission.FieldID, permission.FieldParentID: + values[i] = new(sql.NullInt64) + case permission.FieldKey, permission.FieldName, permission.FieldDesc: + values[i] = new(sql.NullString) + case permission.FieldCreatedAt, permission.FieldUpdatedAt, permission.FieldDeletedAt: + values[i] = new(types.UnixTimestamp) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Permission fields. +func (pe *Permission) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case permission.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = int64(value.Int64) + case permission.FieldCreatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value != nil { + pe.CreatedAt = *value + } + case permission.FieldUpdatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value != nil { + pe.UpdatedAt = *value + } + case permission.FieldDeletedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value != nil { + pe.DeletedAt = *value + } + case permission.FieldKey: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field key", values[i]) + } else if value.Valid { + pe.Key = value.String + } + case permission.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + pe.Name = value.String + } + case permission.FieldDesc: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field desc", values[i]) + } else if value.Valid { + pe.Desc = value.String + } + case permission.FieldParentID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field parent_id", values[i]) + } else if value.Valid { + pe.ParentID = value.Int64 + } + default: + pe.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Permission. +// This includes values selected through modifiers, order, etc. +func (pe *Permission) Value(name string) (ent.Value, error) { + return pe.selectValues.Get(name) +} + +// Update returns a builder for updating this Permission. +// Note that you need to call Permission.Unwrap() before calling this method if this Permission +// was returned from a transaction, and the transaction was committed or rolled back. +func (pe *Permission) Update() *PermissionUpdateOne { + return NewPermissionClient(pe.config).UpdateOne(pe) +} + +// Unwrap unwraps the Permission entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (pe *Permission) Unwrap() *Permission { + _tx, ok := pe.config.driver.(*txDriver) + if !ok { + panic("ent: Permission is not a transactional entity") + } + pe.config.driver = _tx.drv + return pe +} + +// String implements the fmt.Stringer. +func (pe *Permission) String() string { + var builder strings.Builder + builder.WriteString("Permission(") + builder.WriteString(fmt.Sprintf("id=%v, ", pe.ID)) + builder.WriteString("created_at=") + builder.WriteString(fmt.Sprintf("%v", pe.CreatedAt)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(fmt.Sprintf("%v", pe.UpdatedAt)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(fmt.Sprintf("%v", pe.DeletedAt)) + builder.WriteString(", ") + builder.WriteString("key=") + builder.WriteString(pe.Key) + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(pe.Name) + builder.WriteString(", ") + builder.WriteString("desc=") + builder.WriteString(pe.Desc) + builder.WriteString(", ") + builder.WriteString("parent_id=") + builder.WriteString(fmt.Sprintf("%v", pe.ParentID)) + builder.WriteByte(')') + return builder.String() +} + +// Permissions is a parsable slice of Permission. +type Permissions []*Permission diff --git a/internal/app/pkg/ent/ent/permission/permission.go b/internal/app/pkg/ent/ent/permission/permission.go new file mode 100644 index 00000000..e9efa5d5 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission/permission.go @@ -0,0 +1,126 @@ +// Code generated by ent, DO NOT EDIT. + +package permission + +import ( + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the permission type in the database. + Label = "permission" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldKey holds the string denoting the key field in the database. + FieldKey = "key" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldDesc holds the string denoting the desc field in the database. + FieldDesc = "desc" + // FieldParentID holds the string denoting the parent_id field in the database. + FieldParentID = "parent_id" + // Table holds the table name of the permission in the database. + Table = "permissions" +) + +// Columns holds all SQL columns for permission fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldKey, + FieldName, + FieldDesc, + FieldParentID, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + 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 _ "go-scaffold/internal/app/pkg/ent/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() types.UnixTimestamp + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() types.UnixTimestamp + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() types.UnixTimestamp + // KeyValidator is a validator for the "key" field. It is called by the builders before save. + KeyValidator func(string) error + // DefaultName holds the default value on creation for the "name" field. + DefaultName string + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // DefaultDesc holds the default value on creation for the "desc" field. + DefaultDesc string + // DescValidator is a validator for the "desc" field. It is called by the builders before save. + DescValidator func(string) error + // DefaultParentID holds the default value on creation for the "parent_id" field. + DefaultParentID int64 +) + +// OrderOption defines the ordering options for the Permission queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByKey orders the results by the key field. +func ByKey(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldKey, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByDesc orders the results by the desc field. +func ByDesc(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDesc, opts...).ToFunc() +} + +// ByParentID orders the results by the parent_id field. +func ByParentID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldParentID, opts...).ToFunc() +} diff --git a/internal/app/pkg/ent/ent/permission/where.go b/internal/app/pkg/ent/ent/permission/where.go new file mode 100644 index 00000000..809dc399 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission/where.go @@ -0,0 +1,487 @@ +// Code generated by ent, DO NOT EDIT. + +package permission + +import ( + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldID, id)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldDeletedAt, v)) +} + +// Key applies equality check predicate on the "key" field. It's identical to KeyEQ. +func Key(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldKey, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldName, v)) +} + +// Desc applies equality check predicate on the "desc" field. It's identical to DescEQ. +func Desc(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldDesc, v)) +} + +// ParentID applies equality check predicate on the "parent_id" field. It's identical to ParentIDEQ. +func ParentID(v int64) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldParentID, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v types.UnixTimestamp) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.Permission { + return predicate.Permission(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.Permission { + return predicate.Permission(sql.FieldNotNull(FieldDeletedAt)) +} + +// KeyEQ applies the EQ predicate on the "key" field. +func KeyEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldKey, v)) +} + +// KeyNEQ applies the NEQ predicate on the "key" field. +func KeyNEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldKey, v)) +} + +// KeyIn applies the In predicate on the "key" field. +func KeyIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldKey, vs...)) +} + +// KeyNotIn applies the NotIn predicate on the "key" field. +func KeyNotIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldKey, vs...)) +} + +// KeyGT applies the GT predicate on the "key" field. +func KeyGT(v string) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldKey, v)) +} + +// KeyGTE applies the GTE predicate on the "key" field. +func KeyGTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldKey, v)) +} + +// KeyLT applies the LT predicate on the "key" field. +func KeyLT(v string) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldKey, v)) +} + +// KeyLTE applies the LTE predicate on the "key" field. +func KeyLTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldKey, v)) +} + +// KeyContains applies the Contains predicate on the "key" field. +func KeyContains(v string) predicate.Permission { + return predicate.Permission(sql.FieldContains(FieldKey, v)) +} + +// KeyHasPrefix applies the HasPrefix predicate on the "key" field. +func KeyHasPrefix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasPrefix(FieldKey, v)) +} + +// KeyHasSuffix applies the HasSuffix predicate on the "key" field. +func KeyHasSuffix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasSuffix(FieldKey, v)) +} + +// KeyEqualFold applies the EqualFold predicate on the "key" field. +func KeyEqualFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldEqualFold(FieldKey, v)) +} + +// KeyContainsFold applies the ContainsFold predicate on the "key" field. +func KeyContainsFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldContainsFold(FieldKey, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Permission { + return predicate.Permission(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldContainsFold(FieldName, v)) +} + +// DescEQ applies the EQ predicate on the "desc" field. +func DescEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldDesc, v)) +} + +// DescNEQ applies the NEQ predicate on the "desc" field. +func DescNEQ(v string) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldDesc, v)) +} + +// DescIn applies the In predicate on the "desc" field. +func DescIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldDesc, vs...)) +} + +// DescNotIn applies the NotIn predicate on the "desc" field. +func DescNotIn(vs ...string) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldDesc, vs...)) +} + +// DescGT applies the GT predicate on the "desc" field. +func DescGT(v string) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldDesc, v)) +} + +// DescGTE applies the GTE predicate on the "desc" field. +func DescGTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldDesc, v)) +} + +// DescLT applies the LT predicate on the "desc" field. +func DescLT(v string) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldDesc, v)) +} + +// DescLTE applies the LTE predicate on the "desc" field. +func DescLTE(v string) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldDesc, v)) +} + +// DescContains applies the Contains predicate on the "desc" field. +func DescContains(v string) predicate.Permission { + return predicate.Permission(sql.FieldContains(FieldDesc, v)) +} + +// DescHasPrefix applies the HasPrefix predicate on the "desc" field. +func DescHasPrefix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasPrefix(FieldDesc, v)) +} + +// DescHasSuffix applies the HasSuffix predicate on the "desc" field. +func DescHasSuffix(v string) predicate.Permission { + return predicate.Permission(sql.FieldHasSuffix(FieldDesc, v)) +} + +// DescEqualFold applies the EqualFold predicate on the "desc" field. +func DescEqualFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldEqualFold(FieldDesc, v)) +} + +// DescContainsFold applies the ContainsFold predicate on the "desc" field. +func DescContainsFold(v string) predicate.Permission { + return predicate.Permission(sql.FieldContainsFold(FieldDesc, v)) +} + +// ParentIDEQ applies the EQ predicate on the "parent_id" field. +func ParentIDEQ(v int64) predicate.Permission { + return predicate.Permission(sql.FieldEQ(FieldParentID, v)) +} + +// ParentIDNEQ applies the NEQ predicate on the "parent_id" field. +func ParentIDNEQ(v int64) predicate.Permission { + return predicate.Permission(sql.FieldNEQ(FieldParentID, v)) +} + +// ParentIDIn applies the In predicate on the "parent_id" field. +func ParentIDIn(vs ...int64) predicate.Permission { + return predicate.Permission(sql.FieldIn(FieldParentID, vs...)) +} + +// ParentIDNotIn applies the NotIn predicate on the "parent_id" field. +func ParentIDNotIn(vs ...int64) predicate.Permission { + return predicate.Permission(sql.FieldNotIn(FieldParentID, vs...)) +} + +// ParentIDGT applies the GT predicate on the "parent_id" field. +func ParentIDGT(v int64) predicate.Permission { + return predicate.Permission(sql.FieldGT(FieldParentID, v)) +} + +// ParentIDGTE applies the GTE predicate on the "parent_id" field. +func ParentIDGTE(v int64) predicate.Permission { + return predicate.Permission(sql.FieldGTE(FieldParentID, v)) +} + +// ParentIDLT applies the LT predicate on the "parent_id" field. +func ParentIDLT(v int64) predicate.Permission { + return predicate.Permission(sql.FieldLT(FieldParentID, v)) +} + +// ParentIDLTE applies the LTE predicate on the "parent_id" field. +func ParentIDLTE(v int64) predicate.Permission { + return predicate.Permission(sql.FieldLTE(FieldParentID, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Permission) predicate.Permission { + return predicate.Permission(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Permission) predicate.Permission { + return predicate.Permission(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Permission) predicate.Permission { + return predicate.Permission(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/internal/app/pkg/ent/ent/permission_create.go b/internal/app/pkg/ent/ent/permission_create.go new file mode 100644 index 00000000..af59b93b --- /dev/null +++ b/internal/app/pkg/ent/ent/permission_create.go @@ -0,0 +1,365 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// PermissionCreate is the builder for creating a Permission entity. +type PermissionCreate struct { + config + mutation *PermissionMutation + hooks []Hook +} + +// SetCreatedAt sets the "created_at" field. +func (pc *PermissionCreate) SetCreatedAt(tt types.UnixTimestamp) *PermissionCreate { + pc.mutation.SetCreatedAt(tt) + return pc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableCreatedAt(tt *types.UnixTimestamp) *PermissionCreate { + if tt != nil { + pc.SetCreatedAt(*tt) + } + return pc +} + +// SetUpdatedAt sets the "updated_at" field. +func (pc *PermissionCreate) SetUpdatedAt(tt types.UnixTimestamp) *PermissionCreate { + pc.mutation.SetUpdatedAt(tt) + return pc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableUpdatedAt(tt *types.UnixTimestamp) *PermissionCreate { + if tt != nil { + pc.SetUpdatedAt(*tt) + } + return pc +} + +// SetDeletedAt sets the "deleted_at" field. +func (pc *PermissionCreate) SetDeletedAt(tt types.UnixTimestamp) *PermissionCreate { + pc.mutation.SetDeletedAt(tt) + return pc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableDeletedAt(tt *types.UnixTimestamp) *PermissionCreate { + if tt != nil { + pc.SetDeletedAt(*tt) + } + return pc +} + +// SetKey sets the "key" field. +func (pc *PermissionCreate) SetKey(s string) *PermissionCreate { + pc.mutation.SetKey(s) + return pc +} + +// SetName sets the "name" field. +func (pc *PermissionCreate) SetName(s string) *PermissionCreate { + pc.mutation.SetName(s) + return pc +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableName(s *string) *PermissionCreate { + if s != nil { + pc.SetName(*s) + } + return pc +} + +// SetDesc sets the "desc" field. +func (pc *PermissionCreate) SetDesc(s string) *PermissionCreate { + pc.mutation.SetDesc(s) + return pc +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableDesc(s *string) *PermissionCreate { + if s != nil { + pc.SetDesc(*s) + } + return pc +} + +// SetParentID sets the "parent_id" field. +func (pc *PermissionCreate) SetParentID(i int64) *PermissionCreate { + pc.mutation.SetParentID(i) + return pc +} + +// SetNillableParentID sets the "parent_id" field if the given value is not nil. +func (pc *PermissionCreate) SetNillableParentID(i *int64) *PermissionCreate { + if i != nil { + pc.SetParentID(*i) + } + return pc +} + +// SetID sets the "id" field. +func (pc *PermissionCreate) SetID(i int64) *PermissionCreate { + pc.mutation.SetID(i) + return pc +} + +// Mutation returns the PermissionMutation object of the builder. +func (pc *PermissionCreate) Mutation() *PermissionMutation { + return pc.mutation +} + +// Save creates the Permission in the database. +func (pc *PermissionCreate) Save(ctx context.Context) (*Permission, error) { + if err := pc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (pc *PermissionCreate) SaveX(ctx context.Context) *Permission { + v, err := pc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pc *PermissionCreate) Exec(ctx context.Context) error { + _, err := pc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pc *PermissionCreate) ExecX(ctx context.Context) { + if err := pc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (pc *PermissionCreate) defaults() error { + if _, ok := pc.mutation.CreatedAt(); !ok { + if permission.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized permission.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := permission.DefaultCreatedAt() + pc.mutation.SetCreatedAt(v) + } + if _, ok := pc.mutation.UpdatedAt(); !ok { + if permission.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized permission.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := permission.DefaultUpdatedAt() + pc.mutation.SetUpdatedAt(v) + } + if _, ok := pc.mutation.Name(); !ok { + v := permission.DefaultName + pc.mutation.SetName(v) + } + if _, ok := pc.mutation.Desc(); !ok { + v := permission.DefaultDesc + pc.mutation.SetDesc(v) + } + if _, ok := pc.mutation.ParentID(); !ok { + v := permission.DefaultParentID + pc.mutation.SetParentID(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (pc *PermissionCreate) check() error { + if _, ok := pc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Permission.created_at"`)} + } + if _, ok := pc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Permission.updated_at"`)} + } + if _, ok := pc.mutation.Key(); !ok { + return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "Permission.key"`)} + } + if v, ok := pc.mutation.Key(); ok { + if err := permission.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "Permission.key": %w`, err)} + } + } + if _, ok := pc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Permission.name"`)} + } + if v, ok := pc.mutation.Name(); ok { + if err := permission.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Permission.name": %w`, err)} + } + } + if _, ok := pc.mutation.Desc(); !ok { + return &ValidationError{Name: "desc", err: errors.New(`ent: missing required field "Permission.desc"`)} + } + if v, ok := pc.mutation.Desc(); ok { + if err := permission.DescValidator(v); err != nil { + return &ValidationError{Name: "desc", err: fmt.Errorf(`ent: validator failed for field "Permission.desc": %w`, err)} + } + } + if _, ok := pc.mutation.ParentID(); !ok { + return &ValidationError{Name: "parent_id", err: errors.New(`ent: missing required field "Permission.parent_id"`)} + } + return nil +} + +func (pc *PermissionCreate) sqlSave(ctx context.Context) (*Permission, error) { + if err := pc.check(); err != nil { + return nil, err + } + _node, _spec := pc.createSpec() + if err := sqlgraph.CreateNode(ctx, pc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + } + pc.mutation.id = &_node.ID + pc.mutation.done = true + return _node, nil +} + +func (pc *PermissionCreate) createSpec() (*Permission, *sqlgraph.CreateSpec) { + var ( + _node = &Permission{config: pc.config} + _spec = sqlgraph.NewCreateSpec(permission.Table, sqlgraph.NewFieldSpec(permission.FieldID, field.TypeInt64)) + ) + if id, ok := pc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := pc.mutation.CreatedAt(); ok { + _spec.SetField(permission.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := pc.mutation.UpdatedAt(); ok { + _spec.SetField(permission.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := pc.mutation.DeletedAt(); ok { + _spec.SetField(permission.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if value, ok := pc.mutation.Key(); ok { + _spec.SetField(permission.FieldKey, field.TypeString, value) + _node.Key = value + } + if value, ok := pc.mutation.Name(); ok { + _spec.SetField(permission.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := pc.mutation.Desc(); ok { + _spec.SetField(permission.FieldDesc, field.TypeString, value) + _node.Desc = value + } + if value, ok := pc.mutation.ParentID(); ok { + _spec.SetField(permission.FieldParentID, field.TypeInt64, value) + _node.ParentID = value + } + return _node, _spec +} + +// PermissionCreateBulk is the builder for creating many Permission entities in bulk. +type PermissionCreateBulk struct { + config + builders []*PermissionCreate +} + +// Save creates the Permission entities in the database. +func (pcb *PermissionCreateBulk) Save(ctx context.Context) ([]*Permission, error) { + specs := make([]*sqlgraph.CreateSpec, len(pcb.builders)) + nodes := make([]*Permission, len(pcb.builders)) + mutators := make([]Mutator, len(pcb.builders)) + for i := range pcb.builders { + func(i int, root context.Context) { + builder := pcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*PermissionMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, pcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, pcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, pcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (pcb *PermissionCreateBulk) SaveX(ctx context.Context) []*Permission { + v, err := pcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pcb *PermissionCreateBulk) Exec(ctx context.Context) error { + _, err := pcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pcb *PermissionCreateBulk) ExecX(ctx context.Context) { + if err := pcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/permission_delete.go b/internal/app/pkg/ent/ent/permission_delete.go new file mode 100644 index 00000000..09da7f72 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// PermissionDelete is the builder for deleting a Permission entity. +type PermissionDelete struct { + config + hooks []Hook + mutation *PermissionMutation +} + +// Where appends a list predicates to the PermissionDelete builder. +func (pd *PermissionDelete) Where(ps ...predicate.Permission) *PermissionDelete { + pd.mutation.Where(ps...) + return pd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (pd *PermissionDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, pd.sqlExec, pd.mutation, pd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (pd *PermissionDelete) ExecX(ctx context.Context) int { + n, err := pd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (pd *PermissionDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(permission.Table, sqlgraph.NewFieldSpec(permission.FieldID, field.TypeInt64)) + if ps := pd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, pd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + pd.mutation.done = true + return affected, err +} + +// PermissionDeleteOne is the builder for deleting a single Permission entity. +type PermissionDeleteOne struct { + pd *PermissionDelete +} + +// Where appends a list predicates to the PermissionDelete builder. +func (pdo *PermissionDeleteOne) Where(ps ...predicate.Permission) *PermissionDeleteOne { + pdo.pd.mutation.Where(ps...) + return pdo +} + +// Exec executes the deletion query. +func (pdo *PermissionDeleteOne) Exec(ctx context.Context) error { + n, err := pdo.pd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{permission.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (pdo *PermissionDeleteOne) ExecX(ctx context.Context) { + if err := pdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/permission_query.go b/internal/app/pkg/ent/ent/permission_query.go new file mode 100644 index 00000000..1d566b12 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission_query.go @@ -0,0 +1,548 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// PermissionQuery is the builder for querying Permission entities. +type PermissionQuery struct { + config + ctx *QueryContext + order []permission.OrderOption + inters []Interceptor + predicates []predicate.Permission + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the PermissionQuery builder. +func (pq *PermissionQuery) Where(ps ...predicate.Permission) *PermissionQuery { + pq.predicates = append(pq.predicates, ps...) + return pq +} + +// Limit the number of records to be returned by this query. +func (pq *PermissionQuery) Limit(limit int) *PermissionQuery { + pq.ctx.Limit = &limit + return pq +} + +// Offset to start from. +func (pq *PermissionQuery) Offset(offset int) *PermissionQuery { + pq.ctx.Offset = &offset + return pq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (pq *PermissionQuery) Unique(unique bool) *PermissionQuery { + pq.ctx.Unique = &unique + return pq +} + +// Order specifies how the records should be ordered. +func (pq *PermissionQuery) Order(o ...permission.OrderOption) *PermissionQuery { + pq.order = append(pq.order, o...) + return pq +} + +// First returns the first Permission entity from the query. +// Returns a *NotFoundError when no Permission was found. +func (pq *PermissionQuery) First(ctx context.Context) (*Permission, error) { + nodes, err := pq.Limit(1).All(setContextOp(ctx, pq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{permission.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (pq *PermissionQuery) FirstX(ctx context.Context) *Permission { + node, err := pq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Permission ID from the query. +// Returns a *NotFoundError when no Permission ID was found. +func (pq *PermissionQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = pq.Limit(1).IDs(setContextOp(ctx, pq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{permission.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (pq *PermissionQuery) FirstIDX(ctx context.Context) int64 { + id, err := pq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Permission entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Permission entity is found. +// Returns a *NotFoundError when no Permission entities are found. +func (pq *PermissionQuery) Only(ctx context.Context) (*Permission, error) { + nodes, err := pq.Limit(2).All(setContextOp(ctx, pq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{permission.Label} + default: + return nil, &NotSingularError{permission.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (pq *PermissionQuery) OnlyX(ctx context.Context) *Permission { + node, err := pq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Permission ID in the query. +// Returns a *NotSingularError when more than one Permission ID is found. +// Returns a *NotFoundError when no entities are found. +func (pq *PermissionQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = pq.Limit(2).IDs(setContextOp(ctx, pq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{permission.Label} + default: + err = &NotSingularError{permission.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (pq *PermissionQuery) OnlyIDX(ctx context.Context) int64 { + id, err := pq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Permissions. +func (pq *PermissionQuery) All(ctx context.Context) ([]*Permission, error) { + ctx = setContextOp(ctx, pq.ctx, "All") + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Permission, *PermissionQuery]() + return withInterceptors[[]*Permission](ctx, pq, qr, pq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (pq *PermissionQuery) AllX(ctx context.Context) []*Permission { + nodes, err := pq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Permission IDs. +func (pq *PermissionQuery) IDs(ctx context.Context) (ids []int64, err error) { + if pq.ctx.Unique == nil && pq.path != nil { + pq.Unique(true) + } + ctx = setContextOp(ctx, pq.ctx, "IDs") + if err = pq.Select(permission.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (pq *PermissionQuery) IDsX(ctx context.Context) []int64 { + ids, err := pq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (pq *PermissionQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, pq.ctx, "Count") + if err := pq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, pq, querierCount[*PermissionQuery](), pq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (pq *PermissionQuery) CountX(ctx context.Context) int { + count, err := pq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (pq *PermissionQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, pq.ctx, "Exist") + switch _, err := pq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (pq *PermissionQuery) ExistX(ctx context.Context) bool { + exist, err := pq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the PermissionQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (pq *PermissionQuery) Clone() *PermissionQuery { + if pq == nil { + return nil + } + return &PermissionQuery{ + config: pq.config, + ctx: pq.ctx.Clone(), + order: append([]permission.OrderOption{}, pq.order...), + inters: append([]Interceptor{}, pq.inters...), + predicates: append([]predicate.Permission{}, pq.predicates...), + // clone intermediate query. + sql: pq.sql.Clone(), + path: pq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Permission.Query(). +// GroupBy(permission.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (pq *PermissionQuery) GroupBy(field string, fields ...string) *PermissionGroupBy { + pq.ctx.Fields = append([]string{field}, fields...) + grbuild := &PermissionGroupBy{build: pq} + grbuild.flds = &pq.ctx.Fields + grbuild.label = permission.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// } +// +// client.Permission.Query(). +// Select(permission.FieldCreatedAt). +// Scan(ctx, &v) +func (pq *PermissionQuery) Select(fields ...string) *PermissionSelect { + pq.ctx.Fields = append(pq.ctx.Fields, fields...) + sbuild := &PermissionSelect{PermissionQuery: pq} + sbuild.label = permission.Label + sbuild.flds, sbuild.scan = &pq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a PermissionSelect configured with the given aggregations. +func (pq *PermissionQuery) Aggregate(fns ...AggregateFunc) *PermissionSelect { + return pq.Select().Aggregate(fns...) +} + +func (pq *PermissionQuery) prepareQuery(ctx context.Context) error { + for _, inter := range pq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, pq); err != nil { + return err + } + } + } + for _, f := range pq.ctx.Fields { + if !permission.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if pq.path != nil { + prev, err := pq.path(ctx) + if err != nil { + return err + } + pq.sql = prev + } + return nil +} + +func (pq *PermissionQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Permission, error) { + var ( + nodes = []*Permission{} + _spec = pq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Permission).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Permission{config: pq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, pq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (pq *PermissionQuery) sqlCount(ctx context.Context) (int, error) { + _spec := pq.querySpec() + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + _spec.Node.Columns = pq.ctx.Fields + if len(pq.ctx.Fields) > 0 { + _spec.Unique = pq.ctx.Unique != nil && *pq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, pq.driver, _spec) +} + +func (pq *PermissionQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(permission.Table, permission.Columns, sqlgraph.NewFieldSpec(permission.FieldID, field.TypeInt64)) + _spec.From = pq.sql + if unique := pq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if pq.path != nil { + _spec.Unique = true + } + if fields := pq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, permission.FieldID) + for i := range fields { + if fields[i] != permission.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := pq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := pq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := pq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := pq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (pq *PermissionQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(pq.driver.Dialect()) + t1 := builder.Table(permission.Table) + columns := pq.ctx.Fields + if len(columns) == 0 { + columns = permission.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if pq.sql != nil { + selector = pq.sql + selector.Select(selector.Columns(columns...)...) + } + if pq.ctx.Unique != nil && *pq.ctx.Unique { + selector.Distinct() + } + for _, m := range pq.modifiers { + m(selector) + } + for _, p := range pq.predicates { + p(selector) + } + for _, p := range pq.order { + p(selector) + } + if offset := pq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := pq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (pq *PermissionQuery) Modify(modifiers ...func(s *sql.Selector)) *PermissionSelect { + pq.modifiers = append(pq.modifiers, modifiers...) + return pq.Select() +} + +// PermissionGroupBy is the group-by builder for Permission entities. +type PermissionGroupBy struct { + selector + build *PermissionQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (pgb *PermissionGroupBy) Aggregate(fns ...AggregateFunc) *PermissionGroupBy { + pgb.fns = append(pgb.fns, fns...) + return pgb +} + +// Scan applies the selector query and scans the result into the given value. +func (pgb *PermissionGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, pgb.build.ctx, "GroupBy") + if err := pgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PermissionQuery, *PermissionGroupBy](ctx, pgb.build, pgb, pgb.build.inters, v) +} + +func (pgb *PermissionGroupBy) sqlScan(ctx context.Context, root *PermissionQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(pgb.fns)) + for _, fn := range pgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*pgb.flds)+len(pgb.fns)) + for _, f := range *pgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*pgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := pgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// PermissionSelect is the builder for selecting fields of Permission entities. +type PermissionSelect struct { + *PermissionQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ps *PermissionSelect) Aggregate(fns ...AggregateFunc) *PermissionSelect { + ps.fns = append(ps.fns, fns...) + return ps +} + +// Scan applies the selector query and scans the result into the given value. +func (ps *PermissionSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ps.ctx, "Select") + if err := ps.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*PermissionQuery, *PermissionSelect](ctx, ps.PermissionQuery, ps, ps.inters, v) +} + +func (ps *PermissionSelect) sqlScan(ctx context.Context, root *PermissionQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ps.fns)) + for _, fn := range ps.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ps.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ps.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (ps *PermissionSelect) Modify(modifiers ...func(s *sql.Selector)) *PermissionSelect { + ps.modifiers = append(ps.modifiers, modifiers...) + return ps +} diff --git a/internal/app/pkg/ent/ent/permission_update.go b/internal/app/pkg/ent/ent/permission_update.go new file mode 100644 index 00000000..092da640 --- /dev/null +++ b/internal/app/pkg/ent/ent/permission_update.go @@ -0,0 +1,466 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// PermissionUpdate is the builder for updating Permission entities. +type PermissionUpdate struct { + config + hooks []Hook + mutation *PermissionMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Where appends a list predicates to the PermissionUpdate builder. +func (pu *PermissionUpdate) Where(ps ...predicate.Permission) *PermissionUpdate { + pu.mutation.Where(ps...) + return pu +} + +// SetDeletedAt sets the "deleted_at" field. +func (pu *PermissionUpdate) SetDeletedAt(tt types.UnixTimestamp) *PermissionUpdate { + pu.mutation.SetDeletedAt(tt) + return pu +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (pu *PermissionUpdate) SetNillableDeletedAt(tt *types.UnixTimestamp) *PermissionUpdate { + if tt != nil { + pu.SetDeletedAt(*tt) + } + return pu +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (pu *PermissionUpdate) ClearDeletedAt() *PermissionUpdate { + pu.mutation.ClearDeletedAt() + return pu +} + +// SetKey sets the "key" field. +func (pu *PermissionUpdate) SetKey(s string) *PermissionUpdate { + pu.mutation.SetKey(s) + return pu +} + +// SetName sets the "name" field. +func (pu *PermissionUpdate) SetName(s string) *PermissionUpdate { + pu.mutation.SetName(s) + return pu +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (pu *PermissionUpdate) SetNillableName(s *string) *PermissionUpdate { + if s != nil { + pu.SetName(*s) + } + return pu +} + +// SetDesc sets the "desc" field. +func (pu *PermissionUpdate) SetDesc(s string) *PermissionUpdate { + pu.mutation.SetDesc(s) + return pu +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (pu *PermissionUpdate) SetNillableDesc(s *string) *PermissionUpdate { + if s != nil { + pu.SetDesc(*s) + } + return pu +} + +// SetParentID sets the "parent_id" field. +func (pu *PermissionUpdate) SetParentID(i int64) *PermissionUpdate { + pu.mutation.ResetParentID() + pu.mutation.SetParentID(i) + return pu +} + +// SetNillableParentID sets the "parent_id" field if the given value is not nil. +func (pu *PermissionUpdate) SetNillableParentID(i *int64) *PermissionUpdate { + if i != nil { + pu.SetParentID(*i) + } + return pu +} + +// AddParentID adds i to the "parent_id" field. +func (pu *PermissionUpdate) AddParentID(i int64) *PermissionUpdate { + pu.mutation.AddParentID(i) + return pu +} + +// Mutation returns the PermissionMutation object of the builder. +func (pu *PermissionUpdate) Mutation() *PermissionMutation { + return pu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (pu *PermissionUpdate) Save(ctx context.Context) (int, error) { + if err := pu.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (pu *PermissionUpdate) SaveX(ctx context.Context) int { + affected, err := pu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (pu *PermissionUpdate) Exec(ctx context.Context) error { + _, err := pu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pu *PermissionUpdate) ExecX(ctx context.Context) { + if err := pu.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (pu *PermissionUpdate) defaults() error { + if _, ok := pu.mutation.UpdatedAt(); !ok { + if permission.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized permission.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := permission.UpdateDefaultUpdatedAt() + pu.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (pu *PermissionUpdate) check() error { + if v, ok := pu.mutation.Key(); ok { + if err := permission.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "Permission.key": %w`, err)} + } + } + if v, ok := pu.mutation.Name(); ok { + if err := permission.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Permission.name": %w`, err)} + } + } + if v, ok := pu.mutation.Desc(); ok { + if err := permission.DescValidator(v); err != nil { + return &ValidationError{Name: "desc", err: fmt.Errorf(`ent: validator failed for field "Permission.desc": %w`, err)} + } + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (pu *PermissionUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *PermissionUpdate { + pu.modifiers = append(pu.modifiers, modifiers...) + return pu +} + +func (pu *PermissionUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := pu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(permission.Table, permission.Columns, sqlgraph.NewFieldSpec(permission.FieldID, field.TypeInt64)) + if ps := pu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := pu.mutation.UpdatedAt(); ok { + _spec.SetField(permission.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := pu.mutation.DeletedAt(); ok { + _spec.SetField(permission.FieldDeletedAt, field.TypeTime, value) + } + if pu.mutation.DeletedAtCleared() { + _spec.ClearField(permission.FieldDeletedAt, field.TypeTime) + } + if value, ok := pu.mutation.Key(); ok { + _spec.SetField(permission.FieldKey, field.TypeString, value) + } + if value, ok := pu.mutation.Name(); ok { + _spec.SetField(permission.FieldName, field.TypeString, value) + } + if value, ok := pu.mutation.Desc(); ok { + _spec.SetField(permission.FieldDesc, field.TypeString, value) + } + if value, ok := pu.mutation.ParentID(); ok { + _spec.SetField(permission.FieldParentID, field.TypeInt64, value) + } + if value, ok := pu.mutation.AddedParentID(); ok { + _spec.AddField(permission.FieldParentID, field.TypeInt64, value) + } + _spec.AddModifiers(pu.modifiers...) + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{permission.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + pu.mutation.done = true + return n, nil +} + +// PermissionUpdateOne is the builder for updating a single Permission entity. +type PermissionUpdateOne struct { + config + fields []string + hooks []Hook + mutation *PermissionMutation + modifiers []func(*sql.UpdateBuilder) +} + +// SetDeletedAt sets the "deleted_at" field. +func (puo *PermissionUpdateOne) SetDeletedAt(tt types.UnixTimestamp) *PermissionUpdateOne { + puo.mutation.SetDeletedAt(tt) + return puo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (puo *PermissionUpdateOne) SetNillableDeletedAt(tt *types.UnixTimestamp) *PermissionUpdateOne { + if tt != nil { + puo.SetDeletedAt(*tt) + } + return puo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (puo *PermissionUpdateOne) ClearDeletedAt() *PermissionUpdateOne { + puo.mutation.ClearDeletedAt() + return puo +} + +// SetKey sets the "key" field. +func (puo *PermissionUpdateOne) SetKey(s string) *PermissionUpdateOne { + puo.mutation.SetKey(s) + return puo +} + +// SetName sets the "name" field. +func (puo *PermissionUpdateOne) SetName(s string) *PermissionUpdateOne { + puo.mutation.SetName(s) + return puo +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (puo *PermissionUpdateOne) SetNillableName(s *string) *PermissionUpdateOne { + if s != nil { + puo.SetName(*s) + } + return puo +} + +// SetDesc sets the "desc" field. +func (puo *PermissionUpdateOne) SetDesc(s string) *PermissionUpdateOne { + puo.mutation.SetDesc(s) + return puo +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (puo *PermissionUpdateOne) SetNillableDesc(s *string) *PermissionUpdateOne { + if s != nil { + puo.SetDesc(*s) + } + return puo +} + +// SetParentID sets the "parent_id" field. +func (puo *PermissionUpdateOne) SetParentID(i int64) *PermissionUpdateOne { + puo.mutation.ResetParentID() + puo.mutation.SetParentID(i) + return puo +} + +// SetNillableParentID sets the "parent_id" field if the given value is not nil. +func (puo *PermissionUpdateOne) SetNillableParentID(i *int64) *PermissionUpdateOne { + if i != nil { + puo.SetParentID(*i) + } + return puo +} + +// AddParentID adds i to the "parent_id" field. +func (puo *PermissionUpdateOne) AddParentID(i int64) *PermissionUpdateOne { + puo.mutation.AddParentID(i) + return puo +} + +// Mutation returns the PermissionMutation object of the builder. +func (puo *PermissionUpdateOne) Mutation() *PermissionMutation { + return puo.mutation +} + +// Where appends a list predicates to the PermissionUpdate builder. +func (puo *PermissionUpdateOne) Where(ps ...predicate.Permission) *PermissionUpdateOne { + puo.mutation.Where(ps...) + return puo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (puo *PermissionUpdateOne) Select(field string, fields ...string) *PermissionUpdateOne { + puo.fields = append([]string{field}, fields...) + return puo +} + +// Save executes the query and returns the updated Permission entity. +func (puo *PermissionUpdateOne) Save(ctx context.Context) (*Permission, error) { + if err := puo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (puo *PermissionUpdateOne) SaveX(ctx context.Context) *Permission { + node, err := puo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (puo *PermissionUpdateOne) Exec(ctx context.Context) error { + _, err := puo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (puo *PermissionUpdateOne) ExecX(ctx context.Context) { + if err := puo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (puo *PermissionUpdateOne) defaults() error { + if _, ok := puo.mutation.UpdatedAt(); !ok { + if permission.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized permission.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := permission.UpdateDefaultUpdatedAt() + puo.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (puo *PermissionUpdateOne) check() error { + if v, ok := puo.mutation.Key(); ok { + if err := permission.KeyValidator(v); err != nil { + return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "Permission.key": %w`, err)} + } + } + if v, ok := puo.mutation.Name(); ok { + if err := permission.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Permission.name": %w`, err)} + } + } + if v, ok := puo.mutation.Desc(); ok { + if err := permission.DescValidator(v); err != nil { + return &ValidationError{Name: "desc", err: fmt.Errorf(`ent: validator failed for field "Permission.desc": %w`, err)} + } + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (puo *PermissionUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *PermissionUpdateOne { + puo.modifiers = append(puo.modifiers, modifiers...) + return puo +} + +func (puo *PermissionUpdateOne) sqlSave(ctx context.Context) (_node *Permission, err error) { + if err := puo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(permission.Table, permission.Columns, sqlgraph.NewFieldSpec(permission.FieldID, field.TypeInt64)) + id, ok := puo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Permission.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := puo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, permission.FieldID) + for _, f := range fields { + if !permission.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != permission.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := puo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := puo.mutation.UpdatedAt(); ok { + _spec.SetField(permission.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := puo.mutation.DeletedAt(); ok { + _spec.SetField(permission.FieldDeletedAt, field.TypeTime, value) + } + if puo.mutation.DeletedAtCleared() { + _spec.ClearField(permission.FieldDeletedAt, field.TypeTime) + } + if value, ok := puo.mutation.Key(); ok { + _spec.SetField(permission.FieldKey, field.TypeString, value) + } + if value, ok := puo.mutation.Name(); ok { + _spec.SetField(permission.FieldName, field.TypeString, value) + } + if value, ok := puo.mutation.Desc(); ok { + _spec.SetField(permission.FieldDesc, field.TypeString, value) + } + if value, ok := puo.mutation.ParentID(); ok { + _spec.SetField(permission.FieldParentID, field.TypeInt64, value) + } + if value, ok := puo.mutation.AddedParentID(); ok { + _spec.AddField(permission.FieldParentID, field.TypeInt64, value) + } + _spec.AddModifiers(puo.modifiers...) + _node = &Permission{config: puo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{permission.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + puo.mutation.done = true + return _node, nil +} diff --git a/internal/app/pkg/ent/ent/predicate/predicate.go b/internal/app/pkg/ent/ent/predicate/predicate.go index af21dfe3..bab9fae7 100644 --- a/internal/app/pkg/ent/ent/predicate/predicate.go +++ b/internal/app/pkg/ent/ent/predicate/predicate.go @@ -6,5 +6,14 @@ import ( "entgo.io/ent/dialect/sql" ) +// Permission is the predicate function for permission builders. +type Permission func(*sql.Selector) + +// Product is the predicate function for product builders. +type Product func(*sql.Selector) + +// Role is the predicate function for role builders. +type Role func(*sql.Selector) + // User is the predicate function for user builders. type User func(*sql.Selector) diff --git a/internal/app/pkg/ent/ent/product.go b/internal/app/pkg/ent/ent/product.go new file mode 100644 index 00000000..02c8c867 --- /dev/null +++ b/internal/app/pkg/ent/ent/product.go @@ -0,0 +1,161 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/repository/schema/types" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +// Product is the model entity for the Product schema. +type Product struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt types.UnixTimestamp `json:"updated_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt types.UnixTimestamp `json:"deleted_at,omitempty"` + // 名称 + Name string `json:"name,omitempty"` + // 描述 + Desc string `json:"desc,omitempty"` + // 价格 + Price int `json:"price,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Product) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case product.FieldID, product.FieldPrice: + values[i] = new(sql.NullInt64) + case product.FieldName, product.FieldDesc: + values[i] = new(sql.NullString) + case product.FieldCreatedAt, product.FieldUpdatedAt, product.FieldDeletedAt: + values[i] = new(types.UnixTimestamp) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Product fields. +func (pr *Product) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case product.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pr.ID = int64(value.Int64) + case product.FieldCreatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value != nil { + pr.CreatedAt = *value + } + case product.FieldUpdatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value != nil { + pr.UpdatedAt = *value + } + case product.FieldDeletedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value != nil { + pr.DeletedAt = *value + } + case product.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + pr.Name = value.String + } + case product.FieldDesc: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field desc", values[i]) + } else if value.Valid { + pr.Desc = value.String + } + case product.FieldPrice: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field price", values[i]) + } else if value.Valid { + pr.Price = int(value.Int64) + } + default: + pr.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Product. +// This includes values selected through modifiers, order, etc. +func (pr *Product) Value(name string) (ent.Value, error) { + return pr.selectValues.Get(name) +} + +// Update returns a builder for updating this Product. +// Note that you need to call Product.Unwrap() before calling this method if this Product +// was returned from a transaction, and the transaction was committed or rolled back. +func (pr *Product) Update() *ProductUpdateOne { + return NewProductClient(pr.config).UpdateOne(pr) +} + +// Unwrap unwraps the Product entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (pr *Product) Unwrap() *Product { + _tx, ok := pr.config.driver.(*txDriver) + if !ok { + panic("ent: Product is not a transactional entity") + } + pr.config.driver = _tx.drv + return pr +} + +// String implements the fmt.Stringer. +func (pr *Product) String() string { + var builder strings.Builder + builder.WriteString("Product(") + builder.WriteString(fmt.Sprintf("id=%v, ", pr.ID)) + builder.WriteString("created_at=") + builder.WriteString(fmt.Sprintf("%v", pr.CreatedAt)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(fmt.Sprintf("%v", pr.UpdatedAt)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(fmt.Sprintf("%v", pr.DeletedAt)) + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(pr.Name) + builder.WriteString(", ") + builder.WriteString("desc=") + builder.WriteString(pr.Desc) + builder.WriteString(", ") + builder.WriteString("price=") + builder.WriteString(fmt.Sprintf("%v", pr.Price)) + builder.WriteByte(')') + return builder.String() +} + +// Products is a parsable slice of Product. +type Products []*Product diff --git a/internal/app/pkg/ent/ent/product/product.go b/internal/app/pkg/ent/ent/product/product.go new file mode 100644 index 00000000..5d003bd4 --- /dev/null +++ b/internal/app/pkg/ent/ent/product/product.go @@ -0,0 +1,112 @@ +// Code generated by ent, DO NOT EDIT. + +package product + +import ( + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the product type in the database. + Label = "product" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldDesc holds the string denoting the desc field in the database. + FieldDesc = "desc" + // FieldPrice holds the string denoting the price field in the database. + FieldPrice = "price" + // Table holds the table name of the product in the database. + Table = "products" +) + +// Columns holds all SQL columns for product fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldName, + FieldDesc, + FieldPrice, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + 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 _ "go-scaffold/internal/app/pkg/ent/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() types.UnixTimestamp + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() types.UnixTimestamp + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() types.UnixTimestamp + // DefaultName holds the default value on creation for the "name" field. + DefaultName string + // DefaultDesc holds the default value on creation for the "desc" field. + DefaultDesc string + // DefaultPrice holds the default value on creation for the "price" field. + DefaultPrice int +) + +// OrderOption defines the ordering options for the Product queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByDesc orders the results by the desc field. +func ByDesc(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDesc, opts...).ToFunc() +} + +// ByPrice orders the results by the price field. +func ByPrice(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPrice, opts...).ToFunc() +} diff --git a/internal/app/pkg/ent/ent/product/where.go b/internal/app/pkg/ent/ent/product/where.go new file mode 100644 index 00000000..cde8a9d8 --- /dev/null +++ b/internal/app/pkg/ent/ent/product/where.go @@ -0,0 +1,417 @@ +// Code generated by ent, DO NOT EDIT. + +package product + +import ( + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.Product { + return predicate.Product(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.Product { + return predicate.Product(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.Product { + return predicate.Product(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldID, id)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldDeletedAt, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldName, v)) +} + +// Desc applies equality check predicate on the "desc" field. It's identical to DescEQ. +func Desc(v string) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldDesc, v)) +} + +// Price applies equality check predicate on the "price" field. It's identical to PriceEQ. +func Price(v int) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldPrice, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v types.UnixTimestamp) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.Product { + return predicate.Product(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.Product { + return predicate.Product(sql.FieldNotNull(FieldDeletedAt)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Product { + return predicate.Product(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Product { + return predicate.Product(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Product { + return predicate.Product(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Product { + return predicate.Product(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Product { + return predicate.Product(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Product { + return predicate.Product(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Product { + return predicate.Product(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Product { + return predicate.Product(sql.FieldContainsFold(FieldName, v)) +} + +// DescEQ applies the EQ predicate on the "desc" field. +func DescEQ(v string) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldDesc, v)) +} + +// DescNEQ applies the NEQ predicate on the "desc" field. +func DescNEQ(v string) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldDesc, v)) +} + +// DescIn applies the In predicate on the "desc" field. +func DescIn(vs ...string) predicate.Product { + return predicate.Product(sql.FieldIn(FieldDesc, vs...)) +} + +// DescNotIn applies the NotIn predicate on the "desc" field. +func DescNotIn(vs ...string) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldDesc, vs...)) +} + +// DescGT applies the GT predicate on the "desc" field. +func DescGT(v string) predicate.Product { + return predicate.Product(sql.FieldGT(FieldDesc, v)) +} + +// DescGTE applies the GTE predicate on the "desc" field. +func DescGTE(v string) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldDesc, v)) +} + +// DescLT applies the LT predicate on the "desc" field. +func DescLT(v string) predicate.Product { + return predicate.Product(sql.FieldLT(FieldDesc, v)) +} + +// DescLTE applies the LTE predicate on the "desc" field. +func DescLTE(v string) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldDesc, v)) +} + +// DescContains applies the Contains predicate on the "desc" field. +func DescContains(v string) predicate.Product { + return predicate.Product(sql.FieldContains(FieldDesc, v)) +} + +// DescHasPrefix applies the HasPrefix predicate on the "desc" field. +func DescHasPrefix(v string) predicate.Product { + return predicate.Product(sql.FieldHasPrefix(FieldDesc, v)) +} + +// DescHasSuffix applies the HasSuffix predicate on the "desc" field. +func DescHasSuffix(v string) predicate.Product { + return predicate.Product(sql.FieldHasSuffix(FieldDesc, v)) +} + +// DescEqualFold applies the EqualFold predicate on the "desc" field. +func DescEqualFold(v string) predicate.Product { + return predicate.Product(sql.FieldEqualFold(FieldDesc, v)) +} + +// DescContainsFold applies the ContainsFold predicate on the "desc" field. +func DescContainsFold(v string) predicate.Product { + return predicate.Product(sql.FieldContainsFold(FieldDesc, v)) +} + +// PriceEQ applies the EQ predicate on the "price" field. +func PriceEQ(v int) predicate.Product { + return predicate.Product(sql.FieldEQ(FieldPrice, v)) +} + +// PriceNEQ applies the NEQ predicate on the "price" field. +func PriceNEQ(v int) predicate.Product { + return predicate.Product(sql.FieldNEQ(FieldPrice, v)) +} + +// PriceIn applies the In predicate on the "price" field. +func PriceIn(vs ...int) predicate.Product { + return predicate.Product(sql.FieldIn(FieldPrice, vs...)) +} + +// PriceNotIn applies the NotIn predicate on the "price" field. +func PriceNotIn(vs ...int) predicate.Product { + return predicate.Product(sql.FieldNotIn(FieldPrice, vs...)) +} + +// PriceGT applies the GT predicate on the "price" field. +func PriceGT(v int) predicate.Product { + return predicate.Product(sql.FieldGT(FieldPrice, v)) +} + +// PriceGTE applies the GTE predicate on the "price" field. +func PriceGTE(v int) predicate.Product { + return predicate.Product(sql.FieldGTE(FieldPrice, v)) +} + +// PriceLT applies the LT predicate on the "price" field. +func PriceLT(v int) predicate.Product { + return predicate.Product(sql.FieldLT(FieldPrice, v)) +} + +// PriceLTE applies the LTE predicate on the "price" field. +func PriceLTE(v int) predicate.Product { + return predicate.Product(sql.FieldLTE(FieldPrice, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Product) predicate.Product { + return predicate.Product(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Product) predicate.Product { + return predicate.Product(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Product) predicate.Product { + return predicate.Product(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/internal/app/pkg/ent/ent/product_create.go b/internal/app/pkg/ent/ent/product_create.go new file mode 100644 index 00000000..20b8fec4 --- /dev/null +++ b/internal/app/pkg/ent/ent/product_create.go @@ -0,0 +1,337 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// ProductCreate is the builder for creating a Product entity. +type ProductCreate struct { + config + mutation *ProductMutation + hooks []Hook +} + +// SetCreatedAt sets the "created_at" field. +func (pc *ProductCreate) SetCreatedAt(tt types.UnixTimestamp) *ProductCreate { + pc.mutation.SetCreatedAt(tt) + return pc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (pc *ProductCreate) SetNillableCreatedAt(tt *types.UnixTimestamp) *ProductCreate { + if tt != nil { + pc.SetCreatedAt(*tt) + } + return pc +} + +// SetUpdatedAt sets the "updated_at" field. +func (pc *ProductCreate) SetUpdatedAt(tt types.UnixTimestamp) *ProductCreate { + pc.mutation.SetUpdatedAt(tt) + return pc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (pc *ProductCreate) SetNillableUpdatedAt(tt *types.UnixTimestamp) *ProductCreate { + if tt != nil { + pc.SetUpdatedAt(*tt) + } + return pc +} + +// SetDeletedAt sets the "deleted_at" field. +func (pc *ProductCreate) SetDeletedAt(tt types.UnixTimestamp) *ProductCreate { + pc.mutation.SetDeletedAt(tt) + return pc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (pc *ProductCreate) SetNillableDeletedAt(tt *types.UnixTimestamp) *ProductCreate { + if tt != nil { + pc.SetDeletedAt(*tt) + } + return pc +} + +// SetName sets the "name" field. +func (pc *ProductCreate) SetName(s string) *ProductCreate { + pc.mutation.SetName(s) + return pc +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (pc *ProductCreate) SetNillableName(s *string) *ProductCreate { + if s != nil { + pc.SetName(*s) + } + return pc +} + +// SetDesc sets the "desc" field. +func (pc *ProductCreate) SetDesc(s string) *ProductCreate { + pc.mutation.SetDesc(s) + return pc +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (pc *ProductCreate) SetNillableDesc(s *string) *ProductCreate { + if s != nil { + pc.SetDesc(*s) + } + return pc +} + +// SetPrice sets the "price" field. +func (pc *ProductCreate) SetPrice(i int) *ProductCreate { + pc.mutation.SetPrice(i) + return pc +} + +// SetNillablePrice sets the "price" field if the given value is not nil. +func (pc *ProductCreate) SetNillablePrice(i *int) *ProductCreate { + if i != nil { + pc.SetPrice(*i) + } + return pc +} + +// SetID sets the "id" field. +func (pc *ProductCreate) SetID(i int64) *ProductCreate { + pc.mutation.SetID(i) + return pc +} + +// Mutation returns the ProductMutation object of the builder. +func (pc *ProductCreate) Mutation() *ProductMutation { + return pc.mutation +} + +// Save creates the Product in the database. +func (pc *ProductCreate) Save(ctx context.Context) (*Product, error) { + if err := pc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (pc *ProductCreate) SaveX(ctx context.Context) *Product { + v, err := pc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pc *ProductCreate) Exec(ctx context.Context) error { + _, err := pc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pc *ProductCreate) ExecX(ctx context.Context) { + if err := pc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (pc *ProductCreate) defaults() error { + if _, ok := pc.mutation.CreatedAt(); !ok { + if product.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized product.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := product.DefaultCreatedAt() + pc.mutation.SetCreatedAt(v) + } + if _, ok := pc.mutation.UpdatedAt(); !ok { + if product.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized product.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := product.DefaultUpdatedAt() + pc.mutation.SetUpdatedAt(v) + } + if _, ok := pc.mutation.Name(); !ok { + v := product.DefaultName + pc.mutation.SetName(v) + } + if _, ok := pc.mutation.Desc(); !ok { + v := product.DefaultDesc + pc.mutation.SetDesc(v) + } + if _, ok := pc.mutation.Price(); !ok { + v := product.DefaultPrice + pc.mutation.SetPrice(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (pc *ProductCreate) check() error { + if _, ok := pc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Product.created_at"`)} + } + if _, ok := pc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Product.updated_at"`)} + } + if _, ok := pc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Product.name"`)} + } + if _, ok := pc.mutation.Desc(); !ok { + return &ValidationError{Name: "desc", err: errors.New(`ent: missing required field "Product.desc"`)} + } + if _, ok := pc.mutation.Price(); !ok { + return &ValidationError{Name: "price", err: errors.New(`ent: missing required field "Product.price"`)} + } + return nil +} + +func (pc *ProductCreate) sqlSave(ctx context.Context) (*Product, error) { + if err := pc.check(); err != nil { + return nil, err + } + _node, _spec := pc.createSpec() + if err := sqlgraph.CreateNode(ctx, pc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + } + pc.mutation.id = &_node.ID + pc.mutation.done = true + return _node, nil +} + +func (pc *ProductCreate) createSpec() (*Product, *sqlgraph.CreateSpec) { + var ( + _node = &Product{config: pc.config} + _spec = sqlgraph.NewCreateSpec(product.Table, sqlgraph.NewFieldSpec(product.FieldID, field.TypeInt64)) + ) + if id, ok := pc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := pc.mutation.CreatedAt(); ok { + _spec.SetField(product.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := pc.mutation.UpdatedAt(); ok { + _spec.SetField(product.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := pc.mutation.DeletedAt(); ok { + _spec.SetField(product.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if value, ok := pc.mutation.Name(); ok { + _spec.SetField(product.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := pc.mutation.Desc(); ok { + _spec.SetField(product.FieldDesc, field.TypeString, value) + _node.Desc = value + } + if value, ok := pc.mutation.Price(); ok { + _spec.SetField(product.FieldPrice, field.TypeInt, value) + _node.Price = value + } + return _node, _spec +} + +// ProductCreateBulk is the builder for creating many Product entities in bulk. +type ProductCreateBulk struct { + config + builders []*ProductCreate +} + +// Save creates the Product entities in the database. +func (pcb *ProductCreateBulk) Save(ctx context.Context) ([]*Product, error) { + specs := make([]*sqlgraph.CreateSpec, len(pcb.builders)) + nodes := make([]*Product, len(pcb.builders)) + mutators := make([]Mutator, len(pcb.builders)) + for i := range pcb.builders { + func(i int, root context.Context) { + builder := pcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ProductMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, pcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, pcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, pcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (pcb *ProductCreateBulk) SaveX(ctx context.Context) []*Product { + v, err := pcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pcb *ProductCreateBulk) Exec(ctx context.Context) error { + _, err := pcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pcb *ProductCreateBulk) ExecX(ctx context.Context) { + if err := pcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/product_delete.go b/internal/app/pkg/ent/ent/product_delete.go new file mode 100644 index 00000000..5ff368b3 --- /dev/null +++ b/internal/app/pkg/ent/ent/product_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/product" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// ProductDelete is the builder for deleting a Product entity. +type ProductDelete struct { + config + hooks []Hook + mutation *ProductMutation +} + +// Where appends a list predicates to the ProductDelete builder. +func (pd *ProductDelete) Where(ps ...predicate.Product) *ProductDelete { + pd.mutation.Where(ps...) + return pd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (pd *ProductDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, pd.sqlExec, pd.mutation, pd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (pd *ProductDelete) ExecX(ctx context.Context) int { + n, err := pd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (pd *ProductDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(product.Table, sqlgraph.NewFieldSpec(product.FieldID, field.TypeInt64)) + if ps := pd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, pd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + pd.mutation.done = true + return affected, err +} + +// ProductDeleteOne is the builder for deleting a single Product entity. +type ProductDeleteOne struct { + pd *ProductDelete +} + +// Where appends a list predicates to the ProductDelete builder. +func (pdo *ProductDeleteOne) Where(ps ...predicate.Product) *ProductDeleteOne { + pdo.pd.mutation.Where(ps...) + return pdo +} + +// Exec executes the deletion query. +func (pdo *ProductDeleteOne) Exec(ctx context.Context) error { + n, err := pdo.pd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{product.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (pdo *ProductDeleteOne) ExecX(ctx context.Context) { + if err := pdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/product_query.go b/internal/app/pkg/ent/ent/product_query.go new file mode 100644 index 00000000..f2526215 --- /dev/null +++ b/internal/app/pkg/ent/ent/product_query.go @@ -0,0 +1,548 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/product" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// ProductQuery is the builder for querying Product entities. +type ProductQuery struct { + config + ctx *QueryContext + order []product.OrderOption + inters []Interceptor + predicates []predicate.Product + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ProductQuery builder. +func (pq *ProductQuery) Where(ps ...predicate.Product) *ProductQuery { + pq.predicates = append(pq.predicates, ps...) + return pq +} + +// Limit the number of records to be returned by this query. +func (pq *ProductQuery) Limit(limit int) *ProductQuery { + pq.ctx.Limit = &limit + return pq +} + +// Offset to start from. +func (pq *ProductQuery) Offset(offset int) *ProductQuery { + pq.ctx.Offset = &offset + return pq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (pq *ProductQuery) Unique(unique bool) *ProductQuery { + pq.ctx.Unique = &unique + return pq +} + +// Order specifies how the records should be ordered. +func (pq *ProductQuery) Order(o ...product.OrderOption) *ProductQuery { + pq.order = append(pq.order, o...) + return pq +} + +// First returns the first Product entity from the query. +// Returns a *NotFoundError when no Product was found. +func (pq *ProductQuery) First(ctx context.Context) (*Product, error) { + nodes, err := pq.Limit(1).All(setContextOp(ctx, pq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{product.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (pq *ProductQuery) FirstX(ctx context.Context) *Product { + node, err := pq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Product ID from the query. +// Returns a *NotFoundError when no Product ID was found. +func (pq *ProductQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = pq.Limit(1).IDs(setContextOp(ctx, pq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{product.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (pq *ProductQuery) FirstIDX(ctx context.Context) int64 { + id, err := pq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Product entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Product entity is found. +// Returns a *NotFoundError when no Product entities are found. +func (pq *ProductQuery) Only(ctx context.Context) (*Product, error) { + nodes, err := pq.Limit(2).All(setContextOp(ctx, pq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{product.Label} + default: + return nil, &NotSingularError{product.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (pq *ProductQuery) OnlyX(ctx context.Context) *Product { + node, err := pq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Product ID in the query. +// Returns a *NotSingularError when more than one Product ID is found. +// Returns a *NotFoundError when no entities are found. +func (pq *ProductQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = pq.Limit(2).IDs(setContextOp(ctx, pq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{product.Label} + default: + err = &NotSingularError{product.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (pq *ProductQuery) OnlyIDX(ctx context.Context) int64 { + id, err := pq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Products. +func (pq *ProductQuery) All(ctx context.Context) ([]*Product, error) { + ctx = setContextOp(ctx, pq.ctx, "All") + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Product, *ProductQuery]() + return withInterceptors[[]*Product](ctx, pq, qr, pq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (pq *ProductQuery) AllX(ctx context.Context) []*Product { + nodes, err := pq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Product IDs. +func (pq *ProductQuery) IDs(ctx context.Context) (ids []int64, err error) { + if pq.ctx.Unique == nil && pq.path != nil { + pq.Unique(true) + } + ctx = setContextOp(ctx, pq.ctx, "IDs") + if err = pq.Select(product.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (pq *ProductQuery) IDsX(ctx context.Context) []int64 { + ids, err := pq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (pq *ProductQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, pq.ctx, "Count") + if err := pq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, pq, querierCount[*ProductQuery](), pq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (pq *ProductQuery) CountX(ctx context.Context) int { + count, err := pq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (pq *ProductQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, pq.ctx, "Exist") + switch _, err := pq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (pq *ProductQuery) ExistX(ctx context.Context) bool { + exist, err := pq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ProductQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (pq *ProductQuery) Clone() *ProductQuery { + if pq == nil { + return nil + } + return &ProductQuery{ + config: pq.config, + ctx: pq.ctx.Clone(), + order: append([]product.OrderOption{}, pq.order...), + inters: append([]Interceptor{}, pq.inters...), + predicates: append([]predicate.Product{}, pq.predicates...), + // clone intermediate query. + sql: pq.sql.Clone(), + path: pq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Product.Query(). +// GroupBy(product.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (pq *ProductQuery) GroupBy(field string, fields ...string) *ProductGroupBy { + pq.ctx.Fields = append([]string{field}, fields...) + grbuild := &ProductGroupBy{build: pq} + grbuild.flds = &pq.ctx.Fields + grbuild.label = product.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// } +// +// client.Product.Query(). +// Select(product.FieldCreatedAt). +// Scan(ctx, &v) +func (pq *ProductQuery) Select(fields ...string) *ProductSelect { + pq.ctx.Fields = append(pq.ctx.Fields, fields...) + sbuild := &ProductSelect{ProductQuery: pq} + sbuild.label = product.Label + sbuild.flds, sbuild.scan = &pq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a ProductSelect configured with the given aggregations. +func (pq *ProductQuery) Aggregate(fns ...AggregateFunc) *ProductSelect { + return pq.Select().Aggregate(fns...) +} + +func (pq *ProductQuery) prepareQuery(ctx context.Context) error { + for _, inter := range pq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, pq); err != nil { + return err + } + } + } + for _, f := range pq.ctx.Fields { + if !product.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if pq.path != nil { + prev, err := pq.path(ctx) + if err != nil { + return err + } + pq.sql = prev + } + return nil +} + +func (pq *ProductQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Product, error) { + var ( + nodes = []*Product{} + _spec = pq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Product).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Product{config: pq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, pq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (pq *ProductQuery) sqlCount(ctx context.Context) (int, error) { + _spec := pq.querySpec() + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + _spec.Node.Columns = pq.ctx.Fields + if len(pq.ctx.Fields) > 0 { + _spec.Unique = pq.ctx.Unique != nil && *pq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, pq.driver, _spec) +} + +func (pq *ProductQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(product.Table, product.Columns, sqlgraph.NewFieldSpec(product.FieldID, field.TypeInt64)) + _spec.From = pq.sql + if unique := pq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if pq.path != nil { + _spec.Unique = true + } + if fields := pq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, product.FieldID) + for i := range fields { + if fields[i] != product.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := pq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := pq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := pq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := pq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (pq *ProductQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(pq.driver.Dialect()) + t1 := builder.Table(product.Table) + columns := pq.ctx.Fields + if len(columns) == 0 { + columns = product.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if pq.sql != nil { + selector = pq.sql + selector.Select(selector.Columns(columns...)...) + } + if pq.ctx.Unique != nil && *pq.ctx.Unique { + selector.Distinct() + } + for _, m := range pq.modifiers { + m(selector) + } + for _, p := range pq.predicates { + p(selector) + } + for _, p := range pq.order { + p(selector) + } + if offset := pq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := pq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (pq *ProductQuery) Modify(modifiers ...func(s *sql.Selector)) *ProductSelect { + pq.modifiers = append(pq.modifiers, modifiers...) + return pq.Select() +} + +// ProductGroupBy is the group-by builder for Product entities. +type ProductGroupBy struct { + selector + build *ProductQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (pgb *ProductGroupBy) Aggregate(fns ...AggregateFunc) *ProductGroupBy { + pgb.fns = append(pgb.fns, fns...) + return pgb +} + +// Scan applies the selector query and scans the result into the given value. +func (pgb *ProductGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, pgb.build.ctx, "GroupBy") + if err := pgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ProductQuery, *ProductGroupBy](ctx, pgb.build, pgb, pgb.build.inters, v) +} + +func (pgb *ProductGroupBy) sqlScan(ctx context.Context, root *ProductQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(pgb.fns)) + for _, fn := range pgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*pgb.flds)+len(pgb.fns)) + for _, f := range *pgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*pgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := pgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// ProductSelect is the builder for selecting fields of Product entities. +type ProductSelect struct { + *ProductQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ps *ProductSelect) Aggregate(fns ...AggregateFunc) *ProductSelect { + ps.fns = append(ps.fns, fns...) + return ps +} + +// Scan applies the selector query and scans the result into the given value. +func (ps *ProductSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ps.ctx, "Select") + if err := ps.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ProductQuery, *ProductSelect](ctx, ps.ProductQuery, ps, ps.inters, v) +} + +func (ps *ProductSelect) sqlScan(ctx context.Context, root *ProductQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ps.fns)) + for _, fn := range ps.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ps.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ps.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (ps *ProductSelect) Modify(modifiers ...func(s *sql.Selector)) *ProductSelect { + ps.modifiers = append(ps.modifiers, modifiers...) + return ps +} diff --git a/internal/app/pkg/ent/ent/product_update.go b/internal/app/pkg/ent/ent/product_update.go new file mode 100644 index 00000000..fd2e6c98 --- /dev/null +++ b/internal/app/pkg/ent/ent/product_update.go @@ -0,0 +1,402 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// ProductUpdate is the builder for updating Product entities. +type ProductUpdate struct { + config + hooks []Hook + mutation *ProductMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Where appends a list predicates to the ProductUpdate builder. +func (pu *ProductUpdate) Where(ps ...predicate.Product) *ProductUpdate { + pu.mutation.Where(ps...) + return pu +} + +// SetDeletedAt sets the "deleted_at" field. +func (pu *ProductUpdate) SetDeletedAt(tt types.UnixTimestamp) *ProductUpdate { + pu.mutation.SetDeletedAt(tt) + return pu +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (pu *ProductUpdate) SetNillableDeletedAt(tt *types.UnixTimestamp) *ProductUpdate { + if tt != nil { + pu.SetDeletedAt(*tt) + } + return pu +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (pu *ProductUpdate) ClearDeletedAt() *ProductUpdate { + pu.mutation.ClearDeletedAt() + return pu +} + +// SetName sets the "name" field. +func (pu *ProductUpdate) SetName(s string) *ProductUpdate { + pu.mutation.SetName(s) + return pu +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (pu *ProductUpdate) SetNillableName(s *string) *ProductUpdate { + if s != nil { + pu.SetName(*s) + } + return pu +} + +// SetDesc sets the "desc" field. +func (pu *ProductUpdate) SetDesc(s string) *ProductUpdate { + pu.mutation.SetDesc(s) + return pu +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (pu *ProductUpdate) SetNillableDesc(s *string) *ProductUpdate { + if s != nil { + pu.SetDesc(*s) + } + return pu +} + +// SetPrice sets the "price" field. +func (pu *ProductUpdate) SetPrice(i int) *ProductUpdate { + pu.mutation.ResetPrice() + pu.mutation.SetPrice(i) + return pu +} + +// SetNillablePrice sets the "price" field if the given value is not nil. +func (pu *ProductUpdate) SetNillablePrice(i *int) *ProductUpdate { + if i != nil { + pu.SetPrice(*i) + } + return pu +} + +// AddPrice adds i to the "price" field. +func (pu *ProductUpdate) AddPrice(i int) *ProductUpdate { + pu.mutation.AddPrice(i) + return pu +} + +// Mutation returns the ProductMutation object of the builder. +func (pu *ProductUpdate) Mutation() *ProductMutation { + return pu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (pu *ProductUpdate) Save(ctx context.Context) (int, error) { + if err := pu.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (pu *ProductUpdate) SaveX(ctx context.Context) int { + affected, err := pu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (pu *ProductUpdate) Exec(ctx context.Context) error { + _, err := pu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pu *ProductUpdate) ExecX(ctx context.Context) { + if err := pu.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (pu *ProductUpdate) defaults() error { + if _, ok := pu.mutation.UpdatedAt(); !ok { + if product.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized product.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := product.UpdateDefaultUpdatedAt() + pu.mutation.SetUpdatedAt(v) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (pu *ProductUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *ProductUpdate { + pu.modifiers = append(pu.modifiers, modifiers...) + return pu +} + +func (pu *ProductUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := sqlgraph.NewUpdateSpec(product.Table, product.Columns, sqlgraph.NewFieldSpec(product.FieldID, field.TypeInt64)) + if ps := pu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := pu.mutation.UpdatedAt(); ok { + _spec.SetField(product.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := pu.mutation.DeletedAt(); ok { + _spec.SetField(product.FieldDeletedAt, field.TypeTime, value) + } + if pu.mutation.DeletedAtCleared() { + _spec.ClearField(product.FieldDeletedAt, field.TypeTime) + } + if value, ok := pu.mutation.Name(); ok { + _spec.SetField(product.FieldName, field.TypeString, value) + } + if value, ok := pu.mutation.Desc(); ok { + _spec.SetField(product.FieldDesc, field.TypeString, value) + } + if value, ok := pu.mutation.Price(); ok { + _spec.SetField(product.FieldPrice, field.TypeInt, value) + } + if value, ok := pu.mutation.AddedPrice(); ok { + _spec.AddField(product.FieldPrice, field.TypeInt, value) + } + _spec.AddModifiers(pu.modifiers...) + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{product.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + pu.mutation.done = true + return n, nil +} + +// ProductUpdateOne is the builder for updating a single Product entity. +type ProductUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ProductMutation + modifiers []func(*sql.UpdateBuilder) +} + +// SetDeletedAt sets the "deleted_at" field. +func (puo *ProductUpdateOne) SetDeletedAt(tt types.UnixTimestamp) *ProductUpdateOne { + puo.mutation.SetDeletedAt(tt) + return puo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (puo *ProductUpdateOne) SetNillableDeletedAt(tt *types.UnixTimestamp) *ProductUpdateOne { + if tt != nil { + puo.SetDeletedAt(*tt) + } + return puo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (puo *ProductUpdateOne) ClearDeletedAt() *ProductUpdateOne { + puo.mutation.ClearDeletedAt() + return puo +} + +// SetName sets the "name" field. +func (puo *ProductUpdateOne) SetName(s string) *ProductUpdateOne { + puo.mutation.SetName(s) + return puo +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (puo *ProductUpdateOne) SetNillableName(s *string) *ProductUpdateOne { + if s != nil { + puo.SetName(*s) + } + return puo +} + +// SetDesc sets the "desc" field. +func (puo *ProductUpdateOne) SetDesc(s string) *ProductUpdateOne { + puo.mutation.SetDesc(s) + return puo +} + +// SetNillableDesc sets the "desc" field if the given value is not nil. +func (puo *ProductUpdateOne) SetNillableDesc(s *string) *ProductUpdateOne { + if s != nil { + puo.SetDesc(*s) + } + return puo +} + +// SetPrice sets the "price" field. +func (puo *ProductUpdateOne) SetPrice(i int) *ProductUpdateOne { + puo.mutation.ResetPrice() + puo.mutation.SetPrice(i) + return puo +} + +// SetNillablePrice sets the "price" field if the given value is not nil. +func (puo *ProductUpdateOne) SetNillablePrice(i *int) *ProductUpdateOne { + if i != nil { + puo.SetPrice(*i) + } + return puo +} + +// AddPrice adds i to the "price" field. +func (puo *ProductUpdateOne) AddPrice(i int) *ProductUpdateOne { + puo.mutation.AddPrice(i) + return puo +} + +// Mutation returns the ProductMutation object of the builder. +func (puo *ProductUpdateOne) Mutation() *ProductMutation { + return puo.mutation +} + +// Where appends a list predicates to the ProductUpdate builder. +func (puo *ProductUpdateOne) Where(ps ...predicate.Product) *ProductUpdateOne { + puo.mutation.Where(ps...) + return puo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (puo *ProductUpdateOne) Select(field string, fields ...string) *ProductUpdateOne { + puo.fields = append([]string{field}, fields...) + return puo +} + +// Save executes the query and returns the updated Product entity. +func (puo *ProductUpdateOne) Save(ctx context.Context) (*Product, error) { + if err := puo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (puo *ProductUpdateOne) SaveX(ctx context.Context) *Product { + node, err := puo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (puo *ProductUpdateOne) Exec(ctx context.Context) error { + _, err := puo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (puo *ProductUpdateOne) ExecX(ctx context.Context) { + if err := puo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (puo *ProductUpdateOne) defaults() error { + if _, ok := puo.mutation.UpdatedAt(); !ok { + if product.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized product.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := product.UpdateDefaultUpdatedAt() + puo.mutation.SetUpdatedAt(v) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (puo *ProductUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *ProductUpdateOne { + puo.modifiers = append(puo.modifiers, modifiers...) + return puo +} + +func (puo *ProductUpdateOne) sqlSave(ctx context.Context) (_node *Product, err error) { + _spec := sqlgraph.NewUpdateSpec(product.Table, product.Columns, sqlgraph.NewFieldSpec(product.FieldID, field.TypeInt64)) + id, ok := puo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Product.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := puo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, product.FieldID) + for _, f := range fields { + if !product.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != product.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := puo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := puo.mutation.UpdatedAt(); ok { + _spec.SetField(product.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := puo.mutation.DeletedAt(); ok { + _spec.SetField(product.FieldDeletedAt, field.TypeTime, value) + } + if puo.mutation.DeletedAtCleared() { + _spec.ClearField(product.FieldDeletedAt, field.TypeTime) + } + if value, ok := puo.mutation.Name(); ok { + _spec.SetField(product.FieldName, field.TypeString, value) + } + if value, ok := puo.mutation.Desc(); ok { + _spec.SetField(product.FieldDesc, field.TypeString, value) + } + if value, ok := puo.mutation.Price(); ok { + _spec.SetField(product.FieldPrice, field.TypeInt, value) + } + if value, ok := puo.mutation.AddedPrice(); ok { + _spec.AddField(product.FieldPrice, field.TypeInt, value) + } + _spec.AddModifiers(puo.modifiers...) + _node = &Product{config: puo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{product.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + puo.mutation.done = true + return _node, nil +} diff --git a/internal/app/pkg/ent/ent/role.go b/internal/app/pkg/ent/ent/role.go new file mode 100644 index 00000000..a0e4a7ec --- /dev/null +++ b/internal/app/pkg/ent/ent/role.go @@ -0,0 +1,139 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/role" + "go-scaffold/internal/app/repository/schema/types" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +// Role is the model entity for the Role schema. +type Role struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt types.UnixTimestamp `json:"updated_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt types.UnixTimestamp `json:"deleted_at,omitempty"` + // 角色名称 + Name string `json:"name,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Role) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case role.FieldID: + values[i] = new(sql.NullInt64) + case role.FieldName: + values[i] = new(sql.NullString) + case role.FieldCreatedAt, role.FieldUpdatedAt, role.FieldDeletedAt: + values[i] = new(types.UnixTimestamp) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Role fields. +func (r *Role) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case role.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + r.ID = int64(value.Int64) + case role.FieldCreatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value != nil { + r.CreatedAt = *value + } + case role.FieldUpdatedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value != nil { + r.UpdatedAt = *value + } + case role.FieldDeletedAt: + if value, ok := values[i].(*types.UnixTimestamp); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value != nil { + r.DeletedAt = *value + } + case role.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + r.Name = value.String + } + default: + r.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Role. +// This includes values selected through modifiers, order, etc. +func (r *Role) Value(name string) (ent.Value, error) { + return r.selectValues.Get(name) +} + +// Update returns a builder for updating this Role. +// Note that you need to call Role.Unwrap() before calling this method if this Role +// was returned from a transaction, and the transaction was committed or rolled back. +func (r *Role) Update() *RoleUpdateOne { + return NewRoleClient(r.config).UpdateOne(r) +} + +// Unwrap unwraps the Role entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (r *Role) Unwrap() *Role { + _tx, ok := r.config.driver.(*txDriver) + if !ok { + panic("ent: Role is not a transactional entity") + } + r.config.driver = _tx.drv + return r +} + +// String implements the fmt.Stringer. +func (r *Role) String() string { + var builder strings.Builder + builder.WriteString("Role(") + builder.WriteString(fmt.Sprintf("id=%v, ", r.ID)) + builder.WriteString("created_at=") + builder.WriteString(fmt.Sprintf("%v", r.CreatedAt)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(fmt.Sprintf("%v", r.UpdatedAt)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(fmt.Sprintf("%v", r.DeletedAt)) + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(r.Name) + builder.WriteByte(')') + return builder.String() +} + +// Roles is a parsable slice of Role. +type Roles []*Role diff --git a/internal/app/pkg/ent/ent/role/role.go b/internal/app/pkg/ent/ent/role/role.go new file mode 100644 index 00000000..780cb015 --- /dev/null +++ b/internal/app/pkg/ent/ent/role/role.go @@ -0,0 +1,92 @@ +// Code generated by ent, DO NOT EDIT. + +package role + +import ( + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the role type in the database. + Label = "role" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // Table holds the table name of the role in the database. + Table = "roles" +) + +// Columns holds all SQL columns for role fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldName, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + 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 _ "go-scaffold/internal/app/pkg/ent/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() types.UnixTimestamp + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() types.UnixTimestamp + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() types.UnixTimestamp + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error +) + +// OrderOption defines the ordering options for the Role queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} diff --git a/internal/app/pkg/ent/ent/role/where.go b/internal/app/pkg/ent/ent/role/where.go new file mode 100644 index 00000000..ef651dd3 --- /dev/null +++ b/internal/app/pkg/ent/ent/role/where.go @@ -0,0 +1,302 @@ +// Code generated by ent, DO NOT EDIT. + +package role + +import ( + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.Role { + return predicate.Role(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.Role { + return predicate.Role(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.Role { + return predicate.Role(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.Role { + return predicate.Role(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.Role { + return predicate.Role(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.Role { + return predicate.Role(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.Role { + return predicate.Role(sql.FieldLTE(FieldID, id)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldDeletedAt, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldName, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v types.UnixTimestamp) predicate.Role { + return predicate.Role(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.Role { + return predicate.Role(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.Role { + return predicate.Role(sql.FieldNotNull(FieldDeletedAt)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Role { + return predicate.Role(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Role { + return predicate.Role(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Role { + return predicate.Role(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Role { + return predicate.Role(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Role { + return predicate.Role(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Role { + return predicate.Role(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Role { + return predicate.Role(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Role { + return predicate.Role(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Role { + return predicate.Role(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Role { + return predicate.Role(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Role { + return predicate.Role(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Role { + return predicate.Role(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Role { + return predicate.Role(sql.FieldContainsFold(FieldName, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Role) predicate.Role { + return predicate.Role(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Role) predicate.Role { + return predicate.Role(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Role) predicate.Role { + return predicate.Role(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/internal/app/pkg/ent/ent/role_create.go b/internal/app/pkg/ent/ent/role_create.go new file mode 100644 index 00000000..f490e80a --- /dev/null +++ b/internal/app/pkg/ent/ent/role_create.go @@ -0,0 +1,280 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/role" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// RoleCreate is the builder for creating a Role entity. +type RoleCreate struct { + config + mutation *RoleMutation + hooks []Hook +} + +// SetCreatedAt sets the "created_at" field. +func (rc *RoleCreate) SetCreatedAt(tt types.UnixTimestamp) *RoleCreate { + rc.mutation.SetCreatedAt(tt) + return rc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (rc *RoleCreate) SetNillableCreatedAt(tt *types.UnixTimestamp) *RoleCreate { + if tt != nil { + rc.SetCreatedAt(*tt) + } + return rc +} + +// SetUpdatedAt sets the "updated_at" field. +func (rc *RoleCreate) SetUpdatedAt(tt types.UnixTimestamp) *RoleCreate { + rc.mutation.SetUpdatedAt(tt) + return rc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (rc *RoleCreate) SetNillableUpdatedAt(tt *types.UnixTimestamp) *RoleCreate { + if tt != nil { + rc.SetUpdatedAt(*tt) + } + return rc +} + +// SetDeletedAt sets the "deleted_at" field. +func (rc *RoleCreate) SetDeletedAt(tt types.UnixTimestamp) *RoleCreate { + rc.mutation.SetDeletedAt(tt) + return rc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (rc *RoleCreate) SetNillableDeletedAt(tt *types.UnixTimestamp) *RoleCreate { + if tt != nil { + rc.SetDeletedAt(*tt) + } + return rc +} + +// SetName sets the "name" field. +func (rc *RoleCreate) SetName(s string) *RoleCreate { + rc.mutation.SetName(s) + return rc +} + +// SetID sets the "id" field. +func (rc *RoleCreate) SetID(i int64) *RoleCreate { + rc.mutation.SetID(i) + return rc +} + +// Mutation returns the RoleMutation object of the builder. +func (rc *RoleCreate) Mutation() *RoleMutation { + return rc.mutation +} + +// Save creates the Role in the database. +func (rc *RoleCreate) Save(ctx context.Context) (*Role, error) { + if err := rc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, rc.sqlSave, rc.mutation, rc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (rc *RoleCreate) SaveX(ctx context.Context) *Role { + v, err := rc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (rc *RoleCreate) Exec(ctx context.Context) error { + _, err := rc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (rc *RoleCreate) ExecX(ctx context.Context) { + if err := rc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (rc *RoleCreate) defaults() error { + if _, ok := rc.mutation.CreatedAt(); !ok { + if role.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized role.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := role.DefaultCreatedAt() + rc.mutation.SetCreatedAt(v) + } + if _, ok := rc.mutation.UpdatedAt(); !ok { + if role.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized role.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := role.DefaultUpdatedAt() + rc.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (rc *RoleCreate) check() error { + if _, ok := rc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Role.created_at"`)} + } + if _, ok := rc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Role.updated_at"`)} + } + if _, ok := rc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Role.name"`)} + } + if v, ok := rc.mutation.Name(); ok { + if err := role.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Role.name": %w`, err)} + } + } + return nil +} + +func (rc *RoleCreate) sqlSave(ctx context.Context) (*Role, error) { + if err := rc.check(); err != nil { + return nil, err + } + _node, _spec := rc.createSpec() + if err := sqlgraph.CreateNode(ctx, rc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + } + rc.mutation.id = &_node.ID + rc.mutation.done = true + return _node, nil +} + +func (rc *RoleCreate) createSpec() (*Role, *sqlgraph.CreateSpec) { + var ( + _node = &Role{config: rc.config} + _spec = sqlgraph.NewCreateSpec(role.Table, sqlgraph.NewFieldSpec(role.FieldID, field.TypeInt64)) + ) + if id, ok := rc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := rc.mutation.CreatedAt(); ok { + _spec.SetField(role.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := rc.mutation.UpdatedAt(); ok { + _spec.SetField(role.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := rc.mutation.DeletedAt(); ok { + _spec.SetField(role.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if value, ok := rc.mutation.Name(); ok { + _spec.SetField(role.FieldName, field.TypeString, value) + _node.Name = value + } + return _node, _spec +} + +// RoleCreateBulk is the builder for creating many Role entities in bulk. +type RoleCreateBulk struct { + config + builders []*RoleCreate +} + +// Save creates the Role entities in the database. +func (rcb *RoleCreateBulk) Save(ctx context.Context) ([]*Role, error) { + specs := make([]*sqlgraph.CreateSpec, len(rcb.builders)) + nodes := make([]*Role, len(rcb.builders)) + mutators := make([]Mutator, len(rcb.builders)) + for i := range rcb.builders { + func(i int, root context.Context) { + builder := rcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*RoleMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, rcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, rcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, rcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (rcb *RoleCreateBulk) SaveX(ctx context.Context) []*Role { + v, err := rcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (rcb *RoleCreateBulk) Exec(ctx context.Context) error { + _, err := rcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (rcb *RoleCreateBulk) ExecX(ctx context.Context) { + if err := rcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/role_delete.go b/internal/app/pkg/ent/ent/role_delete.go new file mode 100644 index 00000000..9d2c651a --- /dev/null +++ b/internal/app/pkg/ent/ent/role_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/role" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// RoleDelete is the builder for deleting a Role entity. +type RoleDelete struct { + config + hooks []Hook + mutation *RoleMutation +} + +// Where appends a list predicates to the RoleDelete builder. +func (rd *RoleDelete) Where(ps ...predicate.Role) *RoleDelete { + rd.mutation.Where(ps...) + return rd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (rd *RoleDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, rd.sqlExec, rd.mutation, rd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (rd *RoleDelete) ExecX(ctx context.Context) int { + n, err := rd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (rd *RoleDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(role.Table, sqlgraph.NewFieldSpec(role.FieldID, field.TypeInt64)) + if ps := rd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, rd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + rd.mutation.done = true + return affected, err +} + +// RoleDeleteOne is the builder for deleting a single Role entity. +type RoleDeleteOne struct { + rd *RoleDelete +} + +// Where appends a list predicates to the RoleDelete builder. +func (rdo *RoleDeleteOne) Where(ps ...predicate.Role) *RoleDeleteOne { + rdo.rd.mutation.Where(ps...) + return rdo +} + +// Exec executes the deletion query. +func (rdo *RoleDeleteOne) Exec(ctx context.Context) error { + n, err := rdo.rd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{role.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (rdo *RoleDeleteOne) ExecX(ctx context.Context) { + if err := rdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/internal/app/pkg/ent/ent/role_query.go b/internal/app/pkg/ent/ent/role_query.go new file mode 100644 index 00000000..bb230e83 --- /dev/null +++ b/internal/app/pkg/ent/ent/role_query.go @@ -0,0 +1,548 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/role" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// RoleQuery is the builder for querying Role entities. +type RoleQuery struct { + config + ctx *QueryContext + order []role.OrderOption + inters []Interceptor + predicates []predicate.Role + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the RoleQuery builder. +func (rq *RoleQuery) Where(ps ...predicate.Role) *RoleQuery { + rq.predicates = append(rq.predicates, ps...) + return rq +} + +// Limit the number of records to be returned by this query. +func (rq *RoleQuery) Limit(limit int) *RoleQuery { + rq.ctx.Limit = &limit + return rq +} + +// Offset to start from. +func (rq *RoleQuery) Offset(offset int) *RoleQuery { + rq.ctx.Offset = &offset + return rq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (rq *RoleQuery) Unique(unique bool) *RoleQuery { + rq.ctx.Unique = &unique + return rq +} + +// Order specifies how the records should be ordered. +func (rq *RoleQuery) Order(o ...role.OrderOption) *RoleQuery { + rq.order = append(rq.order, o...) + return rq +} + +// First returns the first Role entity from the query. +// Returns a *NotFoundError when no Role was found. +func (rq *RoleQuery) First(ctx context.Context) (*Role, error) { + nodes, err := rq.Limit(1).All(setContextOp(ctx, rq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{role.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (rq *RoleQuery) FirstX(ctx context.Context) *Role { + node, err := rq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Role ID from the query. +// Returns a *NotFoundError when no Role ID was found. +func (rq *RoleQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = rq.Limit(1).IDs(setContextOp(ctx, rq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{role.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (rq *RoleQuery) FirstIDX(ctx context.Context) int64 { + id, err := rq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Role entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Role entity is found. +// Returns a *NotFoundError when no Role entities are found. +func (rq *RoleQuery) Only(ctx context.Context) (*Role, error) { + nodes, err := rq.Limit(2).All(setContextOp(ctx, rq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{role.Label} + default: + return nil, &NotSingularError{role.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (rq *RoleQuery) OnlyX(ctx context.Context) *Role { + node, err := rq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Role ID in the query. +// Returns a *NotSingularError when more than one Role ID is found. +// Returns a *NotFoundError when no entities are found. +func (rq *RoleQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = rq.Limit(2).IDs(setContextOp(ctx, rq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{role.Label} + default: + err = &NotSingularError{role.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (rq *RoleQuery) OnlyIDX(ctx context.Context) int64 { + id, err := rq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Roles. +func (rq *RoleQuery) All(ctx context.Context) ([]*Role, error) { + ctx = setContextOp(ctx, rq.ctx, "All") + if err := rq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Role, *RoleQuery]() + return withInterceptors[[]*Role](ctx, rq, qr, rq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (rq *RoleQuery) AllX(ctx context.Context) []*Role { + nodes, err := rq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Role IDs. +func (rq *RoleQuery) IDs(ctx context.Context) (ids []int64, err error) { + if rq.ctx.Unique == nil && rq.path != nil { + rq.Unique(true) + } + ctx = setContextOp(ctx, rq.ctx, "IDs") + if err = rq.Select(role.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (rq *RoleQuery) IDsX(ctx context.Context) []int64 { + ids, err := rq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (rq *RoleQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, rq.ctx, "Count") + if err := rq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, rq, querierCount[*RoleQuery](), rq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (rq *RoleQuery) CountX(ctx context.Context) int { + count, err := rq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (rq *RoleQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, rq.ctx, "Exist") + switch _, err := rq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (rq *RoleQuery) ExistX(ctx context.Context) bool { + exist, err := rq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the RoleQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (rq *RoleQuery) Clone() *RoleQuery { + if rq == nil { + return nil + } + return &RoleQuery{ + config: rq.config, + ctx: rq.ctx.Clone(), + order: append([]role.OrderOption{}, rq.order...), + inters: append([]Interceptor{}, rq.inters...), + predicates: append([]predicate.Role{}, rq.predicates...), + // clone intermediate query. + sql: rq.sql.Clone(), + path: rq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Role.Query(). +// GroupBy(role.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (rq *RoleQuery) GroupBy(field string, fields ...string) *RoleGroupBy { + rq.ctx.Fields = append([]string{field}, fields...) + grbuild := &RoleGroupBy{build: rq} + grbuild.flds = &rq.ctx.Fields + grbuild.label = role.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt types.UnixTimestamp `json:"created_at,omitempty"` +// } +// +// client.Role.Query(). +// Select(role.FieldCreatedAt). +// Scan(ctx, &v) +func (rq *RoleQuery) Select(fields ...string) *RoleSelect { + rq.ctx.Fields = append(rq.ctx.Fields, fields...) + sbuild := &RoleSelect{RoleQuery: rq} + sbuild.label = role.Label + sbuild.flds, sbuild.scan = &rq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a RoleSelect configured with the given aggregations. +func (rq *RoleQuery) Aggregate(fns ...AggregateFunc) *RoleSelect { + return rq.Select().Aggregate(fns...) +} + +func (rq *RoleQuery) prepareQuery(ctx context.Context) error { + for _, inter := range rq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, rq); err != nil { + return err + } + } + } + for _, f := range rq.ctx.Fields { + if !role.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if rq.path != nil { + prev, err := rq.path(ctx) + if err != nil { + return err + } + rq.sql = prev + } + return nil +} + +func (rq *RoleQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Role, error) { + var ( + nodes = []*Role{} + _spec = rq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Role).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Role{config: rq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + if len(rq.modifiers) > 0 { + _spec.Modifiers = rq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, rq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (rq *RoleQuery) sqlCount(ctx context.Context) (int, error) { + _spec := rq.querySpec() + if len(rq.modifiers) > 0 { + _spec.Modifiers = rq.modifiers + } + _spec.Node.Columns = rq.ctx.Fields + if len(rq.ctx.Fields) > 0 { + _spec.Unique = rq.ctx.Unique != nil && *rq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, rq.driver, _spec) +} + +func (rq *RoleQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(role.Table, role.Columns, sqlgraph.NewFieldSpec(role.FieldID, field.TypeInt64)) + _spec.From = rq.sql + if unique := rq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if rq.path != nil { + _spec.Unique = true + } + if fields := rq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, role.FieldID) + for i := range fields { + if fields[i] != role.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := rq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := rq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := rq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := rq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (rq *RoleQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(rq.driver.Dialect()) + t1 := builder.Table(role.Table) + columns := rq.ctx.Fields + if len(columns) == 0 { + columns = role.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if rq.sql != nil { + selector = rq.sql + selector.Select(selector.Columns(columns...)...) + } + if rq.ctx.Unique != nil && *rq.ctx.Unique { + selector.Distinct() + } + for _, m := range rq.modifiers { + m(selector) + } + for _, p := range rq.predicates { + p(selector) + } + for _, p := range rq.order { + p(selector) + } + if offset := rq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := rq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (rq *RoleQuery) Modify(modifiers ...func(s *sql.Selector)) *RoleSelect { + rq.modifiers = append(rq.modifiers, modifiers...) + return rq.Select() +} + +// RoleGroupBy is the group-by builder for Role entities. +type RoleGroupBy struct { + selector + build *RoleQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (rgb *RoleGroupBy) Aggregate(fns ...AggregateFunc) *RoleGroupBy { + rgb.fns = append(rgb.fns, fns...) + return rgb +} + +// Scan applies the selector query and scans the result into the given value. +func (rgb *RoleGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, rgb.build.ctx, "GroupBy") + if err := rgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*RoleQuery, *RoleGroupBy](ctx, rgb.build, rgb, rgb.build.inters, v) +} + +func (rgb *RoleGroupBy) sqlScan(ctx context.Context, root *RoleQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(rgb.fns)) + for _, fn := range rgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*rgb.flds)+len(rgb.fns)) + for _, f := range *rgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*rgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := rgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// RoleSelect is the builder for selecting fields of Role entities. +type RoleSelect struct { + *RoleQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (rs *RoleSelect) Aggregate(fns ...AggregateFunc) *RoleSelect { + rs.fns = append(rs.fns, fns...) + return rs +} + +// Scan applies the selector query and scans the result into the given value. +func (rs *RoleSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, rs.ctx, "Select") + if err := rs.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*RoleQuery, *RoleSelect](ctx, rs.RoleQuery, rs, rs.inters, v) +} + +func (rs *RoleSelect) sqlScan(ctx context.Context, root *RoleQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(rs.fns)) + for _, fn := range rs.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*rs.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := rs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (rs *RoleSelect) Modify(modifiers ...func(s *sql.Selector)) *RoleSelect { + rs.modifiers = append(rs.modifiers, modifiers...) + return rs +} diff --git a/internal/app/pkg/ent/ent/role_update.go b/internal/app/pkg/ent/ent/role_update.go new file mode 100644 index 00000000..c98afd6d --- /dev/null +++ b/internal/app/pkg/ent/ent/role_update.go @@ -0,0 +1,324 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "go-scaffold/internal/app/pkg/ent/ent/predicate" + "go-scaffold/internal/app/pkg/ent/ent/role" + "go-scaffold/internal/app/repository/schema/types" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// RoleUpdate is the builder for updating Role entities. +type RoleUpdate struct { + config + hooks []Hook + mutation *RoleMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Where appends a list predicates to the RoleUpdate builder. +func (ru *RoleUpdate) Where(ps ...predicate.Role) *RoleUpdate { + ru.mutation.Where(ps...) + return ru +} + +// SetDeletedAt sets the "deleted_at" field. +func (ru *RoleUpdate) SetDeletedAt(tt types.UnixTimestamp) *RoleUpdate { + ru.mutation.SetDeletedAt(tt) + return ru +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ru *RoleUpdate) SetNillableDeletedAt(tt *types.UnixTimestamp) *RoleUpdate { + if tt != nil { + ru.SetDeletedAt(*tt) + } + return ru +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (ru *RoleUpdate) ClearDeletedAt() *RoleUpdate { + ru.mutation.ClearDeletedAt() + return ru +} + +// SetName sets the "name" field. +func (ru *RoleUpdate) SetName(s string) *RoleUpdate { + ru.mutation.SetName(s) + return ru +} + +// Mutation returns the RoleMutation object of the builder. +func (ru *RoleUpdate) Mutation() *RoleMutation { + return ru.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (ru *RoleUpdate) Save(ctx context.Context) (int, error) { + if err := ru.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, ru.sqlSave, ru.mutation, ru.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ru *RoleUpdate) SaveX(ctx context.Context) int { + affected, err := ru.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (ru *RoleUpdate) Exec(ctx context.Context) error { + _, err := ru.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ru *RoleUpdate) ExecX(ctx context.Context) { + if err := ru.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ru *RoleUpdate) defaults() error { + if _, ok := ru.mutation.UpdatedAt(); !ok { + if role.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized role.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := role.UpdateDefaultUpdatedAt() + ru.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ru *RoleUpdate) check() error { + if v, ok := ru.mutation.Name(); ok { + if err := role.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Role.name": %w`, err)} + } + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (ru *RoleUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *RoleUpdate { + ru.modifiers = append(ru.modifiers, modifiers...) + return ru +} + +func (ru *RoleUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := ru.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(role.Table, role.Columns, sqlgraph.NewFieldSpec(role.FieldID, field.TypeInt64)) + if ps := ru.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ru.mutation.UpdatedAt(); ok { + _spec.SetField(role.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := ru.mutation.DeletedAt(); ok { + _spec.SetField(role.FieldDeletedAt, field.TypeTime, value) + } + if ru.mutation.DeletedAtCleared() { + _spec.ClearField(role.FieldDeletedAt, field.TypeTime) + } + if value, ok := ru.mutation.Name(); ok { + _spec.SetField(role.FieldName, field.TypeString, value) + } + _spec.AddModifiers(ru.modifiers...) + if n, err = sqlgraph.UpdateNodes(ctx, ru.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{role.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + ru.mutation.done = true + return n, nil +} + +// RoleUpdateOne is the builder for updating a single Role entity. +type RoleUpdateOne struct { + config + fields []string + hooks []Hook + mutation *RoleMutation + modifiers []func(*sql.UpdateBuilder) +} + +// SetDeletedAt sets the "deleted_at" field. +func (ruo *RoleUpdateOne) SetDeletedAt(tt types.UnixTimestamp) *RoleUpdateOne { + ruo.mutation.SetDeletedAt(tt) + return ruo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ruo *RoleUpdateOne) SetNillableDeletedAt(tt *types.UnixTimestamp) *RoleUpdateOne { + if tt != nil { + ruo.SetDeletedAt(*tt) + } + return ruo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (ruo *RoleUpdateOne) ClearDeletedAt() *RoleUpdateOne { + ruo.mutation.ClearDeletedAt() + return ruo +} + +// SetName sets the "name" field. +func (ruo *RoleUpdateOne) SetName(s string) *RoleUpdateOne { + ruo.mutation.SetName(s) + return ruo +} + +// Mutation returns the RoleMutation object of the builder. +func (ruo *RoleUpdateOne) Mutation() *RoleMutation { + return ruo.mutation +} + +// Where appends a list predicates to the RoleUpdate builder. +func (ruo *RoleUpdateOne) Where(ps ...predicate.Role) *RoleUpdateOne { + ruo.mutation.Where(ps...) + return ruo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (ruo *RoleUpdateOne) Select(field string, fields ...string) *RoleUpdateOne { + ruo.fields = append([]string{field}, fields...) + return ruo +} + +// Save executes the query and returns the updated Role entity. +func (ruo *RoleUpdateOne) Save(ctx context.Context) (*Role, error) { + if err := ruo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, ruo.sqlSave, ruo.mutation, ruo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ruo *RoleUpdateOne) SaveX(ctx context.Context) *Role { + node, err := ruo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (ruo *RoleUpdateOne) Exec(ctx context.Context) error { + _, err := ruo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ruo *RoleUpdateOne) ExecX(ctx context.Context) { + if err := ruo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ruo *RoleUpdateOne) defaults() error { + if _, ok := ruo.mutation.UpdatedAt(); !ok { + if role.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized role.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := role.UpdateDefaultUpdatedAt() + ruo.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ruo *RoleUpdateOne) check() error { + if v, ok := ruo.mutation.Name(); ok { + if err := role.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Role.name": %w`, err)} + } + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (ruo *RoleUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *RoleUpdateOne { + ruo.modifiers = append(ruo.modifiers, modifiers...) + return ruo +} + +func (ruo *RoleUpdateOne) sqlSave(ctx context.Context) (_node *Role, err error) { + if err := ruo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(role.Table, role.Columns, sqlgraph.NewFieldSpec(role.FieldID, field.TypeInt64)) + id, ok := ruo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Role.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := ruo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, role.FieldID) + for _, f := range fields { + if !role.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != role.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := ruo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ruo.mutation.UpdatedAt(); ok { + _spec.SetField(role.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := ruo.mutation.DeletedAt(); ok { + _spec.SetField(role.FieldDeletedAt, field.TypeTime, value) + } + if ruo.mutation.DeletedAtCleared() { + _spec.ClearField(role.FieldDeletedAt, field.TypeTime) + } + if value, ok := ruo.mutation.Name(); ok { + _spec.SetField(role.FieldName, field.TypeString, value) + } + _spec.AddModifiers(ruo.modifiers...) + _node = &Role{config: ruo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, ruo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{role.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + ruo.mutation.done = true + return _node, nil +} diff --git a/internal/app/pkg/ent/ent/runtime/runtime.go b/internal/app/pkg/ent/ent/runtime/runtime.go index f25669e5..4ff4c2f4 100644 --- a/internal/app/pkg/ent/ent/runtime/runtime.go +++ b/internal/app/pkg/ent/ent/runtime/runtime.go @@ -3,6 +3,9 @@ package runtime import ( + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/product" + "go-scaffold/internal/app/pkg/ent/ent/role" "go-scaffold/internal/app/pkg/ent/ent/user" "go-scaffold/internal/app/repository/schema" "go-scaffold/internal/app/repository/schema/types" @@ -12,6 +15,99 @@ import ( // (default values, validators, hooks and policies) and stitches it // to their package variables. func init() { + permissionMixin := schema.Permission{}.Mixin() + permissionMixinHooks1 := permissionMixin[1].Hooks() + permission.Hooks[0] = permissionMixinHooks1[0] + permissionMixinInters1 := permissionMixin[1].Interceptors() + permission.Interceptors[0] = permissionMixinInters1[0] + permissionMixinFields0 := permissionMixin[0].Fields() + _ = permissionMixinFields0 + permissionFields := schema.Permission{}.Fields() + _ = permissionFields + // permissionDescCreatedAt is the schema descriptor for created_at field. + permissionDescCreatedAt := permissionMixinFields0[0].Descriptor() + // permission.DefaultCreatedAt holds the default value on creation for the created_at field. + permission.DefaultCreatedAt = permissionDescCreatedAt.Default.(func() types.UnixTimestamp) + // permissionDescUpdatedAt is the schema descriptor for updated_at field. + permissionDescUpdatedAt := permissionMixinFields0[1].Descriptor() + // permission.DefaultUpdatedAt holds the default value on creation for the updated_at field. + permission.DefaultUpdatedAt = permissionDescUpdatedAt.Default.(func() types.UnixTimestamp) + // permission.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + permission.UpdateDefaultUpdatedAt = permissionDescUpdatedAt.UpdateDefault.(func() types.UnixTimestamp) + // permissionDescKey is the schema descriptor for key field. + permissionDescKey := permissionFields[1].Descriptor() + // permission.KeyValidator is a validator for the "key" field. It is called by the builders before save. + permission.KeyValidator = permissionDescKey.Validators[0].(func(string) error) + // permissionDescName is the schema descriptor for name field. + permissionDescName := permissionFields[2].Descriptor() + // permission.DefaultName holds the default value on creation for the name field. + permission.DefaultName = permissionDescName.Default.(string) + // permission.NameValidator is a validator for the "name" field. It is called by the builders before save. + permission.NameValidator = permissionDescName.Validators[0].(func(string) error) + // permissionDescDesc is the schema descriptor for desc field. + permissionDescDesc := permissionFields[3].Descriptor() + // permission.DefaultDesc holds the default value on creation for the desc field. + permission.DefaultDesc = permissionDescDesc.Default.(string) + // permission.DescValidator is a validator for the "desc" field. It is called by the builders before save. + permission.DescValidator = permissionDescDesc.Validators[0].(func(string) error) + // permissionDescParentID is the schema descriptor for parent_id field. + permissionDescParentID := permissionFields[4].Descriptor() + // permission.DefaultParentID holds the default value on creation for the parent_id field. + permission.DefaultParentID = permissionDescParentID.Default.(int64) + productMixin := schema.Product{}.Mixin() + productMixinHooks1 := productMixin[1].Hooks() + product.Hooks[0] = productMixinHooks1[0] + productMixinInters1 := productMixin[1].Interceptors() + product.Interceptors[0] = productMixinInters1[0] + productMixinFields0 := productMixin[0].Fields() + _ = productMixinFields0 + productFields := schema.Product{}.Fields() + _ = productFields + // productDescCreatedAt is the schema descriptor for created_at field. + productDescCreatedAt := productMixinFields0[0].Descriptor() + // product.DefaultCreatedAt holds the default value on creation for the created_at field. + product.DefaultCreatedAt = productDescCreatedAt.Default.(func() types.UnixTimestamp) + // productDescUpdatedAt is the schema descriptor for updated_at field. + productDescUpdatedAt := productMixinFields0[1].Descriptor() + // product.DefaultUpdatedAt holds the default value on creation for the updated_at field. + product.DefaultUpdatedAt = productDescUpdatedAt.Default.(func() types.UnixTimestamp) + // product.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + product.UpdateDefaultUpdatedAt = productDescUpdatedAt.UpdateDefault.(func() types.UnixTimestamp) + // productDescName is the schema descriptor for name field. + productDescName := productFields[1].Descriptor() + // product.DefaultName holds the default value on creation for the name field. + product.DefaultName = productDescName.Default.(string) + // productDescDesc is the schema descriptor for desc field. + productDescDesc := productFields[2].Descriptor() + // product.DefaultDesc holds the default value on creation for the desc field. + product.DefaultDesc = productDescDesc.Default.(string) + // productDescPrice is the schema descriptor for price field. + productDescPrice := productFields[3].Descriptor() + // product.DefaultPrice holds the default value on creation for the price field. + product.DefaultPrice = productDescPrice.Default.(int) + roleMixin := schema.Role{}.Mixin() + roleMixinHooks1 := roleMixin[1].Hooks() + role.Hooks[0] = roleMixinHooks1[0] + roleMixinInters1 := roleMixin[1].Interceptors() + role.Interceptors[0] = roleMixinInters1[0] + roleMixinFields0 := roleMixin[0].Fields() + _ = roleMixinFields0 + roleFields := schema.Role{}.Fields() + _ = roleFields + // roleDescCreatedAt is the schema descriptor for created_at field. + roleDescCreatedAt := roleMixinFields0[0].Descriptor() + // role.DefaultCreatedAt holds the default value on creation for the created_at field. + role.DefaultCreatedAt = roleDescCreatedAt.Default.(func() types.UnixTimestamp) + // roleDescUpdatedAt is the schema descriptor for updated_at field. + roleDescUpdatedAt := roleMixinFields0[1].Descriptor() + // role.DefaultUpdatedAt holds the default value on creation for the updated_at field. + role.DefaultUpdatedAt = roleDescUpdatedAt.Default.(func() types.UnixTimestamp) + // role.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + role.UpdateDefaultUpdatedAt = roleDescUpdatedAt.UpdateDefault.(func() types.UnixTimestamp) + // roleDescName is the schema descriptor for name field. + roleDescName := roleFields[1].Descriptor() + // role.NameValidator is a validator for the "name" field. It is called by the builders before save. + role.NameValidator = roleDescName.Validators[0].(func(string) error) userMixin := schema.User{}.Mixin() userMixinHooks1 := userMixin[1].Hooks() user.Hooks[0] = userMixinHooks1[0] @@ -31,23 +127,29 @@ func init() { user.DefaultUpdatedAt = userDescUpdatedAt.Default.(func() types.UnixTimestamp) // user.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. user.UpdateDefaultUpdatedAt = userDescUpdatedAt.UpdateDefault.(func() types.UnixTimestamp) - // userDescName is the schema descriptor for name field. - userDescName := userFields[1].Descriptor() - // user.DefaultName holds the default value on creation for the name field. - user.DefaultName = userDescName.Default.(string) - // userDescAge is the schema descriptor for age field. - userDescAge := userFields[2].Descriptor() - // user.DefaultAge holds the default value on creation for the age field. - user.DefaultAge = userDescAge.Default.(int8) - // user.AgeValidator is a validator for the "age" field. It is called by the builders before save. - user.AgeValidator = userDescAge.Validators[0].(func(int8) error) + // userDescUsername is the schema descriptor for username field. + userDescUsername := userFields[1].Descriptor() + // user.DefaultUsername holds the default value on creation for the username field. + user.DefaultUsername = userDescUsername.Default.(string) + // userDescPassword is the schema descriptor for password field. + userDescPassword := userFields[2].Descriptor() + // user.DefaultPassword holds the default value on creation for the password field. + user.DefaultPassword = userDescPassword.Default.(string) + // userDescNickname is the schema descriptor for nickname field. + userDescNickname := userFields[3].Descriptor() + // user.DefaultNickname holds the default value on creation for the nickname field. + user.DefaultNickname = userDescNickname.Default.(string) // userDescPhone is the schema descriptor for phone field. - userDescPhone := userFields[3].Descriptor() + userDescPhone := userFields[4].Descriptor() // user.DefaultPhone holds the default value on creation for the phone field. user.DefaultPhone = userDescPhone.Default.(string) + // userDescSalt is the schema descriptor for salt field. + userDescSalt := userFields[5].Descriptor() + // user.DefaultSalt holds the default value on creation for the salt field. + user.DefaultSalt = userDescSalt.Default.(string) } const ( - Version = "v0.11.7" // Version of ent codegen. - Sum = "h1:V+wKFh0jhAbY/FoU+PPbdMOf2Ma5vh07R/IdF+N/nFg=" // Sum of ent codegen. + Version = "v0.12.3" // Version of ent codegen. + Sum = "h1:N5lO2EOrHpCH5HYfiMOCHYbo+oh5M8GjT0/cx5x6xkk=" // Sum of ent codegen. ) diff --git a/internal/app/pkg/ent/ent/tx.go b/internal/app/pkg/ent/ent/tx.go index 3e6f77f4..87e84776 100644 --- a/internal/app/pkg/ent/ent/tx.go +++ b/internal/app/pkg/ent/ent/tx.go @@ -14,6 +14,12 @@ import ( // Tx is a transactional client that is created by calling Client.Tx(). type Tx struct { config + // Permission is the client for interacting with the Permission builders. + Permission *PermissionClient + // Product is the client for interacting with the Product builders. + Product *ProductClient + // Role is the client for interacting with the Role builders. + Role *RoleClient // User is the client for interacting with the User builders. User *UserClient @@ -147,6 +153,9 @@ func (tx *Tx) Client() *Client { } func (tx *Tx) init() { + tx.Permission = NewPermissionClient(tx.config) + tx.Product = NewProductClient(tx.config) + tx.Role = NewRoleClient(tx.config) tx.User = NewUserClient(tx.config) } @@ -157,7 +166,7 @@ func (tx *Tx) init() { // of them in order to commit or rollback the transaction. // // If a closed transaction is embedded in one of the generated entities, and the entity -// applies a query, for example: User.QueryXXX(), the query will be executed +// applies a query, for example: Permission.QueryXXX(), the query will be executed // through the driver which created this transaction. // // Note that txDriver is not goroutine safe. diff --git a/internal/app/pkg/ent/ent/user.go b/internal/app/pkg/ent/ent/user.go index 6bb3be11..1e459c81 100644 --- a/internal/app/pkg/ent/ent/user.go +++ b/internal/app/pkg/ent/ent/user.go @@ -8,6 +8,7 @@ import ( "go-scaffold/internal/app/repository/schema/types" "strings" + "entgo.io/ent" "entgo.io/ent/dialect/sql" ) @@ -22,12 +23,17 @@ type User struct { UpdatedAt types.UnixTimestamp `json:"updated_at,omitempty"` // DeletedAt holds the value of the "deleted_at" field. DeletedAt types.UnixTimestamp `json:"deleted_at,omitempty"` - // 名称 - Name string `json:"name,omitempty"` - // 年龄 - Age int8 `json:"age,omitempty"` + // 用户名 + Username string `json:"username,omitempty"` + // 密码 + Password string `json:"password,omitempty"` + // 用户名 + Nickname string `json:"nickname,omitempty"` // 电话 Phone string `json:"phone,omitempty"` + // 盐值 + Salt string `json:"salt,omitempty"` + selectValues sql.SelectValues } // scanValues returns the types for scanning values from sql.Rows. @@ -35,14 +41,14 @@ func (*User) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { - case user.FieldID, user.FieldAge: + case user.FieldID: values[i] = new(sql.NullInt64) - case user.FieldName, user.FieldPhone: + case user.FieldUsername, user.FieldPassword, user.FieldNickname, user.FieldPhone, user.FieldSalt: values[i] = new(sql.NullString) case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldDeletedAt: values[i] = new(types.UnixTimestamp) default: - return nil, fmt.Errorf("unexpected column %q for type User", columns[i]) + values[i] = new(sql.UnknownType) } } return values, nil @@ -80,17 +86,23 @@ func (u *User) assignValues(columns []string, values []any) error { } else if value != nil { u.DeletedAt = *value } - case user.FieldName: + case user.FieldUsername: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field username", values[i]) + } else if value.Valid { + u.Username = value.String + } + case user.FieldPassword: if value, ok := values[i].(*sql.NullString); !ok { - return fmt.Errorf("unexpected type %T for field name", values[i]) + return fmt.Errorf("unexpected type %T for field password", values[i]) } else if value.Valid { - u.Name = value.String + u.Password = value.String } - case user.FieldAge: - if value, ok := values[i].(*sql.NullInt64); !ok { - return fmt.Errorf("unexpected type %T for field age", values[i]) + case user.FieldNickname: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field nickname", values[i]) } else if value.Valid { - u.Age = int8(value.Int64) + u.Nickname = value.String } case user.FieldPhone: if value, ok := values[i].(*sql.NullString); !ok { @@ -98,11 +110,25 @@ func (u *User) assignValues(columns []string, values []any) error { } else if value.Valid { u.Phone = value.String } + case user.FieldSalt: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field salt", values[i]) + } else if value.Valid { + u.Salt = value.String + } + default: + u.selectValues.Set(columns[i], values[i]) } } return nil } +// Value returns the ent.Value that was dynamically selected and assigned to the User. +// This includes values selected through modifiers, order, etc. +func (u *User) Value(name string) (ent.Value, error) { + return u.selectValues.Get(name) +} + // Update returns a builder for updating this User. // Note that you need to call User.Unwrap() before calling this method if this User // was returned from a transaction, and the transaction was committed or rolled back. @@ -135,23 +161,23 @@ func (u *User) String() string { builder.WriteString("deleted_at=") builder.WriteString(fmt.Sprintf("%v", u.DeletedAt)) builder.WriteString(", ") - builder.WriteString("name=") - builder.WriteString(u.Name) + builder.WriteString("username=") + builder.WriteString(u.Username) + builder.WriteString(", ") + builder.WriteString("password=") + builder.WriteString(u.Password) builder.WriteString(", ") - builder.WriteString("age=") - builder.WriteString(fmt.Sprintf("%v", u.Age)) + builder.WriteString("nickname=") + builder.WriteString(u.Nickname) builder.WriteString(", ") builder.WriteString("phone=") builder.WriteString(u.Phone) + builder.WriteString(", ") + builder.WriteString("salt=") + builder.WriteString(u.Salt) builder.WriteByte(')') return builder.String() } // Users is a parsable slice of User. type Users []*User - -func (u Users) config(cfg config) { - for _i := range u { - u[_i].config = cfg - } -} diff --git a/internal/app/pkg/ent/ent/user/user.go b/internal/app/pkg/ent/ent/user/user.go index e484e39a..c37e7964 100644 --- a/internal/app/pkg/ent/ent/user/user.go +++ b/internal/app/pkg/ent/ent/user/user.go @@ -6,6 +6,7 @@ import ( "go-scaffold/internal/app/repository/schema/types" "entgo.io/ent" + "entgo.io/ent/dialect/sql" ) const ( @@ -19,12 +20,16 @@ const ( FieldUpdatedAt = "updated_at" // FieldDeletedAt holds the string denoting the deleted_at field in the database. FieldDeletedAt = "deleted_at" - // FieldName holds the string denoting the name field in the database. - FieldName = "name" - // FieldAge holds the string denoting the age field in the database. - FieldAge = "age" + // FieldUsername holds the string denoting the username field in the database. + FieldUsername = "username" + // FieldPassword holds the string denoting the password field in the database. + FieldPassword = "password" + // FieldNickname holds the string denoting the nickname field in the database. + FieldNickname = "nickname" // FieldPhone holds the string denoting the phone field in the database. FieldPhone = "phone" + // FieldSalt holds the string denoting the salt field in the database. + FieldSalt = "salt" // Table holds the table name of the user in the database. Table = "users" ) @@ -35,9 +40,11 @@ var Columns = []string{ FieldCreatedAt, FieldUpdatedAt, FieldDeletedAt, - FieldName, - FieldAge, + FieldUsername, + FieldPassword, + FieldNickname, FieldPhone, + FieldSalt, } // ValidColumn reports if the column name is valid (part of the table columns). @@ -64,12 +71,62 @@ var ( DefaultUpdatedAt func() types.UnixTimestamp // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. UpdateDefaultUpdatedAt func() types.UnixTimestamp - // DefaultName holds the default value on creation for the "name" field. - DefaultName string - // DefaultAge holds the default value on creation for the "age" field. - DefaultAge int8 - // AgeValidator is a validator for the "age" field. It is called by the builders before save. - AgeValidator func(int8) error + // DefaultUsername holds the default value on creation for the "username" field. + DefaultUsername string + // DefaultPassword holds the default value on creation for the "password" field. + DefaultPassword string + // DefaultNickname holds the default value on creation for the "nickname" field. + DefaultNickname string // DefaultPhone holds the default value on creation for the "phone" field. DefaultPhone string + // DefaultSalt holds the default value on creation for the "salt" field. + DefaultSalt string ) + +// OrderOption defines the ordering options for the User queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByUsername orders the results by the username field. +func ByUsername(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUsername, opts...).ToFunc() +} + +// ByPassword orders the results by the password field. +func ByPassword(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPassword, opts...).ToFunc() +} + +// ByNickname orders the results by the nickname field. +func ByNickname(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldNickname, opts...).ToFunc() +} + +// ByPhone orders the results by the phone field. +func ByPhone(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPhone, opts...).ToFunc() +} + +// BySalt orders the results by the salt field. +func BySalt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSalt, opts...).ToFunc() +} diff --git a/internal/app/pkg/ent/ent/user/where.go b/internal/app/pkg/ent/ent/user/where.go index 4f993dce..8ec589f0 100644 --- a/internal/app/pkg/ent/ent/user/where.go +++ b/internal/app/pkg/ent/ent/user/where.go @@ -69,14 +69,19 @@ func DeletedAt(v types.UnixTimestamp) predicate.User { return predicate.User(sql.FieldEQ(FieldDeletedAt, v)) } -// Name applies equality check predicate on the "name" field. It's identical to NameEQ. -func Name(v string) predicate.User { - return predicate.User(sql.FieldEQ(FieldName, v)) +// Username applies equality check predicate on the "username" field. It's identical to UsernameEQ. +func Username(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldUsername, v)) } -// Age applies equality check predicate on the "age" field. It's identical to AgeEQ. -func Age(v int8) predicate.User { - return predicate.User(sql.FieldEQ(FieldAge, v)) +// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ. +func Password(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldPassword, v)) +} + +// Nickname applies equality check predicate on the "nickname" field. It's identical to NicknameEQ. +func Nickname(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldNickname, v)) } // Phone applies equality check predicate on the "phone" field. It's identical to PhoneEQ. @@ -84,6 +89,11 @@ func Phone(v string) predicate.User { return predicate.User(sql.FieldEQ(FieldPhone, v)) } +// Salt applies equality check predicate on the "salt" field. It's identical to SaltEQ. +func Salt(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldSalt, v)) +} + // CreatedAtEQ applies the EQ predicate on the "created_at" field. func CreatedAtEQ(v types.UnixTimestamp) predicate.User { return predicate.User(sql.FieldEQ(FieldCreatedAt, v)) @@ -214,109 +224,199 @@ func DeletedAtNotNil() predicate.User { return predicate.User(sql.FieldNotNull(FieldDeletedAt)) } -// NameEQ applies the EQ predicate on the "name" field. -func NameEQ(v string) predicate.User { - return predicate.User(sql.FieldEQ(FieldName, v)) +// UsernameEQ applies the EQ predicate on the "username" field. +func UsernameEQ(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldUsername, v)) +} + +// UsernameNEQ applies the NEQ predicate on the "username" field. +func UsernameNEQ(v string) predicate.User { + return predicate.User(sql.FieldNEQ(FieldUsername, v)) +} + +// UsernameIn applies the In predicate on the "username" field. +func UsernameIn(vs ...string) predicate.User { + return predicate.User(sql.FieldIn(FieldUsername, vs...)) +} + +// UsernameNotIn applies the NotIn predicate on the "username" field. +func UsernameNotIn(vs ...string) predicate.User { + return predicate.User(sql.FieldNotIn(FieldUsername, vs...)) +} + +// UsernameGT applies the GT predicate on the "username" field. +func UsernameGT(v string) predicate.User { + return predicate.User(sql.FieldGT(FieldUsername, v)) +} + +// UsernameGTE applies the GTE predicate on the "username" field. +func UsernameGTE(v string) predicate.User { + return predicate.User(sql.FieldGTE(FieldUsername, v)) +} + +// UsernameLT applies the LT predicate on the "username" field. +func UsernameLT(v string) predicate.User { + return predicate.User(sql.FieldLT(FieldUsername, v)) +} + +// UsernameLTE applies the LTE predicate on the "username" field. +func UsernameLTE(v string) predicate.User { + return predicate.User(sql.FieldLTE(FieldUsername, v)) +} + +// UsernameContains applies the Contains predicate on the "username" field. +func UsernameContains(v string) predicate.User { + return predicate.User(sql.FieldContains(FieldUsername, v)) +} + +// UsernameHasPrefix applies the HasPrefix predicate on the "username" field. +func UsernameHasPrefix(v string) predicate.User { + return predicate.User(sql.FieldHasPrefix(FieldUsername, v)) +} + +// UsernameHasSuffix applies the HasSuffix predicate on the "username" field. +func UsernameHasSuffix(v string) predicate.User { + return predicate.User(sql.FieldHasSuffix(FieldUsername, v)) +} + +// UsernameEqualFold applies the EqualFold predicate on the "username" field. +func UsernameEqualFold(v string) predicate.User { + return predicate.User(sql.FieldEqualFold(FieldUsername, v)) +} + +// UsernameContainsFold applies the ContainsFold predicate on the "username" field. +func UsernameContainsFold(v string) predicate.User { + return predicate.User(sql.FieldContainsFold(FieldUsername, v)) +} + +// PasswordEQ applies the EQ predicate on the "password" field. +func PasswordEQ(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldPassword, v)) +} + +// PasswordNEQ applies the NEQ predicate on the "password" field. +func PasswordNEQ(v string) predicate.User { + return predicate.User(sql.FieldNEQ(FieldPassword, v)) +} + +// PasswordIn applies the In predicate on the "password" field. +func PasswordIn(vs ...string) predicate.User { + return predicate.User(sql.FieldIn(FieldPassword, vs...)) +} + +// PasswordNotIn applies the NotIn predicate on the "password" field. +func PasswordNotIn(vs ...string) predicate.User { + return predicate.User(sql.FieldNotIn(FieldPassword, vs...)) +} + +// PasswordGT applies the GT predicate on the "password" field. +func PasswordGT(v string) predicate.User { + return predicate.User(sql.FieldGT(FieldPassword, v)) } -// NameNEQ applies the NEQ predicate on the "name" field. -func NameNEQ(v string) predicate.User { - return predicate.User(sql.FieldNEQ(FieldName, v)) +// PasswordGTE applies the GTE predicate on the "password" field. +func PasswordGTE(v string) predicate.User { + return predicate.User(sql.FieldGTE(FieldPassword, v)) } -// NameIn applies the In predicate on the "name" field. -func NameIn(vs ...string) predicate.User { - return predicate.User(sql.FieldIn(FieldName, vs...)) +// PasswordLT applies the LT predicate on the "password" field. +func PasswordLT(v string) predicate.User { + return predicate.User(sql.FieldLT(FieldPassword, v)) } -// NameNotIn applies the NotIn predicate on the "name" field. -func NameNotIn(vs ...string) predicate.User { - return predicate.User(sql.FieldNotIn(FieldName, vs...)) +// PasswordLTE applies the LTE predicate on the "password" field. +func PasswordLTE(v string) predicate.User { + return predicate.User(sql.FieldLTE(FieldPassword, v)) } -// NameGT applies the GT predicate on the "name" field. -func NameGT(v string) predicate.User { - return predicate.User(sql.FieldGT(FieldName, v)) +// PasswordContains applies the Contains predicate on the "password" field. +func PasswordContains(v string) predicate.User { + return predicate.User(sql.FieldContains(FieldPassword, v)) } -// NameGTE applies the GTE predicate on the "name" field. -func NameGTE(v string) predicate.User { - return predicate.User(sql.FieldGTE(FieldName, v)) +// PasswordHasPrefix applies the HasPrefix predicate on the "password" field. +func PasswordHasPrefix(v string) predicate.User { + return predicate.User(sql.FieldHasPrefix(FieldPassword, v)) } -// NameLT applies the LT predicate on the "name" field. -func NameLT(v string) predicate.User { - return predicate.User(sql.FieldLT(FieldName, v)) +// PasswordHasSuffix applies the HasSuffix predicate on the "password" field. +func PasswordHasSuffix(v string) predicate.User { + return predicate.User(sql.FieldHasSuffix(FieldPassword, v)) } -// NameLTE applies the LTE predicate on the "name" field. -func NameLTE(v string) predicate.User { - return predicate.User(sql.FieldLTE(FieldName, v)) +// PasswordEqualFold applies the EqualFold predicate on the "password" field. +func PasswordEqualFold(v string) predicate.User { + return predicate.User(sql.FieldEqualFold(FieldPassword, v)) } -// NameContains applies the Contains predicate on the "name" field. -func NameContains(v string) predicate.User { - return predicate.User(sql.FieldContains(FieldName, v)) +// PasswordContainsFold applies the ContainsFold predicate on the "password" field. +func PasswordContainsFold(v string) predicate.User { + return predicate.User(sql.FieldContainsFold(FieldPassword, v)) } -// NameHasPrefix applies the HasPrefix predicate on the "name" field. -func NameHasPrefix(v string) predicate.User { - return predicate.User(sql.FieldHasPrefix(FieldName, v)) +// NicknameEQ applies the EQ predicate on the "nickname" field. +func NicknameEQ(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldNickname, v)) } -// NameHasSuffix applies the HasSuffix predicate on the "name" field. -func NameHasSuffix(v string) predicate.User { - return predicate.User(sql.FieldHasSuffix(FieldName, v)) +// NicknameNEQ applies the NEQ predicate on the "nickname" field. +func NicknameNEQ(v string) predicate.User { + return predicate.User(sql.FieldNEQ(FieldNickname, v)) } -// NameEqualFold applies the EqualFold predicate on the "name" field. -func NameEqualFold(v string) predicate.User { - return predicate.User(sql.FieldEqualFold(FieldName, v)) +// NicknameIn applies the In predicate on the "nickname" field. +func NicknameIn(vs ...string) predicate.User { + return predicate.User(sql.FieldIn(FieldNickname, vs...)) } -// NameContainsFold applies the ContainsFold predicate on the "name" field. -func NameContainsFold(v string) predicate.User { - return predicate.User(sql.FieldContainsFold(FieldName, v)) +// NicknameNotIn applies the NotIn predicate on the "nickname" field. +func NicknameNotIn(vs ...string) predicate.User { + return predicate.User(sql.FieldNotIn(FieldNickname, vs...)) } -// AgeEQ applies the EQ predicate on the "age" field. -func AgeEQ(v int8) predicate.User { - return predicate.User(sql.FieldEQ(FieldAge, v)) +// NicknameGT applies the GT predicate on the "nickname" field. +func NicknameGT(v string) predicate.User { + return predicate.User(sql.FieldGT(FieldNickname, v)) } -// AgeNEQ applies the NEQ predicate on the "age" field. -func AgeNEQ(v int8) predicate.User { - return predicate.User(sql.FieldNEQ(FieldAge, v)) +// NicknameGTE applies the GTE predicate on the "nickname" field. +func NicknameGTE(v string) predicate.User { + return predicate.User(sql.FieldGTE(FieldNickname, v)) } -// AgeIn applies the In predicate on the "age" field. -func AgeIn(vs ...int8) predicate.User { - return predicate.User(sql.FieldIn(FieldAge, vs...)) +// NicknameLT applies the LT predicate on the "nickname" field. +func NicknameLT(v string) predicate.User { + return predicate.User(sql.FieldLT(FieldNickname, v)) } -// AgeNotIn applies the NotIn predicate on the "age" field. -func AgeNotIn(vs ...int8) predicate.User { - return predicate.User(sql.FieldNotIn(FieldAge, vs...)) +// NicknameLTE applies the LTE predicate on the "nickname" field. +func NicknameLTE(v string) predicate.User { + return predicate.User(sql.FieldLTE(FieldNickname, v)) } -// AgeGT applies the GT predicate on the "age" field. -func AgeGT(v int8) predicate.User { - return predicate.User(sql.FieldGT(FieldAge, v)) +// NicknameContains applies the Contains predicate on the "nickname" field. +func NicknameContains(v string) predicate.User { + return predicate.User(sql.FieldContains(FieldNickname, v)) } -// AgeGTE applies the GTE predicate on the "age" field. -func AgeGTE(v int8) predicate.User { - return predicate.User(sql.FieldGTE(FieldAge, v)) +// NicknameHasPrefix applies the HasPrefix predicate on the "nickname" field. +func NicknameHasPrefix(v string) predicate.User { + return predicate.User(sql.FieldHasPrefix(FieldNickname, v)) } -// AgeLT applies the LT predicate on the "age" field. -func AgeLT(v int8) predicate.User { - return predicate.User(sql.FieldLT(FieldAge, v)) +// NicknameHasSuffix applies the HasSuffix predicate on the "nickname" field. +func NicknameHasSuffix(v string) predicate.User { + return predicate.User(sql.FieldHasSuffix(FieldNickname, v)) } -// AgeLTE applies the LTE predicate on the "age" field. -func AgeLTE(v int8) predicate.User { - return predicate.User(sql.FieldLTE(FieldAge, v)) +// NicknameEqualFold applies the EqualFold predicate on the "nickname" field. +func NicknameEqualFold(v string) predicate.User { + return predicate.User(sql.FieldEqualFold(FieldNickname, v)) +} + +// NicknameContainsFold applies the ContainsFold predicate on the "nickname" field. +func NicknameContainsFold(v string) predicate.User { + return predicate.User(sql.FieldContainsFold(FieldNickname, v)) } // PhoneEQ applies the EQ predicate on the "phone" field. @@ -384,6 +484,71 @@ func PhoneContainsFold(v string) predicate.User { return predicate.User(sql.FieldContainsFold(FieldPhone, v)) } +// SaltEQ applies the EQ predicate on the "salt" field. +func SaltEQ(v string) predicate.User { + return predicate.User(sql.FieldEQ(FieldSalt, v)) +} + +// SaltNEQ applies the NEQ predicate on the "salt" field. +func SaltNEQ(v string) predicate.User { + return predicate.User(sql.FieldNEQ(FieldSalt, v)) +} + +// SaltIn applies the In predicate on the "salt" field. +func SaltIn(vs ...string) predicate.User { + return predicate.User(sql.FieldIn(FieldSalt, vs...)) +} + +// SaltNotIn applies the NotIn predicate on the "salt" field. +func SaltNotIn(vs ...string) predicate.User { + return predicate.User(sql.FieldNotIn(FieldSalt, vs...)) +} + +// SaltGT applies the GT predicate on the "salt" field. +func SaltGT(v string) predicate.User { + return predicate.User(sql.FieldGT(FieldSalt, v)) +} + +// SaltGTE applies the GTE predicate on the "salt" field. +func SaltGTE(v string) predicate.User { + return predicate.User(sql.FieldGTE(FieldSalt, v)) +} + +// SaltLT applies the LT predicate on the "salt" field. +func SaltLT(v string) predicate.User { + return predicate.User(sql.FieldLT(FieldSalt, v)) +} + +// SaltLTE applies the LTE predicate on the "salt" field. +func SaltLTE(v string) predicate.User { + return predicate.User(sql.FieldLTE(FieldSalt, v)) +} + +// SaltContains applies the Contains predicate on the "salt" field. +func SaltContains(v string) predicate.User { + return predicate.User(sql.FieldContains(FieldSalt, v)) +} + +// SaltHasPrefix applies the HasPrefix predicate on the "salt" field. +func SaltHasPrefix(v string) predicate.User { + return predicate.User(sql.FieldHasPrefix(FieldSalt, v)) +} + +// SaltHasSuffix applies the HasSuffix predicate on the "salt" field. +func SaltHasSuffix(v string) predicate.User { + return predicate.User(sql.FieldHasSuffix(FieldSalt, v)) +} + +// SaltEqualFold applies the EqualFold predicate on the "salt" field. +func SaltEqualFold(v string) predicate.User { + return predicate.User(sql.FieldEqualFold(FieldSalt, v)) +} + +// SaltContainsFold applies the ContainsFold predicate on the "salt" field. +func SaltContainsFold(v string) predicate.User { + return predicate.User(sql.FieldContainsFold(FieldSalt, v)) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User(func(s *sql.Selector) { diff --git a/internal/app/pkg/ent/ent/user_create.go b/internal/app/pkg/ent/ent/user_create.go index 7e2a24b6..bc0884c8 100644 --- a/internal/app/pkg/ent/ent/user_create.go +++ b/internal/app/pkg/ent/ent/user_create.go @@ -62,30 +62,44 @@ func (uc *UserCreate) SetNillableDeletedAt(tt *types.UnixTimestamp) *UserCreate return uc } -// SetName sets the "name" field. -func (uc *UserCreate) SetName(s string) *UserCreate { - uc.mutation.SetName(s) +// SetUsername sets the "username" field. +func (uc *UserCreate) SetUsername(s string) *UserCreate { + uc.mutation.SetUsername(s) return uc } -// SetNillableName sets the "name" field if the given value is not nil. -func (uc *UserCreate) SetNillableName(s *string) *UserCreate { +// SetNillableUsername sets the "username" field if the given value is not nil. +func (uc *UserCreate) SetNillableUsername(s *string) *UserCreate { if s != nil { - uc.SetName(*s) + uc.SetUsername(*s) } return uc } -// SetAge sets the "age" field. -func (uc *UserCreate) SetAge(i int8) *UserCreate { - uc.mutation.SetAge(i) +// SetPassword sets the "password" field. +func (uc *UserCreate) SetPassword(s string) *UserCreate { + uc.mutation.SetPassword(s) return uc } -// SetNillableAge sets the "age" field if the given value is not nil. -func (uc *UserCreate) SetNillableAge(i *int8) *UserCreate { - if i != nil { - uc.SetAge(*i) +// SetNillablePassword sets the "password" field if the given value is not nil. +func (uc *UserCreate) SetNillablePassword(s *string) *UserCreate { + if s != nil { + uc.SetPassword(*s) + } + return uc +} + +// SetNickname sets the "nickname" field. +func (uc *UserCreate) SetNickname(s string) *UserCreate { + uc.mutation.SetNickname(s) + return uc +} + +// SetNillableNickname sets the "nickname" field if the given value is not nil. +func (uc *UserCreate) SetNillableNickname(s *string) *UserCreate { + if s != nil { + uc.SetNickname(*s) } return uc } @@ -104,6 +118,20 @@ func (uc *UserCreate) SetNillablePhone(s *string) *UserCreate { return uc } +// SetSalt sets the "salt" field. +func (uc *UserCreate) SetSalt(s string) *UserCreate { + uc.mutation.SetSalt(s) + return uc +} + +// SetNillableSalt sets the "salt" field if the given value is not nil. +func (uc *UserCreate) SetNillableSalt(s *string) *UserCreate { + if s != nil { + uc.SetSalt(*s) + } + return uc +} + // SetID sets the "id" field. func (uc *UserCreate) SetID(i int64) *UserCreate { uc.mutation.SetID(i) @@ -120,7 +148,7 @@ func (uc *UserCreate) Save(ctx context.Context) (*User, error) { if err := uc.defaults(); err != nil { return nil, err } - return withHooks[*User, UserMutation](ctx, uc.sqlSave, uc.mutation, uc.hooks) + return withHooks(ctx, uc.sqlSave, uc.mutation, uc.hooks) } // SaveX calls Save and panics if Save returns an error. @@ -161,18 +189,26 @@ func (uc *UserCreate) defaults() error { v := user.DefaultUpdatedAt() uc.mutation.SetUpdatedAt(v) } - if _, ok := uc.mutation.Name(); !ok { - v := user.DefaultName - uc.mutation.SetName(v) + if _, ok := uc.mutation.Username(); !ok { + v := user.DefaultUsername + uc.mutation.SetUsername(v) } - if _, ok := uc.mutation.Age(); !ok { - v := user.DefaultAge - uc.mutation.SetAge(v) + if _, ok := uc.mutation.Password(); !ok { + v := user.DefaultPassword + uc.mutation.SetPassword(v) + } + if _, ok := uc.mutation.Nickname(); !ok { + v := user.DefaultNickname + uc.mutation.SetNickname(v) } if _, ok := uc.mutation.Phone(); !ok { v := user.DefaultPhone uc.mutation.SetPhone(v) } + if _, ok := uc.mutation.Salt(); !ok { + v := user.DefaultSalt + uc.mutation.SetSalt(v) + } return nil } @@ -184,20 +220,21 @@ func (uc *UserCreate) check() error { if _, ok := uc.mutation.UpdatedAt(); !ok { return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "User.updated_at"`)} } - if _, ok := uc.mutation.Name(); !ok { - return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "User.name"`)} + if _, ok := uc.mutation.Username(); !ok { + return &ValidationError{Name: "username", err: errors.New(`ent: missing required field "User.username"`)} } - if _, ok := uc.mutation.Age(); !ok { - return &ValidationError{Name: "age", err: errors.New(`ent: missing required field "User.age"`)} + if _, ok := uc.mutation.Password(); !ok { + return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "User.password"`)} } - if v, ok := uc.mutation.Age(); ok { - if err := user.AgeValidator(v); err != nil { - return &ValidationError{Name: "age", err: fmt.Errorf(`ent: validator failed for field "User.age": %w`, err)} - } + if _, ok := uc.mutation.Nickname(); !ok { + return &ValidationError{Name: "nickname", err: errors.New(`ent: missing required field "User.nickname"`)} } if _, ok := uc.mutation.Phone(); !ok { return &ValidationError{Name: "phone", err: errors.New(`ent: missing required field "User.phone"`)} } + if _, ok := uc.mutation.Salt(); !ok { + return &ValidationError{Name: "salt", err: errors.New(`ent: missing required field "User.salt"`)} + } return nil } @@ -224,13 +261,7 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { var ( _node = &User{config: uc.config} - _spec = &sqlgraph.CreateSpec{ - Table: user.Table, - ID: &sqlgraph.FieldSpec{ - Type: field.TypeInt64, - Column: user.FieldID, - }, - } + _spec = sqlgraph.NewCreateSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64)) ) if id, ok := uc.mutation.ID(); ok { _node.ID = id @@ -248,18 +279,26 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { _spec.SetField(user.FieldDeletedAt, field.TypeTime, value) _node.DeletedAt = value } - if value, ok := uc.mutation.Name(); ok { - _spec.SetField(user.FieldName, field.TypeString, value) - _node.Name = value + if value, ok := uc.mutation.Username(); ok { + _spec.SetField(user.FieldUsername, field.TypeString, value) + _node.Username = value + } + if value, ok := uc.mutation.Password(); ok { + _spec.SetField(user.FieldPassword, field.TypeString, value) + _node.Password = value } - if value, ok := uc.mutation.Age(); ok { - _spec.SetField(user.FieldAge, field.TypeInt8, value) - _node.Age = value + if value, ok := uc.mutation.Nickname(); ok { + _spec.SetField(user.FieldNickname, field.TypeString, value) + _node.Nickname = value } if value, ok := uc.mutation.Phone(); ok { _spec.SetField(user.FieldPhone, field.TypeString, value) _node.Phone = value } + if value, ok := uc.mutation.Salt(); ok { + _spec.SetField(user.FieldSalt, field.TypeString, value) + _node.Salt = value + } return _node, _spec } @@ -287,8 +326,8 @@ func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) { return nil, err } builder.mutation = mutation - nodes[i], specs[i] = builder.createSpec() var err error + nodes[i], specs[i] = builder.createSpec() if i < len(mutators)-1 { _, err = mutators[i+1].Mutate(root, ucb.builders[i+1].mutation) } else { diff --git a/internal/app/pkg/ent/ent/user_delete.go b/internal/app/pkg/ent/ent/user_delete.go index a7373a7d..3d3b2586 100644 --- a/internal/app/pkg/ent/ent/user_delete.go +++ b/internal/app/pkg/ent/ent/user_delete.go @@ -27,7 +27,7 @@ func (ud *UserDelete) Where(ps ...predicate.User) *UserDelete { // Exec executes the deletion query and returns how many vertices were deleted. func (ud *UserDelete) Exec(ctx context.Context) (int, error) { - return withHooks[int, UserMutation](ctx, ud.sqlExec, ud.mutation, ud.hooks) + return withHooks(ctx, ud.sqlExec, ud.mutation, ud.hooks) } // ExecX is like Exec, but panics if an error occurs. @@ -40,15 +40,7 @@ func (ud *UserDelete) ExecX(ctx context.Context) int { } func (ud *UserDelete) sqlExec(ctx context.Context) (int, error) { - _spec := &sqlgraph.DeleteSpec{ - Node: &sqlgraph.NodeSpec{ - Table: user.Table, - ID: &sqlgraph.FieldSpec{ - Type: field.TypeInt64, - Column: user.FieldID, - }, - }, - } + _spec := sqlgraph.NewDeleteSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64)) if ps := ud.mutation.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { for i := range ps { diff --git a/internal/app/pkg/ent/ent/user_query.go b/internal/app/pkg/ent/ent/user_query.go index 95f06e9e..44ad5825 100644 --- a/internal/app/pkg/ent/ent/user_query.go +++ b/internal/app/pkg/ent/ent/user_query.go @@ -18,7 +18,7 @@ import ( type UserQuery struct { config ctx *QueryContext - order []OrderFunc + order []user.OrderOption inters []Interceptor predicates []predicate.User modifiers []func(*sql.Selector) @@ -53,7 +53,7 @@ func (uq *UserQuery) Unique(unique bool) *UserQuery { } // Order specifies how the records should be ordered. -func (uq *UserQuery) Order(o ...OrderFunc) *UserQuery { +func (uq *UserQuery) Order(o ...user.OrderOption) *UserQuery { uq.order = append(uq.order, o...) return uq } @@ -178,10 +178,12 @@ func (uq *UserQuery) AllX(ctx context.Context) []*User { } // IDs executes the query and returns a list of User IDs. -func (uq *UserQuery) IDs(ctx context.Context) ([]int64, error) { - var ids []int64 +func (uq *UserQuery) IDs(ctx context.Context) (ids []int64, err error) { + if uq.ctx.Unique == nil && uq.path != nil { + uq.Unique(true) + } ctx = setContextOp(ctx, uq.ctx, "IDs") - if err := uq.Select(user.FieldID).Scan(ctx, &ids); err != nil { + if err = uq.Select(user.FieldID).Scan(ctx, &ids); err != nil { return nil, err } return ids, nil @@ -245,7 +247,7 @@ func (uq *UserQuery) Clone() *UserQuery { return &UserQuery{ config: uq.config, ctx: uq.ctx.Clone(), - order: append([]OrderFunc{}, uq.order...), + order: append([]user.OrderOption{}, uq.order...), inters: append([]Interceptor{}, uq.inters...), predicates: append([]predicate.User{}, uq.predicates...), // clone intermediate query. @@ -369,20 +371,12 @@ func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) { } func (uq *UserQuery) querySpec() *sqlgraph.QuerySpec { - _spec := &sqlgraph.QuerySpec{ - Node: &sqlgraph.NodeSpec{ - Table: user.Table, - Columns: user.Columns, - ID: &sqlgraph.FieldSpec{ - Type: field.TypeInt64, - Column: user.FieldID, - }, - }, - From: uq.sql, - Unique: true, - } + _spec := sqlgraph.NewQuerySpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64)) + _spec.From = uq.sql if unique := uq.ctx.Unique; unique != nil { _spec.Unique = *unique + } else if uq.path != nil { + _spec.Unique = true } if fields := uq.ctx.Fields; len(fields) > 0 { _spec.Node.Columns = make([]string, 0, len(fields)) diff --git a/internal/app/pkg/ent/ent/user_update.go b/internal/app/pkg/ent/ent/user_update.go index c52770c2..f6e47252 100644 --- a/internal/app/pkg/ent/ent/user_update.go +++ b/internal/app/pkg/ent/ent/user_update.go @@ -49,38 +49,45 @@ func (uu *UserUpdate) ClearDeletedAt() *UserUpdate { return uu } -// SetName sets the "name" field. -func (uu *UserUpdate) SetName(s string) *UserUpdate { - uu.mutation.SetName(s) +// SetUsername sets the "username" field. +func (uu *UserUpdate) SetUsername(s string) *UserUpdate { + uu.mutation.SetUsername(s) return uu } -// SetNillableName sets the "name" field if the given value is not nil. -func (uu *UserUpdate) SetNillableName(s *string) *UserUpdate { +// SetNillableUsername sets the "username" field if the given value is not nil. +func (uu *UserUpdate) SetNillableUsername(s *string) *UserUpdate { if s != nil { - uu.SetName(*s) + uu.SetUsername(*s) } return uu } -// SetAge sets the "age" field. -func (uu *UserUpdate) SetAge(i int8) *UserUpdate { - uu.mutation.ResetAge() - uu.mutation.SetAge(i) +// SetPassword sets the "password" field. +func (uu *UserUpdate) SetPassword(s string) *UserUpdate { + uu.mutation.SetPassword(s) return uu } -// SetNillableAge sets the "age" field if the given value is not nil. -func (uu *UserUpdate) SetNillableAge(i *int8) *UserUpdate { - if i != nil { - uu.SetAge(*i) +// SetNillablePassword sets the "password" field if the given value is not nil. +func (uu *UserUpdate) SetNillablePassword(s *string) *UserUpdate { + if s != nil { + uu.SetPassword(*s) } return uu } -// AddAge adds i to the "age" field. -func (uu *UserUpdate) AddAge(i int8) *UserUpdate { - uu.mutation.AddAge(i) +// SetNickname sets the "nickname" field. +func (uu *UserUpdate) SetNickname(s string) *UserUpdate { + uu.mutation.SetNickname(s) + return uu +} + +// SetNillableNickname sets the "nickname" field if the given value is not nil. +func (uu *UserUpdate) SetNillableNickname(s *string) *UserUpdate { + if s != nil { + uu.SetNickname(*s) + } return uu } @@ -98,6 +105,20 @@ func (uu *UserUpdate) SetNillablePhone(s *string) *UserUpdate { return uu } +// SetSalt sets the "salt" field. +func (uu *UserUpdate) SetSalt(s string) *UserUpdate { + uu.mutation.SetSalt(s) + return uu +} + +// SetNillableSalt sets the "salt" field if the given value is not nil. +func (uu *UserUpdate) SetNillableSalt(s *string) *UserUpdate { + if s != nil { + uu.SetSalt(*s) + } + return uu +} + // Mutation returns the UserMutation object of the builder. func (uu *UserUpdate) Mutation() *UserMutation { return uu.mutation @@ -108,7 +129,7 @@ func (uu *UserUpdate) Save(ctx context.Context) (int, error) { if err := uu.defaults(); err != nil { return 0, err } - return withHooks[int, UserMutation](ctx, uu.sqlSave, uu.mutation, uu.hooks) + return withHooks(ctx, uu.sqlSave, uu.mutation, uu.hooks) } // SaveX is like Save, but panics if an error occurs. @@ -145,16 +166,6 @@ func (uu *UserUpdate) defaults() error { return nil } -// check runs all checks and user-defined validators on the builder. -func (uu *UserUpdate) check() error { - if v, ok := uu.mutation.Age(); ok { - if err := user.AgeValidator(v); err != nil { - return &ValidationError{Name: "age", err: fmt.Errorf(`ent: validator failed for field "User.age": %w`, err)} - } - } - return nil -} - // Modify adds a statement modifier for attaching custom logic to the UPDATE statement. func (uu *UserUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *UserUpdate { uu.modifiers = append(uu.modifiers, modifiers...) @@ -162,19 +173,7 @@ func (uu *UserUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *UserUpdat } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - if err := uu.check(); err != nil { - return n, err - } - _spec := &sqlgraph.UpdateSpec{ - Node: &sqlgraph.NodeSpec{ - Table: user.Table, - Columns: user.Columns, - ID: &sqlgraph.FieldSpec{ - Type: field.TypeInt64, - Column: user.FieldID, - }, - }, - } + _spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64)) if ps := uu.mutation.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { for i := range ps { @@ -191,18 +190,21 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { if uu.mutation.DeletedAtCleared() { _spec.ClearField(user.FieldDeletedAt, field.TypeTime) } - if value, ok := uu.mutation.Name(); ok { - _spec.SetField(user.FieldName, field.TypeString, value) + if value, ok := uu.mutation.Username(); ok { + _spec.SetField(user.FieldUsername, field.TypeString, value) } - if value, ok := uu.mutation.Age(); ok { - _spec.SetField(user.FieldAge, field.TypeInt8, value) + if value, ok := uu.mutation.Password(); ok { + _spec.SetField(user.FieldPassword, field.TypeString, value) } - if value, ok := uu.mutation.AddedAge(); ok { - _spec.AddField(user.FieldAge, field.TypeInt8, value) + if value, ok := uu.mutation.Nickname(); ok { + _spec.SetField(user.FieldNickname, field.TypeString, value) } if value, ok := uu.mutation.Phone(); ok { _spec.SetField(user.FieldPhone, field.TypeString, value) } + if value, ok := uu.mutation.Salt(); ok { + _spec.SetField(user.FieldSalt, field.TypeString, value) + } _spec.AddModifiers(uu.modifiers...) if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -245,38 +247,45 @@ func (uuo *UserUpdateOne) ClearDeletedAt() *UserUpdateOne { return uuo } -// SetName sets the "name" field. -func (uuo *UserUpdateOne) SetName(s string) *UserUpdateOne { - uuo.mutation.SetName(s) +// SetUsername sets the "username" field. +func (uuo *UserUpdateOne) SetUsername(s string) *UserUpdateOne { + uuo.mutation.SetUsername(s) return uuo } -// SetNillableName sets the "name" field if the given value is not nil. -func (uuo *UserUpdateOne) SetNillableName(s *string) *UserUpdateOne { +// SetNillableUsername sets the "username" field if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableUsername(s *string) *UserUpdateOne { if s != nil { - uuo.SetName(*s) + uuo.SetUsername(*s) } return uuo } -// SetAge sets the "age" field. -func (uuo *UserUpdateOne) SetAge(i int8) *UserUpdateOne { - uuo.mutation.ResetAge() - uuo.mutation.SetAge(i) +// SetPassword sets the "password" field. +func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne { + uuo.mutation.SetPassword(s) return uuo } -// SetNillableAge sets the "age" field if the given value is not nil. -func (uuo *UserUpdateOne) SetNillableAge(i *int8) *UserUpdateOne { - if i != nil { - uuo.SetAge(*i) +// SetNillablePassword sets the "password" field if the given value is not nil. +func (uuo *UserUpdateOne) SetNillablePassword(s *string) *UserUpdateOne { + if s != nil { + uuo.SetPassword(*s) } return uuo } -// AddAge adds i to the "age" field. -func (uuo *UserUpdateOne) AddAge(i int8) *UserUpdateOne { - uuo.mutation.AddAge(i) +// SetNickname sets the "nickname" field. +func (uuo *UserUpdateOne) SetNickname(s string) *UserUpdateOne { + uuo.mutation.SetNickname(s) + return uuo +} + +// SetNillableNickname sets the "nickname" field if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableNickname(s *string) *UserUpdateOne { + if s != nil { + uuo.SetNickname(*s) + } return uuo } @@ -294,11 +303,31 @@ func (uuo *UserUpdateOne) SetNillablePhone(s *string) *UserUpdateOne { return uuo } +// SetSalt sets the "salt" field. +func (uuo *UserUpdateOne) SetSalt(s string) *UserUpdateOne { + uuo.mutation.SetSalt(s) + return uuo +} + +// SetNillableSalt sets the "salt" field if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableSalt(s *string) *UserUpdateOne { + if s != nil { + uuo.SetSalt(*s) + } + return uuo +} + // Mutation returns the UserMutation object of the builder. func (uuo *UserUpdateOne) Mutation() *UserMutation { return uuo.mutation } +// Where appends a list predicates to the UserUpdate builder. +func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne { + uuo.mutation.Where(ps...) + return uuo +} + // Select allows selecting one or more fields (columns) of the returned entity. // The default is selecting all fields defined in the entity schema. func (uuo *UserUpdateOne) Select(field string, fields ...string) *UserUpdateOne { @@ -311,7 +340,7 @@ func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { if err := uuo.defaults(); err != nil { return nil, err } - return withHooks[*User, UserMutation](ctx, uuo.sqlSave, uuo.mutation, uuo.hooks) + return withHooks(ctx, uuo.sqlSave, uuo.mutation, uuo.hooks) } // SaveX is like Save, but panics if an error occurs. @@ -348,16 +377,6 @@ func (uuo *UserUpdateOne) defaults() error { return nil } -// check runs all checks and user-defined validators on the builder. -func (uuo *UserUpdateOne) check() error { - if v, ok := uuo.mutation.Age(); ok { - if err := user.AgeValidator(v); err != nil { - return &ValidationError{Name: "age", err: fmt.Errorf(`ent: validator failed for field "User.age": %w`, err)} - } - } - return nil -} - // Modify adds a statement modifier for attaching custom logic to the UPDATE statement. func (uuo *UserUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *UserUpdateOne { uuo.modifiers = append(uuo.modifiers, modifiers...) @@ -365,19 +384,7 @@ func (uuo *UserUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *UserU } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) { - if err := uuo.check(); err != nil { - return _node, err - } - _spec := &sqlgraph.UpdateSpec{ - Node: &sqlgraph.NodeSpec{ - Table: user.Table, - Columns: user.Columns, - ID: &sqlgraph.FieldSpec{ - Type: field.TypeInt64, - Column: user.FieldID, - }, - }, - } + _spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64)) id, ok := uuo.mutation.ID() if !ok { return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "User.id" for update`)} @@ -411,18 +418,21 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) if uuo.mutation.DeletedAtCleared() { _spec.ClearField(user.FieldDeletedAt, field.TypeTime) } - if value, ok := uuo.mutation.Name(); ok { - _spec.SetField(user.FieldName, field.TypeString, value) + if value, ok := uuo.mutation.Username(); ok { + _spec.SetField(user.FieldUsername, field.TypeString, value) } - if value, ok := uuo.mutation.Age(); ok { - _spec.SetField(user.FieldAge, field.TypeInt8, value) + if value, ok := uuo.mutation.Password(); ok { + _spec.SetField(user.FieldPassword, field.TypeString, value) } - if value, ok := uuo.mutation.AddedAge(); ok { - _spec.AddField(user.FieldAge, field.TypeInt8, value) + if value, ok := uuo.mutation.Nickname(); ok { + _spec.SetField(user.FieldNickname, field.TypeString, value) } if value, ok := uuo.mutation.Phone(); ok { _spec.SetField(user.FieldPhone, field.TypeString, value) } + if value, ok := uuo.mutation.Salt(); ok { + _spec.SetField(user.FieldSalt, field.TypeString, value) + } _spec.AddModifiers(uuo.modifiers...) _node = &User{config: uuo.config} _spec.Assign = _node.assignValues diff --git a/internal/app/pkg/ent/provide.go b/internal/app/pkg/ent/provide.go index 219f4158..0c56e037 100644 --- a/internal/app/pkg/ent/provide.go +++ b/internal/app/pkg/ent/provide.go @@ -1,17 +1,16 @@ package ent import ( - "context" + "database/sql" + "log/slog" "go-scaffold/internal/app/pkg/ent/ent" "go-scaffold/internal/config" - - "golang.org/x/exp/slog" ) // Provide db client -func Provide(ctx context.Context, env config.Env, conf config.DBConn, logger *slog.Logger) (*ent.Client, func(), error) { - client, err := New(ctx, env, conf, logger) +func Provide(env config.Env, conf config.DBConn, logger *slog.Logger, db *sql.DB) (*ent.Client, func(), error) { + client, err := New(env, conf, logger, db) if err != nil { return nil, nil, err } diff --git a/internal/app/pkg/errors/errors.go b/internal/app/pkg/errors/errors.go index cd3e7b52..b9f2943b 100644 --- a/internal/app/pkg/errors/errors.go +++ b/internal/app/pkg/errors/errors.go @@ -1,17 +1,14 @@ package errors -// NoErrorCode code when there are no errors -const NoErrorCode = 10000 - // standard errors var ( - ErrServerError = New("server error", 10001, "SERVER_ERROR") - ErrBadRequest = New("bad request", 10002, "BAD_REQUEST") - ErrValidateError = New("parameters validate error", 10003, "VALIDATE_ERROR") - ErrUnauthorized = New("unauthorized", 10004, "UNAUTHORIZED") - ErrPermissionDenied = New("permission denied", 10005, "PERMISSION_DENIED") - ErrResourceNotFound = New("resource not found", 10006, "RESOURCE_NOT_FOUND") - ErrTooManyRequest = New("too many request", 10007, "TOO_MANY_REQUEST") + ErrInternalError = New("internal error", 10001, "INTERNAL_ERROR") + ErrBadCall = New("bad call", 20001, "BAD_CALL") + ErrValidateError = New("parameters validate error", 20002, "VALIDATE_ERROR") + ErrInvalidAuthorized = New("invalid authorized", 20003, "INVALID_AUTHORIZED") + ErrAccessDenied = New("access denied", 20004, "ACCESS_DENIED") + ErrResourceNotFound = New("resource not found", 20005, "RESOURCE_NOT_FOUND") + ErrCallsTooFrequently = New("call too frequently", 20006, "CALLS_TOO_FREQUENTLY") ) // Error application internal error @@ -19,17 +16,30 @@ type Error struct { msg string code int label string + error error } // New returns an error that formats as the given text. func New(text string, code int, label string) *Error { - return &Error{text, code, label} + return &Error{text, code, label, nil} } func (e *Error) Error() string { return e.msg } +func (e *Error) Cause() error { + return e.error +} + +func (e *Error) Unwrap() error { + return e.error +} + +func (e *Error) Msg() string { + return e.msg +} + func (e *Error) Code() int { return e.code } @@ -42,3 +52,8 @@ func (e *Error) WithMsg(msg string) *Error { e.msg = msg return e } + +func (e *Error) WithError(err error) *Error { + e.error = err + return e +} diff --git a/internal/app/pkg/gorm/dialector.go b/internal/app/pkg/gorm/dialector.go index 0616aadf..46565f6f 100644 --- a/internal/app/pkg/gorm/dialector.go +++ b/internal/app/pkg/gorm/dialector.go @@ -1,12 +1,12 @@ package gorm import ( - "go-scaffold/internal/app/pkg/db" - "go-scaffold/internal/config" - "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/gorm" + + "go-scaffold/internal/app/pkg/db" + "go-scaffold/internal/config" ) // NewDialect build dialect diff --git a/internal/app/pkg/gorm/gorm.go b/internal/app/pkg/gorm/gorm.go index a2a1bce7..7076b775 100644 --- a/internal/app/pkg/gorm/gorm.go +++ b/internal/app/pkg/gorm/gorm.go @@ -3,16 +3,16 @@ package gorm import ( "context" "errors" + "log/slog" "time" - "go-scaffold/internal/app/pkg/db" - "go-scaffold/internal/config" - glog "go-scaffold/pkg/log/gorm" - - "golang.org/x/exp/slog" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" "gorm.io/plugin/dbresolver" + + "go-scaffold/internal/app/pkg/db" + "go-scaffold/internal/config" + glog "go-scaffold/pkg/log/gorm" ) // ErrUnsupportedResolverType unsupported resolver type diff --git a/internal/app/pkg/gorm/provide.go b/internal/app/pkg/gorm/provide.go index 4355b1c0..37152ec7 100644 --- a/internal/app/pkg/gorm/provide.go +++ b/internal/app/pkg/gorm/provide.go @@ -2,11 +2,11 @@ package gorm import ( "context" + "log/slog" - "go-scaffold/internal/config" - - "golang.org/x/exp/slog" "gorm.io/gorm" + + "go-scaffold/internal/config" ) // Provide gorm diff --git a/internal/app/pkg/pkg.go b/internal/app/pkg/pkg.go index 3808ef22..9700dd7d 100644 --- a/internal/app/pkg/pkg.go +++ b/internal/app/pkg/pkg.go @@ -1,6 +1,8 @@ package pkg import ( + "github.com/google/wire" + "go-scaffold/internal/app/pkg/casbin" "go-scaffold/internal/app/pkg/client" "go-scaffold/internal/app/pkg/db" @@ -9,8 +11,6 @@ import ( "go-scaffold/internal/app/pkg/gorm" "go-scaffold/internal/app/pkg/redis" "go-scaffold/internal/app/pkg/uid" - - "github.com/google/wire" ) var ProviderSet = wire.NewSet( diff --git a/internal/app/pkg/redis/provide.go b/internal/app/pkg/redis/provide.go index 867d09ee..b1f0c74e 100644 --- a/internal/app/pkg/redis/provide.go +++ b/internal/app/pkg/redis/provide.go @@ -3,9 +3,9 @@ package redis import ( "context" - "go-scaffold/internal/config" - "github.com/go-redis/redis/v8" + + "go-scaffold/internal/config" ) // Provide redis client diff --git a/internal/app/pkg/redis/redis.go b/internal/app/pkg/redis/redis.go index 88ee0a1b..5d5e3dcd 100644 --- a/internal/app/pkg/redis/redis.go +++ b/internal/app/pkg/redis/redis.go @@ -4,9 +4,9 @@ import ( "context" "time" - "go-scaffold/internal/config" - "github.com/go-redis/redis/v8" + + "go-scaffold/internal/config" ) // New build redis client diff --git a/internal/app/repository/casbin_rule.go b/internal/app/repository/casbin_rule.go deleted file mode 100644 index 60330018..00000000 --- a/internal/app/repository/casbin_rule.go +++ /dev/null @@ -1,17 +0,0 @@ -package repository - -type casbinRuleModel struct { - ID uint `gorm:"column:id;primaryKey"` - Ptype string `gorm:"column:ptype"` - V0 string `gorm:"column:v0"` - V1 string `gorm:"column:v1"` - V2 string `gorm:"column:v2"` - V3 string `gorm:"column:v3"` - V4 string `gorm:"column:v4"` - V5 string `gorm:"column:v5"` -} - -// TableName 表名 -func (r casbinRuleModel) TableName() string { - return "casbin_rules" -} diff --git a/internal/app/repository/permission.go b/internal/app/repository/permission.go new file mode 100644 index 00000000..d1e44071 --- /dev/null +++ b/internal/app/repository/permission.go @@ -0,0 +1,172 @@ +package repository + +import ( + "context" + "fmt" + + "github.com/casbin/casbin/v2" + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/permission" +) + +var _ PermissionRepositoryInterface = (*PermissionRepository)(nil) + +type ( + PermissionFindListParam struct { + Keyword string + } + + PermissionRepositoryInterface interface { + Filter(ctx context.Context, param PermissionFindListParam) ([]*domain.Permission, error) + FindList(ctx context.Context, idList []int64) ([]*domain.Permission, error) + FindOne(ctx context.Context, id int64) (*domain.Permission, error) + FindOneByKey(ctx context.Context, key string) (*domain.Permission, error) + Exist(ctx context.Context, id int64) (bool, error) + KeyExist(ctx context.Context, key string) (bool, error) + KeyExistExcludeID(ctx context.Context, key string, excludeID int64) (bool, error) + HasChild(ctx context.Context, id int64) (bool, error) + Create(ctx context.Context, e domain.Permission) error + Update(ctx context.Context, e domain.Permission) error + Delete(ctx context.Context, e domain.Permission) error + } +) + +type PermissionRepository struct { + client *ent.Client + enforcer *casbin.Enforcer +} + +func NewPermissionRepository(client *ent.Client, enforcer *casbin.Enforcer) *PermissionRepository { + return &PermissionRepository{ + client: client, + enforcer: enforcer, + } +} + +func (r *PermissionRepository) Filter(ctx context.Context, param PermissionFindListParam) ([]*domain.Permission, error) { + query := r.client.Permission.Query() + + if param.Keyword != "" { + query.Where( + permission.Or( + permission.NameContains(param.Keyword), + permission.DescContains(param.Keyword), + ), + ) + } + + list, err := query. + Order(ent.Desc(permission.FieldUpdatedAt)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + entities := make([]*domain.Permission, 0, len(list)) + for _, i := range list { + entities = append(entities, (&permissionModel{i}).toEntity()) + } + + return entities, nil +} + +func (r *PermissionRepository) FindList(ctx context.Context, idList []int64) ([]*domain.Permission, error) { + data, err := r.client.Permission.Query(). + Where(permission.IDIn(idList...)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + list := make([]*domain.Permission, 0, len(data)) + for _, item := range data { + list = append(list, (&permissionModel{item}).toEntity()) + } + return list, nil +} + +func (r *PermissionRepository) FindOne(ctx context.Context, id int64) (*domain.Permission, error) { + m, err := r.client.Permission.Get(ctx, id) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&permissionModel{m}).toEntity(), nil +} + +func (r *PermissionRepository) FindOneByKey(ctx context.Context, key string) (*domain.Permission, error) { + m, err := r.client.Permission.Query().Where(permission.KeyEQ(key)).Only(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&permissionModel{m}).toEntity(), nil +} + +func (r *PermissionRepository) Exist(ctx context.Context, id int64) (bool, error) { + exist, err := r.client.Permission.Query().Where(permission.IDEQ(id)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) KeyExist(ctx context.Context, key string) (bool, error) { + exist, err := r.client.Permission.Query().Where(permission.KeyEQ(key)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) KeyExistExcludeID(ctx context.Context, key string, excludeID int64) (bool, error) { + exist, err := r.client.Permission.Query().Where( + permission.KeyEQ(key), + permission.IDNEQ(excludeID), + ).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) HasChild(ctx context.Context, id int64) (bool, error) { + count, err := r.client.Permission.Query().Where(permission.ParentIDEQ(id)).Count(ctx) + return count > 0, errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) Create(ctx context.Context, e domain.Permission) error { + _, err := r.client.Permission.Create(). + SetKey(e.Key). + SetName(e.Name). + SetDesc(e.Desc). + SetParentID(e.ParentID). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) Update(ctx context.Context, e domain.Permission) error { + _, err := r.client.Permission. + UpdateOneID(e.ID). + SetKey(e.Key). + SetName(e.Name). + SetDesc(e.Desc). + SetParentID(e.ParentID). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *PermissionRepository) Delete(ctx context.Context, e domain.Permission) error { + _, err := r.enforcer.DeletePermission(fmt.Sprintf("%d", e.ID)) + if err != nil { + return errors.WithStack(err) + } + + return errors.WithStack(r.client.Permission.DeleteOneID(e.ID).Exec(ctx)) +} + +type permissionModel struct { + *ent.Permission +} + +func (m *permissionModel) toEntity() *domain.Permission { + return &domain.Permission{ + ID: m.ID, + Key: m.Key, + Name: m.Name, + Desc: m.Desc, + ParentID: m.ParentID, + } +} diff --git a/internal/app/repository/policy.go b/internal/app/repository/policy.go new file mode 100644 index 00000000..25d1ad59 --- /dev/null +++ b/internal/app/repository/policy.go @@ -0,0 +1,35 @@ +package repository + +import ( + "fmt" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +func GetPolicyUser(userID int64) string { + return fmt.Sprintf("user_%d", userID) +} + +func FromPolicyUser(user string) (int64, error) { + us := strings.Trim(user, "user_") + userID, err := strconv.ParseInt(us, 10, 64) + if err != nil { + return 0, errors.WithStack(err) + } + return userID, nil +} + +func GetPolicyRole(roleID int64) string { + return fmt.Sprintf("role_%d", roleID) +} + +func FromPolicyRole(role string) (int64, error) { + rs := strings.Trim(role, "role_") + roleID, err := strconv.ParseInt(rs, 10, 64) + if err != nil { + return 0, errors.WithStack(err) + } + return roleID, nil +} diff --git a/internal/app/repository/product.go b/internal/app/repository/product.go new file mode 100644 index 00000000..5e2e4a27 --- /dev/null +++ b/internal/app/repository/product.go @@ -0,0 +1,114 @@ +package repository + +import ( + "context" + + "github.com/pkg/errors" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/product" +) + +var _ ProductRepositoryInterface = (*ProductRepository)(nil) + +type ( + ProductFindListParam struct { + Keyword string + } + + ProductRepositoryInterface interface { + Filter(ctx context.Context, param ProductFindListParam) ([]*domain.Product, error) + FindOne(ctx context.Context, id int64) (*domain.Product, error) + Exist(ctx context.Context, id int64) (bool, error) + Create(ctx context.Context, e domain.Product) error + Update(ctx context.Context, e domain.Product) error + Delete(ctx context.Context, e domain.Product) error + } +) + +type ProductRepository struct { + client *ent.Client +} + +func NewProductRepository(client *ent.Client) *ProductRepository { + return &ProductRepository{ + client: client, + } +} + +func (r *ProductRepository) Filter(ctx context.Context, param ProductFindListParam) ([]*domain.Product, error) { + query := r.client.Product.Query() + + if param.Keyword != "" { + query.Where( + product.Or( + product.NameContains(param.Keyword), + product.DescContains(param.Keyword), + ), + ) + } + + list, err := query. + Order(ent.Desc(product.FieldUpdatedAt)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + entities := make([]*domain.Product, 0, len(list)) + for _, i := range list { + entities = append(entities, (&productModel{i}).toEntity()) + } + + return entities, nil +} + +func (r *ProductRepository) FindOne(ctx context.Context, id int64) (*domain.Product, error) { + m, err := r.client.Product.Get(ctx, id) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&productModel{m}).toEntity(), nil +} + +func (r *ProductRepository) Exist(ctx context.Context, id int64) (bool, error) { + exist, err := r.client.Product.Query().Where(product.IDEQ(id)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *ProductRepository) Create(ctx context.Context, e domain.Product) error { + _, err := r.client.Product.Create(). + SetName(e.Name). + SetDesc(e.Desc). + SetPrice(e.Price). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *ProductRepository) Update(ctx context.Context, e domain.Product) error { + _, err := r.client.Product. + UpdateOneID(e.ID). + SetName(e.Name). + SetDesc(e.Desc). + SetPrice(e.Price). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *ProductRepository) Delete(ctx context.Context, e domain.Product) error { + return errors.WithStack(r.client.Product.DeleteOneID(e.ID).Exec(ctx)) +} + +type productModel struct { + *ent.Product +} + +func (m *productModel) toEntity() *domain.Product { + return &domain.Product{ + ID: m.ID, + Name: m.Name, + Desc: m.Desc, + Price: m.Price, + } +} diff --git a/internal/app/repository/repository.go b/internal/app/repository/repository.go index bc26e993..86469490 100644 --- a/internal/app/repository/repository.go +++ b/internal/app/repository/repository.go @@ -1,37 +1,45 @@ package repository import ( - "go-scaffold/internal/app/domain" - "go-scaffold/internal/app/pkg/ent/ent" - berr "go-scaffold/internal/app/pkg/errors" + "errors" "github.com/google/wire" - "github.com/pkg/errors" + "gorm.io/gorm" "gorm.io/plugin/soft_delete" + + "go-scaffold/internal/app/pkg/ent/ent" ) var ProviderSet = wire.NewSet( - wire.NewSet(wire.Bind(new(domain.UserRepository), new(*UserRepository)), NewUserRepository), + wire.NewSet(wire.Bind(new(UserRepositoryInterface), new(*UserRepository)), NewUserRepository), + wire.NewSet(wire.Bind(new(RoleRepositoryInterface), new(*RoleRepository)), NewRoleRepository), + wire.NewSet(wire.Bind(new(PermissionRepositoryInterface), new(*PermissionRepository)), NewPermissionRepository), + wire.NewSet(wire.Bind(new(ProductRepositoryInterface), new(*ProductRepository)), NewProductRepository), ) -// BaseModel 基础模型 -// 自动更新时间戳、软删除 -type BaseModel struct { - ID int64 `gorm:"primaryKey"` - CreatedAt int64 `gorm:"NOT NULL"` - UpdatedAt int64 `gorm:"NOT NULL;DEFAULT:0"` - DeletedAt soft_delete.DeletedAt `gorm:"index;NOT NULL;DEFAULT:0"` +var ErrRecordNotFound = errors.New("record not found") + +func IsNotFound(err error) bool { + return errors.Is(err, ErrRecordNotFound) || errors.Is(err, gorm.ErrRecordNotFound) || ent.IsNotFound(err) } -// convertError 转换 ent 包的错误为内部错误 -// -// 屏蔽 repository 层的内部实现 -func convertError(err error) error { +// handleError handle ent and gorm error +// masking the internal implementation of the repository layer +func handleError(err error) error { if err == nil { return nil } - if ent.IsNotFound(err) { - return errors.WithStack(berr.ErrResourceNotFound) + if errors.Is(err, gorm.ErrRecordNotFound) || ent.IsNotFound(err) { + return ErrRecordNotFound } - return errors.WithStack(err) + return err +} + +// baseModel base model +// automatic update of timestamps, soft delete +type baseModel struct { + ID int64 `gorm:"primaryKey"` + CreatedAt int64 `gorm:"NOT NULL"` + UpdatedAt int64 `gorm:"NOT NULL;DEFAULT:0"` + DeletedAt soft_delete.DeletedAt `gorm:"index;NOT NULL;DEFAULT:0"` } diff --git a/internal/app/repository/role.go b/internal/app/repository/role.go new file mode 100644 index 00000000..7d73a48f --- /dev/null +++ b/internal/app/repository/role.go @@ -0,0 +1,193 @@ +package repository + +import ( + "context" + "fmt" + "strconv" + + "github.com/casbin/casbin/v2" + "github.com/pkg/errors" + "github.com/samber/lo" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/role" +) + +var _ RoleRepositoryInterface = (*RoleRepository)(nil) + +type ( + RoleFindListParam struct { + Keyword string + } + + RoleRepositoryInterface interface { + Filter(ctx context.Context, param RoleFindListParam) ([]*domain.Role, error) + FindList(ctx context.Context, idList []int64) ([]*domain.Role, error) + FindOne(ctx context.Context, id int64) (*domain.Role, error) + Exist(ctx context.Context, id int64) (bool, error) + NameExist(ctx context.Context, name string) (bool, error) + NameExistExcludeID(ctx context.Context, name string, excludeID int64) (bool, error) + Create(ctx context.Context, e domain.Role) error + Update(ctx context.Context, e domain.Role) error + Delete(ctx context.Context, e domain.Role) error + GrantPermissions(ctx context.Context, role int64, permissions []int64) error + GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) + } +) + +type RoleRepository struct { + client *ent.Client + enforcer *casbin.Enforcer +} + +func NewRoleRepository(client *ent.Client, enforcer *casbin.Enforcer) *RoleRepository { + return &RoleRepository{ + client: client, + enforcer: enforcer, + } +} + +func (r *RoleRepository) Filter(ctx context.Context, param RoleFindListParam) ([]*domain.Role, error) { + query := r.client.Role.Query() + + if param.Keyword != "" { + query.Where(role.NameContains(param.Keyword)) + } + + list, err := query. + Order(ent.Desc(role.FieldUpdatedAt)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + entities := make([]*domain.Role, 0, len(list)) + for _, i := range list { + entities = append(entities, (&roleModel{i}).toEntity()) + } + + return entities, nil +} + +func (r *RoleRepository) FindList(ctx context.Context, idList []int64) ([]*domain.Role, error) { + data, err := r.client.Role.Query(). + Where(role.IDIn(idList...)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + list := make([]*domain.Role, 0, len(data)) + for _, item := range data { + list = append(list, (&roleModel{item}).toEntity()) + } + return list, nil +} + +func (r *RoleRepository) FindOne(ctx context.Context, id int64) (*domain.Role, error) { + m, err := r.client.Role.Get(ctx, id) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&roleModel{m}).toEntity(), nil +} + +func (r *RoleRepository) Exist(ctx context.Context, id int64) (bool, error) { + exist, err := r.client.Role.Query().Where(role.IDEQ(id)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) NameExist(ctx context.Context, name string) (bool, error) { + exist, err := r.client.Role.Query().Where(role.NameEQ(name)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) NameExistExcludeID(ctx context.Context, name string, excludeID int64) (bool, error) { + exist, err := r.client.Role.Query().Where( + role.NameEQ(name), + role.IDNEQ(excludeID), + ).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) Create(ctx context.Context, e domain.Role) error { + _, err := r.client.Role.Create(). + SetName(e.Name). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) Update(ctx context.Context, e domain.Role) error { + _, err := r.client.Role. + UpdateOneID(e.ID). + SetName(e.Name). + Save(ctx) + return errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) Delete(ctx context.Context, e domain.Role) error { + _, err := r.enforcer.DeleteRole(GetPolicyRole(e.ID)) + if err != nil { + return errors.WithStack(err) + } + + return errors.WithStack(r.client.Role.DeleteOneID(e.ID).Exec(ctx)) +} + +func (r *RoleRepository) GrantPermissions(ctx context.Context, role int64, permissions []int64) error { + policyRole := GetPolicyRole(role) + + _, err := r.enforcer.DeletePermissionsForUser(policyRole) + if err != nil { + return errors.WithStack(handleError(err)) + } + + ps := lo.Map(permissions, func(p int64, index int) []string { + return []string{fmt.Sprintf("%d", p)} + }) + + _, err = r.enforcer.AddPermissionsForUser(policyRole, ps...) + return errors.WithStack(handleError(err)) +} + +func (r *RoleRepository) GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) { + pss := r.enforcer.GetPermissionsForUser(GetPolicyRole(id)) + + ps := make([]int64, 0, len(pss)) + for _, s := range pss { + if len(s) < 2 { + continue + } + i, err := strconv.ParseInt(s[1], 10, 64) + if err != nil { + return nil, errors.WithStack(err) + } + ps = append(ps, i) + } + + data, err := r.client.Permission.Query(). + Where(permission.IDIn(ps...)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + list := make([]*domain.Permission, 0, len(data)) + for _, item := range data { + list = append(list, (&permissionModel{item}).toEntity()) + } + return list, err +} + +type roleModel struct { + *ent.Role +} + +func (m *roleModel) toEntity() *domain.Role { + return &domain.Role{ + ID: m.ID, + Name: m.Name, + } +} diff --git a/internal/app/repository/schema/mixin/soft_delete.go b/internal/app/repository/schema/mixin/soft_delete.go index dde81661..feed2736 100644 --- a/internal/app/repository/schema/mixin/soft_delete.go +++ b/internal/app/repository/schema/mixin/soft_delete.go @@ -5,15 +5,15 @@ import ( "fmt" "time" - gen "go-scaffold/internal/app/pkg/ent/ent" - "go-scaffold/internal/app/pkg/ent/ent/hook" - "go-scaffold/internal/app/pkg/ent/ent/intercept" - "go-scaffold/internal/app/repository/schema/types" - "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/schema/field" "entgo.io/ent/schema/mixin" + + gen "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/hook" + "go-scaffold/internal/app/pkg/ent/ent/intercept" + "go-scaffold/internal/app/repository/schema/types" ) // UnexpectedMutationTypeError mutation does not implement the specified interface diff --git a/internal/app/repository/schema/mixin/time.go b/internal/app/repository/schema/mixin/time.go index 5addbf26..25e384c4 100644 --- a/internal/app/repository/schema/mixin/time.go +++ b/internal/app/repository/schema/mixin/time.go @@ -3,11 +3,11 @@ package mixin import ( "time" - "go-scaffold/internal/app/repository/schema/types" - "entgo.io/ent" "entgo.io/ent/schema/field" "entgo.io/ent/schema/mixin" + + "go-scaffold/internal/app/repository/schema/types" ) type TimeMixin struct { diff --git a/internal/app/repository/schema/permission.go b/internal/app/repository/schema/permission.go new file mode 100644 index 00000000..cda09bc3 --- /dev/null +++ b/internal/app/repository/schema/permission.go @@ -0,0 +1,55 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" + + "go-scaffold/internal/app/repository/schema/mixin" +) + +// Permission holds the schema definition for the Permission entity. +type Permission struct { + ent.Schema +} + +func (Permission) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{ + Table: "permissions", + Options: "COMMENT='权限表'", + }, + entsql.WithComments(true), + } +} + +func (Permission) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixin.TimeMixin{}, + mixin.SoftDeleteMixin{}, + } +} + +func (Permission) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("key"), + } +} + +// Fields of the Permission. +func (Permission) Fields() []ent.Field { + return []ent.Field{ + field.Int64("id").Unique().Immutable(), + field.String("key").Unique().MaxLen(128).Comment("权限标识"), + field.String("name").Default("").MaxLen(128).Comment("权限名称"), + field.String("desc").Default("").MaxLen(255).Comment("权限描述"), + field.Int64("parent_id").Default(0).Comment("父级权限 id"), + } +} + +// Edges of the Permission. +func (Permission) Edges() []ent.Edge { + return nil +} diff --git a/internal/app/repository/schema/product.go b/internal/app/repository/schema/product.go new file mode 100644 index 00000000..b3bc8aed --- /dev/null +++ b/internal/app/repository/schema/product.go @@ -0,0 +1,54 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" + + "go-scaffold/internal/app/repository/schema/mixin" +) + +// Product holds the schema definition for the Product entity. +type Product struct { + ent.Schema +} + +func (Product) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{ + Table: "products", + Options: "COMMENT='产品表'", + }, + entsql.WithComments(true), + } +} + +func (Product) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixin.TimeMixin{}, + mixin.SoftDeleteMixin{}, + } +} + +func (Product) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("name"), + } +} + +// Fields of the Product. +func (Product) Fields() []ent.Field { + return []ent.Field{ + field.Int64("id").Unique().Immutable(), + field.String("name").Default("").Comment("名称"), + field.String("desc").Default("").Comment("描述"), + field.Int("price").Default(0).Comment("价格"), + } +} + +// Edges of the Product. +func (Product) Edges() []ent.Edge { + return nil +} diff --git a/internal/app/repository/schema/role.go b/internal/app/repository/schema/role.go new file mode 100644 index 00000000..8c6d31c3 --- /dev/null +++ b/internal/app/repository/schema/role.go @@ -0,0 +1,45 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" + + "go-scaffold/internal/app/repository/schema/mixin" +) + +// Role holds the schema definition for the Role entity. +type Role struct { + ent.Schema +} + +func (Role) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{ + Table: "roles", + Options: "COMMENT='角色表'", + }, + entsql.WithComments(true), + } +} + +func (Role) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixin.TimeMixin{}, + mixin.SoftDeleteMixin{}, + } +} + +// Fields of the Role. +func (Role) Fields() []ent.Field { + return []ent.Field{ + field.Int64("id").Unique().Immutable(), + field.String("name").Unique().MaxLen(32).Comment("角色名称"), + } +} + +// Edges of the Role. +func (Role) Edges() []ent.Edge { + return nil +} diff --git a/internal/app/repository/schema/user.go b/internal/app/repository/schema/user.go index dd713e31..f81e03f0 100644 --- a/internal/app/repository/schema/user.go +++ b/internal/app/repository/schema/user.go @@ -1,13 +1,13 @@ package schema import ( - "go-scaffold/internal/app/repository/schema/mixin" - "entgo.io/ent" "entgo.io/ent/dialect/entsql" "entgo.io/ent/schema" "entgo.io/ent/schema/field" "entgo.io/ent/schema/index" + + "go-scaffold/internal/app/repository/schema/mixin" ) // User holds the schema definition for the User entity. @@ -34,7 +34,7 @@ func (User) Mixin() []ent.Mixin { func (User) Indexes() []ent.Index { return []ent.Index{ - index.Fields("name"), + index.Fields("username"), index.Fields("phone"), } } @@ -43,9 +43,11 @@ func (User) Indexes() []ent.Index { func (User) Fields() []ent.Field { return []ent.Field{ field.Int64("id").Unique().Immutable(), - field.String("name").Default("").Comment("名称"), - field.Int8("age").Default(0).Positive().Comment("年龄"), + field.String("username").Default("").Comment("用户名"), + field.String("password").Default("").Comment("密码"), + field.String("nickname").Default("").Comment("用户名"), field.String("phone").Default("").Comment("电话"), + field.String("salt").Default("").Comment("盐值"), } } diff --git a/internal/app/repository/user.go b/internal/app/repository/user.go index 8287cdec..1f3b5dc8 100644 --- a/internal/app/repository/user.go +++ b/internal/app/repository/user.go @@ -2,100 +2,245 @@ package repository import ( "context" + "strconv" + + "github.com/casbin/casbin/v2" + "github.com/pkg/errors" + "github.com/samber/lo" "go-scaffold/internal/app/domain" "go-scaffold/internal/app/pkg/ent/ent" + "go-scaffold/internal/app/pkg/ent/ent/permission" + "go-scaffold/internal/app/pkg/ent/ent/role" "go-scaffold/internal/app/pkg/ent/ent/user" ) -var _ domain.UserRepository = (*UserRepository)(nil) +var _ UserRepositoryInterface = (*UserRepository)(nil) + +type ( + UserFindListParam struct { + Keyword string + } + + UserRepositoryInterface interface { + Filter(ctx context.Context, param UserFindListParam) ([]*domain.User, error) + FindOne(ctx context.Context, id int64) (*domain.User, error) + FindOneByUsername(ctx context.Context, username string) (*domain.User, error) + Exist(ctx context.Context, id int64) (bool, error) + UsernameExist(ctx context.Context, username string) (bool, error) + UsernameExistExcludeID(ctx context.Context, username string, excludeID int64) (bool, error) + Create(ctx context.Context, e domain.User) (*domain.User, error) + Update(ctx context.Context, e domain.User) (*domain.User, error) + Delete(ctx context.Context, e domain.User) error + AssignRoles(ctx context.Context, user int64, roles []int64) error + GetRoles(ctx context.Context, id int64) ([]*domain.Role, error) + GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) + } +) -// UserRepository 用户仓储 type UserRepository struct { - client *ent.Client + client *ent.Client + enforcer *casbin.Enforcer } -// NewUserRepository 构造用户仓储 -func NewUserRepository(client *ent.Client) *UserRepository { +func NewUserRepository(client *ent.Client, enforcer *casbin.Enforcer) *UserRepository { return &UserRepository{ - client: client, + client: client, + enforcer: enforcer, } } -// FindListParam 列表查询参数 -type FindListParam struct { - Keyword string -} - -// FindList 列表查询 -func (r *UserRepository) FindList(ctx context.Context, param domain.FindUserListParam) ([]*domain.User, error) { +func (r *UserRepository) Filter(ctx context.Context, param UserFindListParam) ([]*domain.User, error) { query := r.client.User.Query() if param.Keyword != "" { - query.Where(user.NameContains(param.Keyword)) + query.Where( + user.Or( + user.UsernameContains(param.Keyword), + user.NicknameContains(param.Keyword), + user.PhoneContains(param.Keyword), + ), + ) } list, err := query. Order(ent.Desc(user.FieldUpdatedAt)). All(ctx) if err != nil { - return nil, convertError(err) + return nil, errors.WithStack(handleError(err)) } entities := make([]*domain.User, 0, len(list)) for _, i := range list { - entities = append(entities, toUserEntity(*i)) + entities = append(entities, (&userModel{i}).toEntity()) } return entities, nil } -// FindOneByID 根据 id 查询详情 -func (r *UserRepository) FindOneByID(ctx context.Context, id domain.ID) (*domain.User, error) { - m, err := r.client.User.Get(ctx, id.Int64()) +func (r *UserRepository) FindOne(ctx context.Context, id int64) (*domain.User, error) { + m, err := r.client.User.Get(ctx, id) if err != nil { - return nil, convertError(err) + return nil, errors.WithStack(handleError(err)) } - return toUserEntity(*m), nil + return (&userModel{m}).toEntity(), nil +} + +func (r *UserRepository) FindOneByUsername(ctx context.Context, username string) (*domain.User, error) { + m, err := r.client.User.Query(). + Where(user.UsernameEQ(username)). + Only(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&userModel{m}).toEntity(), nil +} + +func (r *UserRepository) Exist(ctx context.Context, id int64) (bool, error) { + exist, err := r.client.User.Query().Where(user.IDEQ(id)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) } -// Exist 数据是否存在 -func (r *UserRepository) Exist(ctx context.Context, id domain.ID) (bool, error) { - exist, err := r.client.User.Query().Where(user.IDEQ(id.Int64())).Exist(ctx) - return exist, convertError(err) +func (r *UserRepository) UsernameExist(ctx context.Context, username string) (bool, error) { + exist, err := r.client.User.Query().Where(user.UsernameEQ(username)).Exist(ctx) + return exist, errors.WithStack(handleError(err)) } -// Create 创建数据 -func (r *UserRepository) Create(ctx context.Context, m domain.User) error { - _, err := r.client.User.Create(). - SetName(m.Name). - SetAge(m.Age). - SetPhone(m.Phone). +func (r *UserRepository) UsernameExistExcludeID(ctx context.Context, username string, excludeID int64) (bool, error) { + exist, err := r.client.User.Query().Where( + user.UsernameEQ(username), + user.IDNEQ(excludeID), + ).Exist(ctx) + return exist, errors.WithStack(handleError(err)) +} + +func (r *UserRepository) Create(ctx context.Context, e domain.User) (*domain.User, error) { + m, err := r.client.User.Create(). + SetUsername(e.Username). + SetPassword(string(e.Password)). + SetNickname(e.Nickname). + SetPhone(e.Phone). + SetSalt(e.Salt). Save(ctx) - return convertError(err) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&userModel{m}).toEntity(), nil } -// Update 保存数据 -func (r *UserRepository) Update(ctx context.Context, m domain.User) error { - _, err := r.client.User. - UpdateOneID(m.ID.Int64()). - SetName(m.Name). - SetAge(m.Age). - SetPhone(m.Phone). +func (r *UserRepository) Update(ctx context.Context, e domain.User) (*domain.User, error) { + m, err := r.client.User. + UpdateOneID(e.ID). + SetUsername(e.Username). + SetPassword(string(e.Password)). + SetNickname(e.Nickname). + SetPhone(e.Phone). + SetSalt(e.Salt). Save(ctx) - return convertError(err) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + return (&userModel{m}).toEntity(), nil +} + +func (r *UserRepository) Delete(ctx context.Context, e domain.User) error { + _, err := r.enforcer.DeleteUser(GetPolicyUser(e.ID)) + if err != nil { + return errors.WithStack(err) + } + + return errors.WithStack(r.client.User.DeleteOneID(e.ID).Exec(ctx)) +} + +func (r *UserRepository) AssignRoles(ctx context.Context, user int64, roles []int64) error { + policyUser := GetPolicyUser(user) + + _, err := r.enforcer.DeleteRolesForUser(policyUser) + if err != nil { + return errors.WithStack(handleError(err)) + } + + rs := lo.Map(roles, func(r int64, index int) string { + return GetPolicyRole(r) + }) + + _, err = r.enforcer.AddRolesForUser(policyUser, rs) + return errors.WithStack(handleError(err)) +} + +func (r *UserRepository) GetRoles(ctx context.Context, id int64) ([]*domain.Role, error) { + rss, err := r.enforcer.GetRolesForUser(GetPolicyUser(id)) + if err != nil { + return nil, errors.WithStack(err) + } + + rs := make([]int64, 0, len(rss)) + for _, s := range rss { + i, err := FromPolicyRole(s) + if err != nil { + return nil, err + } + rs = append(rs, i) + } + + data, err := r.client.Role.Query(). + Where(role.IDIn(rs...)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + list := make([]*domain.Role, 0, len(data)) + for _, item := range data { + list = append(list, (&roleModel{item}).toEntity()) + } + return list, err +} + +func (r *UserRepository) GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) { + pss, err := r.enforcer.GetImplicitPermissionsForUser(GetPolicyUser(id)) + if err != nil { + return nil, errors.WithStack(err) + } + + ps := make([]int64, 0, len(pss)) + for _, s := range pss { + if len(s) < 2 { + continue + } + i, err := strconv.ParseInt(s[1], 10, 64) + if err != nil { + return nil, errors.WithStack(err) + } + ps = append(ps, i) + } + ps = lo.Uniq(ps) + + data, err := r.client.Permission.Query(). + Where(permission.IDIn(ps...)). + All(ctx) + if err != nil { + return nil, errors.WithStack(handleError(err)) + } + + list := make([]*domain.Permission, 0, len(data)) + for _, item := range data { + list = append(list, (&permissionModel{item}).toEntity()) + } + return list, err } -// Delete 删除数据 -func (r *UserRepository) Delete(ctx context.Context, user domain.User) error { - return convertError(r.client.User.DeleteOneID(user.ID.Int64()).Exec(ctx)) +type userModel struct { + *ent.User } -func toUserEntity(m ent.User) *domain.User { +func (m *userModel) toEntity() *domain.User { return &domain.User{ - ID: domain.ID(m.ID), - Name: m.Name, - Age: m.Age, - Phone: m.Phone, + ID: m.ID, + Username: m.Username, + Password: domain.Password(m.Password), + Nickname: m.Nickname, + Phone: m.Phone, + Salt: m.Salt, } } diff --git a/internal/app/service/token.go b/internal/app/service/token.go new file mode 100644 index 00000000..efa08293 --- /dev/null +++ b/internal/app/service/token.go @@ -0,0 +1,67 @@ +package service + +import ( + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/pkg/errors" +) + +type AccountTokenData struct { + UserID int64 `json:"userID"` +} + +type AccountTokenClaims struct { + jwt.RegisteredClaims + Data *AccountTokenData `json:"data"` +} + +type AccountTokenService struct { + Key string + Expire time.Duration +} + +func NewAccountTokenService(key string) *AccountTokenService { + return &AccountTokenService{ + Key: key, + } +} + +func (s *AccountTokenService) Generate(expire time.Duration, data AccountTokenData) (string, error) { + claims := AccountTokenClaims{ + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(expire)), + }, + Data: &data, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + sign, err := token.SignedString([]byte(s.Key)) + if err != nil { + return "", errors.WithStack(err) + } + + return sign, nil +} + +func (s *AccountTokenService) ValidateToken(token string) (*AccountTokenClaims, error) { + t, err := jwt.ParseWithClaims(token, &AccountTokenClaims{}, func(token *jwt.Token) (any, error) { + return []byte(s.Key), nil + }) + + claim, ok := t.Claims.(*AccountTokenClaims) + if !t.Valid || !ok { + return nil, errors.WithStack(err) + } + + return claim, nil +} + +func ParseAccountTokenUnverified(token string) (*AccountTokenClaims, error) { + t, _, err := jwt.NewParser().ParseUnverified(token, &AccountTokenClaims{}) + if err != nil { + return nil, errors.WithStack(err) + } + + return t.Claims.(*AccountTokenClaims), nil +} diff --git a/internal/app/tests/db.go b/internal/app/tests/db.go index 1bdc2a5d..43c88632 100644 --- a/internal/app/tests/db.go +++ b/internal/app/tests/db.go @@ -2,16 +2,16 @@ package tests import ( "database/sql" + "log/slog" "time" - igorm "go-scaffold/internal/app/pkg/gorm" - "go-scaffold/internal/config" - glog "go-scaffold/pkg/log/gorm" - "github.com/DATA-DOG/go-sqlmock" - "golang.org/x/exp/slog" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" + + igorm "go-scaffold/internal/app/pkg/gorm" + "go-scaffold/internal/config" + glog "go-scaffold/pkg/log/gorm" ) type DB struct { @@ -47,14 +47,14 @@ func NewDB(logger *slog.Logger) (*DB, func(), error) { cleanup := func() { sdb, err := gdb.DB() if err != nil { - logger.Error("get sql db error", err) + logger.Error("get sql db error", slog.Any("error", err)) } if err := sdb.Close(); err != nil { - logger.Error("close sql db error", err) + logger.Error("close sql db error", slog.Any("error", err)) } if err := mdb.Close(); err != nil { - logger.Error("close mock db error", err) + logger.Error("close mock db error", slog.Any("error", err)) } } diff --git a/internal/app/tests/logger.go b/internal/app/tests/logger.go index aaf6df21..b29a7b12 100644 --- a/internal/app/tests/logger.go +++ b/internal/app/tests/logger.go @@ -2,11 +2,10 @@ package tests import ( "io" + "log/slog" "os" "go-scaffold/pkg/log" - - "golang.org/x/exp/slog" ) // NewLogger init slog logger diff --git a/internal/app/tests/redis.go b/internal/app/tests/redis.go index fc2fd176..bb9a24bf 100644 --- a/internal/app/tests/redis.go +++ b/internal/app/tests/redis.go @@ -1,9 +1,10 @@ package tests import ( + "log/slog" + "github.com/go-redis/redis/v8" "github.com/go-redis/redismock/v8" - "golang.org/x/exp/slog" ) // Redis client wrapper @@ -18,7 +19,7 @@ func NewRDB(logger *slog.Logger) (*Redis, func(), error) { cleanup := func() { if err := client.Close(); err != nil { - logger.Error("close redis client", err) + logger.Error("close redis client", slog.Any("error", err)) } } diff --git a/internal/app/tests/tests.go b/internal/app/tests/tests.go index 8a59a387..842204ea 100644 --- a/internal/app/tests/tests.go +++ b/internal/app/tests/tests.go @@ -2,10 +2,10 @@ package tests import ( "flag" + "log/slog" "testing" "github.com/google/wire" - "golang.org/x/exp/slog" ) const appName = "go-scaffold-test" diff --git a/internal/app/usecase/account.go b/internal/app/usecase/account.go new file mode 100644 index 00000000..59b3213e --- /dev/null +++ b/internal/app/usecase/account.go @@ -0,0 +1,47 @@ +package usecase + +import ( + "context" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/repository" + "go-scaffold/internal/app/service" +) + +var _ AccountUseCaseInterface = (*AccountUseCase)(nil) + +type AccountUseCaseInterface interface { + Login(ctx context.Context, user domain.User) (string, error) + Logout(ctx context.Context, user domain.User) error +} + +type AccountUseCase struct { + repo repository.UserRepositoryInterface +} + +func NewAccountUseCase( + repo repository.UserRepositoryInterface, +) *AccountUseCase { + return &AccountUseCase{ + repo: repo, + } +} + +func (c AccountUseCase) Login(ctx context.Context, user domain.User) (string, error) { + tokenExpire := domain.AccountTokenExpireDuration + + data := service.AccountTokenData{ + UserID: user.ID, + } + return service.NewAccountTokenService(user.Salt).Generate(tokenExpire, data) +} + +func (c AccountUseCase) Logout(ctx context.Context, user domain.User) error { + user.RefreshSalt() + + if _, err := c.repo.Update(ctx, user); err != nil { + return err + } + + return nil +} diff --git a/internal/app/usecase/permission.go b/internal/app/usecase/permission.go new file mode 100644 index 00000000..97992868 --- /dev/null +++ b/internal/app/usecase/permission.go @@ -0,0 +1,56 @@ +package usecase + +import ( + "context" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/repository" +) + +var _ PermissionUseCaseInterface = (*PermissionUseCase)(nil) + +type PermissionUseCaseInterface interface { + Create(ctx context.Context, product domain.Permission) error + Update(ctx context.Context, product domain.Permission) error + Delete(ctx context.Context, product domain.Permission) error + Detail(ctx context.Context, id int64) (*domain.Permission, error) + List(ctx context.Context, param PermissionListParam) ([]*domain.Permission, error) +} + +type PermissionUseCase struct { + repo repository.PermissionRepositoryInterface +} + +func NewPermissionUseCase( + repo repository.PermissionRepositoryInterface, +) *PermissionUseCase { + return &PermissionUseCase{ + repo: repo, + } +} + +func (c *PermissionUseCase) Create(ctx context.Context, product domain.Permission) error { + return c.repo.Create(ctx, product) +} + +func (c *PermissionUseCase) Update(ctx context.Context, product domain.Permission) error { + return c.repo.Update(ctx, product) +} + +func (c *PermissionUseCase) Delete(ctx context.Context, product domain.Permission) error { + return c.repo.Delete(ctx, product) +} + +func (c *PermissionUseCase) Detail(ctx context.Context, id int64) (*domain.Permission, error) { + return c.repo.FindOne(ctx, id) +} + +type PermissionListParam struct { + Keyword string +} + +func (c *PermissionUseCase) List(ctx context.Context, param PermissionListParam) ([]*domain.Permission, error) { + return c.repo.Filter(ctx, repository.PermissionFindListParam{ + Keyword: param.Keyword, + }) +} diff --git a/internal/app/usecase/product.go b/internal/app/usecase/product.go new file mode 100644 index 00000000..7427ef37 --- /dev/null +++ b/internal/app/usecase/product.go @@ -0,0 +1,56 @@ +package usecase + +import ( + "context" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/repository" +) + +var _ ProductUseCaseInterface = (*ProductUseCase)(nil) + +type ProductUseCaseInterface interface { + Create(ctx context.Context, product domain.Product) error + Update(ctx context.Context, product domain.Product) error + Delete(ctx context.Context, product domain.Product) error + Detail(ctx context.Context, id int64) (*domain.Product, error) + List(ctx context.Context, param ProductListParam) ([]*domain.Product, error) +} + +type ProductUseCase struct { + repo repository.ProductRepositoryInterface +} + +func NewProductUseCase( + repo repository.ProductRepositoryInterface, +) *ProductUseCase { + return &ProductUseCase{ + repo: repo, + } +} + +func (c *ProductUseCase) Create(ctx context.Context, product domain.Product) error { + return c.repo.Create(ctx, product) +} + +func (c *ProductUseCase) Update(ctx context.Context, product domain.Product) error { + return c.repo.Update(ctx, product) +} + +func (c *ProductUseCase) Delete(ctx context.Context, product domain.Product) error { + return c.repo.Delete(ctx, product) +} + +func (c *ProductUseCase) Detail(ctx context.Context, id int64) (*domain.Product, error) { + return c.repo.FindOne(ctx, id) +} + +type ProductListParam struct { + Keyword string +} + +func (c *ProductUseCase) List(ctx context.Context, param ProductListParam) ([]*domain.Product, error) { + return c.repo.Filter(ctx, repository.ProductFindListParam{ + Keyword: param.Keyword, + }) +} diff --git a/internal/app/usecase/role.go b/internal/app/usecase/role.go new file mode 100644 index 00000000..ac474566 --- /dev/null +++ b/internal/app/usecase/role.go @@ -0,0 +1,66 @@ +package usecase + +import ( + "context" + + "go-scaffold/internal/app/domain" + "go-scaffold/internal/app/repository" +) + +var _ RoleUseCaseInterface = (*RoleUseCase)(nil) + +type RoleUseCaseInterface interface { + Create(ctx context.Context, product domain.Role) error + Update(ctx context.Context, product domain.Role) error + Delete(ctx context.Context, product domain.Role) error + Detail(ctx context.Context, id int64) (*domain.Role, error) + List(ctx context.Context, param RoleListParam) ([]*domain.Role, error) + GrantPermissions(ctx context.Context, role int64, permissions []int64) error + GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) +} + +type RoleUseCase struct { + repo repository.RoleRepositoryInterface +} + +func NewRoleUseCase( + repo repository.RoleRepositoryInterface, +) *RoleUseCase { + return &RoleUseCase{ + repo: repo, + } +} + +func (c *RoleUseCase) Create(ctx context.Context, product domain.Role) error { + return c.repo.Create(ctx, product) +} + +func (c *RoleUseCase) Update(ctx context.Context, product domain.Role) error { + return c.repo.Update(ctx, product) +} + +func (c *RoleUseCase) Delete(ctx context.Context, product domain.Role) error { + return c.repo.Delete(ctx, product) +} + +func (c *RoleUseCase) Detail(ctx context.Context, id int64) (*domain.Role, error) { + return c.repo.FindOne(ctx, id) +} + +type RoleListParam struct { + Keyword string +} + +func (c *RoleUseCase) List(ctx context.Context, param RoleListParam) ([]*domain.Role, error) { + return c.repo.Filter(ctx, repository.RoleFindListParam{ + Keyword: param.Keyword, + }) +} + +func (c *RoleUseCase) GrantPermissions(ctx context.Context, role int64, permissions []int64) error { + return c.repo.GrantPermissions(ctx, role, permissions) +} + +func (c *RoleUseCase) GetPermissions(ctx context.Context, id int64) ([]*domain.Permission, error) { + return c.repo.GetPermissions(ctx, id) +} diff --git a/internal/app/usecase/usecase.go b/internal/app/usecase/usecase.go index a661f673..8069a1be 100644 --- a/internal/app/usecase/usecase.go +++ b/internal/app/usecase/usecase.go @@ -1,11 +1,13 @@ package usecase import ( - "go-scaffold/internal/app/domain" - "github.com/google/wire" ) var ProviderSet = wire.NewSet( - wire.NewSet(wire.Bind(new(domain.UserUseCase), new(*UserUseCase)), NewUserUseCase), + wire.NewSet(wire.Bind(new(AccountUseCaseInterface), new(*AccountUseCase)), NewAccountUseCase), + wire.NewSet(wire.Bind(new(UserUseCaseInterface), new(*UserUseCase)), NewUserUseCase), + wire.NewSet(wire.Bind(new(RoleUseCaseInterface), new(*RoleUseCase)), NewRoleUseCase), + wire.NewSet(wire.Bind(new(PermissionUseCaseInterface), new(*PermissionUseCase)), NewPermissionUseCase), + wire.NewSet(wire.Bind(new(ProductUseCaseInterface), new(*ProductUseCase)), NewProductUseCase), ) diff --git a/internal/app/usecase/user.go b/internal/app/usecase/user.go index b5394eaa..2b10b4fd 100644 --- a/internal/app/usecase/user.go +++ b/internal/app/usecase/user.go @@ -4,63 +4,68 @@ import ( "context" "go-scaffold/internal/app/domain" - berr "go-scaffold/internal/app/pkg/errors" - - "github.com/pkg/errors" + "go-scaffold/internal/app/repository" ) -var _ domain.UserUseCase = (*UserUseCase)(nil) +var _ UserUseCaseInterface = (*UserUseCase)(nil) + +type UserUseCaseInterface interface { + Create(ctx context.Context, user domain.User) (*domain.User, error) + Update(ctx context.Context, user domain.User) (*domain.User, error) + Delete(ctx context.Context, user domain.User) error + Detail(ctx context.Context, id int64) (*domain.User, error) + List(ctx context.Context, param UserListParam) ([]*domain.User, error) + AssignRoles(ctx context.Context, user int64, roles []int64) error + GetRoles(ctx context.Context, user int64) ([]*domain.Role, error) + GetPermissions(ctx context.Context, user int64) ([]*domain.Permission, error) +} -// UserUseCase 用户用例 type UserUseCase struct { - repo domain.UserRepository + repo repository.UserRepositoryInterface } -// NewUserUseCase 构造用户用例 func NewUserUseCase( - repo domain.UserRepository, + repo repository.UserRepositoryInterface, ) *UserUseCase { return &UserUseCase{ repo: repo, } } -// Create 新增用户 -func (u *UserUseCase) Create(ctx context.Context, user domain.User) error { - return u.repo.Create(ctx, user) +func (c *UserUseCase) Create(ctx context.Context, user domain.User) (*domain.User, error) { + return c.repo.Create(ctx, user) } -// Update 更新用户 -func (u *UserUseCase) Update(ctx context.Context, user domain.User) error { - ok, err := u.repo.Exist(ctx, user.ID) - if err != nil { - return err - } - if !ok { - return errors.WithStack(berr.ErrResourceNotFound) - } - - return u.repo.Update(ctx, user) +func (c *UserUseCase) Update(ctx context.Context, user domain.User) (*domain.User, error) { + return c.repo.Update(ctx, user) } -// Delete 删除用户 -func (u *UserUseCase) Delete(ctx context.Context, id domain.ID) error { - user, err := u.repo.FindOneByID(ctx, id) - if err != nil { - return err - } +func (c *UserUseCase) Delete(ctx context.Context, user domain.User) error { + return c.repo.Delete(ctx, user) +} - return u.repo.Delete(ctx, *user) +func (c *UserUseCase) Detail(ctx context.Context, id int64) (*domain.User, error) { + return c.repo.FindOne(ctx, id) } -// Detail 用户详情 -func (u *UserUseCase) Detail(ctx context.Context, id domain.ID) (*domain.User, error) { - return u.repo.FindOneByID(ctx, id) +type UserListParam struct { + Keyword string } -// List 用户列表 -func (u *UserUseCase) List(ctx context.Context, param domain.UserListParam) ([]*domain.User, error) { - return u.repo.FindList(ctx, domain.FindUserListParam{ +func (c *UserUseCase) List(ctx context.Context, param UserListParam) ([]*domain.User, error) { + return c.repo.Filter(ctx, repository.UserFindListParam{ Keyword: param.Keyword, }) } + +func (c *UserUseCase) AssignRoles(ctx context.Context, user int64, roles []int64) error { + return c.repo.AssignRoles(ctx, user, roles) +} + +func (c *UserUseCase) GetRoles(ctx context.Context, user int64) ([]*domain.Role, error) { + return c.repo.GetRoles(ctx, user) +} + +func (c *UserUseCase) GetPermissions(ctx context.Context, user int64) ([]*domain.Permission, error) { + return c.repo.GetPermissions(ctx, user) +} diff --git a/internal/command/base.go b/internal/command/base.go index 7a9696d0..791afdba 100644 --- a/internal/command/base.go +++ b/internal/command/base.go @@ -3,14 +3,9 @@ package command import ( "context" "io" + "log/slog" "os" - "go-scaffold/internal/config" - "go-scaffold/pkg/ioutils" - "go-scaffold/pkg/log" - iklog "go-scaffold/pkg/log/kratos" - "go-scaffold/pkg/trace" - "github.com/go-kratos/kratos/contrib/config/apollo/v2" kconfig "github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/config/file" @@ -19,7 +14,12 @@ import ( "github.com/spf13/cobra" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/propagation" - "golang.org/x/exp/slog" + + "go-scaffold/internal/config" + "go-scaffold/pkg/ioutils" + "go-scaffold/pkg/log" + iklog "go-scaffold/pkg/log/kratos" + "go-scaffold/pkg/trace" ) type baseCmd struct { diff --git a/internal/command/flag.go b/internal/command/flag.go index 73d6f0ca..1dff8b8a 100644 --- a/internal/command/flag.go +++ b/internal/command/flag.go @@ -1,10 +1,10 @@ package command import ( - "go-scaffold/internal/config" - "github.com/spf13/cobra" "github.com/spf13/pflag" + + "go-scaffold/internal/config" ) var ( diff --git a/internal/command/migrate.go b/internal/command/migrate.go index 66c099de..beb9f68a 100644 --- a/internal/command/migrate.go +++ b/internal/command/migrate.go @@ -6,14 +6,15 @@ import ( "fmt" "os" "strconv" + "strings" "time" - "go-scaffold/internal/config" - printer "github.com/fatih/color" "github.com/olekukonko/tablewriter" migrate "github.com/rubenv/sql-migrate" "github.com/spf13/cobra" + + "go-scaffold/internal/config" ) // create a migration file like this: @@ -232,6 +233,21 @@ func newMigrateDownCmd() *migrateDownCmd { } func (c *migrateDownCmd) run(args []string) { + if len(args) == 0 { + printer.Yellow("this will roll back all migrations, yes/no?") + + ret := "" + _, err := fmt.Scan(&ret) + if err != nil { + c.printError(err) + return + } + + if strings.ToLower(ret) != "yes" && strings.ToLower(ret) != "y" { + return + } + } + n, err := c.applyMigrations(args, migrate.Down) if err != nil { c.printError(err) diff --git a/internal/command/server.go b/internal/command/server.go index 2e2a4aa8..5956a2e3 100644 --- a/internal/command/server.go +++ b/internal/command/server.go @@ -2,6 +2,7 @@ package command import ( "context" + "log/slog" "os/signal" "syscall" @@ -67,7 +68,7 @@ func (c *serverCmd) run(ctx context.Context) { select { case err := <-stop: - c.logger.Error("start server error", err) + c.logger.Error("start server error", slog.Any("error", err)) return case <-signalCtx.Done(): } diff --git a/internal/command/wire.go b/internal/command/wire.go index 6ee1d03e..279d85b9 100644 --- a/internal/command/wire.go +++ b/internal/command/wire.go @@ -6,6 +6,9 @@ package command import ( "context" "database/sql" + "log/slog" + + "github.com/google/wire" "go-scaffold/internal/app" "go-scaffold/internal/app/adapter/cron" @@ -14,9 +17,6 @@ import ( "go-scaffold/internal/app/pkg" "go-scaffold/internal/config" "go-scaffold/pkg/trace" - - "github.com/google/wire" - "golang.org/x/exp/slog" ) func initServer( diff --git a/internal/command/wire_gen.go b/internal/command/wire_gen.go index cd659f65..be7f7065 100644 --- a/internal/command/wire_gen.go +++ b/internal/command/wire_gen.go @@ -23,14 +23,16 @@ import ( "go-scaffold/internal/app/adapter/server/http/handler/v1" "go-scaffold/internal/app/adapter/server/http/router" "go-scaffold/internal/app/controller" + "go-scaffold/internal/app/pkg/casbin" "go-scaffold/internal/app/pkg/client" "go-scaffold/internal/app/pkg/db" "go-scaffold/internal/app/pkg/ent" + "go-scaffold/internal/app/pkg/gorm" "go-scaffold/internal/app/repository" "go-scaffold/internal/app/usecase" "go-scaffold/internal/config" "go-scaffold/pkg/trace" - "golang.org/x/exp/slog" + "log/slog" ) // Injectors from wire.go: @@ -40,47 +42,107 @@ func initServer(contextContext context.Context, appName config.AppName, env conf if err != nil { return nil, nil, err } + dbConn, err := config.GetDBConn() + if err != nil { + return nil, nil, err + } + sqlDB, cleanup, err := db.Provide(contextContext, dbConn) + if err != nil { + return nil, nil, err + } + entClient, cleanup2, err := ent.Provide(env, dbConn, logger, sqlDB) + if err != nil { + cleanup() + return nil, nil, err + } + configCasbin, err := config.GetHTTPCasbin() + if err != nil { + cleanup2() + cleanup() + return nil, nil, err + } + configDB, err := config.GetDB() + if err != nil { + cleanup2() + cleanup() + return nil, nil, err + } + gormDB, cleanup3, err := gorm.Provide(contextContext, configDB, logger) + if err != nil { + cleanup2() + cleanup() + return nil, nil, err + } + enforcer, err := casbin.Provide(env, configCasbin, dbConn, logger, gormDB, sqlDB) + if err != nil { + cleanup3() + cleanup2() + cleanup() + return nil, nil, err + } + userRepository := repository.NewUserRepository(entClient, enforcer) + accountUseCase := usecase.NewAccountUseCase(userRepository) + accountTokenController := controller.NewAccountTokenController(accountUseCase, userRepository) + roleRepository := repository.NewRoleRepository(entClient, enforcer) + permissionRepository := repository.NewPermissionRepository(entClient, enforcer) + accountPermissionController := controller.NewAccountPermissionController(roleRepository, permissionRepository, enforcer) greetController := controller.NewGreetController() greetHandler := v1.NewGreetHandler(greetController) services, err := config.GetServices() if err != nil { + cleanup3() + cleanup2() + cleanup() return nil, nil, err } clientGRPC := client.ProvideGRPC() traceHandler := v1.NewTraceHandler(logger, services, httpServer, traceTrace, clientGRPC) kafka, err := config.GetKafka() if err != nil { + cleanup3() + cleanup2() + cleanup() return nil, nil, err } producerController := controller.NewProducerController(kafka) producerHandler := v1.NewProducerHandler(producerController) - dbConn, err := config.GetDBConn() - if err != nil { - return nil, nil, err - } - entClient, cleanup, err := ent.Provide(contextContext, env, dbConn, logger) - if err != nil { - return nil, nil, err - } - userRepository := repository.NewUserRepository(entClient) userUseCase := usecase.NewUserUseCase(userRepository) - userController := controller.NewUserController(userUseCase) + accountController := controller.NewAccountController(accountUseCase, userUseCase, userRepository) + accountHandler := v1.NewAccountHandler(accountController) + userController := controller.NewUserController(userUseCase, userRepository, roleRepository) userHandler := v1.NewUserHandler(userController) - apiV1Group := router.NewAPIV1Group(greetHandler, traceHandler, producerHandler, userHandler) + roleUseCase := usecase.NewRoleUseCase(roleRepository) + roleController := controller.NewRoleController(roleUseCase, roleRepository, permissionRepository) + roleHandler := v1.NewRoleHandler(roleController) + permissionUseCase := usecase.NewPermissionUseCase(permissionRepository) + permissionController := controller.NewPermissionController(permissionUseCase, permissionRepository) + permissionHandler := v1.NewPermissionHandler(permissionController) + productRepository := repository.NewProductRepository(entClient) + productUseCase := usecase.NewProductUseCase(productRepository) + productController := controller.NewProductController(productUseCase, productRepository) + productHandler := v1.NewProductHandler(productController) + apiV1Group := router.NewAPIV1Group(accountTokenController, accountPermissionController, greetHandler, traceHandler, producerHandler, accountHandler, userHandler, roleHandler, permissionHandler, productHandler) apiGroup := router.NewAPIGroup(env, logger, httpServer, apiV1Group) handler := router.New(logger, appName, env, httpServer, apiGroup) server2 := http.New(httpServer, handler) grpcServer, err := config.GetGRPCServer() if err != nil { + cleanup3() + cleanup2() cleanup() return nil, nil, err } v1GreetHandler := v1_2.NewGreetHandler(logger, greetController) v1UserHandler := v1_2.NewUserHandler(logger, userController) - routerRouter := router2.New(v1GreetHandler, v1UserHandler) + v1RoleHandler := v1_2.NewRoleHandler(logger, roleController) + v1PermissionHandler := v1_2.NewPermissionHandler(logger, permissionController) + v1ProductHandler := v1_2.NewProductHandler(logger, productController) + routerRouter := router2.New(v1GreetHandler, v1UserHandler, v1RoleHandler, v1PermissionHandler, v1ProductHandler) server3 := grpc.New(grpcServer, routerRouter) serverServer := server.New(contextContext, appName, server2, server3) return serverServer, func() { + cleanup3() + cleanup2() cleanup() }, nil } diff --git a/internal/config/config.go b/internal/config/config.go index 14fd35fb..69fffbd1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,7 +12,6 @@ var ErrEntryNotConfigured = errors.New("the configuration entry is not configure var ProviderSet = wire.NewSet( GetApp, GetHTTPServer, - GetHTTPJWT, GetHTTPCasbin, GetGRPCServer, GetServices, @@ -70,14 +69,6 @@ func GetHTTPServer() (HTTPServer, error) { return getEntry(httpConfig.Server) } -func GetHTTPJWT() (JWT, error) { - httpConfig, err := getHTTP() - if err != nil { - return JWT{}, err - } - return getEntry(httpConfig.JWT) -} - func GetHTTPCasbin() (Casbin, error) { httpConfig, err := getHTTP() if err != nil { diff --git a/internal/config/server.go b/internal/config/server.go index bd5e96b9..5f0b20f7 100644 --- a/internal/config/server.go +++ b/internal/config/server.go @@ -5,7 +5,6 @@ import "time" // HTTP the HTTP config type HTTP struct { Server *HTTPServer `json:"server"` - JWT *JWT `json:"jwt"` Casbin *Casbin `json:"casbin"` } @@ -25,15 +24,6 @@ func (HTTPServer) GetName() string { return "http.server" } -// JWT the JWT config -type JWT struct { - Key string `json:"key"` -} - -func (JWT) GetName() string { - return "http.jwt" -} - // Casbin casbin config type Casbin struct { Model CasbinModel `json:"model"` @@ -53,18 +43,16 @@ type CasbinModel struct { type ( // CasbinAdapter casbin adapter CasbinAdapter struct { - File *CasbinFileAdapter `json:"file"` + File string `json:"file"` Gorm *CasbinGormAdapter `json:"gorm"` - } - - CasbinFileAdapter struct { - Path string `json:"path"` + Ent *CasbinEntAdapter `json:"ent"` } // CasbinGormAdapter casbin gorm adapter - CasbinGormAdapter struct { - TableName string `json:"tableName"` - } + CasbinGormAdapter struct{} + + // CasbinEntAdapter casbin ent adapter + CasbinEntAdapter struct{} ) // GRPC the gRPC config diff --git a/internal/config/watch.go b/internal/config/watch.go index 1c40209a..0ea5ea79 100644 --- a/internal/config/watch.go +++ b/internal/config/watch.go @@ -1,8 +1,9 @@ package config import ( + "log/slog" + kconfig "github.com/go-kratos/kratos/v2/config" - "golang.org/x/exp/slog" ) var watchKeys = []string{ @@ -18,7 +19,7 @@ func Watch(logger *slog.Logger, source kconfig.Config, cm *Config) error { logger.With(slog.String("key", key)).Debug("config has changed") if err := source.Scan(cm); err != nil { - logger.Error("scan config to model failed", err) + logger.Error("scan config to model failed", slog.Any("error", err)) } }); err != nil { return err diff --git a/migrations/20230510004346-create_users_table.sql b/migrations/20230510004346-create_users_table.sql index 9cba0006..a90a5173 100644 --- a/migrations/20230510004346-create_users_table.sql +++ b/migrations/20230510004346-create_users_table.sql @@ -3,14 +3,18 @@ CREATE TABLE IF NOT EXISTS `users` ( `id` int unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(64) NOT NULL DEFAULT '' COMMENT '名称', - `age` tinyint NOT NULL DEFAULT 0 COMMENT '年龄', + `username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名', + `password` varchar(64) NOT NULL DEFAULT '' COMMENT '密码', + `nickname` varchar(64) NOT NULL DEFAULT '' COMMENT '昵称', `phone` varchar(11) NOT NULL DEFAULT '' COMMENT '电话', + `salt` varchar(64) NOT NULL DEFAULT '' COMMENT '盐值', `created_at` bigint NOT NULL DEFAULT 0, `updated_at` bigint NOT NULL DEFAULT 0, `deleted_at` bigint unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`id`), - KEY `idx_deleted_at` (`deleted_at`) + UNIQUE `username` (`username`), + KEY `phone` (`phone`), + KEY `deleted_at` (`deleted_at`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='用户表'; diff --git a/migrations/20230510004740-create_casbin_rule_table.sql b/migrations/20230510004740-create_casbin_rule_table.sql deleted file mode 100644 index bd7ae7ef..00000000 --- a/migrations/20230510004740-create_casbin_rule_table.sql +++ /dev/null @@ -1,20 +0,0 @@ --- +migrate Up - -CREATE TABLE IF NOT EXISTS `casbin_rule` -( - `id` bigint unsigned NOT NULL AUTO_INCREMENT, - `ptype` varchar(100) DEFAULT NULL, - `v0` varchar(100) DEFAULT NULL, - `v1` varchar(100) DEFAULT NULL, - `v2` varchar(100) DEFAULT NULL, - `v3` varchar(100) DEFAULT NULL, - `v4` varchar(100) DEFAULT NULL, - `v5` varchar(100) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `idx_casbin_rule` (`ptype`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`) -) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4; - --- +migrate Down - -DROP TABLE IF EXISTS `casbin_rule`; \ No newline at end of file diff --git a/migrations/20230728103932-create_products_table.sql b/migrations/20230728103932-create_products_table.sql new file mode 100644 index 00000000..32b4f2ee --- /dev/null +++ b/migrations/20230728103932-create_products_table.sql @@ -0,0 +1,20 @@ +-- +migrate Up + +CREATE TABLE IF NOT EXISTS `products` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL DEFAULT '' COMMENT '名称', + `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '描述', + `price` int NOT NULL DEFAULT 0 COMMENT '价格', + `created_at` bigint NOT NULL DEFAULT 0, + `updated_at` bigint NOT NULL DEFAULT 0, + `deleted_at` bigint unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `name` (`name`), + KEY `deleted_at` (`deleted_at`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='产品表'; + +-- +migrate Down + +DROP TABLE IF EXISTS `products`; \ No newline at end of file diff --git a/migrations/20230822175206-create_permissions_table.sql b/migrations/20230822175206-create_permissions_table.sql new file mode 100644 index 00000000..8a7331df --- /dev/null +++ b/migrations/20230822175206-create_permissions_table.sql @@ -0,0 +1,21 @@ +-- +migrate Up + +CREATE TABLE IF NOT EXISTS `permissions` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `key` varchar(128) NOT NULL DEFAULT '' COMMENT '权限标识', + `name` varchar(128) NOT NULL DEFAULT '' COMMENT '权限名称', + `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '权限描述', + `parent_id` int unsigned NOT NULL DEFAULT 0 COMMENT '父级权限 id', + `created_at` bigint NOT NULL DEFAULT 0, + `updated_at` bigint NOT NULL DEFAULT 0, + `deleted_at` bigint unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE `key` (`key`), + KEY `deleted_at` (`deleted_at`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='权限表'; + +-- +migrate Down + +DROP TABLE IF EXISTS `permissions`; \ No newline at end of file diff --git a/migrations/20230822182128-create_roles_table.sql b/migrations/20230822182128-create_roles_table.sql new file mode 100644 index 00000000..730c1f8c --- /dev/null +++ b/migrations/20230822182128-create_roles_table.sql @@ -0,0 +1,18 @@ +-- +migrate Up + +CREATE TABLE IF NOT EXISTS `roles` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(32) NOT NULL DEFAULT '' COMMENT '角色名称', + `created_at` bigint NOT NULL DEFAULT 0, + `updated_at` bigint NOT NULL DEFAULT 0, + `deleted_at` bigint unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE `name` (`name`), + KEY `deleted_at` (`deleted_at`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='角色表'; + +-- +migrate Down + +DROP TABLE IF EXISTS `roles`; \ No newline at end of file diff --git a/migrations/20230905134244-insert_permissions_table_data.sql b/migrations/20230905134244-insert_permissions_table_data.sql new file mode 100644 index 00000000..6e0bb9d9 --- /dev/null +++ b/migrations/20230905134244-insert_permissions_table_data.sql @@ -0,0 +1,45 @@ +-- +migrate Up + +START TRANSACTION; + +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) VALUES ('/users', '用户管理', 0, unix_timestamp(), unix_timestamp()); +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) +VALUES ('GET /api/v1/users', '用户列表', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/user', '用户详情', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/user', '用户新增', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('PUT /api/v1/user', '用户更新', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('DELETE /api/v1/user', '用户删除', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/user/roles', '分配用户角色', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/user/roles', '获取用户角色', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/users') AS t), unix_timestamp(), unix_timestamp()); + +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) VALUES ('/roles', '角色管理', 0, unix_timestamp(), unix_timestamp()); +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) +VALUES ('GET /api/v1/roles', '角色列表', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/role', '角色详情', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/role', '角色新增', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('PUT /api/v1/role', '角色更新', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('DELETE /api/v1/role', '角色删除', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/role/permissions', '授予角色权限', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/role/permissions', '获取角色权限', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/roles') AS t), unix_timestamp(), unix_timestamp()); + +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) VALUES ('/permissions', '权限管理', 0, unix_timestamp(), unix_timestamp()); +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) +VALUES ('GET /api/v1/permissions', '权限列表', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/permissions') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/permission', '权限详情', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/permissions') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/permission', '权限新增', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/permissions') AS t), unix_timestamp(), unix_timestamp()), + ('PUT /api/v1/permission', '权限更新', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/permissions') AS t), unix_timestamp(), unix_timestamp()), + ('DELETE /api/v1/permission', '权限删除', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/permissions') AS t), unix_timestamp(), unix_timestamp()); + +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) VALUES ('/products', '产品管理', 0, unix_timestamp(), unix_timestamp()); +INSERT INTO permissions (`key`, name, parent_id, created_at, updated_at) +VALUES ('GET /api/v1/products', '产品列表', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/products') AS t), unix_timestamp(), unix_timestamp()), + ('GET /api/v1/product', '产品详情', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/products') AS t), unix_timestamp(), unix_timestamp()), + ('POST /api/v1/product', '产品新增', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/products') AS t), unix_timestamp(), unix_timestamp()), + ('PUT /api/v1/product', '产品更新', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/products') AS t), unix_timestamp(), unix_timestamp()), + ('DELETE /api/v1/product', '产品删除', (SELECT id FROM (SELECT id FROM permissions WHERE `key` = '/products') AS t), unix_timestamp(), unix_timestamp()); + +COMMIT; + +-- +migrate Down + +TRUNCATE TABLE permissions; diff --git a/pkg/log/cron/logger.go b/pkg/log/cron/logger.go index 7d09ff11..b84d77e1 100644 --- a/pkg/log/cron/logger.go +++ b/pkg/log/cron/logger.go @@ -2,10 +2,9 @@ package cron import ( "context" + "log/slog" "go-scaffold/pkg/log" - - "golang.org/x/exp/slog" ) // Logger adapts to cron.Logger diff --git a/pkg/log/ent/logger.go b/pkg/log/ent/logger.go index 43d1f969..2d6db331 100644 --- a/pkg/log/ent/logger.go +++ b/pkg/log/ent/logger.go @@ -2,10 +2,9 @@ package ent import ( "context" + "log/slog" "go-scaffold/pkg/log" - - "golang.org/x/exp/slog" ) const defaultMessageKey = "msg" diff --git a/pkg/log/gorm/logger.go b/pkg/log/gorm/logger.go index 721e51da..61d80b1a 100644 --- a/pkg/log/gorm/logger.go +++ b/pkg/log/gorm/logger.go @@ -4,13 +4,13 @@ import ( "context" "errors" "fmt" + "log/slog" "time" - "go-scaffold/pkg/log" - - "golang.org/x/exp/slog" "gorm.io/gorm" "gorm.io/gorm/logger" + + "go-scaffold/pkg/log" ) // Config is logger config diff --git a/pkg/log/kratos/logger.go b/pkg/log/kratos/logger.go index ee32c01a..65e3c72c 100644 --- a/pkg/log/kratos/logger.go +++ b/pkg/log/kratos/logger.go @@ -2,11 +2,11 @@ package kratos import ( "context" - - "go-scaffold/pkg/log" + "log/slog" klog "github.com/go-kratos/kratos/v2/log" - "golang.org/x/exp/slog" + + "go-scaffold/pkg/log" ) var _ klog.Logger = (*Logger)(nil) diff --git a/pkg/log/log.go b/pkg/log/log.go index e6dc89cc..8a616f41 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -2,21 +2,24 @@ package log import ( "context" + "fmt" "go/build" "io" + "log/slog" "os" "path/filepath" "runtime" "strings" "time" + "github.com/pkg/errors" + ierrors "go-scaffold/pkg/errors" "go-scaffold/pkg/path" - - "github.com/pkg/errors" - "golang.org/x/exp/slog" ) +const AttrErrorKey = "error" + var ( // DefaultLevel default log level DefaultLevel = Info @@ -28,8 +31,8 @@ var ( DefaultWriter = os.Stdout ) -// option is logger option -type option struct { +// config is logger config +type config struct { level Level format Format writer io.Writer @@ -37,47 +40,46 @@ type option struct { attrs []slog.Attr } -// OptionFunc optional function -type OptionFunc func(logger *option) +type Option func(c *config) // WithLevel set log level -func WithLevel(level Level) OptionFunc { - return func(logger *option) { - logger.level = level +func WithLevel(level Level) Option { + return func(c *config) { + c.level = level } } // WithFormat set log format -func WithFormat(format Format) OptionFunc { - return func(logger *option) { - logger.format = format +func WithFormat(format Format) Option { + return func(c *config) { + c.format = format } } // WithWriter set log writer -func WithWriter(writer io.Writer) OptionFunc { - return func(logger *option) { - logger.writer = writer +func WithWriter(writer io.Writer) Option { + return func(c *config) { + c.writer = writer } } // WithGroup set log group -func WithGroup(group string) OptionFunc { - return func(logger *option) { - logger.group = group +func WithGroup(group string) Option { + return func(c *config) { + c.group = group } } // WithAttrs set log key-value pair -func WithAttrs(attrs []slog.Attr) OptionFunc { - return func(logger *option) { - logger.attrs = attrs +func WithAttrs(attrs []slog.Attr) Option { + return func(c *config) { + c.attrs = attrs } } // New build *slog.Logger -func New(options ...OptionFunc) *slog.Logger { - logger := &option{ +func New(options ...Option) *slog.Logger { + logger := &config{ level: DefaultLevel, format: DefaultFormat, writer: DefaultWriter, @@ -87,7 +89,7 @@ func New(options ...OptionFunc) *slog.Logger { opf(logger) } - ops := slog.HandlerOptions{ + ops := &slog.HandlerOptions{ AddSource: true, Level: logger.level.Convert(), ReplaceAttr: ReplaceAttr, @@ -95,9 +97,9 @@ func New(options ...OptionFunc) *slog.Logger { var handler slog.Handler if logger.format == Text { - handler = ops.NewTextHandler(logger.writer) + handler = slog.NewTextHandler(logger.writer, ops) } else { - handler = ops.NewJSONHandler(logger.writer) + handler = slog.NewJSONHandler(logger.writer, ops) } if logger.group != "" { @@ -153,8 +155,9 @@ func ReplaceAttr(groups []string, a slog.Attr) slog.Attr { case slog.LevelKey: return slog.String(a.Key, strings.ToLower(a.Value.String())) case slog.SourceKey: - return slog.String(a.Key, getBriefSource(a.Value.String())) - case slog.ErrorKey: + value := a.Value.Any().(*slog.Source) + return slog.String(a.Key, fmt.Sprintf("%s:%d", getBriefSource(value.File), value.Line)) + case AttrErrorKey: v, ok := a.Value.Any().(interface { StackTrace() errors.StackTrace }) @@ -170,10 +173,10 @@ func ReplaceAttr(groups []string, a slog.Attr) slog.Attr { // NewNop returns a no-op logger func NewNop() *slog.Logger { nopLevel := slog.Level(-99) - ops := slog.HandlerOptions{ + ops := &slog.HandlerOptions{ Level: nopLevel, } - handler := ops.NewTextHandler(io.Discard) + handler := slog.NewTextHandler(io.Discard, ops) return slog.New(handler) } @@ -197,7 +200,7 @@ func (l *Logger) Log(ctx context.Context, depth int, err error, level slog.Level runtime.Callers(depth, pcs[:]) r := slog.NewRecord(time.Now(), level, msg, pcs[0]) if err != nil { - r.Add(slog.ErrorKey, err) + r.Add(AttrErrorKey, err) } r.Add(attrs...) if ctx == nil { diff --git a/pkg/trace/trace.go b/pkg/trace/trace.go index da1a16db..e57c433d 100644 --- a/pkg/trace/trace.go +++ b/pkg/trace/trace.go @@ -19,25 +19,24 @@ type Trace struct { tracerProvider *sdktrace.TracerProvider } -// OptionFunc optional function -type OptionFunc func(t *Trace) +type Option func(t *Trace) // WithServiceName optional service name -func WithServiceName(serviceName string) OptionFunc { +func WithServiceName(serviceName string) Option { return func(t *Trace) { t.serviceName = serviceName } } // WithEnv optional environment value -func WithEnv(env string) OptionFunc { +func WithEnv(env string) Option { return func(t *Trace) { t.env = env } } // New build Trace -func New(endpoint string, options ...OptionFunc) (*Trace, error) { +func New(endpoint string, options ...Option) (*Trace, error) { t := &Trace{} for _, option := range options { option(t) diff --git a/pkg/validator/validator.go b/pkg/validator/validator.go index 5fb41552..909c31ec 100644 --- a/pkg/validator/validator.go +++ b/pkg/validator/validator.go @@ -2,6 +2,7 @@ package validator import ( "errors" + "unicode" "github.com/nyaruka/phonenumbers" ) @@ -12,6 +13,9 @@ var ( // ErrInvalidPhoneNumber invalid phone number ErrInvalidPhoneNumber = errors.New("phone number format is invalid") + + // ErrPasswordComplexityTooLow password complexity too low + ErrPasswordComplexityTooLow = errors.New("password complexity too low") ) // IsPhoneNumber check whether it is a phone number @@ -34,3 +38,39 @@ func IsPhoneNumber(value any) error { return nil } + +// PasswordComplexity validate password complexity +func PasswordComplexity(value any) error { + password, ok := value.(string) + if !ok { + return ErrAssertTypeToStringFailed + } + + var ( + existNumber bool + existUpper bool + existLower bool + existSymbol bool + ) + + for _, v := range password { + if unicode.IsNumber(v) && !existNumber { + existNumber = true + } + if unicode.IsUpper(v) && !existUpper { + existUpper = true + } + if unicode.IsLower(v) && !existLower { + existLower = true + } + if unicode.IsPunct(v) && !existSymbol { + existSymbol = true + } + } + + if !existNumber || !existUpper || !existLower || !existSymbol { + return ErrPasswordComplexityTooLow + } + + return nil +}