diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a56a16 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +go.sum +account/ +gen_result/ +etc/service.yaml +client/ \ No newline at end of file diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..5518484 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,140 @@ +run: + timeout: 3m + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + # Include test files or not. + # Default: true + tests: false + +# Reference URL: https://golangci-lint.run/usage/linters/ +linters: + # Disable everything by default so upgrades to not include new - default + # enabled- linters. + disable-all: true + # Specifically enable linters we want to use. + enable: + # - depguard + - errcheck + # - godot + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - misspell + - revive + # - staticcheck + - typecheck + - unused + # - wsl + - asasalint + - asciicheck + - bidichk + - bodyclose + # - containedctx + - contextcheck + # - cyclop + # - varnamelen + # - gci + - wastedassign + - whitespace + # - wrapcheck + - thelper + - tparallel + - unconvert + - unparam + - usestdlibvars + - tenv + - testableexamples + - stylecheck + - sqlclosecheck + - nosprintfhostport + - paralleltest + - prealloc + - predeclared + - promlinter + - reassign + - rowserrcheck + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - decorder + - dogsled + # - dupl + - dupword + - durationcheck + - errchkjson + - errname + - errorlint + # - execinquery + - exhaustive + - exportloopref + - forbidigo + - forcetypeassert + # - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + # - godox + # - goerr113 + # - gofumpt + - goheader + - gomoddirectives + # - gomodguard always failed + - goprintffuncname + - gosec + - grouper + - importas + - interfacebloat + # - ireturn + - lll + - loggercheck + - maintidx + - makezero + +issues: + exclude-rules: + - path: _test\.go + linters: + - funlen + - goconst + - interfacer + - dupl + - lll + - goerr113 + - errcheck + - gocritic + - cyclop + - wrapcheck + - gocognit + - contextcheck + +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 40 + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 10 + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 200 + # Tab width in spaces. + # Default: 1 + tab-width: 1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bb182f6 --- /dev/null +++ b/Makefile @@ -0,0 +1,81 @@ +# go-zero 生成風格 +GO_ZERO_STYLE=go_zero + +GO ?= go +GOFMT ?= gofmt "-s" +GOFILES := $(shell find . -name "*.go") +LDFLAGS := -s -w +VERSION="v1.0.3" +DOCKER_REPO="igs170911/notification" + +.PHONY: test +test: # 進行測試 + go test -v --cover ./... + +.PHONY: fmt +fmt: # 格式優化 + $(GOFMT) -w $(GOFILES) + goimports -w ./ + +.PHONY: gen-rpc +gen-rpc: # 建立 rpc code + goctl rpc protoc ./generate/protobuf/service.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. + go mod tidy + @echo "Generate core-api files successfully" + +.PHONY: gen-clean +gen-clean: # 建立 rpc code + rm -rf ./client + rm -rf ./etc + rm -rf ./gen_result + rm -rf ./internal + rm -rf go.mod + rm -rf go.sum + rm -rf service.go + @echo "Generate core-api files successfully" + +.PHONY: run-docker +run-docker: # 建立 rpc code + docker run --platform=linux/arm64/v8 -p 8080:8080 $(DOCKER_REPO):$(VERSION) + +.PHONY: build-docker +build-docker: + cp ./build/Dockerfile Dockerfile + docker buildx build -t $(DOCKER_REPO):$(VERSION) --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/ed_25519)" . + rm -rf Dockerfile + @echo "Generate core-api files successfully" + +.PHONY: gen-my-sql-model +gen-my-sql-model: # 建立 rpc 資料庫 + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020012_account_uid_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020013_user_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230719061241_machine_node.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + @echo "Generate mysql model files successfully" + +gen-mongo-model: # 建立 rpc 資料庫 + # 只產生 Model 剩下的要自己撰寫,連欄位名稱也是 + goctl model mongo -t AutoId --dir ./internal/model/mongo --style $(GO_ZERO_STYLE) + @echo "Generate mongo model files successfully" + +#goctl model mysql ddl -s ./generate/database/mysql/20240819090248_create_role_permission_table.up.sql --style go_zero -d ./internal/model -i '' (沒cache) +#goctl model mysql ddl -c no -s ./generate/database/mysql/20240816014305_create_permission_table.up.sql --style go_zero -d ./internal/model -i '' (有cache) + +.PHONY: mock-gen +mock-gen: # 建立 mock 資料 + mockgen -source=./internal/domain/usecase/uid_generate.go -destination=./internal/mock/usecase/uid_generate.go -package=mock + mockgen -source=./internal/model/account_model_gen.go -destination=./internal/mock/model/account_model_gen.go -package=mock + mockgen -source=./internal/model/account_model.go -destination=./internal/mock/model/account_model.go -package=mock + mockgen -source=./internal/model/account_to_uid_model_gen.go -destination=./internal/mock/model/account_to_uid_model_gen.go -package=mock + mockgen -source=./internal/model/account_to_uid_model.go -destination=./internal/mock/model/account_to_uidmodel.go -package=mock + mockgen -source=./internal/model/machine_node_model_gen.go -destination=./internal/mock/model/machine_node_model_gen.go -package=mock + mockgen -source=./internal/model/machine_node_model.go -destination=./internal/mock/model/machine_node_model.go -package=mock + mockgen -source=./internal/model/user_table_model_gen.go -destination=./internal/mock/model/user_table_model_gen.go -package=mock + mockgen -source=./internal/model/user_table_model.go -destination=./internal/mock/model/user_table_model.go -package=mock + mockgen -source=./internal/model/mongo/auto_id_model_gen.go -destination=./internal/mock/model/auto_id_model_gen.go -package=mock + mockgen -source=./internal/model/mongo/auto_id_model.go -destination=./internal/mock/model/auto_id_model.go -package=mock + @echo "Generate mock files successfully" + +.PHONY: migrate-database +migrate-database: + migrate -source file://generate/database/mysql -database 'mysql://root:yytt@tcp(127.0.0.1:3306)/digimon_member' up diff --git a/etc/service.example.yaml b/etc/service.example.yaml new file mode 100644 index 0000000..f144f35 --- /dev/null +++ b/etc/service.example.yaml @@ -0,0 +1,37 @@ +Name: member.rpc +ListenOn: 0.0.0.0:8080 +Etcd: + Hosts: + - 127.0.0.1:2379 + Key: member.rpc +DB: + DsnString: root:yytt@tcp(127.0.0.1:3306)/ark_member?charset=utf8mb4&parseTime=true&loc=Asia%2FTaipei +Cache: + - Host: 127.0.0.1:7001 + type: cluster + - Host: 127.0.0.1:7002 + type: cluster + - Host: 127.0.0.1:7003 + type: cluster + - Host: 127.0.0.1:7004 + type: cluster + - Host: 127.0.0.1:7005 + type: cluster + - Host: 127.0.0.1:7006 + type: cluster + +Bcrypt: + Cost: 10 + +RedisCluster: + Host: 127.0.0.1:7001 + Type: cluster + +Mongo: + Schema: mongodb + Host: 127.0.0.1 + User: "" + Password: "" + Port: "27017" + Database: digimon_member + Collection: count diff --git a/generate/database/mongo/20240422112701_audo_id.up.js b/generate/database/mongo/20240422112701_audo_id.up.js new file mode 100644 index 0000000..86e2f63 --- /dev/null +++ b/generate/database/mongo/20240422112701_audo_id.up.js @@ -0,0 +1,2 @@ +use digimon_member; +db.getCollection("count").createIndex({ "name": 1 }); diff --git a/generate/database/mysql/20230529020011_account_table.down.sql b/generate/database/mysql/20230529020011_account_table.down.sql new file mode 100644 index 0000000..e807a6d --- /dev/null +++ b/generate/database/mysql/20230529020011_account_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `account`; diff --git a/generate/database/mysql/20230529020011_account_table.up.sql b/generate/database/mysql/20230529020011_account_table.up.sql new file mode 100644 index 0000000..d113a59 --- /dev/null +++ b/generate/database/mysql/20230529020011_account_table.up.sql @@ -0,0 +1,10 @@ +CREATE TABLE `account` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `account` VARCHAR(50) NOT NULL, + `token` VARCHAR(255) NOT NULL, + `platform` INT NOT NULL COMMENT '平台類型 1. ark 2. google', + `create_time` BIGINT NOT NULL DEFAULT 0, + `update_time` BIGINT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE INDEX `uk_account` (`account` ASC) +)ENGINE=InnoDB COMMENT='帳號'; diff --git a/generate/database/mysql/20230529020012_account_uid_table.down.sql b/generate/database/mysql/20230529020012_account_uid_table.down.sql new file mode 100644 index 0000000..dd19471 --- /dev/null +++ b/generate/database/mysql/20230529020012_account_uid_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `account_to_uid`; diff --git a/generate/database/mysql/20230529020012_account_uid_table.up.sql b/generate/database/mysql/20230529020012_account_uid_table.up.sql new file mode 100644 index 0000000..3d7b5e6 --- /dev/null +++ b/generate/database/mysql/20230529020012_account_uid_table.up.sql @@ -0,0 +1,9 @@ +CREATE TABLE `account_to_uid` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `account` VARCHAR(50) NOT NULL, + `uid` VARCHAR(255) NOT NULL, + `type` tinyint DEFAULT 0 NOT NULL COMMENT '1 手機 2 信箱 3 自定義帳號', + PRIMARY KEY (`id`), + UNIQUE INDEX `uk_account` (`account` ASC), + INDEX `idx_uid` (`uid` ASC) +)ENGINE=InnoDB COMMENT='帳號轉換表'; diff --git a/generate/database/mysql/20230529020013_user_table.down.sql b/generate/database/mysql/20230529020013_user_table.down.sql new file mode 100644 index 0000000..45aaa85 --- /dev/null +++ b/generate/database/mysql/20230529020013_user_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `user_table`; diff --git a/generate/database/mysql/20230529020013_user_table.up.sql b/generate/database/mysql/20230529020013_user_table.up.sql new file mode 100644 index 0000000..0db127c --- /dev/null +++ b/generate/database/mysql/20230529020013_user_table.up.sql @@ -0,0 +1,17 @@ +CREATE TABLE `user_table` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `verify_type` tinyint DEFAULT 0 NOT NULL COMMENT '驗證類型 0. 異常 1.信箱 2.手機 3. GA 4.不驗證', + `alarm_type` tinyint DEFAULT 0 NOT NULL COMMENT '告警狀態 0. 異常 1. 正常(未告警) 2.系統告警中', + `status` tinyint DEFAULT 0 NOT NULL COMMENT '會員狀態 0. 異常 1. 尚未驗證 2. 啟用 3. 停權中 4. 信箱以驗證 5. 手機以驗證 6. GA 以驗證', + `uid` VARCHAR(255) NOT NULL COMMENT '唯一辨識碼', + `nick_name` VARCHAR(255) DEFAULT '' COMMENT '暱稱', + `language` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '使用語言', + `currency` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '使用幣別', + `avatar` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '會員頭像', + `create_time` BIGINT NOT NULL DEFAULT 0, + `update_time` BIGINT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + INDEX `idx_create_time` (`create_time` ASC), + INDEX `idx_nick_name` (`nick_name` ASC), + UNIQUE INDEX `uk_uid` (`uid` ASC) +)ENGINE=InnoDB COMMENT='使用者資訊'; diff --git a/generate/database/mysql/20230719061241_machine_node.down.sql b/generate/database/mysql/20230719061241_machine_node.down.sql new file mode 100644 index 0000000..b299591 --- /dev/null +++ b/generate/database/mysql/20230719061241_machine_node.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `machine_node`; \ No newline at end of file diff --git a/generate/database/mysql/20230719061241_machine_node.up.sql b/generate/database/mysql/20230719061241_machine_node.up.sql new file mode 100644 index 0000000..855ccd8 --- /dev/null +++ b/generate/database/mysql/20230719061241_machine_node.up.sql @@ -0,0 +1,7 @@ +CREATE TABLE `machine_node` ( + `id` bigint AUTO_INCREMENT NOT NULL COMMENT '流水號', + `create_time` bigint DEFAULT 0 NOT NULL COMMENT '創建時間', + `update_time` bigint DEFAULT 0 NOT NULL COMMENT '更新時間', + `host_name` varchar(200) DEFAULT '' NOT NULL COMMENT 'host name', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='machineID Assigner for Generator'; diff --git a/generate/database/mysql/create/20230529020000_create_schema.down.sql b/generate/database/mysql/create/20230529020000_create_schema.down.sql new file mode 100644 index 0000000..7bcbe27 --- /dev/null +++ b/generate/database/mysql/create/20230529020000_create_schema.down.sql @@ -0,0 +1 @@ +DROP DATABASE IF EXISTS `digimon_member`; \ No newline at end of file diff --git a/generate/database/mysql/create/20230529020000_create_schema.up.sql b/generate/database/mysql/create/20230529020000_create_schema.up.sql new file mode 100644 index 0000000..1b00479 --- /dev/null +++ b/generate/database/mysql/create/20230529020000_create_schema.up.sql @@ -0,0 +1 @@ +CREATE DATABASE IF NOT EXISTS `digimon_member`; \ No newline at end of file diff --git a/generate/database/readme.md b/generate/database/readme.md new file mode 100644 index 0000000..4db6e02 --- /dev/null +++ b/generate/database/readme.md @@ -0,0 +1,39 @@ +# migrate +數據庫遷移工具 + +[golang-migrate](https://github.com/golang-migrate/migrate) + +## 安裝 make +```shell +brew install Makefile +``` + +## 安裝 golang-migrate +```shell +brew install golang-migrate +``` + +## 執行刪除 mysql schema + +```shell +migrate -source file://database/migrations/mysql -database 'mysql://account:password@tcp(127.0.0.1:3306)/esc_c2c' down +``` + +## 執行安裝 mysql schema + +```shell +migrate -source file://database/migrations/mysql -database 'mysql://account:password@tcp(127.0.0.1:3306)/esc_c2c' up +``` + +## 執行刪除 mongo schema + +```shell +migrate -source file://database/migrations/mongodb -database 'mongodb://127.0.0.1:27017/esc_c2c' down +``` + +## 執行安裝 mongo schema + +```shell +migrate -source file://database/migrations/mongodb -database 'mongodb://127.0.0.1:27017/esc_c2c' up +``` + diff --git a/generate/protobuf/service.proto b/generate/protobuf/service.proto new file mode 100644 index 0000000..19bcffe --- /dev/null +++ b/generate/protobuf/service.proto @@ -0,0 +1,196 @@ +syntax = "proto3"; + +package member; +option go_package="./member"; + +// OKResp +message OKResp {} +// NoneReq +message NoneReq {} + +// ================ enum ================ +enum VerifyType { + VERIFY_NONE = 0; // 初始(異常) + VERIFY_EMAIL = 1; + VERIFY_PHONE = 2; + VERIFY_GOOGLE = 3; // google 驗證器 + VERIFY_NOT = 4; // 尚未 +} + +enum AlarmType { + ALARM_NONE = 0; // 初始(異常) + ALARM_NOT = 1; // 未告警 + ALARM_SYSTEM = 2; // 系統告警中 +} + +enum MemberStatus { + STATUS_NONE = 0; // 初始(異常) + STATUS_VERIFY = 1; // 尚未驗證 + STATUS_COMPLETE = 2; // 帳號啟用中 + STATUS_DISABLE = 3; // 帳號停權中 + STATUS_EMAIL = 4; // 信箱以驗證 + STATUS_PHONE = 5; // 手機以驗證 + STATUS_GA = 6; // GA 已綁定 +} + +// ================ enum ================ + + +// ================ common ================ +message Pager { + int64 total =1; + int64 size=2; + int64 index=3; +} +// ================ common ================ + + +// ================ account ================ +message CreateLoginUserReq { + string login_id = 1; + int64 platform = 2; + string token = 3; +} + +message BindingUserReq { + string uid = 1; + string login_id = 2; + int64 type = 3; +} + +message BindingUserResp { + string uid = 1; + string login_id = 2; + int64 type = 3; +} + +message CreateUserInfoReq { + string uid = 1; + VerifyType verify_type = 2; + AlarmType alarm_type = 3; + MemberStatus status = 4; + string language = 5; + string currency = 6; + optional string avatar= 7; + optional string nick_name = 8; +} + +message GetAccountInfoResp { + CreateLoginUserReq data = 1; +} + +// UpdateUserInfoReq 不處理邏輯給不給改,這裡只關新增修改刪除 +message UpdateUserInfoReq { + string uid = 1; + optional string language = 2; + optional string currency = 3; + optional string nick_name = 4; + optional string avatar = 5; + optional VerifyType verify_type = 6; + optional AlarmType alarm_type = 7; + optional MemberStatus status = 8; +} + +message GetUIDByAccountReq { + string account = 1; +} + +message GetUidByAccountResp { + string uid = 1; + string account =2; +} + +message UpdateTokenReq { + string account = 1; + string token = 2; + int64 platform=3; +} + +message GenerateRefreshCodeReq { + string account = 1; + int32 code_type =2; +} + +message VerifyCode { + string verify_code = 1; +} + +message GenerateRefreshCodeResp { + VerifyCode data = 1; +} + +message VerifyRefreshCodeReq { + string account = 1; + int32 code_type =2; + string verify_code = 3; +} + +message UpdateStatusReq { + string uid = 1; + MemberStatus status = 2; +} + +message GetUserInfoReq { + string uid = 1; + optional string nick_name =2; +} + +message UserInfo { + string uid = 1; + VerifyType verify_type = 2; + AlarmType alarm_type = 3; + MemberStatus status = 4; + string language = 5; + string currency = 6; + string avatar = 7; + optional string nick_name = 8; +} + +message GetUserInfoResp { + UserInfo data = 1; +} + +message ListUserInfoReq { + optional VerifyType verify_type = 1; + optional AlarmType alarm_type = 2; + optional MemberStatus status = 3; + optional int64 create_start_time = 4; + optional int64 create_end_time = 5; + int64 page_size =6; + int64 page_index=7; +} + +message ListUserInfoResp { + repeated UserInfo data = 1; + Pager page =2; +} + + +service Account { + // CreateUserAccount 建立帳號與密碼 -> 可登入,但可不可以做其他事情看業務流程,也可以只註冊就好 + rpc CreateUserAccount(CreateLoginUserReq) returns(OKResp); + // GetUserAccountInfo 取得帳號密碼資料 + rpc GetUserAccountInfo(GetUIDByAccountReq) returns(GetAccountInfoResp); + // UpdateUserToken 更新密碼 + rpc UpdateUserToken(UpdateTokenReq) returns(OKResp); + // GetUidByAccount 用帳號換取 UID + rpc GetUidByAccount(GetUIDByAccountReq) returns(GetUidByAccountResp); + // BindAccount 綁定帳號 -> account bind to UID + rpc BindAccount(BindingUserReq) returns(BindingUserResp); + // BindUserInfo 初次,綁定 User Info + rpc BindUserInfo(CreateUserInfoReq) returns(OKResp); + // UpdateUserInfo 更新 User Info + rpc UpdateUserInfo(UpdateUserInfoReq) returns(OKResp); + // UpdateStatus 修改狀態 + rpc UpdateStatus(UpdateStatusReq) returns(OKResp); + // GetUserInfo 取得會員資訊 + rpc GetUserInfo(GetUserInfoReq) returns(GetUserInfoResp); + // ListMember 取得會員列表 + rpc ListMember(ListUserInfoReq) returns(ListUserInfoResp); + // GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的 + rpc GenerateRefreshCode(GenerateRefreshCodeReq) returns(GenerateRefreshCodeResp); + // VerifyRefreshCode 驗證忘記密碼 token + rpc VerifyRefreshCode(VerifyRefreshCodeReq) returns(OKResp); + +} +// ================ account ================ \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fdce8a4 --- /dev/null +++ b/go.mod @@ -0,0 +1,115 @@ +module app-cloudep-member-server + +go 1.22.3 + +require ( + code.30cm.net/digimon/library-go/errors v1.0.1 + code.30cm.net/digimon/library-go/validator v1.0.0 + github.com/alicebob/miniredis/v2 v2.33.0 + github.com/bwmarrin/snowflake v0.3.0 + github.com/go-sql-driver/mysql v1.8.1 + github.com/stretchr/testify v1.9.0 + github.com/zeromicro/go-zero v1.7.0 + go.mongodb.org/mongo-driver v1.16.0 + go.uber.org/goleak v1.3.0 + go.uber.org/mock v0.4.0 + golang.org/x/crypto v0.25.0 + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.34.2 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.8 // indirect + github.com/leodido/go-urn v1.4.0 // 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.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/redis/go-redis/v9 v9.6.1 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect + go.etcd.io/etcd/api/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/v3 v3.5.15 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/automaxprocs v1.5.3 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.29.3 // indirect + k8s.io/apimachinery v0.29.4 // indirect + k8s.io/client-go v0.29.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100755 index 0000000..696a3f7 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,33 @@ +package config + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/zrpc" +) + +type Config struct { + zrpc.RpcServerConf + // 加上 DB 結構體 + DB struct { + DsnString string + } + // 快取 + Cache cache.CacheConf + // 密碼加密層數 + Bcrypt struct { + Cost int + } + // Redis Cluster + RedisCluster redis.RedisConf + + Mongo struct { + Schema string + User string + Password string + Host string + Port string + Database string + Collection string + } +} diff --git a/internal/domain/const.go b/internal/domain/const.go new file mode 100644 index 0000000..b5e1c29 --- /dev/null +++ b/internal/domain/const.go @@ -0,0 +1,30 @@ +package domain + +const ( + DefaultPageSize = 100 + DefaultPageIndex = 1 + Scope = 10 +) + +const InitAutoId = 10000000 +const DefaultReferralCodeLen = 8 + +var ConvertTable = [...]string{ + "O", "D", "W", "X", "Y", + "G", "B", "C", "H", "E", + "F", "A", "Q", "I", "J", + "L", "M", "N", "Z", "K", + "P", "V", "R", "S", "T", +} + +type AccountType int8 + +func (a AccountType) ToInt64() int64 { + return int64(a) +} + +const ( + AccountTypePhone AccountType = 1 + AccountTypeMail AccountType = 2 + AccountTypeAccount AccountType = 3 +) diff --git a/internal/domain/usecase/errors.go b/internal/domain/usecase/errors.go new file mode 100644 index 0000000..0455dfa --- /dev/null +++ b/internal/domain/usecase/errors.go @@ -0,0 +1,21 @@ +package usecase + +import ( + ers "code.30cm.net/digimon/library-go/errors" + "code.30cm.net/digimon/library-go/errors/code" +) + +// 12 represents Scope +// 100 represents Category +// 9 represents Detail error code +// full code 12009 只會有 系統以及錯誤碼,category 是給系統判定用的 +// 目前 Scope 以及分類要系統共用,係向的錯誤各自服務實作就好 + +const ( + UIDOutOfRangeErrorCode = iota + 1 +) + +// UIDOutOfRangeErrorCodeError 20001 Token 簽名錯誤 +func UIDOutOfRangeErrorCodeError(msg string) *ers.LibError { + return ers.NewErr(code.CloudEPMember, code.CatInput, UIDOutOfRangeErrorCode, msg) +} diff --git a/internal/domain/usecase/uid_generate.go b/internal/domain/usecase/uid_generate.go new file mode 100644 index 0000000..3f9bbb8 --- /dev/null +++ b/internal/domain/usecase/uid_generate.go @@ -0,0 +1,7 @@ +package usecase + +import "context" + +type UIDGenerateUseCase interface { + Generate(ctx context.Context) (string, error) +} diff --git a/internal/lib/middleware/with_context.go b/internal/lib/middleware/with_context.go new file mode 100644 index 0000000..ba39f1a --- /dev/null +++ b/internal/lib/middleware/with_context.go @@ -0,0 +1,28 @@ +package middleware + +import ( + "context" + "errors" + "time" + + ers "code.30cm.net/digimon/library-go/errors" + "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc" +) + +const defaultTimeout = 30 * time.Second + +func TimeoutMiddleware(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + + newCtx, cancelCtx := context.WithTimeout(ctx, defaultTimeout) + defer func() { + cancelCtx() + + if errors.Is(newCtx.Err(), context.DeadlineExceeded) { + err = ers.SystemTimeoutError(info.FullMethod) + logx.Errorf("Method: %s, request %v, timeout: %d", info.FullMethod, req, defaultTimeout) + } + }() + + return handler(ctx, req) +} diff --git a/internal/lib/snackflow/error.go b/internal/lib/snackflow/error.go new file mode 100644 index 0000000..45327f2 --- /dev/null +++ b/internal/lib/snackflow/error.go @@ -0,0 +1,18 @@ +package snowflake + +import ( + "fmt" + "time" +) + +type NewNodeError struct { + machineNodeID int64 + startTime time.Time + + Err error +} + +func (e *NewNodeError) Error() string { + return fmt.Sprintf("new node fail machineNodeID: %d, startTime: %s, err: %v", + e.machineNodeID, e.startTime, e.Err) +} diff --git a/internal/lib/snackflow/error_test.go b/internal/lib/snackflow/error_test.go new file mode 100644 index 0000000..48c64b4 --- /dev/null +++ b/internal/lib/snackflow/error_test.go @@ -0,0 +1,54 @@ +package snowflake + +import ( + "fmt" + "testing" + "time" +) + +func TestNewNodeError_Error(t *testing.T) { + startTime, err := time.Parse(time.DateOnly, "2023-07-20") + if err != nil { + t.Error(err) + } + + t.Parallel() + + type fields struct { + machineNodeID int64 + startTime time.Time + Err error + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "success", + fields: fields{ + machineNodeID: 1, + startTime: startTime, + Err: nil, + }, + want: fmt.Sprintf("new node fail machineNodeID: %d, startTime: %s, err: %v", + 1, "2023-07-20 00:00:00 +0000 UTC", nil), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + e := &NewNodeError{ + machineNodeID: tt.fields.machineNodeID, + startTime: tt.fields.startTime, + Err: tt.fields.Err, + } + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/lib/snackflow/readme.md b/internal/lib/snackflow/readme.md new file mode 100644 index 0000000..bdf2d8d --- /dev/null +++ b/internal/lib/snackflow/readme.md @@ -0,0 +1,8 @@ +### +# snowflake + +```go +import "yt.com/backend/common.git/snowflake" +``` + +### 量級超過1024 再來做解決 \ No newline at end of file diff --git a/internal/lib/snackflow/snowflake.go b/internal/lib/snackflow/snowflake.go new file mode 100644 index 0000000..09f3fb6 --- /dev/null +++ b/internal/lib/snackflow/snowflake.go @@ -0,0 +1,81 @@ +package snowflake + +import ( + "fmt" + "sync" + "time" + + "github.com/bwmarrin/snowflake" +) + +var mu sync.Mutex + +// Snowflake provides a way to NewNode for Generate UID. +type Snowflake struct { + machineNodeID int64 + + startTime time.Time +} + +// Option is the options type to configure Snowflake. +type Option func(*Snowflake) + +// New returns a new Snowflake instance with the provided options. +func New(opts ...Option) *Snowflake { + s := &Snowflake{ + // default machine 1 + machineNodeID: 1, + } + + for _, opt := range opts { + opt(s) + } + + return s +} + +// WithMachineNodeID adds machineID total 10bit = 1024 machine number. +func WithMachineNodeID(machineNodeID int64) Option { + return func(snowflake *Snowflake) { + snowflake.machineNodeID = machineNodeID + } +} + +// WithStartTime adds snowflake start timestamp in milliseconds. +func WithStartTime(startTime time.Time) Option { + return func(snowflake *Snowflake) { + snowflake.startTime = startTime + } +} + +// GetNowDate return nowTodayDate e.g. 2023-07-20 00:00:00 +0000 UTC. +func GetNowDate() (time.Time, error) { + startTime := time.Now().UTC().Format(time.DateOnly) + + st, err := time.Parse(time.DateOnly, startTime) + if err != nil { + return time.Time{}, fmt.Errorf("time.Parse failed :%w", err) + } + + return st, nil +} + +// NewNode return snowflake node use Generate UID. +func (s *Snowflake) NewNode() (*snowflake.Node, error) { + mu.Lock() + defer mu.Unlock() + + snowflake.Epoch = s.startTime.UnixMilli() + + node, err := snowflake.NewNode(s.machineNodeID) + if err != nil { + return nil, fmt.Errorf("snowflake.NewNode, failed :%w", + &NewNodeError{ + machineNodeID: s.machineNodeID, + startTime: s.startTime, + Err: err, + }) + } + + return node, nil +} diff --git a/internal/lib/snackflow/snowflake_test.go b/internal/lib/snackflow/snowflake_test.go new file mode 100644 index 0000000..2b477af --- /dev/null +++ b/internal/lib/snackflow/snowflake_test.go @@ -0,0 +1,148 @@ +package snowflake + +import ( + "flag" + "os" + "reflect" + "testing" + "time" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + leak := flag.Bool("leak", false, "use leak detector") + flag.Parse() + + if *leak { + goleak.VerifyTestMain(m) + + return + } + + os.Exit(m.Run()) +} + +func TestSnowflake(t *testing.T) { + st, err := GetNowDate() + if err != nil { + t.Error(err) + } + + t.Parallel() + + type args struct { + machineNodeID int64 + startTime time.Time + } + tests := []struct { + name string + args args + want *Snowflake + + wantDeepEqualErr bool + wantNewNodeErr bool + }{ + { + name: "success", + args: args{ + machineNodeID: 10, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 10, + startTime: st, + }, + wantDeepEqualErr: false, + wantNewNodeErr: false, + }, + { + name: "failed machine node ID negative number", + args: args{ + machineNodeID: -1, + startTime: time.Time{}, + }, + want: &Snowflake{ + machineNodeID: -1, + startTime: time.Time{}, + }, + wantDeepEqualErr: false, + wantNewNodeErr: true, + }, + { + name: "failed snowflake struct field by machine node ID", + args: args{ + machineNodeID: 10, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 2, + startTime: st, + }, + wantDeepEqualErr: true, + wantNewNodeErr: false, + }, + { + name: "failed snowflake struct field by startTime", + args: args{ + machineNodeID: 2, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 2, + startTime: time.Time{}, + }, + wantDeepEqualErr: true, + wantNewNodeErr: false, + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got := New( + WithMachineNodeID(tt.args.machineNodeID), + WithStartTime(tt.args.startTime), + ) + + if !reflect.DeepEqual(got, tt.want) != tt.wantDeepEqualErr { + t.Errorf("Snowflake.New() = %v, want %v", got, tt.want) + } + + node, err := got.NewNode() + if (err != nil) != tt.wantNewNodeErr { + t.Errorf("NewNode() = %v, want %v", err != nil, tt.wantNewNodeErr) + } + + if err == nil { + id := node.Generate().Int64() + if id <= 0 { + t.Errorf("node.Generate().Int64() = %v, want %s", id, "id > 0") + } + } + }) + } +} + +func BenchmarkSnowflake(b *testing.B) { + st, err := GetNowDate() + if err != nil { + b.Error(err) + } + + snowflake := New( + WithMachineNodeID(1), + WithStartTime(st), + ) + + node, err := snowflake.NewNode() + if err != nil { + b.Error(err) + } + + for i := 0; i < b.N; i++ { + node.Generate().Int64() + } +} diff --git a/internal/mock/lib/validate.go b/internal/mock/lib/validate.go new file mode 100644 index 0000000..dd852f8 --- /dev/null +++ b/internal/mock/lib/validate.go @@ -0,0 +1,73 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./validate.go +// +// Generated by this command: +// +// mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib +// + +// Package lib is a generated GoMock package. +package lib + +import ( + reflect "reflect" + + required "code.30cm.net/digimon/library-go/validator" + + gomock "go.uber.org/mock/gomock" +) + +// MockValidate is a mock of Validate interface. +type MockValidate struct { + ctrl *gomock.Controller + recorder *MockValidateMockRecorder +} + +// MockValidateMockRecorder is the mock recorder for MockValidate. +type MockValidateMockRecorder struct { + mock *MockValidate +} + +// NewMockValidate creates a new mock instance. +func NewMockValidate(ctrl *gomock.Controller) *MockValidate { + mock := &MockValidate{ctrl: ctrl} + mock.recorder = &MockValidateMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockValidate) EXPECT() *MockValidateMockRecorder { + return m.recorder +} + +// BindToValidator mocks base method. +func (m *MockValidate) BindToValidator(opts ...required.Option) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BindToValidator", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindToValidator indicates an expected call of BindToValidator. +func (mr *MockValidateMockRecorder) BindToValidator(opts ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindToValidator", reflect.TypeOf((*MockValidate)(nil).BindToValidator), opts...) +} + +// ValidateAll mocks base method. +func (m *MockValidate) ValidateAll(obj any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateAll", obj) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateAll indicates an expected call of ValidateAll. +func (mr *MockValidateMockRecorder) ValidateAll(obj any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAll", reflect.TypeOf((*MockValidate)(nil).ValidateAll), obj) +} diff --git a/internal/mock/model/account_model.go b/internal/mock/model/account_model.go new file mode 100644 index 0000000..b2a650b --- /dev/null +++ b/internal/mock/model/account_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_model.go -destination=./internal/mock/model/account_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountModel is a mock of AccountModel interface. +type MockAccountModel struct { + ctrl *gomock.Controller + recorder *MockAccountModelMockRecorder +} + +// MockAccountModelMockRecorder is the mock recorder for MockAccountModel. +type MockAccountModelMockRecorder struct { + mock *MockAccountModel +} + +// NewMockAccountModel creates a new mock instance. +func NewMockAccountModel(ctrl *gomock.Controller) *MockAccountModel { + mock := &MockAccountModel{ctrl: ctrl} + mock.recorder = &MockAccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountModel) EXPECT() *MockAccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_model_gen.go b/internal/mock/model/account_model_gen.go new file mode 100644 index 0000000..2ffb134 --- /dev/null +++ b/internal/mock/model/account_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_model_gen.go -destination=./internal/mock/model/account_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountModel is a mock of accountModel interface. +type MockaccountModel struct { + ctrl *gomock.Controller + recorder *MockaccountModelMockRecorder +} + +// MockaccountModelMockRecorder is the mock recorder for MockaccountModel. +type MockaccountModelMockRecorder struct { + mock *MockaccountModel +} + +// NewMockaccountModel creates a new mock instance. +func NewMockaccountModel(ctrl *gomock.Controller) *MockaccountModel { + mock := &MockaccountModel{ctrl: ctrl} + mock.recorder = &MockaccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountModel) EXPECT() *MockaccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uid_model_gen.go b/internal/mock/model/account_to_uid_model_gen.go new file mode 100644 index 0000000..1ff6123 --- /dev/null +++ b/internal/mock/model/account_to_uid_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_to_uid_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_to_uid_model_gen.go -destination=./internal/mock/model/account_to_uid_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountToUidModel is a mock of accountToUidModel interface. +type MockaccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockaccountToUidModelMockRecorder +} + +// MockaccountToUidModelMockRecorder is the mock recorder for MockaccountToUidModel. +type MockaccountToUidModelMockRecorder struct { + mock *MockaccountToUidModel +} + +// NewMockaccountToUidModel creates a new mock instance. +func NewMockaccountToUidModel(ctrl *gomock.Controller) *MockaccountToUidModel { + mock := &MockaccountToUidModel{ctrl: ctrl} + mock.recorder = &MockaccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountToUidModel) EXPECT() *MockaccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uidmodel.go b/internal/mock/model/account_to_uidmodel.go new file mode 100644 index 0000000..756031f --- /dev/null +++ b/internal/mock/model/account_to_uidmodel.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_to_uid_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_to_uid_model.go -destination=./internal/mock/model/account_to_uidmodel.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountToUidModel is a mock of AccountToUidModel interface. +type MockAccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockAccountToUidModelMockRecorder +} + +// MockAccountToUidModelMockRecorder is the mock recorder for MockAccountToUidModel. +type MockAccountToUidModelMockRecorder struct { + mock *MockAccountToUidModel +} + +// NewMockAccountToUidModel creates a new mock instance. +func NewMockAccountToUidModel(ctrl *gomock.Controller) *MockAccountToUidModel { + mock := &MockAccountToUidModel{ctrl: ctrl} + mock.recorder = &MockAccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountToUidModel) EXPECT() *MockAccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/auto_id_model.go b/internal/mock/model/auto_id_model.go new file mode 100644 index 0000000..f506d0d --- /dev/null +++ b/internal/mock/model/auto_id_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/mongo/auto_id_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/mongo/auto_id_model.go -destination=./internal/mock/model/auto_id_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model/mongo" + context "context" + reflect "reflect" + + mongo "go.mongodb.org/mongo-driver/mongo" + gomock "go.uber.org/mock/gomock" +) + +// MockAutoIdModel is a mock of AutoIdModel interface. +type MockAutoIdModel struct { + ctrl *gomock.Controller + recorder *MockAutoIdModelMockRecorder +} + +// MockAutoIdModelMockRecorder is the mock recorder for MockAutoIdModel. +type MockAutoIdModelMockRecorder struct { + mock *MockAutoIdModel +} + +// NewMockAutoIdModel creates a new mock instance. +func NewMockAutoIdModel(ctrl *gomock.Controller) *MockAutoIdModel { + mock := &MockAutoIdModel{ctrl: ctrl} + mock.recorder = &MockAutoIdModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAutoIdModel) EXPECT() *MockAutoIdModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAutoIdModel) Delete(ctx context.Context, id string) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAutoIdModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAutoIdModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAutoIdModel) FindOne(ctx context.Context, id string) (*model.AutoId, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AutoId) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAutoIdModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAutoIdModel)(nil).FindOne), ctx, id) +} + +// Inc mocks base method. +func (m *MockAutoIdModel) Inc(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Inc", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Inc indicates an expected call of Inc. +func (mr *MockAutoIdModelMockRecorder) Inc(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Inc", reflect.TypeOf((*MockAutoIdModel)(nil).Inc), ctx, data) +} + +// Insert mocks base method. +func (m *MockAutoIdModel) Insert(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAutoIdModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAutoIdModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAutoIdModel) Update(ctx context.Context, data *model.AutoId) (*mongo.UpdateResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(*mongo.UpdateResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockAutoIdModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAutoIdModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/auto_id_model_gen.go b/internal/mock/model/auto_id_model_gen.go new file mode 100644 index 0000000..d329a09 --- /dev/null +++ b/internal/mock/model/auto_id_model_gen.go @@ -0,0 +1,101 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/mongo/auto_id_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/mongo/auto_id_model_gen.go -destination=./internal/mock/model/auto_id_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model/mongo" + context "context" + reflect "reflect" + + mongo "go.mongodb.org/mongo-driver/mongo" + gomock "go.uber.org/mock/gomock" +) + +// MockautoIdModel is a mock of autoIdModel interface. +type MockautoIdModel struct { + ctrl *gomock.Controller + recorder *MockautoIdModelMockRecorder +} + +// MockautoIdModelMockRecorder is the mock recorder for MockautoIdModel. +type MockautoIdModelMockRecorder struct { + mock *MockautoIdModel +} + +// NewMockautoIdModel creates a new mock instance. +func NewMockautoIdModel(ctrl *gomock.Controller) *MockautoIdModel { + mock := &MockautoIdModel{ctrl: ctrl} + mock.recorder = &MockautoIdModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockautoIdModel) EXPECT() *MockautoIdModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockautoIdModel) Delete(ctx context.Context, id string) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Delete indicates an expected call of Delete. +func (mr *MockautoIdModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockautoIdModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockautoIdModel) FindOne(ctx context.Context, id string) (*model.AutoId, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AutoId) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockautoIdModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockautoIdModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockautoIdModel) Insert(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert. +func (mr *MockautoIdModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockautoIdModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockautoIdModel) Update(ctx context.Context, data *model.AutoId) (*mongo.UpdateResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(*mongo.UpdateResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockautoIdModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockautoIdModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model.go b/internal/mock/model/machine_node_model.go new file mode 100644 index 0000000..3dfc332 --- /dev/null +++ b/internal/mock/model/machine_node_model.go @@ -0,0 +1,100 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/machine_node_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/machine_node_model.go -destination=./internal/mock/model/machine_node_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockMachineNodeModel is a mock of MachineNodeModel interface. +type MockMachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockMachineNodeModelMockRecorder +} + +// MockMachineNodeModelMockRecorder is the mock recorder for MockMachineNodeModel. +type MockMachineNodeModelMockRecorder struct { + mock *MockMachineNodeModel +} + +// NewMockMachineNodeModel creates a new mock instance. +func NewMockMachineNodeModel(ctrl *gomock.Controller) *MockMachineNodeModel { + mock := &MockMachineNodeModel{ctrl: ctrl} + mock.recorder = &MockMachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMachineNodeModel) EXPECT() *MockMachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockMachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockMachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockMachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockMachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockMachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockMachineNodeModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockMachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockMachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockMachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockMachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockMachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockMachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model_gen.go b/internal/mock/model/machine_node_model_gen.go new file mode 100644 index 0000000..e8c053d --- /dev/null +++ b/internal/mock/model/machine_node_model_gen.go @@ -0,0 +1,100 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/machine_node_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/machine_node_model_gen.go -destination=./internal/mock/model/machine_node_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockmachineNodeModel is a mock of machineNodeModel interface. +type MockmachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockmachineNodeModelMockRecorder +} + +// MockmachineNodeModelMockRecorder is the mock recorder for MockmachineNodeModel. +type MockmachineNodeModelMockRecorder struct { + mock *MockmachineNodeModel +} + +// NewMockmachineNodeModel creates a new mock instance. +func NewMockmachineNodeModel(ctrl *gomock.Controller) *MockmachineNodeModel { + mock := &MockmachineNodeModel{ctrl: ctrl} + mock.recorder = &MockmachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockmachineNodeModel) EXPECT() *MockmachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockmachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockmachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockmachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockmachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockmachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockmachineNodeModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockmachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockmachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockmachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockmachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockmachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockmachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/user_table_model.go b/internal/mock/model/user_table_model.go new file mode 100644 index 0000000..7370944 --- /dev/null +++ b/internal/mock/model/user_table_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/user_table_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/user_table_model.go -destination=./internal/mock/model/user_table_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockUserTableModel is a mock of UserTableModel interface. +type MockUserTableModel struct { + ctrl *gomock.Controller + recorder *MockUserTableModelMockRecorder +} + +// MockUserTableModelMockRecorder is the mock recorder for MockUserTableModel. +type MockUserTableModelMockRecorder struct { + mock *MockUserTableModel +} + +// NewMockUserTableModel creates a new mock instance. +func NewMockUserTableModel(ctrl *gomock.Controller) *MockUserTableModel { + mock := &MockUserTableModel{ctrl: ctrl} + mock.recorder = &MockUserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUserTableModel) EXPECT() *MockUserTableModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockUserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockUserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockUserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockUserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockUserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockUserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByUid mocks base method. +func (m *MockUserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockUserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockUserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockUserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockUserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUserTableModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockUserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockUserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUserTableModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/user_table_model_gen.go b/internal/mock/model/user_table_model_gen.go new file mode 100644 index 0000000..14cd694 --- /dev/null +++ b/internal/mock/model/user_table_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/user_table_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/user_table_model_gen.go -destination=./internal/mock/model/user_table_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockuserTableModel is a mock of userTableModel interface. +type MockuserTableModel struct { + ctrl *gomock.Controller + recorder *MockuserTableModelMockRecorder +} + +// MockuserTableModelMockRecorder is the mock recorder for MockuserTableModel. +type MockuserTableModelMockRecorder struct { + mock *MockuserTableModel +} + +// NewMockuserTableModel creates a new mock instance. +func NewMockuserTableModel(ctrl *gomock.Controller) *MockuserTableModel { + mock := &MockuserTableModel{ctrl: ctrl} + mock.recorder = &MockuserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockuserTableModel) EXPECT() *MockuserTableModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockuserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockuserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockuserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockuserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockuserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockuserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByUid mocks base method. +func (m *MockuserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockuserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockuserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockuserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockuserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockuserTableModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockuserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockuserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockuserTableModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/usecase/uid_generate.go b/internal/mock/usecase/uid_generate.go new file mode 100644 index 0000000..235d1af --- /dev/null +++ b/internal/mock/usecase/uid_generate.go @@ -0,0 +1,55 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/domain/usecase/uid_generate.go +// +// Generated by this command: +// +// mockgen -source=./internal/domain/usecase/uid_generate.go -destination=./internal/mock/usecase/uid_generate.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockUIDGenerateUseCase is a mock of UIDGenerateUseCase interface. +type MockUIDGenerateUseCase struct { + ctrl *gomock.Controller + recorder *MockUIDGenerateUseCaseMockRecorder +} + +// MockUIDGenerateUseCaseMockRecorder is the mock recorder for MockUIDGenerateUseCase. +type MockUIDGenerateUseCaseMockRecorder struct { + mock *MockUIDGenerateUseCase +} + +// NewMockUIDGenerateUseCase creates a new mock instance. +func NewMockUIDGenerateUseCase(ctrl *gomock.Controller) *MockUIDGenerateUseCase { + mock := &MockUIDGenerateUseCase{ctrl: ctrl} + mock.recorder = &MockUIDGenerateUseCaseMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUIDGenerateUseCase) EXPECT() *MockUIDGenerateUseCaseMockRecorder { + return m.recorder +} + +// Generate mocks base method. +func (m *MockUIDGenerateUseCase) Generate(ctx context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Generate", ctx) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Generate indicates an expected call of Generate. +func (mr *MockUIDGenerateUseCaseMockRecorder) Generate(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockUIDGenerateUseCase)(nil).Generate), ctx) +} diff --git a/internal/model/account_model.go b/internal/model/account_model.go new file mode 100755 index 0000000..2a63d72 --- /dev/null +++ b/internal/model/account_model.go @@ -0,0 +1,47 @@ +package model + +import ( + "context" + "database/sql" + "fmt" + + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ AccountModel = (*customAccountModel)(nil) + +type ( + // AccountModel is an interface to be customized, add more methods here, + // and implement the added methods in customAccountModel. + AccountModel interface { + accountModel + UpdateTokenByLoginID(ctx context.Context, account string, token string) error + } + + customAccountModel struct { + *defaultAccountModel + } +) + +// NewAccountModel returns a model for the database table. +func NewAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AccountModel { + return &customAccountModel{ + defaultAccountModel: newAccountModel(conn, c, opts...), + } +} + +func (m *defaultAccountModel) UpdateTokenByLoginID(ctx context.Context, account string, token string) error { + data, err := m.FindOneByAccount(ctx, account) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `token` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, token, data.Id) + }, accountAccountKey, accountIdKey) + return err +} diff --git a/internal/model/account_model_gen.go b/internal/model/account_model_gen.go new file mode 100755 index 0000000..97c22bf --- /dev/null +++ b/internal/model/account_model_gen.go @@ -0,0 +1,154 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + accountFieldNames = builder.RawFieldNames(&Account{}) + accountRows = strings.Join(accountFieldNames, ",") + accountRowsExpectAutoSet = strings.Join(stringx.Remove(accountFieldNames, "`id`"), ",") + accountRowsWithPlaceHolder = strings.Join(stringx.Remove(accountFieldNames, "`id`"), "=?,") + "=?" + + cacheAccountIdPrefix = "cache:account:id:" + cacheAccountAccountPrefix = "cache:account:account:" +) + +type ( + accountModel interface { + Insert(ctx context.Context, data *Account) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Account, error) + FindOneByAccount(ctx context.Context, account string) (*Account, error) + Update(ctx context.Context, data *Account) error + Delete(ctx context.Context, id int64) error + } + + defaultAccountModel struct { + sqlc.CachedConn + table string + } + + Account struct { + Id int64 `db:"id"` + Account string `db:"account"` + Token string `db:"token"` + Platform int64 `db:"platform"` // 平台類型 1. ark 2. google + CreateTime int64 `db:"create_time"` + UpdateTime int64 `db:"update_time"` + } +) + +func newAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAccountModel { + return &defaultAccountModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`account`", + } +} + +func (m *defaultAccountModel) withSession(session sqlx.Session) *defaultAccountModel { + return &defaultAccountModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`account`", + } +} + +func (m *defaultAccountModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, accountAccountKey, accountIdKey) + return err +} + +func (m *defaultAccountModel) FindOne(ctx context.Context, id int64) (*Account, error) { + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, id) + var resp Account + err := m.QueryRowCtx(ctx, &resp, accountIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountModel) FindOneByAccount(ctx context.Context, account string) (*Account, error) { + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, account) + var resp Account + err := m.QueryRowIndexCtx(ctx, &resp, accountAccountKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `account` = ? limit 1", accountRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, account); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountModel) Insert(ctx context.Context, data *Account) (sql.Result, error) { + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, accountRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.Account, data.Token, data.Platform, data.CreateTime, data.UpdateTime) + }, accountAccountKey, accountIdKey) + return ret, err +} + +func (m *defaultAccountModel) Update(ctx context.Context, newData *Account) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, accountRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.Account, newData.Token, newData.Platform, newData.CreateTime, newData.UpdateTime, newData.Id) + }, accountAccountKey, accountIdKey) + return err +} + +func (m *defaultAccountModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheAccountIdPrefix, primary) +} + +func (m *defaultAccountModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultAccountModel) tableName() string { + return m.table +} diff --git a/internal/model/account_to_uid_model.go b/internal/model/account_to_uid_model.go new file mode 100755 index 0000000..095457e --- /dev/null +++ b/internal/model/account_to_uid_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ AccountToUidModel = (*customAccountToUidModel)(nil) + +type ( + // AccountToUidModel is an interface to be customized, add more methods here, + // and implement the added methods in customAccountToUidModel. + AccountToUidModel interface { + accountToUidModel + } + + customAccountToUidModel struct { + *defaultAccountToUidModel + } +) + +// NewAccountToUidModel returns a model for the database table. +func NewAccountToUidModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AccountToUidModel { + return &customAccountToUidModel{ + defaultAccountToUidModel: newAccountToUidModel(conn, c, opts...), + } +} diff --git a/internal/model/account_to_uid_model_gen.go b/internal/model/account_to_uid_model_gen.go new file mode 100755 index 0000000..75aea24 --- /dev/null +++ b/internal/model/account_to_uid_model_gen.go @@ -0,0 +1,152 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + accountToUidFieldNames = builder.RawFieldNames(&AccountToUid{}) + accountToUidRows = strings.Join(accountToUidFieldNames, ",") + accountToUidRowsExpectAutoSet = strings.Join(stringx.Remove(accountToUidFieldNames, "`id`"), ",") + accountToUidRowsWithPlaceHolder = strings.Join(stringx.Remove(accountToUidFieldNames, "`id`"), "=?,") + "=?" + + cacheAccountToUidIdPrefix = "cache:accountToUid:id:" + cacheAccountToUidAccountPrefix = "cache:accountToUid:account:" +) + +type ( + accountToUidModel interface { + Insert(ctx context.Context, data *AccountToUid) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*AccountToUid, error) + FindOneByAccount(ctx context.Context, account string) (*AccountToUid, error) + Update(ctx context.Context, data *AccountToUid) error + Delete(ctx context.Context, id int64) error + } + + defaultAccountToUidModel struct { + sqlc.CachedConn + table string + } + + AccountToUid struct { + Id int64 `db:"id"` + Account string `db:"account"` + Uid string `db:"uid"` + Type int64 `db:"type"` // 1 手機 2 信箱 3 自定義帳號 + } +) + +func newAccountToUidModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAccountToUidModel { + return &defaultAccountToUidModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`account_to_uid`", + } +} + +func (m *defaultAccountToUidModel) withSession(session sqlx.Session) *defaultAccountToUidModel { + return &defaultAccountToUidModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`account_to_uid`", + } +} + +func (m *defaultAccountToUidModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, accountToUidAccountKey, accountToUidIdKey) + return err +} + +func (m *defaultAccountToUidModel) FindOne(ctx context.Context, id int64) (*AccountToUid, error) { + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, id) + var resp AccountToUid + err := m.QueryRowCtx(ctx, &resp, accountToUidIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountToUidRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*AccountToUid, error) { + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, account) + var resp AccountToUid + err := m.QueryRowIndexCtx(ctx, &resp, accountToUidAccountKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `account` = ? limit 1", accountToUidRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, account); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountToUidModel) Insert(ctx context.Context, data *AccountToUid) (sql.Result, error) { + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, accountToUidRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.Account, data.Uid, data.Type) + }, accountToUidAccountKey, accountToUidIdKey) + return ret, err +} + +func (m *defaultAccountToUidModel) Update(ctx context.Context, newData *AccountToUid) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, accountToUidRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.Account, newData.Uid, newData.Type, newData.Id) + }, accountToUidAccountKey, accountToUidIdKey) + return err +} + +func (m *defaultAccountToUidModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, primary) +} + +func (m *defaultAccountToUidModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountToUidRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultAccountToUidModel) tableName() string { + return m.table +} diff --git a/internal/model/machine_node_model.go b/internal/model/machine_node_model.go new file mode 100755 index 0000000..0bd7cd2 --- /dev/null +++ b/internal/model/machine_node_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ MachineNodeModel = (*customMachineNodeModel)(nil) + +type ( + // MachineNodeModel is an interface to be customized, add more methods here, + // and implement the added methods in customMachineNodeModel. + MachineNodeModel interface { + machineNodeModel + } + + customMachineNodeModel struct { + *defaultMachineNodeModel + } +) + +// NewMachineNodeModel returns a model for the database table. +func NewMachineNodeModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) MachineNodeModel { + return &customMachineNodeModel{ + defaultMachineNodeModel: newMachineNodeModel(conn, c, opts...), + } +} diff --git a/internal/model/machine_node_model_gen.go b/internal/model/machine_node_model_gen.go new file mode 100755 index 0000000..37d29b5 --- /dev/null +++ b/internal/model/machine_node_model_gen.go @@ -0,0 +1,117 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + machineNodeFieldNames = builder.RawFieldNames(&MachineNode{}) + machineNodeRows = strings.Join(machineNodeFieldNames, ",") + machineNodeRowsExpectAutoSet = strings.Join(stringx.Remove(machineNodeFieldNames, "`id`"), ",") + machineNodeRowsWithPlaceHolder = strings.Join(stringx.Remove(machineNodeFieldNames, "`id`"), "=?,") + "=?" + + cacheMachineNodeIdPrefix = "cache:machineNode:id:" +) + +type ( + machineNodeModel interface { + Insert(ctx context.Context, data *MachineNode) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*MachineNode, error) + Update(ctx context.Context, data *MachineNode) error + Delete(ctx context.Context, id int64) error + } + + defaultMachineNodeModel struct { + sqlc.CachedConn + table string + } + + MachineNode struct { + Id int64 `db:"id"` // 流水號 + CreateTime int64 `db:"create_time"` // 創建時間 + UpdateTime int64 `db:"update_time"` // 更新時間 + HostName string `db:"host_name"` // host name + } +) + +func newMachineNodeModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultMachineNodeModel { + return &defaultMachineNodeModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`machine_node`", + } +} + +func (m *defaultMachineNodeModel) withSession(session sqlx.Session) *defaultMachineNodeModel { + return &defaultMachineNodeModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`machine_node`", + } +} + +func (m *defaultMachineNodeModel) Delete(ctx context.Context, id int64) error { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, id) + _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, machineNodeIdKey) + return err +} + +func (m *defaultMachineNodeModel) FindOne(ctx context.Context, id int64) (*MachineNode, error) { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, id) + var resp MachineNode + err := m.QueryRowCtx(ctx, &resp, machineNodeIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", machineNodeRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultMachineNodeModel) Insert(ctx context.Context, data *MachineNode) (sql.Result, error) { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, machineNodeRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.CreateTime, data.UpdateTime, data.HostName) + }, machineNodeIdKey) + return ret, err +} + +func (m *defaultMachineNodeModel) Update(ctx context.Context, data *MachineNode) error { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, data.Id) + _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, machineNodeRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, data.CreateTime, data.UpdateTime, data.HostName, data.Id) + }, machineNodeIdKey) + return err +} + +func (m *defaultMachineNodeModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, primary) +} + +func (m *defaultMachineNodeModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", machineNodeRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultMachineNodeModel) tableName() string { + return m.table +} diff --git a/internal/model/mongo/auto_id_model.go b/internal/model/mongo/auto_id_model.go new file mode 100644 index 0000000..9a60ea3 --- /dev/null +++ b/internal/model/mongo/auto_id_model.go @@ -0,0 +1,50 @@ +package model + +import ( + "context" + "time" + + "github.com/zeromicro/go-zero/core/stores/mon" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" +) + +var _ AutoIdModel = (*customAutoIdModel)(nil) + +type ( + // AutoIdModel is an interface to be customized, add more methods here, + // and implement the added methods in customAutoIdModel. + AutoIdModel interface { + autoIdModel + Inc(ctx context.Context, data *AutoId) error + } + + customAutoIdModel struct { + *defaultAutoIdModel + } +) + +// NewAutoIdModel returns a model for the mongo. +func NewAutoIdModel(url, db, collection string) AutoIdModel { + conn := mon.MustNewModel(url, db, collection) + return &customAutoIdModel{ + defaultAutoIdModel: newDefaultAutoIdModel(conn), + } +} + +func (m *customAutoIdModel) Inc(ctx context.Context, data *AutoId) error { + // 定義查詢的條件 + filter := bson.M{"name": "auto_id"} + + // 定義更新的操作,包括自增和更新時間 + update := bson.M{ + "$inc": bson.M{"counter": 1}, // 自增 counter + "$set": bson.M{"updateAt": time.Now().UTC()}, // 設置 updateAt 為當前時間 + } + // 使用 FindOneAndUpdate 並將結果解碼到 data 中 + err := m.conn.FindOneAndUpdate(ctx, &data, filter, update, + options.FindOneAndUpdate().SetUpsert(true), + options.FindOneAndUpdate().SetReturnDocument(options.After)) + + return err +} diff --git a/internal/model/mongo/auto_id_model_gen.go b/internal/model/mongo/auto_id_model_gen.go new file mode 100644 index 0000000..058a8cc --- /dev/null +++ b/internal/model/mongo/auto_id_model_gen.go @@ -0,0 +1,74 @@ +// Code generated by goctl. DO NOT EDIT. +package model + +import ( + "context" + "time" + + "github.com/zeromicro/go-zero/core/stores/mon" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" +) + +type autoIdModel interface { + Insert(ctx context.Context, data *AutoId) error + FindOne(ctx context.Context, id string) (*AutoId, error) + Update(ctx context.Context, data *AutoId) (*mongo.UpdateResult, error) + Delete(ctx context.Context, id string) (int64, error) +} + +type defaultAutoIdModel struct { + conn *mon.Model +} + +func newDefaultAutoIdModel(conn *mon.Model) *defaultAutoIdModel { + return &defaultAutoIdModel{conn: conn} +} + +func (m *defaultAutoIdModel) Insert(ctx context.Context, data *AutoId) error { + if data.ID.IsZero() { + data.ID = primitive.NewObjectID() + data.CreateAt = time.Now().UTC() + data.UpdateAt = time.Now().UTC() + } + + _, err := m.conn.InsertOne(ctx, data) + return err +} + +func (m *defaultAutoIdModel) FindOne(ctx context.Context, id string) (*AutoId, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return nil, ErrInvalidObjectId + } + + var data AutoId + + err = m.conn.FindOne(ctx, &data, bson.M{"_id": oid}) + switch err { + case nil: + return &data, nil + case mon.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAutoIdModel) Update(ctx context.Context, data *AutoId) (*mongo.UpdateResult, error) { + data.UpdateAt = time.Now().UTC() + + res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data}) + return res, err +} + +func (m *defaultAutoIdModel) Delete(ctx context.Context, id string) (int64, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return 0, ErrInvalidObjectId + } + + res, err := m.conn.DeleteOne(ctx, bson.M{"_id": oid}) + return res, err +} diff --git a/internal/model/mongo/auto_id_types.go b/internal/model/mongo/auto_id_types.go new file mode 100644 index 0000000..34b5467 --- /dev/null +++ b/internal/model/mongo/auto_id_types.go @@ -0,0 +1,15 @@ +package model + +import ( + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" +) + +type AutoId struct { + ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` + Name string `bson:"name,omitempty" json:"name,omitempty"` + Counter uint64 `bson:"counter" json:"counter"` + UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` + CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` +} diff --git a/internal/model/mongo/error.go b/internal/model/mongo/error.go new file mode 100644 index 0000000..27d9244 --- /dev/null +++ b/internal/model/mongo/error.go @@ -0,0 +1,12 @@ +package model + +import ( + "errors" + + "github.com/zeromicro/go-zero/core/stores/mon" +) + +var ( + ErrNotFound = mon.ErrNotFound + ErrInvalidObjectId = errors.New("invalid objectId") +) diff --git a/internal/model/user_table_model.go b/internal/model/user_table_model.go new file mode 100755 index 0000000..2242070 --- /dev/null +++ b/internal/model/user_table_model.go @@ -0,0 +1,212 @@ +package model + +import ( + "app-cloudep-member-server/gen_result/pb/member" + "context" + "database/sql" + "fmt" + "strings" + "time" + + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ UserTableModel = (*customUserTableModel)(nil) + +type ( + // UserTableModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserTableModel. + UserTableModel interface { + userTableModel + FindOneByNickName(ctx context.Context, uid string) (*UserTable, error) + ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) + Count(ctx context.Context) (int64, error) + UpdateStatus(ctx context.Context, uid string, status int32) error + UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error + } + + customUserTableModel struct { + *defaultUserTableModel + } + + UserQueryParams struct { + RoleId *string + VerifyType *int32 + AlarmType *int32 + Status *int32 + CreateStartTime *int64 + CreateEndTime *int64 + PageSize int64 + PageIndex int64 + } +) + +// NewUserTableModel returns a model for the database table. +func NewUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UserTableModel { + return &customUserTableModel{ + defaultUserTableModel: newUserTableModel(conn, c, opts...), + } +} + +func (m *defaultUserTableModel) FindOneByNickName(ctx context.Context, nickName string) (*UserTable, error) { + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, nickName) + var resp UserTable + err := m.QueryRowIndexCtx(ctx, &resp, userTableUidKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `nick_name` = ? limit 1", userTableRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, nickName); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) { + query := fmt.Sprintf("select %s from %s", userTableRows, m.table) + var args = make([]any, 0, 10) + var conditions []string + + if params.RoleId != nil { + conditions = append(conditions, "role_id = ?") + args = append(args, *params.RoleId) + } + + if params.VerifyType != nil { + conditions = append(conditions, "verify_type = ?") + args = append(args, *params.VerifyType) + } + + if params.AlarmType != nil { + conditions = append(conditions, "alarm_type = ?") + args = append(args, *params.AlarmType) + } + + if params.Status != nil { + conditions = append(conditions, "status = ?") + args = append(args, *params.Status) + } + + if params.CreateStartTime != nil { + conditions = append(conditions, "create_time >= ?") + args = append(args, *params.CreateStartTime) + } + + if params.CreateEndTime != nil { + conditions = append(conditions, "create_time <= ?") + args = append(args, *params.CreateEndTime) + } + + // 加入條件到查詢語句中 + if len(conditions) > 0 { + query += " WHERE " + strings.Join(conditions, " AND ") + } + + // 分頁處理 + offset := (params.PageIndex - 1) * params.PageSize + query += " LIMIT ? OFFSET ?" + args = append(args, params.PageSize, offset) + + var users []*UserTable + err := m.QueryRowsNoCacheCtx(ctx, &users, query, args...) + if err != nil { + return nil, err + } + + return users, nil +} + +func (m *defaultUserTableModel) Count(ctx context.Context) (int64, error) { + var count int64 + query := fmt.Sprintf("select count(*) from %s", m.table) + err := m.QueryRowNoCacheCtx(ctx, &count, query) + if err != nil { + return 0, err + } + return count, nil +} + +func (m *defaultUserTableModel) UpdateStatus(ctx context.Context, uid string, status int32) error { + data, err := m.FindOneByUid(ctx, uid) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `status` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, status, data.Id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error { + data, err := m.FindOneByUid(ctx, newData.Uid) + if err != nil { + return err + } + + // 初始化缓存键 + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + + query := fmt.Sprintf("update %s set ", m.table) + var args []interface{} + var updates []string + + if newData.VerifyType != nil { + updates = append(updates, "verify_type = ?") + args = append(args, *newData.VerifyType) + } + if newData.AlarmType != nil { + updates = append(updates, "alarm_type = ?") + args = append(args, *newData.AlarmType) + } + if newData.Status != nil { + updates = append(updates, "status = ?") + args = append(args, *newData.Status) + } + + if newData.Language != nil { + updates = append(updates, "language = ?") + args = append(args, *newData.Language) + } + if newData.Currency != nil { + updates = append(updates, "currency = ?") + args = append(args, *newData.Currency) + } + if newData.NickName != nil { + updates = append(updates, "nick_name = ?") + args = append(args, *newData.NickName) + } + if newData.Avatar != nil { + updates = append(updates, "avatar = ?") + args = append(args, *newData.Avatar) + } + + if len(updates) == 0 { + return nil + } + + update := time.Now().UTC().Unix() + updates = append(updates, "update_time = ?") + args = append(args, &update) + + query += strings.Join(updates, ", ") + " where `id` = ?" + args = append(args, data.Id) + + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + return conn.ExecCtx(ctx, query, args...) + }, userTableIdKey, userTableUidKey) + + return err +} diff --git a/internal/model/user_table_model_gen.go b/internal/model/user_table_model_gen.go new file mode 100755 index 0000000..80a8b5f --- /dev/null +++ b/internal/model/user_table_model_gen.go @@ -0,0 +1,159 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + userTableFieldNames = builder.RawFieldNames(&UserTable{}) + userTableRows = strings.Join(userTableFieldNames, ",") + userTableRowsExpectAutoSet = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), ",") + userTableRowsWithPlaceHolder = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), "=?,") + "=?" + + cacheUserTableIdPrefix = "cache:userTable:id:" + cacheUserTableUidPrefix = "cache:userTable:uid:" +) + +type ( + userTableModel interface { + Insert(ctx context.Context, data *UserTable) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*UserTable, error) + FindOneByUid(ctx context.Context, uid string) (*UserTable, error) + Update(ctx context.Context, data *UserTable) error + Delete(ctx context.Context, id int64) error + } + + defaultUserTableModel struct { + sqlc.CachedConn + table string + } + + UserTable struct { + Id int64 `db:"id"` + VerifyType int64 `db:"verify_type"` // 驗證類型 0. 異常 1.信箱 2.手機 3. GA 4.不驗證 + AlarmType int64 `db:"alarm_type"` // 告警狀態 0. 異常 1. 正常(未告警) 2.系統告警中 + Status int64 `db:"status"` // 會員狀態 0. 異常 1. 尚未驗證 2. 啟用 3. 停權中 4. 信箱以驗證 5. 手機以驗證 6. GA 以驗證 + Uid string `db:"uid"` // 唯一辨識碼 + NickName string `db:"nick_name"` // 暱稱 + Language string `db:"language"` // 使用語言 + Currency string `db:"currency"` // 使用幣別 + Avatar string `db:"avatar"` // 會員頭像 + CreateTime int64 `db:"create_time"` + UpdateTime int64 `db:"update_time"` + } +) + +func newUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultUserTableModel { + return &defaultUserTableModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`user_table`", + } +} + +func (m *defaultUserTableModel) withSession(session sqlx.Session) *defaultUserTableModel { + return &defaultUserTableModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`user_table`", + } +} + +func (m *defaultUserTableModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) FindOne(ctx context.Context, id int64) (*UserTable, error) { + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, id) + var resp UserTable + err := m.QueryRowCtx(ctx, &resp, userTableIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", userTableRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) FindOneByUid(ctx context.Context, uid string) (*UserTable, error) { + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, uid) + var resp UserTable + err := m.QueryRowIndexCtx(ctx, &resp, userTableUidKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `uid` = ? limit 1", userTableRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, uid); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) Insert(ctx context.Context, data *UserTable) (sql.Result, error) { + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, userTableRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.VerifyType, data.AlarmType, data.Status, data.Uid, data.NickName, data.Language, data.Currency, data.Avatar, data.CreateTime, data.UpdateTime) + }, userTableIdKey, userTableUidKey) + return ret, err +} + +func (m *defaultUserTableModel) Update(ctx context.Context, newData *UserTable) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userTableRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.VerifyType, newData.AlarmType, newData.Status, newData.Uid, newData.NickName, newData.Language, newData.Currency, newData.Avatar, newData.CreateTime, newData.UpdateTime, newData.Id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheUserTableIdPrefix, primary) +} + +func (m *defaultUserTableModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", userTableRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultUserTableModel) tableName() string { + return m.table +} diff --git a/internal/model/vars.go b/internal/model/vars.go new file mode 100644 index 0000000..69ca814 --- /dev/null +++ b/internal/model/vars.go @@ -0,0 +1,5 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var ErrNotFound = sqlx.ErrNotFound diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go new file mode 100644 index 0000000..185c057 --- /dev/null +++ b/internal/svc/service_context.go @@ -0,0 +1,56 @@ +package svc + +import ( + "app-cloudep-member-server/internal/config" + "app-cloudep-member-server/internal/domain" + domainUC "app-cloudep-member-server/internal/domain/usecase" + "app-cloudep-member-server/internal/model" + mgo "app-cloudep-member-server/internal/model/mongo" + "app-cloudep-member-server/internal/usecase" + "fmt" + + ers "code.30cm.net/digimon/library-go/errors" + vi "code.30cm.net/digimon/library-go/validator" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +type ServiceContext struct { + Config config.Config + Validate vi.Validate + + AccountModel model.AccountModel + UserModel model.UserTableModel + AccountToUidModel model.AccountToUidModel + GenUIDUseCase domainUC.UIDGenerateUseCase + Redis redis.Redis +} + +func NewServiceContext(c config.Config) *ServiceContext { + // 設置 + ers.Scope = domain.Scope + + sqlConn := sqlx.NewMysql(c.DB.DsnString) + newRedis, err := redis.NewRedis(c.RedisCluster, redis.Cluster()) + if err != nil { + panic(err) + } + mongo := mgo.NewAutoIdModel( + fmt.Sprintf( + "%s://%s:%s", c.Mongo.Schema, + c.Mongo.Host, c.Mongo.Port), + c.Mongo.Database, + c.Mongo.Collection) + + return &ServiceContext{ + Config: c, + Validate: vi.MustValidator(vi.WithAccount("account")), + Redis: *newRedis, + UserModel: model.NewUserTableModel(sqlConn, c.Cache), + AccountToUidModel: model.NewAccountToUidModel(sqlConn, c.Cache), + AccountModel: model.NewAccountModel(sqlConn, c.Cache), + GenUIDUseCase: usecase.MustGenerateUseCase(usecase.GenerateUseCaseParam{ + GenerateUIDRepo: mongo, + }), + } +} diff --git a/internal/usecase/google_authenticator.go b/internal/usecase/google_authenticator.go new file mode 100644 index 0000000..aed2454 --- /dev/null +++ b/internal/usecase/google_authenticator.go @@ -0,0 +1 @@ +package usecase diff --git a/internal/usecase/uid_generate.go b/internal/usecase/uid_generate.go new file mode 100644 index 0000000..649abe4 --- /dev/null +++ b/internal/usecase/uid_generate.go @@ -0,0 +1,76 @@ +package usecase + +import ( + "app-cloudep-member-server/internal/domain" + "app-cloudep-member-server/internal/domain/usecase" + mgo "app-cloudep-member-server/internal/model/mongo" + "context" + "math" + "strconv" + "strings" +) + +type GenerateUseCaseParam struct { + GenerateUIDRepo mgo.AutoIdModel +} + +type GenerateUseCase struct { + generateUIDRepo mgo.AutoIdModel +} + +func MustGenerateUseCase(param GenerateUseCaseParam) usecase.UIDGenerateUseCase { + return &GenerateUseCase{ + generateUIDRepo: param.GenerateUIDRepo, + } +} + +// Generate 利用 mongo 創立全局唯一的 ark id +// TODO 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法 +func (g GenerateUseCase) Generate(ctx context.Context) (string, error) { + var data mgo.AutoId + err := g.generateUIDRepo.Inc(ctx, &data) + if err != nil { + return "", err + } + + uid := strconv.Itoa(int(domain.InitAutoId + data.Counter)) + code, err := generateReferralCode(uid) + if err != nil { + return "", err + } + + return code, nil +} + +// generateReferralCode 從 UID 生成 referralCode +func generateReferralCode(uid string) (string, error) { + uidInt, err := strconv.ParseInt(uid, 10, 64) + if err != nil { + return "", err + } + + maxReferralUIDBoundary := int64(math.Pow(float64(len(domain.ConvertTable)), float64(domain.DefaultReferralCodeLen))) + if uidInt > maxReferralUIDBoundary { + return "", usecase.UIDOutOfRangeErrorCodeError("uid encode out of range") + } + + encoded := encodeToBase(uidInt, 10, domain.DefaultReferralCodeLen) + + return encoded, nil +} + +func encodeToBase(num int64, base int, length int) string { + result := "" + for num > 0 { + index := num % int64(base) + result = domain.ConvertTable[index] + result + num /= int64(base) + } + + // makes sure the length fo result feats the input length + if len(result) < length { + result = strings.Repeat(domain.ConvertTable[0], length-len(result)) + result + } + + return result +} diff --git a/internal/usecase/uid_generate_test.go b/internal/usecase/uid_generate_test.go new file mode 100644 index 0000000..355b341 --- /dev/null +++ b/internal/usecase/uid_generate_test.go @@ -0,0 +1,35 @@ +package usecase + +import ( + "testing" +) + +// 單元測試 +func TestEncodeToBase(t *testing.T) { + tests := []struct { + num int64 + base int + length int + want string + }{ + // 測試基礎情況 + {num: 0, base: 10, length: 6, want: "OOOOOO"}, + {num: 1, base: 10, length: 6, want: "OOOOOD"}, + + {num: 24, base: 10, length: 6, want: "OOOOWY"}, + {num: 25, base: 10, length: 6, want: "OOOOWG"}, + {num: 1, base: 10, length: 4, want: "OOOD"}, + {num: 24, base: 10, length: 4, want: "OOWY"}, + {num: 25, base: 10, length: 5, want: "OOOWG"}, + {num: 1234567890, base: 10, length: 10, want: "DWXYGBCHEO"}, // 測試大數情況 + } + + for _, tt := range tests { + t.Run("encodeToBase", func(t *testing.T) { + got := encodeToBase(tt.num, tt.base, tt.length) + if got != tt.want { + t.Errorf("encodeToBase(%d, %d, %d) = %s; want %s", tt.num, tt.base, tt.length, got, tt.want) + } + }) + } +} diff --git a/internal/utils/password.go b/internal/utils/password.go new file mode 100644 index 0000000..5f10af9 --- /dev/null +++ b/internal/utils/password.go @@ -0,0 +1,20 @@ +package utils + +import ( + "golang.org/x/crypto/bcrypt" +) + +func HashPassword(password string, cost int) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), cost) + return string(bytes), err +} + +func CheckPasswordHash(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} + +func GetHashingCost(hashedPassword []byte) int { + cost, _ := bcrypt.Cost(hashedPassword) + return cost +} diff --git a/service.go b/service.go new file mode 100644 index 0000000..f6a8cc9 --- /dev/null +++ b/service.go @@ -0,0 +1,40 @@ +package main + +import ( + "flag" + + "github.com/zeromicro/go-zero/core/logx" + + "app-cloudep-member-server/gen_result/pb/member" + "app-cloudep-member-server/internal/config" + accountServer "app-cloudep-member-server/internal/server/account" + "app-cloudep-member-server/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/service" + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var configFile = flag.String("f", "etc/service.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + ctx := svc.NewServiceContext(c) + + s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) { + member.RegisterAccountServer(grpcServer, accountServer.NewAccountServer(ctx)) + + if c.Mode == service.DevMode || c.Mode == service.TestMode { + reflection.Register(grpcServer) + } + }) + defer s.Stop() + + logx.Info("Starting rpc server at %s...\n", c.ListenOn) + s.Start() +}