feat(app): 初始化应用服务并更新API接口定义

- 新增应用服务入口文件 app.go,配置服务启动参数及跨域支持
- 更新 appclient 包,增加基础响应结构体和分页用户查询、初始化数据库等 RPC 接口
- 修改 app.proto 文件,完善消息类型定义,包括认证令牌、用户信息、验证码等结构
- 添加 app.yaml 配置文件,设定服务名称、端口、超时时间及日志配置
- 删除旧版无用的 api.api 相关文件,清理冗余代码
- 生成完整的 Swagger 文档描述文件 app.json,包含所有 API 路径与模型定义
This commit is contained in:
huanglei19951029 2025-12-12 16:11:01 +08:00
parent cd34f7a6c3
commit 538f6e7e39
69 changed files with 4436 additions and 650 deletions

138
api/Makefile Normal file
View File

@ -0,0 +1,138 @@
# Custom configuration | 独立配置
# Service name | 项目名称
SERVICE=App
# Service name in specific style | 项目经过style格式化的名称
SERVICE_STYLE=app
# Service name in lowercase | 项目名称全小写格式
SERVICE_LOWER=app
# Service name in snake format | 项目名称下划线格式
SERVICE_SNAKE=app
# Service name in snake format | 项目名称短杠格式
SERVICE_DASH=app
# The project version, if you don't use git, you should set it manually | 项目版本如果不使用git请手动设置
VERSION=$(shell git describe --tags --always)
# The project file name style | 项目文件命名风格
PROJECT_STYLE=go_zero
# Whether to use i18n | 是否启用 i18n
PROJECT_I18N=true
# The suffix after build or compile | 构建后缀
PROJECT_BUILD_SUFFIX=api
# Swagger type, support yml,json | Swagger 文件类型支持yml,json
SWAGGER_TYPE=json
# Ent enabled features | Ent 启用的官方特性
ENT_FEATURE=sql/execquery,intercept
# Auto generate API data for initialization | 自动生成 API 初始化数据
AUTO_API_INIT_DATA=true
# The arch of the build | 构建的架构
GOARCH=amd64
# The repository of docker | Docker 仓库地址
DOCKER_REPO=docker.io/xxx
# ---- You may not need to modify the codes below | 下面的代码大概率不需要更改 ----
model=all
group=all
GO ?= go
GOFMT ?= gofmt "-s"
GOFILES := $(shell find . -name "*.go")
LDFLAGS := -s -w
.PHONY: test
test: # Run test for the project | 运行项目测试
go test -v --cover ./internal/..
.PHONY: fmt
fmt: # Format the codes | 格式化代码
$(GOFMT) -w $(GOFILES)
.PHONY: lint
lint: # Run go linter | 运行代码错误分析
golangci-lint run -D staticcheck
.PHONY: tools
tools: # Install the necessary tools | 安装必要的工具
$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest;
$(GO) install github.com/go-swagger/go-swagger/cmd/swagger@latest
.PHONY: docker
docker: # Build the docker image | 构建 docker 镜像
docker build -f Dockerfile -t $(DOCKER_REPO)/$(SERVICE_DASH)-$(PROJECT_BUILD_SUFFIX):$(VERSION) .
@echo "Build docker successfully"
.PHONY: publish-docker
publish-docker: # Publish docker image | 发布 docker 镜像
docker push $(DOCKER_REPO)/$(SERVICE_DASH)-$(PROJECT_BUILD_SUFFIX):$(VERSION)
@echo "Publish docker successfully"
.PHONY: gen-swagger
gen-swagger: # Generate swagger file | 生成 swagger 文件
swagger generate spec --output=./$(SERVICE_STYLE).$(SWAGGER_TYPE) --scan-models --exclude-deps
@echo "Generate swagger successfully"
.PHONY: serve-swagger
serve-swagger: # Run the swagger server | 运行 swagger 服务
lsof -i:36666 | awk 'NR!=1 {print $2}' | xargs killall -9 || true
swagger serve -F=swagger --port 36666 $(SERVICE_STYLE).$(SWAGGER_TYPE)
@echo "Serve swagger-ui successfully"
.PHONY: gen-api
gen-api: # Generate API files | 生成 API 的代码
goctls api go --api ./desc/all.api --dir ./ --trans_err=true --style=$(PROJECT_STYLE)
swagger generate spec --output=./$(SERVICE_STYLE).$(SWAGGER_TYPE) --scan-models --exclude-deps
@echo "Generate API codes successfully"
.PHONY: gen-ent
gen-ent: # Generate Ent codes | 生成 Ent 的代码
go run -mod=mod entgo.io/ent/cmd/ent generate --template glob="./ent/template/*.tmpl" ./ent/schema --feature $(ENT_FEATURE)
@echo "Generate Ent codes successfully"
.PHONY: gen-api-ent-logic
gen-api-ent-logic: # Generate CRUD logic from Ent, need to set model and group | 根据 Ent 生成 CRUD 代码,需要设置 model 和 group
goctls api ent --schema=./ent/schema --style=$(PROJECT_STYLE) --api_service_name=$(SERVICE) --output=./ --model=$(model) --group=$(group) --i18n=$(PROJECT_I18N) --overwrite=true --api_data=$(AUTO_API_INIT_DATA)
@echo "Generate CRUD codes from Ent successfully"
.PHONY: build-win
build-win: # Build project for Windows | 构建Windows下的可执行文件
env CGO_ENABLED=0 GOOS=windows GOARCH=$(GOARCH) go build -ldflags "$(LDFLAGS)" -trimpath -o $(SERVICE_STYLE)_$(PROJECT_BUILD_SUFFIX).exe $(SERVICE_STYLE).go
@echo "Build project for Windows successfully"
.PHONY: build-mac
build-mac: # Build project for MacOS | 构建MacOS下的可执行文件
env CGO_ENABLED=0 GOOS=darwin GOARCH=$(GOARCH) go build -ldflags "$(LDFLAGS)" -trimpath -o $(SERVICE_STYLE)_$(PROJECT_BUILD_SUFFIX) $(SERVICE_STYLE).go
@echo "Build project for MacOS successfully"
.PHONY: build-linux
build-linux: # Build project for Linux | 构建Linux下的可执行文件
env CGO_ENABLED=0 GOOS=linux GOARCH=$(GOARCH) go build -ldflags "$(LDFLAGS)" -trimpath -o $(SERVICE_STYLE)_$(PROJECT_BUILD_SUFFIX) $(SERVICE_STYLE).go
@echo "Build project for Linux successfully"
.PHONY: help
help: # Show help | 显示帮助
@grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done
.PHONY: format-api
format-api: # Format API files | 格式化 API 文件
@echo "Formatting API files..."
@if [ -f "./desc/all.api" ]; then \
goctl api format --dir ./desc ; \
echo "API files formatted successfully"; \
else \
echo "API files not found in ./desc directory"; \
fi
@if [ -f "./*.api" ]; then \
goctl api format --dir . --force; \
echo "Root directory API files formatted successfully"; \
fi

View File

@ -1,15 +0,0 @@
syntax = "v1"
type Request {
Name string `path:"name,options=you|me"`
}
type Response {
Message string `json:"message"`
}
service api-api {
@handler ApiHandler
get /from/:name (Request) returns (Response)
}

View File

@ -1,34 +0,0 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package main
import (
"flag"
"fmt"
"mingyang-admin-app/api/internal/config"
"mingyang-admin-app/api/internal/handler"
"mingyang-admin-app/api/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/api-api.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}

53
api/app.go Normal file
View File

@ -0,0 +1,53 @@
// app
//
// Description: app service
//
// Schemes: http, https
// Host: localhost:0
// BasePath: /
// Version: 0.0.1
// SecurityDefinitions:
// Token:
// type: apiKey
// name: Authorization
// in: header
// Security:
// Token:
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
package main
import (
"flag"
"fmt"
"mingyang-admin-app-api/internal/config"
"mingyang-admin-app-api/internal/handler"
"mingyang-admin-app-api/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/app.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c, conf.UseEnv())
server := rest.MustNewServer(c.RestConf, rest.WithCors(c.CROSConf.Address))
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}

924
api/app.json Normal file
View File

@ -0,0 +1,924 @@
{
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"schemes": [
"http",
"https"
],
"swagger": "2.0",
"info": {
"description": "Description: app service",
"title": "app",
"version": "0.0.1"
},
"host": "localhost:0",
"basePath": "/",
"paths": {
"/get/verifyCode": {
"post": {
"description": "GetVerifyCode | 获取验证码",
"tags": [
"user"
],
"summary": "GetVerifyCode | 获取验证码",
"operationId": "GetVerifyCode",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"$ref": "#/definitions/VerifyCodeReq"
}
}
],
"responses": {
"200": {
"description": "VerifyCodeResp",
"schema": {
"$ref": "#/definitions/VerifyCodeResp"
}
}
}
}
},
"/init/database": {
"get": {
"description": "Initialize database | 初始化数据库",
"tags": [
"base"
],
"summary": "Initialize database | 初始化数据库",
"operationId": "InitDatabase",
"responses": {
"200": {
"description": "BaseMsgResp",
"schema": {
"$ref": "#/definitions/BaseMsgResp"
}
}
}
}
},
"/login": {
"post": {
"description": "Login | 登录",
"tags": [
"user"
],
"summary": "Login | 登录",
"operationId": "Login",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"$ref": "#/definitions/LoginReq"
}
}
],
"responses": {
"200": {
"description": "LoginResp",
"schema": {
"$ref": "#/definitions/LoginResp"
}
}
}
}
},
"/register": {
"post": {
"description": "Register | 注册",
"tags": [
"user"
],
"summary": "Register | 注册",
"operationId": "Register",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"$ref": "#/definitions/RegisterReq"
}
}
],
"responses": {
"200": {
"description": "RegisterResp",
"schema": {
"$ref": "#/definitions/RegisterResp"
}
}
}
}
}
},
"definitions": {
"AuthToken": {
"type": "object",
"properties": {
"accessToken": {
"description": "access_token",
"type": "string",
"x-go-name": "AccessToken"
},
"accessTokenExpires": {
"description": "access_token_expires",
"type": "integer",
"format": "int64",
"x-go-name": "AccessTokenExpires"
},
"refreshToken": {
"description": "refresh_token",
"type": "string",
"x-go-name": "RefreshToken"
},
"refreshTokenExpires": {
"description": "refresh_token_expires",
"type": "integer",
"format": "int64",
"x-go-name": "RefreshTokenExpires"
},
"tokenType": {
"description": "token_type 类型",
"type": "string",
"x-go-name": "TokenType"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseDataInfo": {
"description": "The basic response with data | 基础带数据信息",
"type": "object",
"properties": {
"code": {
"description": "Error code | 错误代码",
"type": "integer",
"format": "int64",
"x-go-name": "Code"
},
"data": {
"description": "Data | 数据",
"type": "string",
"x-go-name": "Data"
},
"msg": {
"description": "Message | 提示信息",
"type": "string",
"x-go-name": "Msg"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseIDInfo": {
"description": "The base ID response data | 基础ID信息",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "string",
"format": "uint64",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseIDInt32Info": {
"description": "The base ID response data (int32) | 基础ID信息 (int32)",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "integer",
"format": "int32",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseIDInt64Info": {
"description": "The base ID response data (int64) | 基础ID信息 (int64)",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "integer",
"format": "int64",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseIDStringInfo": {
"description": "The base ID response data (string) | 基础ID信息 (string)",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "string",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseIDUint32Info": {
"description": "The base ID response data (uint32) | 基础ID信息 (uint32)",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "integer",
"format": "uint32",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseListInfo": {
"description": "The basic response with data | 基础带数据信息",
"type": "object",
"properties": {
"data": {
"description": "Data | 数据",
"type": "string",
"x-go-name": "Data"
},
"total": {
"description": "The total number of data | 数据总数",
"type": "integer",
"format": "uint64",
"x-go-name": "Total"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseMsgResp": {
"description": "The basic response without data | 基础不带数据信息",
"type": "object",
"properties": {
"code": {
"description": "Error code | 错误代码",
"type": "integer",
"format": "int64",
"x-go-name": "Code"
},
"msg": {
"description": "Message | 提示信息",
"type": "string",
"x-go-name": "Msg"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"BaseUUIDInfo": {
"description": "The base UUID response data | 基础UUID信息",
"type": "object",
"properties": {
"createdAt": {
"description": "Create date | 创建日期",
"type": "integer",
"format": "int64",
"x-go-name": "CreatedAt"
},
"id": {
"description": "ID",
"type": "string",
"x-go-name": "Id"
},
"updatedAt": {
"description": "Update date | 更新日期",
"type": "integer",
"format": "int64",
"x-go-name": "UpdatedAt"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDInt32PathReq": {
"description": "Basic ID request (int32) | 基础ID地址参数请求 (int32)",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "integer",
"format": "int32"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDInt32Req": {
"description": "Basic ID request (int32) | 基础ID参数请求 (int32)",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "integer",
"format": "int32",
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDInt64PathReq": {
"description": "Basic ID request (int64) | 基础ID地址参数请求 (int64)",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "integer",
"format": "int64"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDInt64Req": {
"description": "Basic ID request (int64) | 基础ID参数请求 (int64)",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "integer",
"format": "int64",
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDPathReq": {
"description": "Basic ID request | 基础ID地址参数请求",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "integer",
"format": "uint64"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDReq": {
"description": "Basic ID request | 基础ID参数请求",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "string",
"format": "uint64",
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDStringPathReq": {
"description": "Basic ID request (string) | 基础ID地址参数请求 (string)",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "string"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDStringReq": {
"description": "Basic ID request (string) | 基础ID参数请求 (string)",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "string",
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDUint32PathReq": {
"description": "Basic ID request (uint32) | 基础ID地址参数请求 (uint32)",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "integer",
"format": "uint32"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDUint32Req": {
"description": "Basic ID request (uint32) | 基础ID参数请求 (uint32)",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "integer",
"format": "uint32",
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDsInt32Req": {
"description": "Basic IDs request (int32) | 基础ID数组参数请求 (int32)",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "IDs",
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDsInt64Req": {
"description": "Basic IDs request (int64) | 基础ID数组参数请求 (int64)",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "IDs",
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDsReq": {
"description": "Basic IDs request | 基础ID数组参数请求",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "IDs",
"type": "array",
"items": {
"type": "integer",
"format": "uint64"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDsStringReq": {
"description": "Basic IDs request (string) | 基础ID数组参数请求 (string)",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "IDs",
"type": "array",
"items": {
"type": "string"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"IDsUint32Req": {
"description": "Basic IDs request (uint32) | 基础ID数组参数请求 (uint32)",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "IDs",
"type": "array",
"items": {
"type": "integer",
"format": "uint32"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"LoginReq": {
"type": "object",
"properties": {
"clientIp": {
"description": "ClientIP",
"type": "string",
"x-go-name": "ClientIP"
},
"loginPlatform": {
"description": "登录系统",
"type": "string",
"x-go-name": "LoginPlatform"
},
"loginType": {
"description": "登录方式",
"type": "string",
"x-go-name": "LoginType"
},
"password": {
"description": "Password",
"type": "string",
"x-go-name": "Password"
},
"userName": {
"description": "UserName or Email or Mobile",
"type": "string",
"x-go-name": "UserName"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"LoginResp": {
"type": "object",
"properties": {
"AuthToken": {
"$ref": "#/definitions/AuthToken"
},
"UserInfo": {
"$ref": "#/definitions/UserInfo"
},
"code": {
"description": "Error code | 错误代码",
"type": "integer",
"format": "int64",
"x-go-name": "Code"
},
"msg": {
"description": "Message | 提示信息",
"type": "string",
"x-go-name": "Msg"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"PageInfo": {
"description": "The page request parameters | 列表请求参数",
"type": "object",
"required": [
"page",
"pageSize"
],
"properties": {
"page": {
"description": "Page number | 第几页",
"type": "integer",
"format": "uint64",
"minimum": 0,
"x-go-name": "Page"
},
"pageSize": {
"description": "Page size | 单页数据行数",
"type": "integer",
"format": "uint64",
"maximum": 100000,
"x-go-name": "PageSize"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"RegisterReq": {
"type": "object",
"properties": {
"accountType": {
"description": "账户注册类型:手机或邮箱",
"type": "integer",
"format": "uint8",
"x-go-name": "AccountType"
},
"birthday": {
"description": "生日",
"type": "integer",
"format": "uint32",
"x-go-name": "Birthday"
},
"captcha": {
"description": "验证码",
"type": "string",
"x-go-name": "Captcha"
},
"captchaId": {
"description": "验证码ID",
"type": "string",
"x-go-name": "CaptchaId"
},
"gender": {
"description": "Gender male or female or other , 男,女,其他",
"type": "string",
"x-go-name": "Gender"
},
"nickName": {
"description": "昵称",
"type": "string",
"x-go-name": "NickName"
},
"passwordHash": {
"description": "密码加密后的值",
"type": "string",
"x-go-name": "PasswordHash"
},
"registerSource": {
"description": "注册来源 app,pc",
"type": "string",
"x-go-name": "RegisterSource"
},
"sex": {
"description": "性别",
"type": "integer",
"format": "uint8",
"x-go-name": "Sex"
},
"value": {
"description": "手机号或邮箱地址注册",
"type": "string",
"x-go-name": "Value"
},
"verificationType": {
"description": "VerificationType 类型 1 手机 2 邮箱",
"type": "integer",
"format": "uint32",
"x-go-name": "VerificationType"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"RegisterResp": {
"type": "object",
"properties": {
"authToken": {
"$ref": "#/definitions/AuthToken"
},
"userInfo": {
"$ref": "#/definitions/UserInfo"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"UUIDPathReq": {
"description": "Basic UUID request in path | 基础UUID地址参数请求",
"type": "object",
"required": [
"Id"
],
"properties": {
"Id": {
"description": "ID",
"type": "string"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"UUIDReq": {
"description": "Basic UUID request | 基础UUID参数请求",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "ID",
"type": "string",
"maxLength": 36,
"minLength": 36,
"x-go-name": "Id"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"UUIDsReq": {
"description": "Basic UUID array request | 基础UUID数组参数请求",
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"description": "Ids",
"type": "array",
"items": {
"type": "string"
},
"x-go-name": "Ids"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"UserInfo": {
"type": "object",
"properties": {
"avatar": {
"description": "头像",
"type": "string",
"x-go-name": "Avatar"
},
"birthday": {
"description": "生日",
"type": "integer",
"format": "int64",
"x-go-name": "Birthday"
},
"email": {
"description": "邮箱",
"type": "string",
"x-go-name": "Email"
},
"gender": {
"description": "Gender male or female or other , 男,女,其他",
"type": "string",
"x-go-name": "Gender"
},
"id": {
"description": "用户ID",
"type": "integer",
"format": "uint64",
"x-go-name": "Id"
},
"mobile": {
"description": "手机号",
"type": "string",
"x-go-name": "Mobile"
},
"nickName": {
"description": "昵称",
"type": "string",
"x-go-name": "NickName"
},
"registerType": {
"description": "账户注册类型:\n1 手机 2 邮箱",
"type": "integer",
"format": "uint32",
"x-go-name": "RegisterType"
},
"username": {
"description": "用户名",
"type": "string",
"x-go-name": "Username"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"VerifyCodeReq": {
"type": "object",
"properties": {
"accountType": {
"description": "账户注册类型:手机或邮箱",
"type": "integer",
"format": "uint8",
"x-go-name": "AccountType"
},
"value": {
"description": "手机号或邮箱地址",
"type": "string",
"x-go-name": "Value"
},
"verifyCodeType": {
"description": "验证码类型",
"type": "integer",
"format": "uint8",
"x-go-name": "VerifyCodeType"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
},
"VerifyCodeResp": {
"type": "object",
"properties": {
"captchaCode": {
"description": "验证码",
"type": "string",
"x-go-name": "CaptchaCode"
},
"expireTime": {
"description": "过期时间",
"type": "integer",
"format": "uint32",
"x-go-name": "ExpireTime"
}
},
"x-go-package": "mingyang-admin-app-api/internal/types"
}
},
"securityDefinitions": {
"Token": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
},
"security": [
{
"Token": []
}
]
}

2
api/desc/all.api Normal file
View File

@ -0,0 +1,2 @@
import "base.api"
import "./app/user.api"

130
api/desc/app/user.api Normal file
View File

@ -0,0 +1,130 @@
syntax = "v1"
info (
title: "type title here"
desc: "type desc here"
author: "type author here"
email: "type email here"
version: "type version here"
)
type (
VerifyCodeReq {
//验证码类型
VerifyCodeType uint8 `json:"verifyCodeType,optional"`
// 账户注册类型:手机或邮箱
AccountType uint8 `json:"accountType,optional"`
// 手机号或邮箱地址
Value string `json:"value,optional"`
}
VerifyCodeResp {
// 验证码
CaptchaCode string `json:"captchaCode,optional"`
// 过期时间
ExpireTime uint32 `json:"expireTime,optional"`
}
RegisterReq {
// 账户注册类型:手机或邮箱
AccountType uint8 `json:"accountType,optional"`
// 手机号或邮箱地址注册
Value string `json:"value,optional"`
// 昵称
NickName string `json:"nickName,optional"`
// 性别
Sex uint8 `json:"sex,optional"`
//生日
Birthday uint32 `json:"birthday,optional"`
// 密码加密后的值
PasswordHash *string `json:"passwordHash,optional"`
//验证码
Captcha string `json:"captcha,optional"`
// 验证码ID
CaptchaId string `json:"captchaId,optional"`
//VerificationType 类型 1 手机 2 邮箱
VerificationType *uint32 `json:"verificationType,optional"`
// Gender male or female or other , 男,女,其他
Gender *string `json:"gender,optional"`
// 注册来源 app,pc
RegisterSource *string `json:"registerSource,optional"`
}
RegisterResp{
// token信息
AuthToken *AuthToken `json:"authToken,optional"`
User *UserInfo `json:"userInfo,optional"`
}
AuthToken{
// access_token
AccessToken string `json:"accessToken,optional"`
// refresh_token
RefreshToken string `json:"refreshToken,optional"`
// token_type 类型
TokenType string `json:"tokenType,optional"`
//access_token_expires
AccessTokenExpires int64 `json:"accessTokenExpires,optional"`
//refresh_token_expires
RefreshTokenExpires int64 `json:"refreshTokenExpires,optional"`
}
UserInfo{
// 用户ID
Id uint64 `json:"id,optional"`
// 昵称
NickName string `json:"nickName,optional"`
//生日
Birthday int64 `json:"birthday,optional"`
// 头像
Avatar string `json:"avatar,optional"`
// Gender male or female or other , 男,女,其他
Gender *string `json:"gender,optional"`
// 账户注册类型:
// 1 手机 2 邮箱
RegisterType *uint32 `json:"registerType,optional"`
// 手机号
Mobile *string `json:"mobile,optional"`
// 用户名
Username string `json:"username,optional"`
//邮箱
Email *string `json:"email,optional"`
}
LoginReq{
// UserName or Email or Mobile
UserName string `json:"userName"`
// Password
Password string `json:"password"`
// ClientIP
ClientIP string `json:"clientIp"`
// 登录方式
LoginType string `json:"loginType"`
// 登录系统
LoginPlatform string `json:"loginPlatform"`
}
LoginResp{
BaseMsgResp
AuthToken *AuthToken
UserInfo *UserInfo
}
)
@server (
jwt: Auth
group: user
middleware: Authority
)
service App {
// GetVerifyCode | 获取验证码
@handler getVerifyCode
post /get/verifyCode (VerifyCodeReq) returns (VerifyCodeResp)
// Register | 注册
@handler register
post /register (RegisterReq) returns (RegisterResp)
// Login | 登录
@handler login
post /login (LoginReq) returns (LoginResp)
}

230
api/desc/base.api Normal file
View File

@ -0,0 +1,230 @@
syntax = "v1"
// The basic response with data | 基础带数据信息
type BaseDataInfo {
// Error code | 错误代码
Code int `json:"code"`
// Message | 提示信息
Msg string `json:"msg"`
// Data | 数据
Data string `json:"data,omitempty"`
}
// The basic response with data | 基础带数据信息
type BaseListInfo {
// The total number of data | 数据总数
Total uint64 `json:"total"`
// Data | 数据
Data string `json:"data,omitempty"`
}
// The basic response without data | 基础不带数据信息
type BaseMsgResp {
// Error code | 错误代码
Code int `json:"code"`
// Message | 提示信息
Msg string `json:"msg"`
}
// The page request parameters | 列表请求参数
type PageInfo {
// Page number | 第几页
Page uint64 `json:"page" validate:"required,number,gt=0"`
// Page size | 单页数据行数
PageSize uint64 `json:"pageSize" validate:"required,number,lt=100000"`
}
// Basic ID request | 基础ID参数请求
type IDReq {
// ID
// Required: true
Id uint64 `json:"id,string" validate:"number"`
}
// Basic IDs request | 基础ID数组参数请求
type IDsReq {
// IDs
// Required: true
Ids []uint64 `json:"ids,[]string"`
}
// Basic ID request | 基础ID地址参数请求
type IDPathReq {
// ID
// Required: true
Id uint64 `path:"id"`
}
// Basic ID request (int32) | 基础ID参数请求 (int32)
type IDInt32Req {
// ID
// Required: true
Id int32 `json:"id" validate:"number"`
}
// Basic IDs request (int32) | 基础ID数组参数请求 (int32)
type IDsInt32Req {
// IDs
// Required: true
Ids []int32 `json:"ids"`
}
// Basic ID request (int32) | 基础ID地址参数请求 (int32)
type IDInt32PathReq {
// ID
// Required: true
Id int32 `path:"id"`
}
// Basic ID request (uint32) | 基础ID参数请求 (uint32)
type IDUint32Req {
// ID
// Required: true
Id uint32 `json:"id" validate:"number"`
}
// Basic IDs request (uint32) | 基础ID数组参数请求 (uint32)
type IDsUint32Req {
// IDs
// Required: true
Ids []uint32 `json:"ids"`
}
// Basic ID request (uint32) | 基础ID地址参数请求 (uint32)
type IDUint32PathReq {
// ID
// Required: true
Id uint32 `path:"id"`
}
// Basic ID request (int64) | 基础ID参数请求 (int64)
type IDInt64Req {
// ID
// Required: true
Id int64 `json:"id" validate:"number"`
}
// Basic IDs request (int64) | 基础ID数组参数请求 (int64)
type IDsInt64Req {
// IDs
// Required: true
Ids []int64 `json:"ids"`
}
// Basic ID request (int64) | 基础ID地址参数请求 (int64)
type IDInt64PathReq {
// ID
// Required: true
Id int64 `path:"id"`
}
// Basic ID request (string) | 基础ID参数请求 (string)
type IDStringReq {
// ID
// Required: true
Id string `json:"id"`
}
// Basic IDs request (string) | 基础ID数组参数请求 (string)
type IDsStringReq {
// IDs
// Required: true
Ids []string `json:"ids"`
}
// Basic ID request (string) | 基础ID地址参数请求 (string)
type IDStringPathReq {
// ID
// Required: true
Id string `path:"id"`
}
// Basic UUID request in path | 基础UUID地址参数请求
type UUIDPathReq {
// ID
// Required: true
Id string `path:"id"`
}
// Basic UUID request | 基础UUID参数请求
type UUIDReq {
// ID
Id string `json:"id" validate:"required,len=36"`
}
// Basic UUID array request | 基础UUID数组参数请求
type UUIDsReq {
// Ids
// Required: true
Ids []string `json:"ids"`
}
// The base ID response data | 基础ID信息
type BaseIDInfo {
// ID
Id *uint64 `json:"id,string,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (int64) | 基础ID信息 (int64)
type BaseIDInt64Info {
// ID
Id *int64 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (int32) | 基础ID信息 (int32)
type BaseIDInt32Info {
// ID
Id *int32 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (uint32) | 基础ID信息 (uint32)
type BaseIDUint32Info {
// ID
Id *uint32 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base UUID response data | 基础UUID信息
type BaseUUIDInfo {
// ID
Id *string `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (string) | 基础ID信息 (string)
type BaseIDStringInfo {
// ID
Id *string `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
@server (
group: base
)
service App {
// Initialize database | 初始化数据库
@handler initDatabase
get /init/database returns (BaseMsgResp)
}

View File

@ -1,3 +0,0 @@
Name: api-api
Host: 0.0.0.0
Port: 8888

34
api/etc/app.yaml Normal file
View File

@ -0,0 +1,34 @@
Name: App.api
Host: 0.0.0.0
Port: 9902
Timeout: 4000
CROSConf:
Address: '*'
Log:
ServiceName: AppApiLogger
Mode: console
Path: /home/data/logs/App/api
Level: info
Compress: false
Encoding: json
KeepDays: 7
StackCoolDownMillis: 100
RedisConf:
Host: 192.168.201.58:6379
Db: 0
AppRpc:
# Etcd:
# Hosts:
#$ - 192.168.201.58:2379
# Key: core.rpc
Target: 127.0.0.1:9901
Enabled: true
I18nConf:
Dir:

View File

@ -1,3 +1,121 @@
module mingyang-admin-app-api module mingyang-admin-app-api
go 1.25.3 go 1.25.3
require (
github.com/redis/go-redis/v9 v9.16.0
github.com/saas-mingyang/mingyang-admin-common v0.3.3
github.com/zeromicro/go-zero v1.9.1
)
require (
entgo.io/ent v0.14.5 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // 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.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.22.2 // indirect
github.com/go-openapi/jsonreference v0.21.3 // indirect
github.com/go-openapi/swag v0.25.1 // indirect
github.com/go-openapi/swag/cmdutils v0.25.1 // indirect
github.com/go-openapi/swag/conv v0.25.1 // indirect
github.com/go-openapi/swag/fileutils v0.25.1 // indirect
github.com/go-openapi/swag/jsonname v0.25.1 // indirect
github.com/go-openapi/swag/jsonutils v0.25.1 // indirect
github.com/go-openapi/swag/loading v0.25.1 // indirect
github.com/go-openapi/swag/mangling v0.25.1 // indirect
github.com/go-openapi/swag/netutils v0.25.1 // indirect
github.com/go-openapi/swag/stringutils v0.25.1 // indirect
github.com/go-openapi/swag/typeutils v0.25.1 // indirect
github.com/go-openapi/swag/yamlutils v0.25.1 // 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.27.0 // indirect
github.com/go-sql-driver/mysql v1.9.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/pyroscope-go v1.2.7 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.32 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nicksnyder/go-i18n/v2 v2.6.0 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.2 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/etcd/api/v3 v3.6.6 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.6 // indirect
go.etcd.io/etcd/client/v3 v3.6.6 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/mock v0.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.44.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.33.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.39.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.34.2 // indirect
k8s.io/apimachinery v0.34.2 // indirect
k8s.io/client-go v0.34.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
replace github.com/zeromicro/go-zero v1.9.1 => github.com/suyuan32/simple-admin-tools v1.9.1

317
api/go.sum Normal file
View File

@ -0,0 +1,317 @@
entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=
entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI=
github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.22.2 h1:JDQEe4B9j6K3tQ7HQQTZfjR59IURhjjLxet2FB4KHyg=
github.com/go-openapi/jsonpointer v0.22.2/go.mod h1:0lBbqeRsQ5lIanv3LHZBrmRGHLHcQoOXQnf88fHlGWo=
github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc=
github.com/go-openapi/jsonreference v0.21.3/go.mod h1:RqkUP0MrLf37HqxZxrIAtTWW4ZJIK1VzduhXYBEeGc4=
github.com/go-openapi/swag v0.25.1 h1:6uwVsx+/OuvFVPqfQmOOPsqTcm5/GkBhNwLqIR916n8=
github.com/go-openapi/swag v0.25.1/go.mod h1:bzONdGlT0fkStgGPd3bhZf1MnuPkf2YAys6h+jZipOo=
github.com/go-openapi/swag/cmdutils v0.25.1 h1:nDke3nAFDArAa631aitksFGj2omusks88GF1VwdYqPY=
github.com/go-openapi/swag/cmdutils v0.25.1/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
github.com/go-openapi/swag/conv v0.25.1 h1:+9o8YUg6QuqqBM5X6rYL/p1dpWeZRhoIt9x7CCP+he0=
github.com/go-openapi/swag/conv v0.25.1/go.mod h1:Z1mFEGPfyIKPu0806khI3zF+/EUXde+fdeksUl2NiDs=
github.com/go-openapi/swag/fileutils v0.25.1 h1:rSRXapjQequt7kqalKXdcpIegIShhTPXx7yw0kek2uU=
github.com/go-openapi/swag/fileutils v0.25.1/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M=
github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU=
github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo=
github.com/go-openapi/swag/jsonutils v0.25.1 h1:AihLHaD0brrkJoMqEZOBNzTLnk81Kg9cWr+SPtxtgl8=
github.com/go-openapi/swag/jsonutils v0.25.1/go.mod h1:JpEkAjxQXpiaHmRO04N1zE4qbUEg3b7Udll7AMGTNOo=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1 h1:DSQGcdB6G0N9c/KhtpYc71PzzGEIc/fZ1no35x4/XBY=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg=
github.com/go-openapi/swag/loading v0.25.1 h1:6OruqzjWoJyanZOim58iG2vj934TysYVptyaoXS24kw=
github.com/go-openapi/swag/loading v0.25.1/go.mod h1:xoIe2EG32NOYYbqxvXgPzne989bWvSNoWoyQVWEZicc=
github.com/go-openapi/swag/mangling v0.25.1 h1:XzILnLzhZPZNtmxKaz/2xIGPQsBsvmCjrJOWGNz/ync=
github.com/go-openapi/swag/mangling v0.25.1/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ=
github.com/go-openapi/swag/netutils v0.25.1 h1:2wFLYahe40tDUHfKT1GRC4rfa5T1B4GWZ+msEFA4Fl4=
github.com/go-openapi/swag/netutils v0.25.1/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE=
github.com/go-openapi/swag/stringutils v0.25.1 h1:Xasqgjvk30eUe8VKdmyzKtjkVjeiXx1Iz0zDfMNpPbw=
github.com/go-openapi/swag/stringutils v0.25.1/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg=
github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3I3ysiFZqukA=
github.com/go-openapi/swag/typeutils v0.25.1/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8=
github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91oSJLDPF1bmGk=
github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg=
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac=
github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc=
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og=
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ=
github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/redis/go-redis/v9 v9.16.0 h1:OotgqgLSRCmzfqChbQyG1PHC3tLNR89DG4jdOERSEP4=
github.com/redis/go-redis/v9 v9.16.0/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/saas-mingyang/mingyang-admin-common v0.3.3 h1:Pe1IYBaE7v541WKnEFPwiOC9yMzhmvVQ4+rSfRdEC1M=
github.com/saas-mingyang/mingyang-admin-common v0.3.3/go.mod h1:mAweT+3C08LGdr14AQNz9Sx5COPEpTtL6dr5fQAKqWc=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/suyuan32/simple-admin-tools v1.9.1 h1:RRFT2Dn22H/b0A4aB+ixul/6xzmTFXG10ER64DuCS0A=
github.com/suyuan32/simple-admin-tools v1.9.1/go.mod h1:v3y8WAJTCt+g/+Ve0BZuSga38gwdDh/2WNuvve9Tz2Y=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
go.etcd.io/etcd/api/v3 v3.6.6 h1:mcaMp3+7JawWv69p6QShYWS8cIWUOl32bFLb6qf8pOQ=
go.etcd.io/etcd/api/v3 v3.6.6/go.mod h1:f/om26iXl2wSkcTA1zGQv8reJRSLVdoEBsi4JdfMrx4=
go.etcd.io/etcd/client/pkg/v3 v3.6.6 h1:uoqgzSOv2H9KlIF5O1Lsd8sW+eMLuV6wzE3q5GJGQNs=
go.etcd.io/etcd/client/pkg/v3 v3.6.6/go.mod h1:YngfUVmvsvOJ2rRgStIyHsKtOt9SZI2aBJrZiWJhCbI=
go.etcd.io/etcd/client/v3 v3.6.6 h1:G5z1wMf5B9SNexoxOHUGBaULurOZPIgGPsW6CN492ec=
go.etcd.io/etcd/client/v3 v3.6.6/go.mod h1:36Qv6baQ07znPR3+n7t+Rk5VHEzVYPvFfGmfF4wBHV8=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE=
go.opentelemetry.io/otel/exporters/zipkin v1.38.0 h1:0rJ2TmzpHDG+Ib9gPmu3J3cE0zXirumQcKS4wCoZUa0=
go.opentelemetry.io/otel/exporters/zipkin v1.38.0/go.mod h1:Su/nq/K5zRjDKKC3Il0xbViE3juWgG3JDoqLumFx5G0=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4=
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

View File

@ -3,8 +3,17 @@
package config package config
import "github.com/zeromicro/go-zero/rest" import (
"github.com/saas-mingyang/mingyang-admin-common/config"
"github.com/saas-mingyang/mingyang-admin-common/i18n"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct { type Config struct {
rest.RestConf rest.RestConf
RedisConf config.RedisConf
CROSConf config.CROSConf
I18nConf i18n.Conf
AppRpc zrpc.RpcClientConf
} }

View File

@ -1,31 +0,0 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package handler
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"mingyang-admin-app/api/internal/logic"
"mingyang-admin-app/api/internal/svc"
"mingyang-admin-app/api/internal/types"
)
func ApiHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := logic.NewApiLogic(r.Context(), svcCtx)
resp, err := l.Api(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@ -0,0 +1,32 @@
package base
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"mingyang-admin-app-api/internal/logic/base"
"mingyang-admin-app-api/internal/svc"
)
// swagger:route get /init/database base InitDatabase
//
// Initialize database | 初始化数据库
//
// Initialize database | 初始化数据库
//
// Responses:
// 200: BaseMsgResp
func InitDatabaseHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := base.NewInitDatabaseLogic(r.Context(), svcCtx)
resp, err := l.InitDatabase()
if err != nil {
err = svcCtx.Trans.TransError(r.Context(), err)
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@ -1,12 +1,14 @@
// Code generated by goctl. DO NOT EDIT. // Code generated by goctl. DO NOT EDIT.
// goctl 1.9.2 // goctls v1.12.7
package handler package handler
import ( import (
"net/http" "net/http"
"mingyang-admin-app/api/internal/svc" base "mingyang-admin-app-api/internal/handler/base"
user "mingyang-admin-app-api/internal/handler/user"
"mingyang-admin-app-api/internal/svc"
"github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/rest"
) )
@ -16,9 +18,33 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodGet, Method: http.MethodGet,
Path: "/from/:name", Path: "/init/database",
Handler: ApiHandler(serverCtx), Handler: base.InitDatabaseHandler(serverCtx),
}, },
}, },
) )
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.Authority},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/get/verifyCode",
Handler: user.GetVerifyCodeHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/register",
Handler: user.RegisterHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/login",
Handler: user.LoginHandler(serverCtx),
},
}...,
),
//rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
)
} }

View File

@ -0,0 +1,45 @@
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"mingyang-admin-app-api/internal/logic/user"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
)
// swagger:route post /get/verifyCode user GetVerifyCode
//
// GetVerifyCode | 获取验证码
//
// GetVerifyCode | 获取验证码
//
// Parameters:
// + name: body
// require: true
// in: body
// type: VerifyCodeReq
//
// Responses:
// 200: VerifyCodeResp
func GetVerifyCodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.VerifyCodeReq
if err := httpx.Parse(r, &req, true); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := user.NewGetVerifyCodeLogic(r.Context(), svcCtx)
resp, err := l.GetVerifyCode(&req)
if err != nil {
err = svcCtx.Trans.TransError(r.Context(), err)
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@ -0,0 +1,45 @@
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"mingyang-admin-app-api/internal/logic/user"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
)
// swagger:route post /register user Register
//
// Register | 注册
//
// Register | 注册
//
// Parameters:
// + name: body
// require: true
// in: body
// type: RegisterReq
//
// Responses:
// 200: RegisterResp
func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.RegisterReq
if err := httpx.Parse(r, &req, true); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := user.NewRegisterLogic(r.Context(), svcCtx)
resp, err := l.Register(&req)
if err != nil {
err = svcCtx.Trans.TransError(r.Context(), err)
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@ -0,0 +1,25 @@
{
"common": {
"success": "Successfully",
"failed": "Failed",
"updateSuccess": "Update successfully",
"updateFailed": "Update failed",
"createSuccess": "Create successfully",
"createFailed": "Create failed",
"deleteSuccess": "Delete successfully",
"deleteFailed": "Delete failed",
"targetNotExist": "Target does not exist",
"databaseError": "Database error",
"redisError": "Redis error",
"permissionDeny": "User does not have permission to access this interface",
"constraintError": "Operation failed: Data conflict",
"validationError": "Operation failed: Validation failed",
"notSingularError": "Operation failed: Data not unique",
"serviceUnavailable": "Service is unavailable, please check if the service is enabled",
"cacheError": "Cache error"
},
"init": {
"alreadyInit": "The database had been initialized.",
"initializeIsRunning": "The initialization is running..."
}
}

View File

@ -0,0 +1,25 @@
{
"common": {
"success": "成功",
"failed": "失败",
"updateSuccess": "更新成功",
"updateFailed": "更新失败",
"createSuccess": "新建成功",
"createFailed": "新建失败",
"deleteSuccess": "删除成功",
"deleteFailed": "删除失败",
"targetNotExist": "目标不存在",
"databaseError": "数据库错误",
"redisError": "Redis 错误",
"permissionDeny": "用户无权限访问此接口",
"constraintError": "操作失败: 数据冲突",
"validationError": "操作失败: 校验失败",
"notSingularError": "操作失败: 数据不唯一",
"serviceUnavailable": "服务不可用,请检查服务是否已启用",
"cacheError": "缓存出错"
},
"init": {
"initializeIsRunning": "正在初始化...",
"alreadyInit": "数据库已被初始化。"
}
}

View File

@ -0,0 +1,8 @@
package i18n
import (
"embed"
)
//go:embed locale/*.json
var LocaleFS embed.FS

View File

@ -1,33 +0,0 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package logic
import (
"context"
"mingyang-admin-app/api/internal/svc"
"mingyang-admin-app/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ApiLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewApiLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ApiLogic {
return &ApiLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ApiLogic) Api(req *types.Request) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
return
}

View File

@ -0,0 +1,29 @@
package base
import (
"context"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type InitDatabaseLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewInitDatabaseLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InitDatabaseLogic {
return &InitDatabaseLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *InitDatabaseLogic) InitDatabase() (resp *types.BaseMsgResp, err error) {
l.svcCtx.AppRpc.InitDatabase(l.ctx, nil)
return
}

View File

@ -0,0 +1,41 @@
package user
import (
"context"
"github.com/pkg/errors"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
"mingyang-admin-app-rpc/types/app"
"github.com/zeromicro/go-zero/core/logx"
)
type GetVerifyCodeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetVerifyCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetVerifyCodeLogic {
return &GetVerifyCodeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetVerifyCodeLogic) GetVerifyCode(req *types.VerifyCodeReq) (resp *types.VerifyCodeResp, err error) {
verifyCode, err := l.svcCtx.AppRpc.GetVerifyCode(l.ctx, &app.VerifyCodeReq{
AccountType: app.AccountType(req.AccountType),
Value: req.Value,
Type: app.VerifyCodeType(req.VerifyCodeType),
})
if err != nil {
logx.Errorw("failed to get verify code", logx.Field("detail", err))
return nil, errors.New("failed to get verify code")
}
return &types.VerifyCodeResp{
ExpireTime: verifyCode.Expire,
CaptchaCode: verifyCode.CaptchaCode,
}, nil
}

View File

@ -0,0 +1,60 @@
package user
import (
"context"
"mingyang-admin-app-rpc/types/app"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type LoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
return &LoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) {
loginUser, err := l.svcCtx.AppRpc.LoginUser(l.ctx, &app.LoginRequest{
Username: &req.UserName,
Password: &req.Password,
ClientIp: &req.ClientIP,
LoginTyp: &req.LoginType,
LoginPlatform: &req.LoginPlatform,
})
if err != nil {
return nil, err
}
token := loginUser.AuthToken
user := loginUser.User
return &types.LoginResp{
BaseMsgResp: types.BaseMsgResp{
Code: 0,
Msg: "登录成功",
},
AuthToken: &types.AuthToken{
AccessToken: token.AccessToken,
RefreshToken: token.RefreshToken,
TokenType: token.TokenType,
AccessTokenExpires: token.AccessTokenExpires.Seconds,
RefreshTokenExpires: token.RefreshTokenExpires.Seconds,
},
UserInfo: &types.UserInfo{
Id: user.GetId(),
Username: user.GetUsername(),
NickName: user.GetNickname(),
Avatar: user.GetAvatar(),
Gender: user.Gender,
},
}, nil
}

View File

@ -0,0 +1,63 @@
package user
import (
"context"
"mingyang-admin-app-rpc/types/app"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type RegisterLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterLogic {
return &RegisterLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *RegisterLogic) Register(req *types.RegisterReq) (resp *types.RegisterResp, err error) {
user, err := l.svcCtx.AppRpc.RegisterUser(l.ctx, &app.RegisterUserRequest{
Email: &req.Value,
Password: req.PasswordHash,
Username: &req.Value,
NickName: &req.NickName,
Mobile: &req.Value,
Captcha: &req.Captcha,
VerificationType: req.VerificationType,
Gender: req.Gender,
RegistrationSource: req.RegisterSource,
})
if err != nil {
return nil, err
}
getUser := user.GetUser()
token := user.GetAuthToken()
return &types.RegisterResp{
User: &types.UserInfo{
Id: getUser.GetId(),
Username: getUser.GetUsername(),
Mobile: getUser.Mobile,
NickName: getUser.GetNickname(),
Gender: getUser.Gender,
Avatar: getUser.GetAvatar(),
Birthday: getUser.GetBirthdayAt(),
Email: getUser.Email,
},
AuthToken: &types.AuthToken{
AccessToken: token.GetAccessToken(),
RefreshToken: token.GetRefreshToken(),
TokenType: token.GetTokenType(),
AccessTokenExpires: token.AccessTokenExpires.Seconds,
RefreshTokenExpires: token.RefreshTokenExpires.Seconds,
},
}, nil
}

View File

@ -0,0 +1,28 @@
package middleware
import (
"github.com/redis/go-redis/v9"
"net/http"
)
type AuthorityMiddleware struct {
Rds redis.UniversalClient
}
func NewAuthorityMiddleware(rds redis.UniversalClient) *AuthorityMiddleware {
return &AuthorityMiddleware{
Rds: rds,
}
}
func (m *AuthorityMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
/* // get the path
obj := r.URL.Path
// get the method
act := r.Method
// get the role id
roleIds := strings.Split(r.Context().Value("roleId").(string), ",")*/
next(w, r)
}
}

View File

@ -0,0 +1,29 @@
package svc
import (
"github.com/saas-mingyang/mingyang-admin-common/i18n"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
"mingyang-admin-app-api/internal/config"
i18n2 "mingyang-admin-app-api/internal/i18n"
"mingyang-admin-app-api/internal/middleware"
"mingyang-admin-app-rpc/appclient"
)
type ServiceContext struct {
Config config.Config
Trans *i18n.Translator
Authority rest.Middleware
AppRpc appclient.App
}
func NewServiceContext(c config.Config) *ServiceContext {
trans := i18n.NewTranslator(c.I18nConf, i18n2.LocaleFS)
rds := c.RedisConf.MustNewUniversalRedis()
return &ServiceContext{
Authority: middleware.NewAuthorityMiddleware(rds).Handle,
Config: c,
Trans: trans,
AppRpc: appclient.NewApp(zrpc.NewClientIfEnable(c.AppRpc)),
}
}

View File

@ -1,18 +0,0 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package svc
import (
"mingyang-admin-app/api/internal/config"
)
type ServiceContext struct {
Config config.Config
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
}
}

View File

@ -1,12 +1,364 @@
// Code generated by goctl. DO NOT EDIT. // Code generated by goctl. DO NOT EDIT.
// goctl 1.9.2
package types package types
type Request struct { // The basic response with data | 基础带数据信息
Name string `path:"name,options=you|me"` // swagger:model BaseDataInfo
type BaseDataInfo struct {
// Error code | 错误代码
Code int `json:"code"`
// Message | 提示信息
Msg string `json:"msg"`
// Data | 数据
Data string `json:"data,omitempty"`
} }
type Response struct { // The basic response with data | 基础带数据信息
Message string `json:"message"` // swagger:model BaseListInfo
type BaseListInfo struct {
// The total number of data | 数据总数
Total uint64 `json:"total"`
// Data | 数据
Data string `json:"data,omitempty"`
}
// The basic response without data | 基础不带数据信息
// swagger:model BaseMsgResp
type BaseMsgResp struct {
// Error code | 错误代码
Code int `json:"code"`
// Message | 提示信息
Msg string `json:"msg"`
}
// The page request parameters | 列表请求参数
// swagger:model PageInfo
type PageInfo struct {
// Page number | 第几页
// required : true
// min : 0
Page uint64 `json:"page" validate:"required,number,gt=0"`
// Page size | 单页数据行数
// required : true
// max : 100000
PageSize uint64 `json:"pageSize" validate:"required,number,lt=100000"`
}
// Basic ID request | 基础ID参数请求
// swagger:model IDReq
type IDReq struct {
// ID
// Required: true
Id uint64 `json:"id,string" validate:"number"`
}
// Basic IDs request | 基础ID数组参数请求
// swagger:model IDsReq
type IDsReq struct {
// IDs
// Required: true
Ids []uint64 `json:"ids,[]string"`
}
// Basic ID request | 基础ID地址参数请求
// swagger:model IDPathReq
type IDPathReq struct {
// ID
// Required: true
Id uint64 `path:"id"`
}
// Basic ID request (int32) | 基础ID参数请求 (int32)
// swagger:model IDInt32Req
type IDInt32Req struct {
// ID
// Required: true
Id int32 `json:"id" validate:"number"`
}
// Basic IDs request (int32) | 基础ID数组参数请求 (int32)
// swagger:model IDsInt32Req
type IDsInt32Req struct {
// IDs
// Required: true
Ids []int32 `json:"ids"`
}
// Basic ID request (int32) | 基础ID地址参数请求 (int32)
// swagger:model IDInt32PathReq
type IDInt32PathReq struct {
// ID
// Required: true
Id int32 `path:"id"`
}
// Basic ID request (uint32) | 基础ID参数请求 (uint32)
// swagger:model IDUint32Req
type IDUint32Req struct {
// ID
// Required: true
Id uint32 `json:"id" validate:"number"`
}
// Basic IDs request (uint32) | 基础ID数组参数请求 (uint32)
// swagger:model IDsUint32Req
type IDsUint32Req struct {
// IDs
// Required: true
Ids []uint32 `json:"ids"`
}
// Basic ID request (uint32) | 基础ID地址参数请求 (uint32)
// swagger:model IDUint32PathReq
type IDUint32PathReq struct {
// ID
// Required: true
Id uint32 `path:"id"`
}
// Basic ID request (int64) | 基础ID参数请求 (int64)
// swagger:model IDInt64Req
type IDInt64Req struct {
// ID
// Required: true
Id int64 `json:"id" validate:"number"`
}
// Basic IDs request (int64) | 基础ID数组参数请求 (int64)
// swagger:model IDsInt64Req
type IDsInt64Req struct {
// IDs
// Required: true
Ids []int64 `json:"ids"`
}
// Basic ID request (int64) | 基础ID地址参数请求 (int64)
// swagger:model IDInt64PathReq
type IDInt64PathReq struct {
// ID
// Required: true
Id int64 `path:"id"`
}
// Basic ID request (string) | 基础ID参数请求 (string)
// swagger:model IDStringReq
type IDStringReq struct {
// ID
// Required: true
Id string `json:"id"`
}
// Basic IDs request (string) | 基础ID数组参数请求 (string)
// swagger:model IDsStringReq
type IDsStringReq struct {
// IDs
// Required: true
Ids []string `json:"ids"`
}
// Basic ID request (string) | 基础ID地址参数请求 (string)
// swagger:model IDStringPathReq
type IDStringPathReq struct {
// ID
// Required: true
Id string `path:"id"`
}
// Basic UUID request in path | 基础UUID地址参数请求
// swagger:model UUIDPathReq
type UUIDPathReq struct {
// ID
// Required: true
Id string `path:"id"`
}
// Basic UUID request | 基础UUID参数请求
// swagger:model UUIDReq
type UUIDReq struct {
// ID
// required : true
// max length : 36
// min length : 36
Id string `json:"id" validate:"required,len=36"`
}
// Basic UUID array request | 基础UUID数组参数请求
// swagger:model UUIDsReq
type UUIDsReq struct {
// Ids
// Required: true
Ids []string `json:"ids"`
}
// The base ID response data | 基础ID信息
// swagger:model BaseIDInfo
type BaseIDInfo struct {
// ID
Id *uint64 `json:"id,string,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (int64) | 基础ID信息 (int64)
// swagger:model BaseIDInt64Info
type BaseIDInt64Info struct {
// ID
Id *int64 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (int32) | 基础ID信息 (int32)
// swagger:model BaseIDInt32Info
type BaseIDInt32Info struct {
// ID
Id *int32 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (uint32) | 基础ID信息 (uint32)
// swagger:model BaseIDUint32Info
type BaseIDUint32Info struct {
// ID
Id *uint32 `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base UUID response data | 基础UUID信息
// swagger:model BaseUUIDInfo
type BaseUUIDInfo struct {
// ID
Id *string `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// The base ID response data (string) | 基础ID信息 (string)
// swagger:model BaseIDStringInfo
type BaseIDStringInfo struct {
// ID
Id *string `json:"id,optional"`
// Create date | 创建日期
CreatedAt *int64 `json:"createdAt,optional"`
// Update date | 更新日期
UpdatedAt *int64 `json:"updatedAt,optional"`
}
// swagger:model VerifyCodeReq
type VerifyCodeReq struct {
//验证码类型
VerifyCodeType uint8 `json:"verifyCodeType,optional"`
// 账户注册类型:手机或邮箱
AccountType uint8 `json:"accountType,optional"`
// 手机号或邮箱地址
Value string `json:"value,optional"`
}
// swagger:model VerifyCodeResp
type VerifyCodeResp struct {
// 验证码
CaptchaCode string `json:"captchaCode,optional"`
// 过期时间
ExpireTime uint32 `json:"expireTime,optional"`
}
// swagger:model RegisterReq
type RegisterReq struct {
// 账户注册类型:手机或邮箱
AccountType uint8 `json:"accountType,optional"`
// 手机号或邮箱地址注册
Value string `json:"value,optional"`
// 昵称
NickName string `json:"nickName,optional"`
// 性别
Sex uint8 `json:"sex,optional"`
//生日
Birthday uint32 `json:"birthday,optional"`
// 密码加密后的值
PasswordHash *string `json:"passwordHash,optional"`
//验证码
Captcha string `json:"captcha,optional"`
// 验证码ID
CaptchaId string `json:"captchaId,optional"`
//VerificationType 类型 1 手机 2 邮箱
VerificationType *uint32 `json:"verificationType,optional"`
// Gender male or female or other , 男,女,其他
Gender *string `json:"gender,optional"`
// 注册来源 app,pc
RegisterSource *string `json:"registerSource,optional"`
}
// swagger:model RegisterResp
type RegisterResp struct {
// token信息
AuthToken *AuthToken `json:"authToken,optional"`
User *UserInfo `json:"userInfo,optional"`
}
type AuthToken struct {
// access_token
AccessToken string `json:"accessToken,optional"`
// refresh_token
RefreshToken string `json:"refreshToken,optional"`
// token_type 类型
TokenType string `json:"tokenType,optional"`
//access_token_expires
AccessTokenExpires int64 `json:"accessTokenExpires,optional"`
//refresh_token_expires
RefreshTokenExpires int64 `json:"refreshTokenExpires,optional"`
}
// swagger:model UserInfo
type UserInfo struct {
// 用户ID
Id uint64 `json:"id,optional"`
// 昵称
NickName string `json:"nickName,optional"`
//生日
Birthday int64 `json:"birthday,optional"`
// 头像
Avatar string `json:"avatar,optional"`
// Gender male or female or other , 男,女,其他
Gender *string `json:"gender,optional"`
// 账户注册类型:
// 1 手机 2 邮箱
RegisterType *uint32 `json:"registerType,optional"`
// 手机号
Mobile *string `json:"mobile,optional"`
// 用户名
Username string `json:"username,optional"`
//邮箱
Email *string `json:"email,optional"`
}
// swagger:model LoginReq
type LoginReq struct {
// UserName or Email or Mobile
UserName string `json:"userName"`
// Password
Password string `json:"password"`
// ClientIP
ClientIP string `json:"clientIp"`
// 登录方式
LoginType string `json:"loginType"`
// 登录系统
LoginPlatform string `json:"loginPlatform"`
}
// swagger:model LoginResp
type LoginResp struct {
BaseMsgResp
AuthToken *AuthToken
UserInfo *UserInfo
} }

6
go.work Normal file
View File

@ -0,0 +1,6 @@
go 1.25.3
use (
./api
./rpc
)

View File

@ -85,7 +85,7 @@ gen-ent: # Generate Ent codes | 生成 Ent 的代码
@echo "Generate Ent codes successfully" @echo "Generate Ent codes successfully"
.PHONY: gen-rpc-ent-logic .PHONY: gen-rpc-ent-logic
gen-rpc-ent-logic: # Generate logic code.proto from Ent, need model and group params | 根据 Ent 生成逻辑代码, 需要设置 model 和 group gen-rpc-ent-logic: # Generate logic code from Ent, need model and group params | 根据 Ent 生成逻辑代码, 需要设置 model 和 group
goctls rpc ent --schema=./ent/schema --style=$(PROJECT_STYLE) --multiple=false --service_name=$(SERVICE) --output=./ --model=$(model) --group=$(group) --proto_out=./desc/$(shell echo $(model) | tr A-Z a-z).proto --i18n=$(PROJECT_I18N) --overwrite=true goctls rpc ent --schema=./ent/schema --style=$(PROJECT_STYLE) --multiple=false --service_name=$(SERVICE) --output=./ --model=$(model) --group=$(group) --proto_out=./desc/$(shell echo $(model) | tr A-Z a-z).proto --i18n=$(PROJECT_I18N) --overwrite=true
@echo "Generate logic codes from Ent successfully" @echo "Generate logic codes from Ent successfully"

View File

@ -32,21 +32,45 @@ message AuthToken {
string access_token = 1; string access_token = 1;
string refresh_token = 2; string refresh_token = 2;
string token_type = 3; string token_type = 3;
int32 expires_in = 4; google.protobuf.Timestamp access_token_expires = 4;
google.protobuf.Timestamp issued_at = 5; google.protobuf.Timestamp refresh_token_expires = 5;
google.protobuf.Timestamp expires_at = 6; }
repeated string scopes = 7;
message BaseIDResp {
uint64 id = 1;
string msg = 2;
}
message BaseMsg {
string msg = 1;
}
message BaseResp {
string msg = 1;
}
message BaseUUIDResp {
string id = 1;
string msg = 2;
}
// base message
message Empty {}
message IDReq {
uint64 id = 1;
}
message IDsReq {
repeated uint64 ids = 1;
} }
message LoginRequest { message LoginRequest {
optional string username = 1; optional string username = 1;
optional string email = 2; optional string password = 2;
optional string mobile = 3; optional string clientIp = 3;
optional string password = 4; optional string loginTyp = 4;
optional string clientIp = 5; optional string loginPlatform = 5;
optional string platform = 6;
optional string login_type = 7;
optional string login_platform = 8;
} }
message LoginResponse { message LoginResponse {
@ -54,17 +78,37 @@ message LoginResponse {
AuthToken auth_token = 2; AuthToken auth_token = 2;
} }
message PageInfoReq {
uint64 page = 1;
uint64 page_size = 2;
}
message PageUserRequest {
uint64 page = 1;
uint64 page_size = 2;
optional string username = 3;
optional string email = 4;
optional string mobile = 5;
optional string status = 6;
optional string clientIp = 7;
}
message PageUserResponse {
repeated UserInfo users = 1;
uint64 total = 2;
}
message RegisterUserRequest { message RegisterUserRequest {
optional string email = 1; optional string email = 1;
optional string password = 2; optional string password = 2;
optional string username = 3; optional string username = 3;
optional string name = 4; optional string name = 4;
optional string mobile = 5; optional string mobile = 5;
optional string verificationCode = 6; optional string captcha = 6;
optional uint32 verificationType = 7; optional uint32 verificationType = 7;
optional string verificationId = 8;
optional string nickName = 9; optional string nickName = 9;
optional string registrationSource = 10; optional string registrationSource = 10;
optional string gender = 11;
} }
message RegisterUserResponse { message RegisterUserResponse {
@ -74,6 +118,14 @@ message RegisterUserResponse {
bool phone_verification_required = 4; bool phone_verification_required = 4;
} }
message UUIDReq {
string id = 1;
}
message UUIDsReq {
repeated string ids = 1;
}
message UserInfo { message UserInfo {
optional uint64 id = 1; optional uint64 id = 1;
optional string username = 2; optional string username = 2;
@ -94,6 +146,7 @@ message UserInfo {
optional int64 recovery_token_expiry = 17; optional int64 recovery_token_expiry = 17;
optional google.protobuf.Struct metadata = 20; optional google.protobuf.Struct metadata = 20;
optional string registration_source = 21; optional string registration_source = 21;
optional int64 birthday_at = 18;
} }
message VerifyCodeReq { message VerifyCodeReq {
@ -103,8 +156,8 @@ message VerifyCodeReq {
} }
message VerifyCodeResp { message VerifyCodeResp {
optional string code = 1; string captchaCode = 1;
optional uint32 expire = 2; uint32 expire = 2;
} }
// App // App
@ -114,9 +167,14 @@ service App {
rpc GetVerifyCode(VerifyCodeReq) returns (VerifyCodeResp); rpc GetVerifyCode(VerifyCodeReq) returns (VerifyCodeResp);
// //
// group: user // group: user
rpc registerUser(RegisterUserRequest) returns (RegisterUserResponse); rpc RegisterUser(RegisterUserRequest) returns (RegisterUserResponse);
// //
// group: user // group: user
rpc loginUser(LoginRequest) returns (LoginResponse); rpc LoginUser(LoginRequest) returns (LoginResponse);
//
// group: user
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
// group: base
rpc InitDatabase(Empty) returns (BaseResp);
} }

View File

@ -14,10 +14,22 @@ import (
type ( type (
AuthToken = app.AuthToken AuthToken = app.AuthToken
BaseIDResp = app.BaseIDResp
BaseMsg = app.BaseMsg
BaseResp = app.BaseResp
BaseUUIDResp = app.BaseUUIDResp
Empty = app.Empty
IDReq = app.IDReq
IDsReq = app.IDsReq
LoginRequest = app.LoginRequest LoginRequest = app.LoginRequest
LoginResponse = app.LoginResponse LoginResponse = app.LoginResponse
PageInfoReq = app.PageInfoReq
PageUserRequest = app.PageUserRequest
PageUserResponse = app.PageUserResponse
RegisterUserRequest = app.RegisterUserRequest RegisterUserRequest = app.RegisterUserRequest
RegisterUserResponse = app.RegisterUserResponse RegisterUserResponse = app.RegisterUserResponse
UUIDReq = app.UUIDReq
UUIDsReq = app.UUIDsReq
UserInfo = app.UserInfo UserInfo = app.UserInfo
VerifyCodeReq = app.VerifyCodeReq VerifyCodeReq = app.VerifyCodeReq
VerifyCodeResp = app.VerifyCodeResp VerifyCodeResp = app.VerifyCodeResp
@ -29,6 +41,9 @@ type (
RegisterUser(ctx context.Context, in *RegisterUserRequest, opts ...grpc.CallOption) (*RegisterUserResponse, error) RegisterUser(ctx context.Context, in *RegisterUserRequest, opts ...grpc.CallOption) (*RegisterUserResponse, error)
// 用户登录 // 用户登录
LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
// 分页查询用户信息
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
} }
defaultApp struct { defaultApp struct {
@ -59,3 +74,14 @@ func (m *defaultApp) LoginUser(ctx context.Context, in *LoginRequest, opts ...gr
client := app.NewAppClient(m.cli.Conn()) client := app.NewAppClient(m.cli.Conn())
return client.LoginUser(ctx, in, opts...) return client.LoginUser(ctx, in, opts...)
} }
// 分页查询用户信息
func (m *defaultApp) ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error) {
client := app.NewAppClient(m.cli.Conn())
return client.ListUsers(ctx, in, opts...)
}
func (m *defaultApp) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
client := app.NewAppClient(m.cli.Conn())
return client.InitDatabase(ctx, in, opts...)
}

View File

@ -33,8 +33,8 @@ message VerifyCodeReq{
} }
message VerifyCodeResp{ message VerifyCodeResp{
optional string code = 1; // string captchaCode = 1; //
optional uint32 expire = 2; // () uint32 expire = 2; // ()
} }

View File

@ -25,6 +25,7 @@ message UserInfo {
optional int64 recovery_token_expiry = 17; optional int64 recovery_token_expiry = 17;
optional google.protobuf.Struct metadata = 20; optional google.protobuf.Struct metadata = 20;
optional string registration_source = 21; optional string registration_source = 21;
optional int64 birthday_at = 18;
} }
@ -34,11 +35,11 @@ message RegisterUserRequest {
optional string username = 3; optional string username = 3;
optional string name = 4; optional string name = 4;
optional string mobile = 5; optional string mobile = 5;
optional string verificationCode = 6; optional string captcha = 6;
optional uint32 verificationType = 7; optional uint32 verificationType = 7;
optional string verificationId = 8; //
optional string nickName = 9; optional string nickName = 9;
optional string registrationSource = 10; optional string registrationSource = 10;
optional string gender = 11;
} }
message RegisterUserResponse { message RegisterUserResponse {
UserInfo user = 1; UserInfo user = 1;
@ -52,10 +53,8 @@ message AuthToken {
string access_token = 1; string access_token = 1;
string refresh_token = 2; string refresh_token = 2;
string token_type = 3; string token_type = 3;
int32 expires_in = 4; // google.protobuf.Timestamp access_token_expires = 4;
google.protobuf.Timestamp issued_at = 5; google.protobuf.Timestamp refresh_token_expires = 5;
google.protobuf.Timestamp expires_at = 6;
repeated string scopes = 7;
} }
message LoginResponse{ message LoginResponse{
@ -64,20 +63,38 @@ message LoginResponse{
} }
message LoginRequest { message LoginRequest {
optional string username = 1; optional string username = 1;
optional string email = 2; optional string password = 2;
optional string mobile = 3; optional string clientIp = 3;
optional string password = 4; optional string loginTyp = 4;
optional string clientIp = 5; optional string loginPlatform = 5;
optional string platform = 6;
optional string login_type = 7;
optional string login_platform = 8;
} }
message PageUserRequest {
uint64 page = 1;
uint64 page_size = 2;
optional string username = 3;
optional string email = 4;
optional string mobile = 5;
optional string status = 6;
optional string clientIp = 7;
}
message PageUserResponse {
repeated UserInfo users = 1;
uint64 total = 2;
}
// App // App
service App { service App {
// //
// group: user // group: user
rpc registerUser(RegisterUserRequest) returns (RegisterUserResponse); rpc RegisterUser(RegisterUserRequest) returns (RegisterUserResponse);
// //
// group: user // group: user
rpc loginUser(LoginRequest) returns (LoginResponse); rpc LoginUser(LoginRequest) returns (LoginResponse);
//
// group: user
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
} }

54
rpc/desc/base.proto Normal file
View File

@ -0,0 +1,54 @@
syntax = "proto3";
package app;
option go_package = "./app";
// base message
message Empty {}
message IDReq {
uint64 id = 1;
}
message IDsReq {
repeated uint64 ids = 1;
}
message UUIDsReq {
repeated string ids = 1;
}
message UUIDReq {
string id = 1;
}
message BaseResp {
string msg = 1;
}
message PageInfoReq {
uint64 page = 1;
uint64 page_size = 2;
}
message BaseMsg {
string msg = 1;
}
message BaseIDResp {
uint64 id = 1;
string msg = 2;
}
message BaseUUIDResp {
string id = 1;
string msg = 2;
}
service App {
// group: base
rpc InitDatabase(Empty) returns (BaseResp);
}

View File

@ -17,7 +17,7 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/dialect/sql/sqlgraph"
) )
// ent aliases to avoid import conflicts in user's code.proto. // ent aliases to avoid import conflicts in user's code.
type ( type (
Op = ent.Op Op = ent.Op
Hook = ent.Hook Hook = ent.Hook

View File

@ -16,7 +16,7 @@ import (
) )
// The Query interface represents an operation that queries a graph. // The Query interface represents an operation that queries a graph.
// By using this interface, users can write generic code.proto that manipulates // By using this interface, users can write generic code that manipulates
// query builders of different types. // query builders of different types.
type Query interface { type Query interface {
// Type returns the string representation of the query type. // Type returns the string representation of the query type.

View File

@ -21,7 +21,7 @@ var (
{Name: "email", Type: field.TypeString, Unique: true, Size: 255, Comment: "邮箱"}, {Name: "email", Type: field.TypeString, Unique: true, Size: 255, Comment: "邮箱"},
{Name: "mobile", Type: field.TypeString, Nullable: true, Size: 64, Comment: "联系方式"}, {Name: "mobile", Type: field.TypeString, Nullable: true, Size: 64, Comment: "联系方式"},
{Name: "password_hash", Type: field.TypeString, Comment: "密码"}, {Name: "password_hash", Type: field.TypeString, Comment: "密码"},
{Name: "salt", Type: field.TypeString, Size: 32, Comment: "salt盐值"}, {Name: "salt", Type: field.TypeString, Size: 255, Comment: "salt盐值"},
{Name: "nickname", Type: field.TypeString, Size: 50, Comment: "昵称", Default: ""}, {Name: "nickname", Type: field.TypeString, Size: 50, Comment: "昵称", Default: ""},
{Name: "avatar", Type: field.TypeString, Nullable: true, Size: 500, Comment: "头像"}, {Name: "avatar", Type: field.TypeString, Nullable: true, Size: 500, Comment: "头像"},
{Name: "gender", Type: field.TypeEnum, Comment: "性别", Enums: []string{"unknown", "male", "female", "other"}, Default: "unknown"}, {Name: "gender", Type: field.TypeEnum, Comment: "性别", Enums: []string{"unknown", "male", "female", "other"}, Default: "unknown"},
@ -60,27 +60,28 @@ var (
// UserLoginLogsColumns holds the columns for the "user_login_logs" table. // UserLoginLogsColumns holds the columns for the "user_login_logs" table.
UserLoginLogsColumns = []*schema.Column{ UserLoginLogsColumns = []*schema.Column{
{Name: "id", Type: field.TypeUint64, Increment: true}, {Name: "id", Type: field.TypeUint64, Increment: true},
{Name: "created_at", Type: field.TypeTime}, {Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
{Name: "updated_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
{Name: "status", Type: field.TypeUint8, Nullable: true, Default: 1}, {Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
{Name: "tenant_id", Type: field.TypeUint64, Default: 1}, {Name: "tenant_id", Type: field.TypeUint64, Comment: "Tenant ID | 租户 ID", Default: 1},
{Name: "deleted_at", Type: field.TypeTime, Nullable: true}, {Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
{Name: "user_id", Type: field.TypeUint64}, {Name: "user_id", Type: field.TypeUint64, Comment: "用户ID"},
{Name: "login_time", Type: field.TypeTime}, {Name: "login_time", Type: field.TypeTime},
{Name: "login_ip", Type: field.TypeString, Size: 45}, {Name: "login_ip", Type: field.TypeString, Size: 45},
{Name: "login_location", Type: field.TypeString, Nullable: true, Size: 200}, {Name: "login_location", Type: field.TypeString, Nullable: true, Size: 200},
{Name: "login_type", Type: field.TypeEnum, Enums: []string{"password", "sms_code", "email_code", "wechat", "alipay", "apple", "google", "other_third_party"}, Default: "password"}, {Name: "login_type", Type: field.TypeEnum, Enums: []string{"password", "sms_code", "email_code", "wechat", "alipay", "apple", "google", "other_third_party"}, Default: "password"},
{Name: "login_platform", Type: field.TypeEnum, Enums: []string{"ios", "android"}, Default: "android"}, {Name: "login_platform", Type: field.TypeEnum, Enums: []string{"ios", "android", "windows"}, Default: "android"},
{Name: "login_result", Type: field.TypeBool, Default: true}, {Name: "login_result", Type: field.TypeBool, Comment: "登录结果,是否成功", Default: true},
{Name: "failure_reason", Type: field.TypeString, Nullable: true, Size: 500}, {Name: "failure_reason", Type: field.TypeString, Nullable: true, Size: 500},
{Name: "session_id", Type: field.TypeString, Nullable: true, Size: 200}, {Name: "session_id", Type: field.TypeString, Nullable: true, Size: 200},
{Name: "latency_ms", Type: field.TypeInt, Nullable: true}, {Name: "latency_ms", Type: field.TypeInt, Nullable: true},
{Name: "auth_id", Type: field.TypeUint64, Nullable: true}, {Name: "auth_id", Type: field.TypeUint64, Nullable: true, Comment: "auth_id"},
{Name: "additional_data", Type: field.TypeJSON, Nullable: true}, {Name: "additional_data", Type: field.TypeJSON, Nullable: true},
} }
// UserLoginLogsTable holds the schema information for the "user_login_logs" table. // UserLoginLogsTable holds the schema information for the "user_login_logs" table.
UserLoginLogsTable = &schema.Table{ UserLoginLogsTable = &schema.Table{
Name: "user_login_logs", Name: "user_login_logs",
Comment: "user_login_logs Table | 用户登录信息表",
Columns: UserLoginLogsColumns, Columns: UserLoginLogsColumns,
PrimaryKey: []*schema.Column{UserLoginLogsColumns[0]}, PrimaryKey: []*schema.Column{UserLoginLogsColumns[0]},
Indexes: []*schema.Index{ Indexes: []*schema.Index{
@ -124,13 +125,13 @@ var (
// UserThirdAuthsColumns holds the columns for the "user_third_auths" table. // UserThirdAuthsColumns holds the columns for the "user_third_auths" table.
UserThirdAuthsColumns = []*schema.Column{ UserThirdAuthsColumns = []*schema.Column{
{Name: "id", Type: field.TypeUint64, Increment: true}, {Name: "id", Type: field.TypeUint64, Increment: true},
{Name: "created_at", Type: field.TypeTime}, {Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
{Name: "updated_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
{Name: "status", Type: field.TypeUint8, Nullable: true, Default: 1}, {Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
{Name: "tenant_id", Type: field.TypeUint64, Default: 1}, {Name: "tenant_id", Type: field.TypeUint64, Comment: "Tenant ID | 租户 ID", Default: 1},
{Name: "deleted_at", Type: field.TypeTime, Nullable: true}, {Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
{Name: "user_id", Type: field.TypeUint64}, {Name: "user_id", Type: field.TypeUint64, Comment: "用户ID"},
{Name: "openid", Type: field.TypeString, Size: 255}, {Name: "openid", Type: field.TypeString, Nullable: true, Size: 255},
{Name: "unionid", Type: field.TypeString, Nullable: true, Size: 255}, {Name: "unionid", Type: field.TypeString, Nullable: true, Size: 255},
{Name: "access_token", Type: field.TypeString, Nullable: true, Size: 2000}, {Name: "access_token", Type: field.TypeString, Nullable: true, Size: 2000},
{Name: "refresh_token", Type: field.TypeString, Nullable: true, Size: 2000}, {Name: "refresh_token", Type: field.TypeString, Nullable: true, Size: 2000},
@ -140,7 +141,7 @@ var (
{Name: "nickname", Type: field.TypeString, Nullable: true, Size: 100}, {Name: "nickname", Type: field.TypeString, Nullable: true, Size: 100},
{Name: "avatar", Type: field.TypeString, Nullable: true, Size: 500}, {Name: "avatar", Type: field.TypeString, Nullable: true, Size: 500},
{Name: "email", Type: field.TypeString, Nullable: true, Size: 255}, {Name: "email", Type: field.TypeString, Nullable: true, Size: 255},
{Name: "phone", Type: field.TypeString, Nullable: true, Size: 20}, {Name: "mobile", Type: field.TypeString, Nullable: true, Size: 20},
{Name: "is_bound", Type: field.TypeBool, Default: true}, {Name: "is_bound", Type: field.TypeBool, Default: true},
{Name: "bound_at", Type: field.TypeTime}, {Name: "bound_at", Type: field.TypeTime},
{Name: "extra_data", Type: field.TypeJSON, Nullable: true}, {Name: "extra_data", Type: field.TypeJSON, Nullable: true},
@ -148,6 +149,7 @@ var (
// UserThirdAuthsTable holds the schema information for the "user_third_auths" table. // UserThirdAuthsTable holds the schema information for the "user_third_auths" table.
UserThirdAuthsTable = &schema.Table{ UserThirdAuthsTable = &schema.Table{
Name: "user_third_auths", Name: "user_third_auths",
Comment: "user_third_auths Table | 用户token表",
Columns: UserThirdAuthsColumns, Columns: UserThirdAuthsColumns,
PrimaryKey: []*schema.Column{UserThirdAuthsColumns[0]}, PrimaryKey: []*schema.Column{UserThirdAuthsColumns[0]},
} }
@ -163,4 +165,10 @@ func init() {
UserTable.Annotation = &entsql.Annotation{ UserTable.Annotation = &entsql.Annotation{
Table: "user", Table: "user",
} }
UserLoginLogsTable.Annotation = &entsql.Annotation{
Table: "user_login_logs",
}
UserThirdAuthsTable.Annotation = &entsql.Annotation{
Table: "user_third_auths",
}
} }

View File

@ -3227,7 +3227,7 @@ type UserThirdAuthMutation struct {
nickname *string nickname *string
avatar *string avatar *string
email *string email *string
phone *string mobile *string
is_bound *bool is_bound *bool
bound_at *time.Time bound_at *time.Time
extra_data *map[string]interface{} extra_data *map[string]interface{}
@ -3675,9 +3675,22 @@ func (m *UserThirdAuthMutation) OldOpenid(ctx context.Context) (v string, err er
return oldValue.Openid, nil return oldValue.Openid, nil
} }
// ClearOpenid clears the value of the "openid" field.
func (m *UserThirdAuthMutation) ClearOpenid() {
m.openid = nil
m.clearedFields[userthirdauth.FieldOpenid] = struct{}{}
}
// OpenidCleared returns if the "openid" field was cleared in this mutation.
func (m *UserThirdAuthMutation) OpenidCleared() bool {
_, ok := m.clearedFields[userthirdauth.FieldOpenid]
return ok
}
// ResetOpenid resets all changes to the "openid" field. // ResetOpenid resets all changes to the "openid" field.
func (m *UserThirdAuthMutation) ResetOpenid() { func (m *UserThirdAuthMutation) ResetOpenid() {
m.openid = nil m.openid = nil
delete(m.clearedFields, userthirdauth.FieldOpenid)
} }
// SetUnionid sets the "unionid" field. // SetUnionid sets the "unionid" field.
@ -4121,53 +4134,53 @@ func (m *UserThirdAuthMutation) ResetEmail() {
delete(m.clearedFields, userthirdauth.FieldEmail) delete(m.clearedFields, userthirdauth.FieldEmail)
} }
// SetPhone sets the "phone" field. // SetMobile sets the "mobile" field.
func (m *UserThirdAuthMutation) SetPhone(s string) { func (m *UserThirdAuthMutation) SetMobile(s string) {
m.phone = &s m.mobile = &s
} }
// Phone returns the value of the "phone" field in the mutation. // Mobile returns the value of the "mobile" field in the mutation.
func (m *UserThirdAuthMutation) Phone() (r string, exists bool) { func (m *UserThirdAuthMutation) Mobile() (r string, exists bool) {
v := m.phone v := m.mobile
if v == nil { if v == nil {
return return
} }
return *v, true return *v, true
} }
// OldPhone returns the old "phone" field's value of the UserThirdAuth entity. // OldMobile returns the old "mobile" field's value of the UserThirdAuth entity.
// If the UserThirdAuth object wasn't provided to the builder, the object is fetched from the database. // If the UserThirdAuth object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails. // An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *UserThirdAuthMutation) OldPhone(ctx context.Context) (v string, err error) { func (m *UserThirdAuthMutation) OldMobile(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) { if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPhone is only allowed on UpdateOne operations") return v, errors.New("OldMobile is only allowed on UpdateOne operations")
} }
if m.id == nil || m.oldValue == nil { if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPhone requires an ID field in the mutation") return v, errors.New("OldMobile requires an ID field in the mutation")
} }
oldValue, err := m.oldValue(ctx) oldValue, err := m.oldValue(ctx)
if err != nil { if err != nil {
return v, fmt.Errorf("querying old value for OldPhone: %w", err) return v, fmt.Errorf("querying old value for OldMobile: %w", err)
} }
return oldValue.Phone, nil return oldValue.Mobile, nil
} }
// ClearPhone clears the value of the "phone" field. // ClearMobile clears the value of the "mobile" field.
func (m *UserThirdAuthMutation) ClearPhone() { func (m *UserThirdAuthMutation) ClearMobile() {
m.phone = nil m.mobile = nil
m.clearedFields[userthirdauth.FieldPhone] = struct{}{} m.clearedFields[userthirdauth.FieldMobile] = struct{}{}
} }
// PhoneCleared returns if the "phone" field was cleared in this mutation. // MobileCleared returns if the "mobile" field was cleared in this mutation.
func (m *UserThirdAuthMutation) PhoneCleared() bool { func (m *UserThirdAuthMutation) MobileCleared() bool {
_, ok := m.clearedFields[userthirdauth.FieldPhone] _, ok := m.clearedFields[userthirdauth.FieldMobile]
return ok return ok
} }
// ResetPhone resets all changes to the "phone" field. // ResetMobile resets all changes to the "mobile" field.
func (m *UserThirdAuthMutation) ResetPhone() { func (m *UserThirdAuthMutation) ResetMobile() {
m.phone = nil m.mobile = nil
delete(m.clearedFields, userthirdauth.FieldPhone) delete(m.clearedFields, userthirdauth.FieldMobile)
} }
// SetIsBound sets the "is_bound" field. // SetIsBound sets the "is_bound" field.
@ -4374,8 +4387,8 @@ func (m *UserThirdAuthMutation) Fields() []string {
if m.email != nil { if m.email != nil {
fields = append(fields, userthirdauth.FieldEmail) fields = append(fields, userthirdauth.FieldEmail)
} }
if m.phone != nil { if m.mobile != nil {
fields = append(fields, userthirdauth.FieldPhone) fields = append(fields, userthirdauth.FieldMobile)
} }
if m.is_bound != nil { if m.is_bound != nil {
fields = append(fields, userthirdauth.FieldIsBound) fields = append(fields, userthirdauth.FieldIsBound)
@ -4426,8 +4439,8 @@ func (m *UserThirdAuthMutation) Field(name string) (ent.Value, bool) {
return m.Avatar() return m.Avatar()
case userthirdauth.FieldEmail: case userthirdauth.FieldEmail:
return m.Email() return m.Email()
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
return m.Phone() return m.Mobile()
case userthirdauth.FieldIsBound: case userthirdauth.FieldIsBound:
return m.IsBound() return m.IsBound()
case userthirdauth.FieldBoundAt: case userthirdauth.FieldBoundAt:
@ -4475,8 +4488,8 @@ func (m *UserThirdAuthMutation) OldField(ctx context.Context, name string) (ent.
return m.OldAvatar(ctx) return m.OldAvatar(ctx)
case userthirdauth.FieldEmail: case userthirdauth.FieldEmail:
return m.OldEmail(ctx) return m.OldEmail(ctx)
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
return m.OldPhone(ctx) return m.OldMobile(ctx)
case userthirdauth.FieldIsBound: case userthirdauth.FieldIsBound:
return m.OldIsBound(ctx) return m.OldIsBound(ctx)
case userthirdauth.FieldBoundAt: case userthirdauth.FieldBoundAt:
@ -4604,12 +4617,12 @@ func (m *UserThirdAuthMutation) SetField(name string, value ent.Value) error {
} }
m.SetEmail(v) m.SetEmail(v)
return nil return nil
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
v, ok := value.(string) v, ok := value.(string)
if !ok { if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name) return fmt.Errorf("unexpected type %T for field %s", value, name)
} }
m.SetPhone(v) m.SetMobile(v)
return nil return nil
case userthirdauth.FieldIsBound: case userthirdauth.FieldIsBound:
v, ok := value.(bool) v, ok := value.(bool)
@ -4707,6 +4720,9 @@ func (m *UserThirdAuthMutation) ClearedFields() []string {
if m.FieldCleared(userthirdauth.FieldDeletedAt) { if m.FieldCleared(userthirdauth.FieldDeletedAt) {
fields = append(fields, userthirdauth.FieldDeletedAt) fields = append(fields, userthirdauth.FieldDeletedAt)
} }
if m.FieldCleared(userthirdauth.FieldOpenid) {
fields = append(fields, userthirdauth.FieldOpenid)
}
if m.FieldCleared(userthirdauth.FieldUnionid) { if m.FieldCleared(userthirdauth.FieldUnionid) {
fields = append(fields, userthirdauth.FieldUnionid) fields = append(fields, userthirdauth.FieldUnionid)
} }
@ -4734,8 +4750,8 @@ func (m *UserThirdAuthMutation) ClearedFields() []string {
if m.FieldCleared(userthirdauth.FieldEmail) { if m.FieldCleared(userthirdauth.FieldEmail) {
fields = append(fields, userthirdauth.FieldEmail) fields = append(fields, userthirdauth.FieldEmail)
} }
if m.FieldCleared(userthirdauth.FieldPhone) { if m.FieldCleared(userthirdauth.FieldMobile) {
fields = append(fields, userthirdauth.FieldPhone) fields = append(fields, userthirdauth.FieldMobile)
} }
if m.FieldCleared(userthirdauth.FieldExtraData) { if m.FieldCleared(userthirdauth.FieldExtraData) {
fields = append(fields, userthirdauth.FieldExtraData) fields = append(fields, userthirdauth.FieldExtraData)
@ -4760,6 +4776,9 @@ func (m *UserThirdAuthMutation) ClearField(name string) error {
case userthirdauth.FieldDeletedAt: case userthirdauth.FieldDeletedAt:
m.ClearDeletedAt() m.ClearDeletedAt()
return nil return nil
case userthirdauth.FieldOpenid:
m.ClearOpenid()
return nil
case userthirdauth.FieldUnionid: case userthirdauth.FieldUnionid:
m.ClearUnionid() m.ClearUnionid()
return nil return nil
@ -4787,8 +4806,8 @@ func (m *UserThirdAuthMutation) ClearField(name string) error {
case userthirdauth.FieldEmail: case userthirdauth.FieldEmail:
m.ClearEmail() m.ClearEmail()
return nil return nil
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
m.ClearPhone() m.ClearMobile()
return nil return nil
case userthirdauth.FieldExtraData: case userthirdauth.FieldExtraData:
m.ClearExtraData() m.ClearExtraData()
@ -4849,8 +4868,8 @@ func (m *UserThirdAuthMutation) ResetField(name string) error {
case userthirdauth.FieldEmail: case userthirdauth.FieldEmail:
m.ResetEmail() m.ResetEmail()
return nil return nil
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
m.ResetPhone() m.ResetMobile()
return nil return nil
case userthirdauth.FieldIsBound: case userthirdauth.FieldIsBound:
m.ResetIsBound() m.ResetIsBound()

View File

@ -10,7 +10,7 @@ import (
"time" "time"
) )
// The init function reads all schema descriptors with runtime code.proto // The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it // (default values, validators, hooks and policies) and stitches it
// to their package variables. // to their package variables.
func init() { func init() {
@ -226,21 +226,7 @@ func init() {
// userthirdauthDescOpenid is the schema descriptor for openid field. // userthirdauthDescOpenid is the schema descriptor for openid field.
userthirdauthDescOpenid := userthirdauthFields[1].Descriptor() userthirdauthDescOpenid := userthirdauthFields[1].Descriptor()
// userthirdauth.OpenidValidator is a validator for the "openid" field. It is called by the builders before save. // userthirdauth.OpenidValidator is a validator for the "openid" field. It is called by the builders before save.
userthirdauth.OpenidValidator = func() func(string) error { userthirdauth.OpenidValidator = userthirdauthDescOpenid.Validators[0].(func(string) error)
validators := userthirdauthDescOpenid.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(openid string) error {
for _, fn := range fns {
if err := fn(openid); err != nil {
return err
}
}
return nil
}
}()
// userthirdauthDescUnionid is the schema descriptor for unionid field. // userthirdauthDescUnionid is the schema descriptor for unionid field.
userthirdauthDescUnionid := userthirdauthFields[2].Descriptor() userthirdauthDescUnionid := userthirdauthFields[2].Descriptor()
// userthirdauth.UnionidValidator is a validator for the "unionid" field. It is called by the builders before save. // userthirdauth.UnionidValidator is a validator for the "unionid" field. It is called by the builders before save.
@ -269,10 +255,10 @@ func init() {
userthirdauthDescEmail := userthirdauthFields[10].Descriptor() userthirdauthDescEmail := userthirdauthFields[10].Descriptor()
// userthirdauth.EmailValidator is a validator for the "email" field. It is called by the builders before save. // userthirdauth.EmailValidator is a validator for the "email" field. It is called by the builders before save.
userthirdauth.EmailValidator = userthirdauthDescEmail.Validators[0].(func(string) error) userthirdauth.EmailValidator = userthirdauthDescEmail.Validators[0].(func(string) error)
// userthirdauthDescPhone is the schema descriptor for phone field. // userthirdauthDescMobile is the schema descriptor for mobile field.
userthirdauthDescPhone := userthirdauthFields[11].Descriptor() userthirdauthDescMobile := userthirdauthFields[11].Descriptor()
// userthirdauth.PhoneValidator is a validator for the "phone" field. It is called by the builders before save. // userthirdauth.MobileValidator is a validator for the "mobile" field. It is called by the builders before save.
userthirdauth.PhoneValidator = userthirdauthDescPhone.Validators[0].(func(string) error) userthirdauth.MobileValidator = userthirdauthDescMobile.Validators[0].(func(string) error)
// userthirdauthDescIsBound is the schema descriptor for is_bound field. // userthirdauthDescIsBound is the schema descriptor for is_bound field.
userthirdauthDescIsBound := userthirdauthFields[12].Descriptor() userthirdauthDescIsBound := userthirdauthFields[12].Descriptor()
// userthirdauth.DefaultIsBound holds the default value on creation for the is_bound field. // userthirdauth.DefaultIsBound holds the default value on creation for the is_bound field.

View File

@ -45,7 +45,7 @@ func (User) Fields() []ent.Field {
field.String("salt").Comment("salt盐值"). field.String("salt").Comment("salt盐值").
NotEmpty(). NotEmpty().
Sensitive(). Sensitive().
MaxLen(32), MaxLen(255),
// 个人信息 // 个人信息
field.String("nickname").Comment("昵称"). field.String("nickname").Comment("昵称").
Default(""). Default("").

View File

@ -2,6 +2,8 @@ package schema
import ( import (
"entgo.io/ent" "entgo.io/ent"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field" "entgo.io/ent/schema/field"
"entgo.io/ent/schema/index" "entgo.io/ent/schema/index"
"github.com/saas-mingyang/mingyang-admin-common/orm/ent/mixins" "github.com/saas-mingyang/mingyang-admin-common/orm/ent/mixins"
@ -40,7 +42,7 @@ func (UserLoginLog) Fields() []ent.Field {
field.Enum("login_platform"). field.Enum("login_platform").
Values( Values(
"ios", "ios",
"android"). "android", "windows").
Default("android"), Default("android"),
field.Bool("login_result"). field.Bool("login_result").
Comment("登录结果,是否成功"). Comment("登录结果,是否成功").
@ -84,3 +86,11 @@ func (UserLoginLog) Indexes() []ent.Index {
index.Fields("session_id"), index.Fields("session_id"),
} }
} }
func (UserLoginLog) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.WithComments(true),
schema.Comment("user_login_logs Table | 用户登录信息表"),
entsql.Annotation{Table: "user_login_logs"},
}
}

View File

@ -2,6 +2,8 @@ package schema
import ( import (
"entgo.io/ent" "entgo.io/ent"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field" "entgo.io/ent/schema/field"
"github.com/saas-mingyang/mingyang-admin-common/orm/ent/mixins" "github.com/saas-mingyang/mingyang-admin-common/orm/ent/mixins"
mixins2 "mingyang-admin-app-rpc/ent/schema/mixins" mixins2 "mingyang-admin-app-rpc/ent/schema/mixins"
@ -18,7 +20,7 @@ func (UserThirdAuth) Fields() []ent.Field {
field.Uint64("user_id"). field.Uint64("user_id").
Comment("用户ID"), Comment("用户ID"),
field.String("openid"). field.String("openid").
NotEmpty(). Optional().
MaxLen(255), MaxLen(255),
field.String("unionid"). field.String("unionid").
Optional(). Optional().
@ -48,7 +50,7 @@ func (UserThirdAuth) Fields() []ent.Field {
field.String("email"). field.String("email").
Optional(). Optional().
MaxLen(255), MaxLen(255),
field.String("phone"). field.String("mobile").
Optional(). Optional().
MaxLen(20), MaxLen(20),
field.Bool("is_bound"). field.Bool("is_bound").
@ -76,3 +78,11 @@ func (UserThirdAuth) Edges() []ent.Edge {
func (UserThirdAuth) Indexes() []ent.Index { func (UserThirdAuth) Indexes() []ent.Index {
return []ent.Index{} return []ent.Index{}
} }
func (UserThirdAuth) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.WithComments(true),
schema.Comment("user_third_auths Table | 用户token表"),
entsql.Annotation{Table: "user_third_auths"},
}
}

View File

@ -1137,25 +1137,25 @@ func (_m *UserThirdAuthCreate) SetNotNilEmail(value *string) *UserThirdAuthCreat
} }
// set field if value's pointer is not nil. // set field if value's pointer is not nil.
func (_m *UserThirdAuthUpdate) SetNotNilPhone(value *string) *UserThirdAuthUpdate { func (_m *UserThirdAuthUpdate) SetNotNilMobile(value *string) *UserThirdAuthUpdate {
if value != nil { if value != nil {
return _m.SetPhone(*value) return _m.SetMobile(*value)
} }
return _m return _m
} }
// set field if value's pointer is not nil. // set field if value's pointer is not nil.
func (_m *UserThirdAuthUpdateOne) SetNotNilPhone(value *string) *UserThirdAuthUpdateOne { func (_m *UserThirdAuthUpdateOne) SetNotNilMobile(value *string) *UserThirdAuthUpdateOne {
if value != nil { if value != nil {
return _m.SetPhone(*value) return _m.SetMobile(*value)
} }
return _m return _m
} }
// set field if value's pointer is not nil. // set field if value's pointer is not nil.
func (_m *UserThirdAuthCreate) SetNotNilPhone(value *string) *UserThirdAuthCreate { func (_m *UserThirdAuthCreate) SetNotNilMobile(value *string) *UserThirdAuthCreate {
if value != nil { if value != nil {
return _m.SetPhone(*value) return _m.SetMobile(*value)
} }
return _m return _m
} }

View File

@ -157,7 +157,7 @@ func (tx *Tx) init() {
} }
// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. // txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.
// The idea is to support transactions without adding any extra code.proto to the builders. // The idea is to support transactions without adding any extra code to the builders.
// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance. // When a builder calls to driver.Tx(), it gets the same dialect.Tx instance.
// Commit and Rollback are nop for the internal builders and the user must call one // Commit and Rollback are nop for the internal builders and the user must call one
// of them in order to commit or rollback the transaction. // of them in order to commit or rollback the transaction.

View File

@ -13,7 +13,7 @@ import (
"entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql"
) )
// UserLoginLog is the model entity for the UserLoginLog schema. // user_login_logs Table | 用户登录信息表
type UserLoginLog struct { type UserLoginLog struct {
config `json:"-"` config `json:"-"`
// ID of the ent. // ID of the ent.

View File

@ -151,6 +151,7 @@ const DefaultLoginPlatform = LoginPlatformAndroid
const ( const (
LoginPlatformIos LoginPlatform = "ios" LoginPlatformIos LoginPlatform = "ios"
LoginPlatformAndroid LoginPlatform = "android" LoginPlatformAndroid LoginPlatform = "android"
LoginPlatformWindows LoginPlatform = "windows"
) )
func (lp LoginPlatform) String() string { func (lp LoginPlatform) String() string {
@ -160,7 +161,7 @@ func (lp LoginPlatform) String() string {
// LoginPlatformValidator is a validator for the "login_platform" field enum values. It is called by the builders before save. // LoginPlatformValidator is a validator for the "login_platform" field enum values. It is called by the builders before save.
func LoginPlatformValidator(lp LoginPlatform) error { func LoginPlatformValidator(lp LoginPlatform) error {
switch lp { switch lp {
case LoginPlatformIos, LoginPlatformAndroid: case LoginPlatformIos, LoginPlatformAndroid, LoginPlatformWindows:
return nil return nil
default: default:
return fmt.Errorf("userloginlog: invalid enum value for login_platform field: %q", lp) return fmt.Errorf("userloginlog: invalid enum value for login_platform field: %q", lp)

View File

@ -13,7 +13,7 @@ import (
"entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql"
) )
// UserThirdAuth is the model entity for the UserThirdAuth schema. // user_third_auths Table | 用户token表
type UserThirdAuth struct { type UserThirdAuth struct {
config `json:"-"` config `json:"-"`
// ID of the ent. // ID of the ent.
@ -50,8 +50,8 @@ type UserThirdAuth struct {
Avatar string `json:"avatar,omitempty"` Avatar string `json:"avatar,omitempty"`
// Email holds the value of the "email" field. // Email holds the value of the "email" field.
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
// Phone holds the value of the "phone" field. // Mobile holds the value of the "mobile" field.
Phone string `json:"phone,omitempty"` Mobile string `json:"mobile,omitempty"`
// IsBound holds the value of the "is_bound" field. // IsBound holds the value of the "is_bound" field.
IsBound bool `json:"is_bound,omitempty"` IsBound bool `json:"is_bound,omitempty"`
// BoundAt holds the value of the "bound_at" field. // BoundAt holds the value of the "bound_at" field.
@ -72,7 +72,7 @@ func (*UserThirdAuth) scanValues(columns []string) ([]any, error) {
values[i] = new(sql.NullBool) values[i] = new(sql.NullBool)
case userthirdauth.FieldID, userthirdauth.FieldStatus, userthirdauth.FieldTenantID, userthirdauth.FieldUserID: case userthirdauth.FieldID, userthirdauth.FieldStatus, userthirdauth.FieldTenantID, userthirdauth.FieldUserID:
values[i] = new(sql.NullInt64) values[i] = new(sql.NullInt64)
case userthirdauth.FieldOpenid, userthirdauth.FieldUnionid, userthirdauth.FieldAccessToken, userthirdauth.FieldRefreshToken, userthirdauth.FieldPlatformUserID, userthirdauth.FieldNickname, userthirdauth.FieldAvatar, userthirdauth.FieldEmail, userthirdauth.FieldPhone: case userthirdauth.FieldOpenid, userthirdauth.FieldUnionid, userthirdauth.FieldAccessToken, userthirdauth.FieldRefreshToken, userthirdauth.FieldPlatformUserID, userthirdauth.FieldNickname, userthirdauth.FieldAvatar, userthirdauth.FieldEmail, userthirdauth.FieldMobile:
values[i] = new(sql.NullString) values[i] = new(sql.NullString)
case userthirdauth.FieldCreatedAt, userthirdauth.FieldUpdatedAt, userthirdauth.FieldDeletedAt, userthirdauth.FieldAccessTokenExpiry, userthirdauth.FieldBoundAt: case userthirdauth.FieldCreatedAt, userthirdauth.FieldUpdatedAt, userthirdauth.FieldDeletedAt, userthirdauth.FieldAccessTokenExpiry, userthirdauth.FieldBoundAt:
values[i] = new(sql.NullTime) values[i] = new(sql.NullTime)
@ -196,11 +196,11 @@ func (_m *UserThirdAuth) assignValues(columns []string, values []any) error {
} else if value.Valid { } else if value.Valid {
_m.Email = value.String _m.Email = value.String
} }
case userthirdauth.FieldPhone: case userthirdauth.FieldMobile:
if value, ok := values[i].(*sql.NullString); !ok { if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field phone", values[i]) return fmt.Errorf("unexpected type %T for field mobile", values[i])
} else if value.Valid { } else if value.Valid {
_m.Phone = value.String _m.Mobile = value.String
} }
case userthirdauth.FieldIsBound: case userthirdauth.FieldIsBound:
if value, ok := values[i].(*sql.NullBool); !ok { if value, ok := values[i].(*sql.NullBool); !ok {
@ -306,8 +306,8 @@ func (_m *UserThirdAuth) String() string {
builder.WriteString("email=") builder.WriteString("email=")
builder.WriteString(_m.Email) builder.WriteString(_m.Email)
builder.WriteString(", ") builder.WriteString(", ")
builder.WriteString("phone=") builder.WriteString("mobile=")
builder.WriteString(_m.Phone) builder.WriteString(_m.Mobile)
builder.WriteString(", ") builder.WriteString(", ")
builder.WriteString("is_bound=") builder.WriteString("is_bound=")
builder.WriteString(fmt.Sprintf("%v", _m.IsBound)) builder.WriteString(fmt.Sprintf("%v", _m.IsBound))

View File

@ -45,8 +45,8 @@ const (
FieldAvatar = "avatar" FieldAvatar = "avatar"
// FieldEmail holds the string denoting the email field in the database. // FieldEmail holds the string denoting the email field in the database.
FieldEmail = "email" FieldEmail = "email"
// FieldPhone holds the string denoting the phone field in the database. // FieldMobile holds the string denoting the mobile field in the database.
FieldPhone = "phone" FieldMobile = "mobile"
// FieldIsBound holds the string denoting the is_bound field in the database. // FieldIsBound holds the string denoting the is_bound field in the database.
FieldIsBound = "is_bound" FieldIsBound = "is_bound"
// FieldBoundAt holds the string denoting the bound_at field in the database. // FieldBoundAt holds the string denoting the bound_at field in the database.
@ -76,7 +76,7 @@ var Columns = []string{
FieldNickname, FieldNickname,
FieldAvatar, FieldAvatar,
FieldEmail, FieldEmail,
FieldPhone, FieldMobile,
FieldIsBound, FieldIsBound,
FieldBoundAt, FieldBoundAt,
FieldExtraData, FieldExtraData,
@ -119,8 +119,8 @@ var (
AvatarValidator func(string) error AvatarValidator func(string) error
// EmailValidator is a validator for the "email" field. It is called by the builders before save. // EmailValidator is a validator for the "email" field. It is called by the builders before save.
EmailValidator func(string) error EmailValidator func(string) error
// PhoneValidator is a validator for the "phone" field. It is called by the builders before save. // MobileValidator is a validator for the "mobile" field. It is called by the builders before save.
PhoneValidator func(string) error MobileValidator func(string) error
// DefaultIsBound holds the default value on creation for the "is_bound" field. // DefaultIsBound holds the default value on creation for the "is_bound" field.
DefaultIsBound bool DefaultIsBound bool
// DefaultBoundAt holds the default value on creation for the "bound_at" field. // DefaultBoundAt holds the default value on creation for the "bound_at" field.
@ -210,9 +210,9 @@ func ByEmail(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldEmail, opts...).ToFunc() return sql.OrderByField(FieldEmail, opts...).ToFunc()
} }
// ByPhone orders the results by the phone field. // ByMobile orders the results by the mobile field.
func ByPhone(opts ...sql.OrderTermOption) OrderOption { func ByMobile(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPhone, opts...).ToFunc() return sql.OrderByField(FieldMobile, opts...).ToFunc()
} }
// ByIsBound orders the results by the is_bound field. // ByIsBound orders the results by the is_bound field.

View File

@ -129,9 +129,9 @@ func Email(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldEQ(FieldEmail, v)) return predicate.UserThirdAuth(sql.FieldEQ(FieldEmail, v))
} }
// Phone applies equality check predicate on the "phone" field. It's identical to PhoneEQ. // Mobile applies equality check predicate on the "mobile" field. It's identical to MobileEQ.
func Phone(v string) predicate.UserThirdAuth { func Mobile(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldEQ(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldEQ(FieldMobile, v))
} }
// IsBound applies equality check predicate on the "is_bound" field. It's identical to IsBoundEQ. // IsBound applies equality check predicate on the "is_bound" field. It's identical to IsBoundEQ.
@ -459,6 +459,16 @@ func OpenidHasSuffix(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldHasSuffix(FieldOpenid, v)) return predicate.UserThirdAuth(sql.FieldHasSuffix(FieldOpenid, v))
} }
// OpenidIsNil applies the IsNil predicate on the "openid" field.
func OpenidIsNil() predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldIsNull(FieldOpenid))
}
// OpenidNotNil applies the NotNil predicate on the "openid" field.
func OpenidNotNil() predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldNotNull(FieldOpenid))
}
// OpenidEqualFold applies the EqualFold predicate on the "openid" field. // OpenidEqualFold applies the EqualFold predicate on the "openid" field.
func OpenidEqualFold(v string) predicate.UserThirdAuth { func OpenidEqualFold(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldEqualFold(FieldOpenid, v)) return predicate.UserThirdAuth(sql.FieldEqualFold(FieldOpenid, v))
@ -1054,79 +1064,79 @@ func EmailContainsFold(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldContainsFold(FieldEmail, v)) return predicate.UserThirdAuth(sql.FieldContainsFold(FieldEmail, v))
} }
// PhoneEQ applies the EQ predicate on the "phone" field. // MobileEQ applies the EQ predicate on the "mobile" field.
func PhoneEQ(v string) predicate.UserThirdAuth { func MobileEQ(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldEQ(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldEQ(FieldMobile, v))
} }
// PhoneNEQ applies the NEQ predicate on the "phone" field. // MobileNEQ applies the NEQ predicate on the "mobile" field.
func PhoneNEQ(v string) predicate.UserThirdAuth { func MobileNEQ(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldNEQ(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldNEQ(FieldMobile, v))
} }
// PhoneIn applies the In predicate on the "phone" field. // MobileIn applies the In predicate on the "mobile" field.
func PhoneIn(vs ...string) predicate.UserThirdAuth { func MobileIn(vs ...string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldIn(FieldPhone, vs...)) return predicate.UserThirdAuth(sql.FieldIn(FieldMobile, vs...))
} }
// PhoneNotIn applies the NotIn predicate on the "phone" field. // MobileNotIn applies the NotIn predicate on the "mobile" field.
func PhoneNotIn(vs ...string) predicate.UserThirdAuth { func MobileNotIn(vs ...string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldNotIn(FieldPhone, vs...)) return predicate.UserThirdAuth(sql.FieldNotIn(FieldMobile, vs...))
} }
// PhoneGT applies the GT predicate on the "phone" field. // MobileGT applies the GT predicate on the "mobile" field.
func PhoneGT(v string) predicate.UserThirdAuth { func MobileGT(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldGT(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldGT(FieldMobile, v))
} }
// PhoneGTE applies the GTE predicate on the "phone" field. // MobileGTE applies the GTE predicate on the "mobile" field.
func PhoneGTE(v string) predicate.UserThirdAuth { func MobileGTE(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldGTE(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldGTE(FieldMobile, v))
} }
// PhoneLT applies the LT predicate on the "phone" field. // MobileLT applies the LT predicate on the "mobile" field.
func PhoneLT(v string) predicate.UserThirdAuth { func MobileLT(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldLT(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldLT(FieldMobile, v))
} }
// PhoneLTE applies the LTE predicate on the "phone" field. // MobileLTE applies the LTE predicate on the "mobile" field.
func PhoneLTE(v string) predicate.UserThirdAuth { func MobileLTE(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldLTE(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldLTE(FieldMobile, v))
} }
// PhoneContains applies the Contains predicate on the "phone" field. // MobileContains applies the Contains predicate on the "mobile" field.
func PhoneContains(v string) predicate.UserThirdAuth { func MobileContains(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldContains(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldContains(FieldMobile, v))
} }
// PhoneHasPrefix applies the HasPrefix predicate on the "phone" field. // MobileHasPrefix applies the HasPrefix predicate on the "mobile" field.
func PhoneHasPrefix(v string) predicate.UserThirdAuth { func MobileHasPrefix(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldHasPrefix(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldHasPrefix(FieldMobile, v))
} }
// PhoneHasSuffix applies the HasSuffix predicate on the "phone" field. // MobileHasSuffix applies the HasSuffix predicate on the "mobile" field.
func PhoneHasSuffix(v string) predicate.UserThirdAuth { func MobileHasSuffix(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldHasSuffix(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldHasSuffix(FieldMobile, v))
} }
// PhoneIsNil applies the IsNil predicate on the "phone" field. // MobileIsNil applies the IsNil predicate on the "mobile" field.
func PhoneIsNil() predicate.UserThirdAuth { func MobileIsNil() predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldIsNull(FieldPhone)) return predicate.UserThirdAuth(sql.FieldIsNull(FieldMobile))
} }
// PhoneNotNil applies the NotNil predicate on the "phone" field. // MobileNotNil applies the NotNil predicate on the "mobile" field.
func PhoneNotNil() predicate.UserThirdAuth { func MobileNotNil() predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldNotNull(FieldPhone)) return predicate.UserThirdAuth(sql.FieldNotNull(FieldMobile))
} }
// PhoneEqualFold applies the EqualFold predicate on the "phone" field. // MobileEqualFold applies the EqualFold predicate on the "mobile" field.
func PhoneEqualFold(v string) predicate.UserThirdAuth { func MobileEqualFold(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldEqualFold(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldEqualFold(FieldMobile, v))
} }
// PhoneContainsFold applies the ContainsFold predicate on the "phone" field. // MobileContainsFold applies the ContainsFold predicate on the "mobile" field.
func PhoneContainsFold(v string) predicate.UserThirdAuth { func MobileContainsFold(v string) predicate.UserThirdAuth {
return predicate.UserThirdAuth(sql.FieldContainsFold(FieldPhone, v)) return predicate.UserThirdAuth(sql.FieldContainsFold(FieldMobile, v))
} }
// IsBoundEQ applies the EQ predicate on the "is_bound" field. // IsBoundEQ applies the EQ predicate on the "is_bound" field.

View File

@ -102,6 +102,14 @@ func (_c *UserThirdAuthCreate) SetOpenid(v string) *UserThirdAuthCreate {
return _c return _c
} }
// SetNillableOpenid sets the "openid" field if the given value is not nil.
func (_c *UserThirdAuthCreate) SetNillableOpenid(v *string) *UserThirdAuthCreate {
if v != nil {
_c.SetOpenid(*v)
}
return _c
}
// SetUnionid sets the "unionid" field. // SetUnionid sets the "unionid" field.
func (_c *UserThirdAuthCreate) SetUnionid(v string) *UserThirdAuthCreate { func (_c *UserThirdAuthCreate) SetUnionid(v string) *UserThirdAuthCreate {
_c.mutation.SetUnionid(v) _c.mutation.SetUnionid(v)
@ -220,16 +228,16 @@ func (_c *UserThirdAuthCreate) SetNillableEmail(v *string) *UserThirdAuthCreate
return _c return _c
} }
// SetPhone sets the "phone" field. // SetMobile sets the "mobile" field.
func (_c *UserThirdAuthCreate) SetPhone(v string) *UserThirdAuthCreate { func (_c *UserThirdAuthCreate) SetMobile(v string) *UserThirdAuthCreate {
_c.mutation.SetPhone(v) _c.mutation.SetMobile(v)
return _c return _c
} }
// SetNillablePhone sets the "phone" field if the given value is not nil. // SetNillableMobile sets the "mobile" field if the given value is not nil.
func (_c *UserThirdAuthCreate) SetNillablePhone(v *string) *UserThirdAuthCreate { func (_c *UserThirdAuthCreate) SetNillableMobile(v *string) *UserThirdAuthCreate {
if v != nil { if v != nil {
_c.SetPhone(*v) _c.SetMobile(*v)
} }
return _c return _c
} }
@ -349,9 +357,6 @@ func (_c *UserThirdAuthCreate) check() error {
if _, ok := _c.mutation.UserID(); !ok { if _, ok := _c.mutation.UserID(); !ok {
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "UserThirdAuth.user_id"`)} return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "UserThirdAuth.user_id"`)}
} }
if _, ok := _c.mutation.Openid(); !ok {
return &ValidationError{Name: "openid", err: errors.New(`ent: missing required field "UserThirdAuth.openid"`)}
}
if v, ok := _c.mutation.Openid(); ok { if v, ok := _c.mutation.Openid(); ok {
if err := userthirdauth.OpenidValidator(v); err != nil { if err := userthirdauth.OpenidValidator(v); err != nil {
return &ValidationError{Name: "openid", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.openid": %w`, err)} return &ValidationError{Name: "openid", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.openid": %w`, err)}
@ -392,9 +397,9 @@ func (_c *UserThirdAuthCreate) check() error {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)} return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)}
} }
} }
if v, ok := _c.mutation.Phone(); ok { if v, ok := _c.mutation.Mobile(); ok {
if err := userthirdauth.PhoneValidator(v); err != nil { if err := userthirdauth.MobileValidator(v); err != nil {
return &ValidationError{Name: "phone", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.phone": %w`, err)} return &ValidationError{Name: "mobile", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.mobile": %w`, err)}
} }
} }
if _, ok := _c.mutation.IsBound(); !ok { if _, ok := _c.mutation.IsBound(); !ok {
@ -499,9 +504,9 @@ func (_c *UserThirdAuthCreate) createSpec() (*UserThirdAuth, *sqlgraph.CreateSpe
_spec.SetField(userthirdauth.FieldEmail, field.TypeString, value) _spec.SetField(userthirdauth.FieldEmail, field.TypeString, value)
_node.Email = value _node.Email = value
} }
if value, ok := _c.mutation.Phone(); ok { if value, ok := _c.mutation.Mobile(); ok {
_spec.SetField(userthirdauth.FieldPhone, field.TypeString, value) _spec.SetField(userthirdauth.FieldMobile, field.TypeString, value)
_node.Phone = value _node.Mobile = value
} }
if value, ok := _c.mutation.IsBound(); ok { if value, ok := _c.mutation.IsBound(); ok {
_spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value) _spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value)

View File

@ -116,6 +116,12 @@ func (_u *UserThirdAuthUpdate) SetNillableOpenid(v *string) *UserThirdAuthUpdate
return _u return _u
} }
// ClearOpenid clears the value of the "openid" field.
func (_u *UserThirdAuthUpdate) ClearOpenid() *UserThirdAuthUpdate {
_u.mutation.ClearOpenid()
return _u
}
// SetUnionid sets the "unionid" field. // SetUnionid sets the "unionid" field.
func (_u *UserThirdAuthUpdate) SetUnionid(v string) *UserThirdAuthUpdate { func (_u *UserThirdAuthUpdate) SetUnionid(v string) *UserThirdAuthUpdate {
_u.mutation.SetUnionid(v) _u.mutation.SetUnionid(v)
@ -288,23 +294,23 @@ func (_u *UserThirdAuthUpdate) ClearEmail() *UserThirdAuthUpdate {
return _u return _u
} }
// SetPhone sets the "phone" field. // SetMobile sets the "mobile" field.
func (_u *UserThirdAuthUpdate) SetPhone(v string) *UserThirdAuthUpdate { func (_u *UserThirdAuthUpdate) SetMobile(v string) *UserThirdAuthUpdate {
_u.mutation.SetPhone(v) _u.mutation.SetMobile(v)
return _u return _u
} }
// SetNillablePhone sets the "phone" field if the given value is not nil. // SetNillableMobile sets the "mobile" field if the given value is not nil.
func (_u *UserThirdAuthUpdate) SetNillablePhone(v *string) *UserThirdAuthUpdate { func (_u *UserThirdAuthUpdate) SetNillableMobile(v *string) *UserThirdAuthUpdate {
if v != nil { if v != nil {
_u.SetPhone(*v) _u.SetMobile(*v)
} }
return _u return _u
} }
// ClearPhone clears the value of the "phone" field. // ClearMobile clears the value of the "mobile" field.
func (_u *UserThirdAuthUpdate) ClearPhone() *UserThirdAuthUpdate { func (_u *UserThirdAuthUpdate) ClearMobile() *UserThirdAuthUpdate {
_u.mutation.ClearPhone() _u.mutation.ClearMobile()
return _u return _u
} }
@ -431,9 +437,9 @@ func (_u *UserThirdAuthUpdate) check() error {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)} return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)}
} }
} }
if v, ok := _u.mutation.Phone(); ok { if v, ok := _u.mutation.Mobile(); ok {
if err := userthirdauth.PhoneValidator(v); err != nil { if err := userthirdauth.MobileValidator(v); err != nil {
return &ValidationError{Name: "phone", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.phone": %w`, err)} return &ValidationError{Name: "mobile", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.mobile": %w`, err)}
} }
} }
return nil return nil
@ -478,6 +484,9 @@ func (_u *UserThirdAuthUpdate) sqlSave(ctx context.Context) (_node int, err erro
if value, ok := _u.mutation.Openid(); ok { if value, ok := _u.mutation.Openid(); ok {
_spec.SetField(userthirdauth.FieldOpenid, field.TypeString, value) _spec.SetField(userthirdauth.FieldOpenid, field.TypeString, value)
} }
if _u.mutation.OpenidCleared() {
_spec.ClearField(userthirdauth.FieldOpenid, field.TypeString)
}
if value, ok := _u.mutation.Unionid(); ok { if value, ok := _u.mutation.Unionid(); ok {
_spec.SetField(userthirdauth.FieldUnionid, field.TypeString, value) _spec.SetField(userthirdauth.FieldUnionid, field.TypeString, value)
} }
@ -532,11 +541,11 @@ func (_u *UserThirdAuthUpdate) sqlSave(ctx context.Context) (_node int, err erro
if _u.mutation.EmailCleared() { if _u.mutation.EmailCleared() {
_spec.ClearField(userthirdauth.FieldEmail, field.TypeString) _spec.ClearField(userthirdauth.FieldEmail, field.TypeString)
} }
if value, ok := _u.mutation.Phone(); ok { if value, ok := _u.mutation.Mobile(); ok {
_spec.SetField(userthirdauth.FieldPhone, field.TypeString, value) _spec.SetField(userthirdauth.FieldMobile, field.TypeString, value)
} }
if _u.mutation.PhoneCleared() { if _u.mutation.MobileCleared() {
_spec.ClearField(userthirdauth.FieldPhone, field.TypeString) _spec.ClearField(userthirdauth.FieldMobile, field.TypeString)
} }
if value, ok := _u.mutation.IsBound(); ok { if value, ok := _u.mutation.IsBound(); ok {
_spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value) _spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value)
@ -658,6 +667,12 @@ func (_u *UserThirdAuthUpdateOne) SetNillableOpenid(v *string) *UserThirdAuthUpd
return _u return _u
} }
// ClearOpenid clears the value of the "openid" field.
func (_u *UserThirdAuthUpdateOne) ClearOpenid() *UserThirdAuthUpdateOne {
_u.mutation.ClearOpenid()
return _u
}
// SetUnionid sets the "unionid" field. // SetUnionid sets the "unionid" field.
func (_u *UserThirdAuthUpdateOne) SetUnionid(v string) *UserThirdAuthUpdateOne { func (_u *UserThirdAuthUpdateOne) SetUnionid(v string) *UserThirdAuthUpdateOne {
_u.mutation.SetUnionid(v) _u.mutation.SetUnionid(v)
@ -830,23 +845,23 @@ func (_u *UserThirdAuthUpdateOne) ClearEmail() *UserThirdAuthUpdateOne {
return _u return _u
} }
// SetPhone sets the "phone" field. // SetMobile sets the "mobile" field.
func (_u *UserThirdAuthUpdateOne) SetPhone(v string) *UserThirdAuthUpdateOne { func (_u *UserThirdAuthUpdateOne) SetMobile(v string) *UserThirdAuthUpdateOne {
_u.mutation.SetPhone(v) _u.mutation.SetMobile(v)
return _u return _u
} }
// SetNillablePhone sets the "phone" field if the given value is not nil. // SetNillableMobile sets the "mobile" field if the given value is not nil.
func (_u *UserThirdAuthUpdateOne) SetNillablePhone(v *string) *UserThirdAuthUpdateOne { func (_u *UserThirdAuthUpdateOne) SetNillableMobile(v *string) *UserThirdAuthUpdateOne {
if v != nil { if v != nil {
_u.SetPhone(*v) _u.SetMobile(*v)
} }
return _u return _u
} }
// ClearPhone clears the value of the "phone" field. // ClearMobile clears the value of the "mobile" field.
func (_u *UserThirdAuthUpdateOne) ClearPhone() *UserThirdAuthUpdateOne { func (_u *UserThirdAuthUpdateOne) ClearMobile() *UserThirdAuthUpdateOne {
_u.mutation.ClearPhone() _u.mutation.ClearMobile()
return _u return _u
} }
@ -986,9 +1001,9 @@ func (_u *UserThirdAuthUpdateOne) check() error {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)} return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.email": %w`, err)}
} }
} }
if v, ok := _u.mutation.Phone(); ok { if v, ok := _u.mutation.Mobile(); ok {
if err := userthirdauth.PhoneValidator(v); err != nil { if err := userthirdauth.MobileValidator(v); err != nil {
return &ValidationError{Name: "phone", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.phone": %w`, err)} return &ValidationError{Name: "mobile", err: fmt.Errorf(`ent: validator failed for field "UserThirdAuth.mobile": %w`, err)}
} }
} }
return nil return nil
@ -1050,6 +1065,9 @@ func (_u *UserThirdAuthUpdateOne) sqlSave(ctx context.Context) (_node *UserThird
if value, ok := _u.mutation.Openid(); ok { if value, ok := _u.mutation.Openid(); ok {
_spec.SetField(userthirdauth.FieldOpenid, field.TypeString, value) _spec.SetField(userthirdauth.FieldOpenid, field.TypeString, value)
} }
if _u.mutation.OpenidCleared() {
_spec.ClearField(userthirdauth.FieldOpenid, field.TypeString)
}
if value, ok := _u.mutation.Unionid(); ok { if value, ok := _u.mutation.Unionid(); ok {
_spec.SetField(userthirdauth.FieldUnionid, field.TypeString, value) _spec.SetField(userthirdauth.FieldUnionid, field.TypeString, value)
} }
@ -1104,11 +1122,11 @@ func (_u *UserThirdAuthUpdateOne) sqlSave(ctx context.Context) (_node *UserThird
if _u.mutation.EmailCleared() { if _u.mutation.EmailCleared() {
_spec.ClearField(userthirdauth.FieldEmail, field.TypeString) _spec.ClearField(userthirdauth.FieldEmail, field.TypeString)
} }
if value, ok := _u.mutation.Phone(); ok { if value, ok := _u.mutation.Mobile(); ok {
_spec.SetField(userthirdauth.FieldPhone, field.TypeString, value) _spec.SetField(userthirdauth.FieldMobile, field.TypeString, value)
} }
if _u.mutation.PhoneCleared() { if _u.mutation.MobileCleared() {
_spec.ClearField(userthirdauth.FieldPhone, field.TypeString) _spec.ClearField(userthirdauth.FieldMobile, field.TypeString)
} }
if value, ok := _u.mutation.IsBound(); ok { if value, ok := _u.mutation.IsBound(); ok {
_spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value) _spec.SetField(userthirdauth.FieldIsBound, field.TypeBool, value)

View File

@ -1,5 +1,5 @@
Name: rpc.rpc Name: rpc.rpc
ListenOn: 0.0.0.0:8080 ListenOn: 0.0.0.0:9901
DatabaseConf: DatabaseConf:
@ -16,20 +16,18 @@ DatabaseConf:
Debug: true Debug: true
LogSlowThreshold: 600ms LogSlowThreshold: 600ms
RedisConf:
Host: 192.168.201.58:6379
Db: 0
jwt: JWTConf:
access_token_secret: your-super-secret-access-token-key-change-in-production access_token_secret: OAMDAascvzcvasdf
refresh_token_secret: your-super-secret-refresh-token-key-change-in-production refresh_token_secret: ASDZCpajbvasdfasf
access_token_expiry: 24h access_token_expiry: 24h
refresh_token_expiry: 720h refresh_token_expiry: 720h
issuer: user-system issuer: user-system
RedisConf:
Host: 192.168.201.58:6379
Db: 1
Log: Log:
ServiceName: appRpcLogger ServiceName: appRpcLogger
Mode: console Mode: console
@ -40,3 +38,8 @@ Log:
KeepDays: 7 KeepDays: 7
StackCoolDownMillis: 100 StackCoolDownMillis: 100
McmsRpc:
Target: 127.0.0.1:9106
Enabled: true
Timeout: 10000

View File

@ -13,6 +13,7 @@ require (
golang.org/x/crypto v0.44.0 golang.org/x/crypto v0.44.0
google.golang.org/grpc v1.76.0 google.golang.org/grpc v1.76.0
google.golang.org/protobuf v1.36.10 google.golang.org/protobuf v1.36.10
mingyang-admin-simple-admin-message v0.0.1
) )
require ( require (
@ -133,3 +134,5 @@ require (
) )
replace github.com/zeromicro/go-zero v1.9.1 => github.com/suyuan32/simple-admin-tools v1.9.1 replace github.com/zeromicro/go-zero v1.9.1 => github.com/suyuan32/simple-admin-tools v1.9.1
replace mingyang-admin-simple-admin-message v0.0.1 => ../../simple-admin-message-center-tenant

View File

@ -9,13 +9,12 @@ import (
type Config struct { type Config struct {
zrpc.RpcServerConf zrpc.RpcServerConf
DatabaseConf config.DatabaseConf DatabaseConf config.DatabaseConf
JWTConf JWTConfig JWTConf JWTConfig `json:"JWTConf"`
RedisConf config.RedisConf RedisConf config.RedisConf
RedisRedisConf config.RedisConf
AppRpc zrpc.RpcClientConf
IP2Location struct { IP2Location struct {
DBPath string `json:",default=./data/IP2LOCATION-LITE-DB.BIN"` DBPath string `json:",default=./data/IP2LOCATION-LITE-DB.BIN"`
} }
McmsRpc zrpc.RpcClientConf
} }
type JWTConfig struct { type JWTConfig struct {

View File

@ -0,0 +1,35 @@
package base
import (
"context"
"entgo.io/ent/dialect/sql/schema"
"github.com/saas-mingyang/mingyang-admin-common/msg/logmsg"
"github.com/zeromicro/go-zero/core/errorx"
"mingyang-admin-app-rpc/internal/svc"
"mingyang-admin-app-rpc/types/app"
"github.com/zeromicro/go-zero/core/logx"
)
type InitDatabaseLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewInitDatabaseLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InitDatabaseLogic {
return &InitDatabaseLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *InitDatabaseLogic) InitDatabase(in *app.Empty) (*app.BaseResp, error) {
if err := l.svcCtx.DB.Schema.Create(l.ctx, schema.WithForeignKeys(false)); err != nil {
logx.Errorw(logmsg.DatabaseError, logx.Field("detail", err.Error()))
return nil, errorx.NewInternalError(err.Error())
}
return &app.BaseResp{}, nil
}

View File

@ -63,7 +63,7 @@ func (r *CacheRepository) IncrementVerificationAttempts(ctx context.Context, key
return err return err
} }
if data == nil { if data == nil {
return fmt.Errorf("verification code.proto not found") return fmt.Errorf("verification code not found")
} }
data.Attempts++ data.Attempts++
@ -143,7 +143,7 @@ func (r *CacheRepository) RateLimit(ctx context.Context, key string, limit int,
// VerificationCodeData 数据模型 // VerificationCodeData 数据模型
type VerificationCodeData struct { type VerificationCodeData struct {
Code string `json:"code.proto"` Code string `json:"code"`
Attempts int `json:"attempts"` Attempts int `json:"attempts"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }

View File

@ -2,10 +2,16 @@ package code
import ( import (
"context" "context"
"crypto/rand"
"fmt"
"github.com/zeromicro/go-zero/core/errorx"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"math/big"
"mingyang-admin-app-rpc/internal/logic/cacherepo" "mingyang-admin-app-rpc/internal/logic/cacherepo"
"mingyang-admin-app-rpc/internal/svc" "mingyang-admin-app-rpc/internal/svc"
"mingyang-admin-app-rpc/types/app" "mingyang-admin-app-rpc/types/app"
"mingyang-admin-simple-admin-message/types/mcms"
"time"
) )
type GetVerifyCodeLogic struct { type GetVerifyCodeLogic struct {
@ -27,23 +33,116 @@ func NewGetVerifyCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get
// GetVerifyCode 获取验证码 // GetVerifyCode 获取验证码
func (l *GetVerifyCodeLogic) GetVerifyCode(in *app.VerifyCodeReq) (*app.VerifyCodeResp, error) { func (l *GetVerifyCodeLogic) GetVerifyCode(in *app.VerifyCodeReq) (*app.VerifyCodeResp, error) {
codeType := in.GetAccountType() codeType := in.GetAccountType()
targetValue := in.GetValue()
minute := 5 * time.Minute
// 1. 检查缓存中是否有有效的验证码
cachedCode, err := l.CheckCacheVerificationCode(in)
if err != nil {
logx.Errorw("failed to check verification code cache", logx.Field("detail", err))
// 继续生成新验证码,不直接返回错误
}
var code string
// 2. 如果有缓存且有效,复用
if cachedCode != "" {
// 假设 cachedCode 是完整的 "captchaId:code" 格式
code = cachedCode
} else {
// 生成验证码
newCode, err := GenerateSecureCode()
if err != nil {
logx.Errorw("failed to generate verification code", logx.Field("detail", err))
return nil, err
}
code = newCode
}
// 4. 根据类型发送验证码
var sendErr error
switch codeType { switch codeType {
case app.AccountType_MOBILE: case app.AccountType_MOBILE:
// TODO: 调用短信服务获取验证码 // 调用短信服务发送验证码
l.SendMobileMessage(in) sendErr = l.SendMobileMessage(in, code)
if sendErr != nil {
logx.Errorw("failed to send SMS verification code",
logx.Field("detail", sendErr),
logx.Field("mobile", targetValue))
}
case app.AccountType_EMAIL: case app.AccountType_EMAIL:
// TODO: 调用邮件服务获取验证码 // 调用邮件服务发送验证码
l.SendEmailMessage(in) sendErr = l.SendEmailMessage(in, code)
if sendErr != nil {
logx.Errorw("failed to send email verification code",
logx.Field("detail", sendErr),
logx.Field("email", targetValue))
}
default:
return nil, errorx.NewInvalidArgumentError("unsupported account type")
} }
return &app.VerifyCodeResp{}, nil // 5. 如果发送失败,可以考虑清理缓存(可选)
if sendErr != nil {
// 可选:清理刚设置的缓存,避免无效验证码占用空间
// l.cacheRepo.DeleteVerificationCode(l.ctx, targetValue)
return nil, sendErr
} }
cacheKey := fmt.Sprintf("email_verification_code:%s", in.Value)
func (l *GetVerifyCodeLogic) SendMobileMessage(in *app.VerifyCodeReq) { fmt.Printf("cacheKey:%s", cacheKey)
// 7. 设置验证码到缓存
err = l.cacheRepo.SetVerificationCode(l.ctx, cacheKey, code, minute)
if err != nil {
logx.Errorw("failed to set verification code to cache", logx.Field("detail", err))
}
// 6. 返回响应
return &app.VerifyCodeResp{
CaptchaCode: code, // 返回纯数字验证码
Expire: uint32(minute.Seconds()),
}, nil
}
func (l *GetVerifyCodeLogic) SendMobileMessage(in *app.VerifyCodeReq, code string) error {
//l.cacheRepo.SetVerificationCode(l.ctx, in.Value, nil, 10*time.Minute) //l.cacheRepo.SetVerificationCode(l.ctx, in.Value, nil, 10*time.Minute)
return nil
} }
func (l *GetVerifyCodeLogic) SendEmailMessage(in *app.VerifyCodeReq) { func (l *GetVerifyCodeLogic) SendEmailMessage(in *app.VerifyCodeReq, code string) error {
_, err := l.svcCtx.McmsRpc.SendEmail(l.ctx, &mcms.EmailInfo{
Target: []string{in.Value},
Subject: in.Type.String(),
Content: fmt.Sprintf("验证码:%s", code),
})
if err != nil {
logx.Errorw("failed to send email", logx.Field("detail", err))
}
return nil
}
// CheckCacheVerificationCode 检查缓存中是否有验证码,并且未过期
func (l *GetVerifyCodeLogic) CheckCacheVerificationCode(in *app.VerifyCodeReq) (string, error) {
var cacheKey string
if in.AccountType == app.AccountType_EMAIL {
cacheKey = fmt.Sprintf("email_verification_code:%s", in.GetValue())
} else if in.AccountType == app.AccountType_MOBILE {
cacheKey = fmt.Sprintf("mobile_verification_code:%s", in.GetValue())
} else {
return "", nil
}
code, err := l.cacheRepo.GetVerificationCode(l.ctx, cacheKey)
if err != nil || code == nil {
logx.Errorw("failed to get verification code", logx.Field("detail", err))
return "", err
}
return code.Code, nil
}
// GenerateSecureCode 生成密码学安全的6位数字验证码
func GenerateSecureCode() (string, error) {
// 生成一个 [0, 999999] 范围内的大随机整数
max := big.NewInt(1000000) // 上限不包含,所以是 0-999999
_, err := rand.Int(rand.Reader, max)
if err != nil {
return "", err
}
// 格式化为6位数字符串不足6位前面补零
//return fmt.Sprintf("%06d", n.Int64()), nil
return "1234", nil
} }

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/saas-mingyang/mingyang-admin-common/utils/sonyflake" "github.com/saas-mingyang/mingyang-admin-common/utils/sonyflake"
"github.com/saas-mingyang/mingyang-admin-common/utils/uuidx"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"mingyang-admin-app-rpc/ent" "mingyang-admin-app-rpc/ent"
"mingyang-admin-app-rpc/ent/user" "mingyang-admin-app-rpc/ent/user"
@ -51,6 +52,7 @@ func (u *User) CreateUser(ctx context.Context, req *CreateUserData) (*app.UserIn
).Exist(ctx) ).Exist(ctx)
if err != nil { if err != nil {
fmt.Printf("error: %v", err)
return nil, fmt.Errorf("checking existing user: %w", err) return nil, fmt.Errorf("checking existing user: %w", err)
} }
if exists { if exists {
@ -63,12 +65,15 @@ func (u *User) CreateUser(ctx context.Context, req *CreateUserData) (*app.UserIn
SetUsername(req.Username). SetUsername(req.Username).
SetEmail(req.Email). SetEmail(req.Email).
SetMobile(req.Mobile). SetMobile(req.Mobile).
SetGender(req.Gender).
SetSalt(uuidx.NewUUID().String()).
SetPasswordHash(req.PasswordHash). SetPasswordHash(req.PasswordHash).
SetNickname(req.Nickname). SetNickname(req.Nickname).
SetRegistrationSource(req.RegistrationSource). SetRegistrationSource(req.RegistrationSource).
SetMetadata(req.Metadata). SetMetadata(req.Metadata).
Save(ctx) Save(ctx)
if err != nil { if err != nil {
fmt.Printf("error: %v", err)
return nil, fmt.Errorf("creating user: %w", err) return nil, fmt.Errorf("creating user: %w", err)
} }
// 4. 提交事务 // 4. 提交事务
@ -100,6 +105,7 @@ type CreateUserData struct {
Mobile string Mobile string
PasswordHash string PasswordHash string
Nickname string Nickname string
Gender user.Gender
RegistrationSource string RegistrationSource string
Metadata map[string]interface{} Metadata map[string]interface{}
ThirdPartyAuth *ThirdPartyAuthData ThirdPartyAuth *ThirdPartyAuthData

View File

@ -0,0 +1,31 @@
package user
import (
"context"
"mingyang-admin-app-rpc/internal/svc"
"mingyang-admin-app-rpc/types/app"
"github.com/zeromicro/go-zero/core/logx"
)
type ListUsersLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewListUsersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListUsersLogic {
return &ListUsersLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// 分页查询用户信息
func (l *ListUsersLogic) ListUsers(in *app.PageUserRequest) (*app.PageUserResponse, error) {
// todo: add your logic here and delete this line
return &app.PageUserResponse{}, nil
}

View File

@ -14,7 +14,6 @@ import (
"mingyang-admin-app-rpc/ent/user" "mingyang-admin-app-rpc/ent/user"
"mingyang-admin-app-rpc/ent/userloginlog" "mingyang-admin-app-rpc/ent/userloginlog"
"mingyang-admin-app-rpc/internal/jwt_manager" "mingyang-admin-app-rpc/internal/jwt_manager"
"mingyang-admin-app-rpc/internal/util"
"time" "time"
"mingyang-admin-app-rpc/internal/svc" "mingyang-admin-app-rpc/internal/svc"
@ -63,7 +62,9 @@ func (l *LoginUserLogic) LoginUser(in *app.LoginRequest) (*app.LoginResponse, er
} }
// 5. 生成访问令牌和刷新令牌 // 5. 生成访问令牌和刷新令牌
tokenPair, userThirdAuth, err := l.generateTokenPair(user, in) tokenPair, userThirdAuth, err := l.generateTokenPair(user, in)
fmt.Printf("userThirdAuth: %v", userThirdAuth)
if err != nil { if err != nil {
fmt.Printf("generateTokenPair error: %v", err)
return nil, status.Error(codes.Internal, "failed to generate token") return nil, status.Error(codes.Internal, "failed to generate token")
} }
// 6. 记录成功登录日志 // 6. 记录成功登录日志
@ -74,37 +75,20 @@ func (l *LoginUserLogic) LoginUser(in *app.LoginRequest) (*app.LoginResponse, er
func (l *LoginUserLogic) validateLoginRequest(in *app.LoginRequest) error { func (l *LoginUserLogic) validateLoginRequest(in *app.LoginRequest) error {
// 检查登录标识是否提供 // 检查登录标识是否提供
if in.GetUsername() == "" && in.GetMobile() == "" && in.GetEmail() == "" { if in.GetUsername() == "" {
return errors.New("username, mobile or email is required") return errors.New("username, mobile or email is required")
} }
// 检查密码是否提供 // 检查密码是否提供
if in.GetPassword() == "" { if in.GetPassword() == "" {
return errors.New("password is required") return errors.New("password is required")
} }
// 验证邮箱格式(如果提供了邮箱)
if in.GetEmail() != "" && !util.ValidateEmail(in.GetEmail()) {
return errors.New("invalid email format")
}
// 验证手机号格式(如果提供了手机号)
if in.GetMobile() != "" && util.ValidatePhone(in.GetMobile()) {
return errors.New("invalid mobile format")
}
return nil return nil
} }
func (l *LoginUserLogic) getUserByIdentifier(in *app.LoginRequest) (*ent.User, error) { func (l *LoginUserLogic) getUserByIdentifier(in *app.LoginRequest) (*ent.User, error) {
var conditions []predicate.User var conditions []predicate.User
// 根据提供的标识构建查询条件 // 根据提供的标识构建查询条件
if in.GetUsername() != "" {
conditions = append(conditions, user.UsernameEQ(in.GetUsername())) conditions = append(conditions, user.UsernameEQ(in.GetUsername()))
}
if in.GetMobile() != "" {
conditions = append(conditions, user.MobileEQ(in.GetMobile()))
}
if in.GetEmail() != "" {
conditions = append(conditions, user.EmailEQ(in.GetEmail()))
}
// 查询用户,同时加载关联数据(如角色、权限等) // 查询用户,同时加载关联数据(如角色、权限等)
user, err := l.svcCtx.DB.User.Query(). user, err := l.svcCtx.DB.User.Query().
Where(user.Or(conditions...)). Where(user.Or(conditions...)).
@ -153,13 +137,14 @@ func (l *LoginUserLogic) recordLogin(user *ent.User, in *app.LoginRequest, userT
SetUserID(user.ID). SetUserID(user.ID).
SetLoginTime(time.Now()). SetLoginTime(time.Now()).
SetLoginIP(in.GetClientIp()). SetLoginIP(in.GetClientIp()).
SetLoginType(userloginlog.LoginType(in.GetLoginType())). SetLoginType(userloginlog.LoginType(in.GetLoginTyp())).
SetLoginPlatform(userloginlog.LoginPlatform(in.GetPlatform())). SetLoginPlatform(userloginlog.LoginPlatform(in.GetLoginPlatform())).
SetFailureReason("password_incorrect"). SetFailureReason("password_incorrect").
SetLoginResult(loginResult). SetLoginResult(loginResult).
SetAuthID(userThirdAuth.ID). SetAuthID(userThirdAuth.ID).
Save(ctx) Save(ctx)
if err != nil { if err != nil {
fmt.Printf("failed to record login: %v", err)
l.Logger.Errorf("failed to record failed login: %v", err) l.Logger.Errorf("failed to record failed login: %v", err)
} }
} }
@ -171,8 +156,8 @@ func (l *LoginUserLogic) generateTokenPair(user *ent.User, in *app.LoginRequest)
return nil, nil, fmt.Errorf("failed to generate access token: %w", err) return nil, nil, fmt.Errorf("failed to generate access token: %w", err)
} }
// 保存令牌到数据库 // 保存令牌到数据库
userThirdAuth := l.saveRefreshToken(user, tokenPair, in) userThirdAuth, err := l.saveRefreshToken(user, tokenPair, in)
return tokenPair, userThirdAuth, nil return tokenPair, userThirdAuth, err
} }
// 构建登录响应 // 构建登录响应
@ -183,7 +168,8 @@ func (l *LoginUserLogic) buildLoginResponse(user *ent.User, tokenPair *jwt_manag
AccessToken: tokenPair.AccessToken, AccessToken: tokenPair.AccessToken,
RefreshToken: tokenPair.RefreshToken, RefreshToken: tokenPair.RefreshToken,
TokenType: tokenPair.TokenType, TokenType: tokenPair.TokenType,
ExpiresAt: timestamppb.New(tokenPair.AccessTokenExpiresAt), AccessTokenExpires: timestamppb.New(tokenPair.AccessTokenExpiresAt),
RefreshTokenExpires: timestamppb.New(tokenPair.RefreshTokenExpiresAt),
}, },
} }
return response return response
@ -200,7 +186,7 @@ func (l *LoginUserLogic) resetLoginAttempts(user *ent.User) {
} }
// 保存刷新令牌到数据库 // 保存刷新令牌到数据库
func (l *LoginUserLogic) saveRefreshToken(user *ent.User, tokenPair *jwt_manager.TokenPair, in *app.LoginRequest) *ent.UserThirdAuth { func (l *LoginUserLogic) saveRefreshToken(user *ent.User, tokenPair *jwt_manager.TokenPair, in *app.LoginRequest) (*ent.UserThirdAuth, error) {
userThirdAuth, err := l.svcCtx.DB.UserThirdAuth.Create(). userThirdAuth, err := l.svcCtx.DB.UserThirdAuth.Create().
SetUserID(user.ID). SetUserID(user.ID).
SetRefreshToken(tokenPair.RefreshToken). SetRefreshToken(tokenPair.RefreshToken).
@ -208,14 +194,14 @@ func (l *LoginUserLogic) saveRefreshToken(user *ent.User, tokenPair *jwt_manager
SetAccessTokenExpiry(tokenPair.AccessTokenExpiresAt). SetAccessTokenExpiry(tokenPair.AccessTokenExpiresAt).
SetBoundAt(time.Now()). SetBoundAt(time.Now()).
SetID(sonyflake.NextID()). SetID(sonyflake.NextID()).
SetEmail(in.GetEmail()). SetEmail(user.Email).
SetPhone(in.GetMobile()). SetMobile(*user.Mobile).
Save(l.ctx) Save(l.ctx)
if err != nil { if err != nil {
l.Errorf("saveRefreshToken err: %v", err) l.Errorf("saveRefreshToken err: %v", err)
return nil return nil, err
} }
return userThirdAuth return userThirdAuth, nil
} }
func (l *LoginUserLogic) convertUserToProto(u *ent.User) *app.UserInfo { func (l *LoginUserLogic) convertUserToProto(u *ent.User) *app.UserInfo {

View File

@ -8,6 +8,7 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
"mingyang-admin-app-rpc/ent/user"
"mingyang-admin-app-rpc/internal/jwt_manager" "mingyang-admin-app-rpc/internal/jwt_manager"
"mingyang-admin-app-rpc/internal/logic/cacherepo" "mingyang-admin-app-rpc/internal/logic/cacherepo"
"mingyang-admin-app-rpc/internal/svc" "mingyang-admin-app-rpc/internal/svc"
@ -22,6 +23,7 @@ type RegisterUserLogic struct {
svcCtx *svc.ServiceContext svcCtx *svc.ServiceContext
logx.Logger logx.Logger
jwtManager *jwt_manager.JWTManager jwtManager *jwt_manager.JWTManager
cacheRepo *cacherepo.CacheRepository
} }
func NewRegisterUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterUserLogic { func NewRegisterUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterUserLogic {
@ -30,6 +32,7 @@ func NewRegisterUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Regi
svcCtx: svcCtx, svcCtx: svcCtx,
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf), jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf),
Logger: logx.WithContext(ctx), Logger: logx.WithContext(ctx),
cacheRepo: cacherepo.NewCacheRepository(ctx, svcCtx),
} }
} }
@ -68,6 +71,7 @@ func (s *RegisterUserLogic) RegisterUser(req *app.RegisterUserRequest) (*app.Reg
Email: strings.ToLower(strings.TrimSpace(req.GetEmail())), Email: strings.ToLower(strings.TrimSpace(req.GetEmail())),
Mobile: mobile, Mobile: mobile,
PasswordHash: passwordHash, PasswordHash: passwordHash,
Gender: user.Gender(req.GetGender()),
Nickname: req.GetNickName(), Nickname: req.GetNickName(),
RegistrationSource: req.GetRegistrationSource(), RegistrationSource: req.GetRegistrationSource(),
Metadata: map[string]interface{}{ Metadata: map[string]interface{}{
@ -109,9 +113,8 @@ func (s *RegisterUserLogic) RegisterUser(req *app.RegisterUserRequest) (*app.Reg
AccessToken: tokenPair.AccessToken, AccessToken: tokenPair.AccessToken,
RefreshToken: tokenPair.RefreshToken, RefreshToken: tokenPair.RefreshToken,
TokenType: tokenPair.TokenType, TokenType: tokenPair.TokenType,
ExpiresIn: int32(tokenPair.AccessTokenExpiresAt.Sub(time.Now()).Seconds()), AccessTokenExpires: timeToProto(tokenPair.AccessTokenExpiresAt),
IssuedAt: timestamppb.New(time.Now()), RefreshTokenExpires: timeToProto(tokenPair.RefreshTokenExpiresAt),
ExpiresAt: timestamppb.New(tokenPair.AccessTokenExpiresAt),
} }
} }
return response, nil return response, nil
@ -124,27 +127,45 @@ func (s *RegisterUserLogic) validateRegisterRequest(req *app.RegisterUserRequest
// verifyRegistrationCode 验证注册验证码 // verifyRegistrationCode 验证注册验证码
func (s *RegisterUserLogic) verifyRegistrationCode(ctx context.Context, req *app.RegisterUserRequest) error { func (s *RegisterUserLogic) verifyRegistrationCode(ctx context.Context, req *app.RegisterUserRequest) error {
key := req.GetVerificationId() var cacheKey string
cacheRepository := cacherepo.NewCacheRepository(ctx, s.svcCtx) verificationType := req.GetVerificationType()
if app.AccountType(verificationType) == app.AccountType_EMAIL {
cacheKey = fmt.Sprintf("email_verification_code:%s", req.GetEmail())
} else if app.AccountType(verificationType) == app.AccountType_MOBILE {
cacheKey = fmt.Sprintf("mobile_verification_code:%s", req.GetMobile())
} else {
return errors.New("invalid verification type")
}
fmt.Printf("cacheKey: %s", cacheKey)
// 获取验证码数据 // 获取验证码数据
codeData, err := cacheRepository.GetVerificationCode(ctx, key) codeData, err := s.cacheRepo.GetVerificationCode(ctx, cacheKey)
if err != nil { if err != nil {
return fmt.Errorf("failed to get verification code.proto: %w", err) fmt.Printf("Failed to get verification code: %v\n", err)
return fmt.Errorf("failed to get verification code: %w", err)
} }
if codeData == nil { if codeData == nil {
return errors.New("verification code.proto expired or not found") return errors.New("verification code expired or not found")
} }
// 验证验证码 // 验证验证码
if codeData.Code != req.GetVerificationCode() { if codeData.Code != req.GetCaptcha() {
// 增加尝试次数 // 增加尝试次数
if err := cacheRepository.IncrementVerificationAttempts(ctx, key); err != nil { if err := s.cacheRepo.IncrementVerificationAttempts(ctx, cacheKey); err != nil {
fmt.Printf("Failed to increment verification attempts: %v\n", err) fmt.Printf("Failed to increment verification attempts: %v\n", err)
} }
return errors.New("invalid verification code.proto") return errors.New("invalid verification code")
}
// 验证成功,删除验证码
if err := cacheRepository.DeleteVerificationCode(ctx, key); err != nil {
fmt.Printf("Failed to delete verification code.proto: %v\n", err)
} }
/*// 验证成功,删除验证码
if err := s.cacheRepo.DeleteVerificationCode(ctx, cacheKey); err != nil {
fmt.Printf("Failed to delete verification code: %v\n", err)
}*/
return nil return nil
} }
func timeToProto(t time.Time) *timestamppb.Timestamp {
pbTimestamp := timestamppb.New(t)
if err := pbTimestamp.CheckValid(); err != nil {
return nil
}
return pbTimestamp
}

View File

@ -6,6 +6,7 @@ package server
import ( import (
"context" "context"
"mingyang-admin-app-rpc/internal/logic/base"
"mingyang-admin-app-rpc/internal/logic/code" "mingyang-admin-app-rpc/internal/logic/code"
"mingyang-admin-app-rpc/internal/logic/user" "mingyang-admin-app-rpc/internal/logic/user"
"mingyang-admin-app-rpc/internal/svc" "mingyang-admin-app-rpc/internal/svc"
@ -40,3 +41,14 @@ func (s *AppServer) LoginUser(ctx context.Context, in *app.LoginRequest) (*app.L
l := user.NewLoginUserLogic(ctx, s.svcCtx) l := user.NewLoginUserLogic(ctx, s.svcCtx)
return l.LoginUser(in) return l.LoginUser(in)
} }
// 分页查询用户信息
func (s *AppServer) ListUsers(ctx context.Context, in *app.PageUserRequest) (*app.PageUserResponse, error) {
l := user.NewListUsersLogic(ctx, s.svcCtx)
return l.ListUsers(in)
}
func (s *AppServer) InitDatabase(ctx context.Context, in *app.Empty) (*app.BaseResp, error) {
l := base.NewInitDatabaseLogic(ctx, s.svcCtx)
return l.InitDatabase(in)
}

View File

@ -0,0 +1,46 @@
package svc
import (
"github.com/ip2location/ip2location-go/v9"
"github.com/redis/go-redis/v9"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/zrpc"
"mingyang-admin-app-rpc/ent"
"mingyang-admin-app-rpc/internal/config"
"mingyang-admin-simple-admin-message/mcmsclient"
)
type ServiceContext struct {
Config config.Config
DB *ent.Client
Redis redis.UniversalClient
IPDB *ip2location.DB
McmsRpc mcmsclient.Mcms
}
func NewServiceContext(c config.Config) *ServiceContext {
entOpts := []ent.Option{
ent.Log(logx.Info),
ent.Driver(c.DatabaseConf.NewNoCacheDriver()),
}
if c.DatabaseConf.Debug {
entOpts = append(entOpts, ent.Debug())
}
db := ent.NewClient(entOpts...)
ipDB, err := ip2location.OpenDB(c.IP2Location.DBPath)
if err != nil {
logx.Errorw("failed to open ip2location db", logx.Field("detail", err))
}
return &ServiceContext{
Config: c,
DB: db,
IPDB: ipDB,
Redis: c.RedisConf.MustNewUniversalRedis(),
McmsRpc: mcmsclient.NewMcms(zrpc.MustNewClient(c.McmsRpc)),
}
}

View File

@ -1,13 +0,0 @@
package svc
import "mingyang-admin-iot-app/rpc/internal/config"
type ServiceContext struct {
Config config.Config
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
}
}

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,10 @@ const _ = grpc.SupportPackageIsVersion9
const ( const (
App_GetVerifyCode_FullMethodName = "/app.App/GetVerifyCode" App_GetVerifyCode_FullMethodName = "/app.App/GetVerifyCode"
App_RegisterUser_FullMethodName = "/app.App/registerUser" App_RegisterUser_FullMethodName = "/app.App/RegisterUser"
App_LoginUser_FullMethodName = "/app.App/loginUser" App_LoginUser_FullMethodName = "/app.App/LoginUser"
App_ListUsers_FullMethodName = "/app.App/ListUsers"
App_InitDatabase_FullMethodName = "/app.App/InitDatabase"
) )
// AppClient is the client API for App service. // AppClient is the client API for App service.
@ -39,6 +41,11 @@ type AppClient interface {
// 用户登录 // 用户登录
// group: user // group: user
LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
// 分页查询用户信息
// group: user
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
// group: base
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
} }
type appClient struct { type appClient struct {
@ -79,6 +86,26 @@ func (c *appClient) LoginUser(ctx context.Context, in *LoginRequest, opts ...grp
return out, nil return out, nil
} }
func (c *appClient) ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PageUserResponse)
err := c.cc.Invoke(ctx, App_ListUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *appClient) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResp)
err := c.cc.Invoke(ctx, App_InitDatabase_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AppServer is the server API for App service. // AppServer is the server API for App service.
// All implementations must embed UnimplementedAppServer // All implementations must embed UnimplementedAppServer
// for forward compatibility. // for forward compatibility.
@ -94,6 +121,11 @@ type AppServer interface {
// 用户登录 // 用户登录
// group: user // group: user
LoginUser(context.Context, *LoginRequest) (*LoginResponse, error) LoginUser(context.Context, *LoginRequest) (*LoginResponse, error)
// 分页查询用户信息
// group: user
ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error)
// group: base
InitDatabase(context.Context, *Empty) (*BaseResp, error)
mustEmbedUnimplementedAppServer() mustEmbedUnimplementedAppServer()
} }
@ -113,6 +145,12 @@ func (UnimplementedAppServer) RegisterUser(context.Context, *RegisterUserRequest
func (UnimplementedAppServer) LoginUser(context.Context, *LoginRequest) (*LoginResponse, error) { func (UnimplementedAppServer) LoginUser(context.Context, *LoginRequest) (*LoginResponse, error) {
return nil, status.Error(codes.Unimplemented, "method LoginUser not implemented") return nil, status.Error(codes.Unimplemented, "method LoginUser not implemented")
} }
func (UnimplementedAppServer) ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListUsers not implemented")
}
func (UnimplementedAppServer) InitDatabase(context.Context, *Empty) (*BaseResp, error) {
return nil, status.Error(codes.Unimplemented, "method InitDatabase not implemented")
}
func (UnimplementedAppServer) mustEmbedUnimplementedAppServer() {} func (UnimplementedAppServer) mustEmbedUnimplementedAppServer() {}
func (UnimplementedAppServer) testEmbeddedByValue() {} func (UnimplementedAppServer) testEmbeddedByValue() {}
@ -188,6 +226,42 @@ func _App_LoginUser_Handler(srv interface{}, ctx context.Context, dec func(inter
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _App_ListUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PageUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AppServer).ListUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: App_ListUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AppServer).ListUsers(ctx, req.(*PageUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _App_InitDatabase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AppServer).InitDatabase(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: App_InitDatabase_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AppServer).InitDatabase(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
// App_ServiceDesc is the grpc.ServiceDesc for App service. // App_ServiceDesc is the grpc.ServiceDesc for App service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@ -200,13 +274,21 @@ var App_ServiceDesc = grpc.ServiceDesc{
Handler: _App_GetVerifyCode_Handler, Handler: _App_GetVerifyCode_Handler,
}, },
{ {
MethodName: "registerUser", MethodName: "RegisterUser",
Handler: _App_RegisterUser_Handler, Handler: _App_RegisterUser_Handler,
}, },
{ {
MethodName: "loginUser", MethodName: "LoginUser",
Handler: _App_LoginUser_Handler, Handler: _App_LoginUser_Handler,
}, },
{
MethodName: "ListUsers",
Handler: _App_ListUsers_Handler,
},
{
MethodName: "InitDatabase",
Handler: _App_InitDatabase_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "app.proto", Metadata: "app.proto",