# m-gin **Repository Path**: funadmin/m-gin ## Basic Information - **Project Name**: m-gin - **Description**: No description available - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Gin SaaS Admin 基于 **Gin + GORM + Vue 3 + TypeScript** 的多租户 SaaS 后台管理项目,内置平台后台、租户后台、JWT 认证、Casbin RBAC、组织与用户管理、插件机制,并同时支持 MySQL 与 PostgreSQL。 > 本文档中的账号和密码仅用于本地演示环境。共享环境或生产环境不得启用演示初始化,也不得沿用默认密码。 ## 主要能力 - 平台域名与租户域名隔离 - JWT Access Token / Refresh Token 认证 - Casbin RBAC 与菜单、按钮权限 - 用户、角色、菜单、部门、岗位等系统管理能力 - 登录失败计数与临时锁定 - 插件清单校验、安装和生命周期管理 - MySQL 8.4 / PostgreSQL 16 双数据库支持 - Vue 3、TypeScript、Vite、Element Plus 管理端 - Docker Compose 一键启动开发演示环境 ## 技术栈 | 模块 | 技术 | | --- | --- | | 后端 | Go 1.23、Gin 1.10、GORM 1.30 | | 认证与权限 | JWT、bcrypt、Casbin | | 数据库 | MySQL 8.4、PostgreSQL 16 | | 前端 | Vue 3.5、TypeScript、Vite 8、Element Plus、Pinia | | 测试 | Go Test、Vitest | | 部署 | Docker、Docker Compose、Nginx | ## 项目结构 ```text . ├── deploy/ # Docker Compose 配置 ├── public/ # 插件前端静态产物 ├── scripts/ # 项目验证脚本 ├── server/ │ ├── cmd/api/ # API 服务入口 │ ├── cmd/pluginctl/ # 插件校验与安装 CLI │ ├── config/ # Casbin 等后端配置 │ ├── internal/ # 业务、平台能力与基础设施 │ ├── migrations/ # MySQL / PostgreSQL 初始化脚本 │ └── plugins/ # 内置插件 ├── web/ │ ├── src/ # Vue 管理端源码 │ ├── docs/ # 前端与接口专题文档 │ └── tests/ # 前端测试 ├── Makefile # 常用开发命令 └── go.work # Go Workspace ``` ## 快速开始 ### 环境要求 推荐直接使用 Docker 开发环境: - Docker Desktop 或兼容的 Docker Engine - Docker Compose v2 本地开发还需要: - Go 1.23+ - Node.js 22+ - Corepack / pnpm 10 ### 使用 MySQL 启动 ```bash make compose-mysql ``` 默认端口: | 服务 | 地址 | | --- | --- | | 平台后台 | | | 演示租户后台 | | | API | | | MySQL | `127.0.0.1:33060` | 检查 API 健康状态: ```bash curl http://127.0.0.1:8001/health ``` 预期返回: ```json {"code":200,"msg":"success","data":{"status":"ok"},"time":1788417993} ``` `time` 为服务端当前 Unix 时间戳,实际值会变化。 ### 使用 PostgreSQL 启动 ```bash make compose-postgres ``` 默认端口: | 服务 | 地址 | | --- | --- | | 平台后台 | | | 演示租户后台 | | | API | | | PostgreSQL | `127.0.0.1:54320` | ### 域名无法访问时 `.localhost` 域名通常会自动解析到本机。如果当前系统无法解析,可在 hosts 文件中添加: ```text 127.0.0.1 admin.localhost tenant.localhost ``` 不要使用 `http://localhost:8081` 判断平台后台是否正常。当前开发配置会把未绑定域名回退到默认租户,因此 `localhost` 访问的是租户上下文,不是平台上下文。 ### 停止服务 MySQL 环境: ```bash docker compose -f deploy/docker-compose.yml --profile mysql down ``` PostgreSQL 环境: ```bash docker compose -f deploy/docker-compose.yml --profile postgres down ``` 以上命令不会主动删除数据库卷。除非确定数据可丢弃,否则不要追加 `-v`。 ## 演示账号 ### 真实 Go API Docker Compose 开发配置启用了 `APP_BOOTSTRAP_DEMO=true`,首次初始化会创建以下账号: | 后台 | 访问域名 | 账号 | 密码 | | --- | --- | --- | --- | | 平台后台 | `admin.localhost` | `admin` | `admin123` | | 演示租户后台 | `tenant.localhost` | `admin` | `admin123` | 平台后台登录地址(MySQL 环境): ```text http://admin.localhost:8081/login ``` 也可以直接验证登录接口: ```bash curl -H 'Host: admin.localhost' \ -H 'Content-Type: application/json' \ -d '{"username":"admin","password":"admin123"}' \ http://127.0.0.1:8001/admin/auth/login ``` ### 前端 Mock 模式 当 `VITE_APP_MOCK=true` 时,前端 Mock 使用独立演示数据: | 账号 | 密码 | 权限 | | --- | --- | --- | | `admin` | `123456` | 管理员 | | `guest` | `123456` | 只读访客 | **Mock 密码 `123456` 不能用于登录真实 Go API。** 当前前端部分登录提示仍显示 Mock 账号,连接真实 API 时请使用 `admin / admin123`。 ### 默认密码不会覆盖已有账号 演示初始化通过 `FirstOrCreate` 创建用户。数据库中已存在同租户、同用户名的账号时,重启服务不会把密码恢复为默认值。 如果默认密码无法登录,请先确认: 1. 当前访问的是平台域名还是租户域名; 2. 前端连接的是真实 API 还是 Mock; 3. 数据库卷是否沿用了之前创建的数据; 4. 账号是否被修改、禁用或锁定。 已有环境应通过受信任管理员执行密码重置,不建议直接覆盖数据库密码字段。 ## 登录与租户识别 请求进入 `/admin` 后,服务会先根据 Host 识别上下文: ```text 浏览器 → Nginx / Vite Proxy → Gin /admin → Tenant Resolver ├── admin.localhost → 平台上下文(tenant_id = 0) └── tenant.localhost → 演示租户上下文 → JWT / Casbin → Handler / Service → GORM → MySQL 或 PostgreSQL ``` 开发环境允许通过默认租户进行调试;生产环境会关闭该回退能力,必须使用已配置的平台域名或有效租户绑定域名。 ## API 约定 默认 API 前缀为: ```text /admin ``` 核心接口: | 方法 | 路径 | 说明 | | --- | --- | --- | | `GET` | `/health` | 健康检查 | | `POST` | `/admin/auth/login` | 登录 | | `POST` | `/admin/auth/refresh` | 刷新令牌 | | `POST` | `/admin/auth/logout` | 退出登录 | | `GET` | `/admin/auth/me` | 当前用户 | | `GET` | `/admin/auth/menus` | 当前用户菜单 | 登录请求: ```json { "username": "admin", "password": "admin123" } ``` 统一响应结构: ```json { "code": 200, "msg": "success", "data": {}, "time": 1788417993, "requestId": "8d2f7a0c-3c4c-4f42-8f2e-7c1b8e2f4a10" } ``` 响应头会同时返回 `X-Request-ID`,响应体中的 `requestId` 与其一致;客户端自带的该请求头仅在符合安全字符格式时复用,否则由服务端生成。更多前端接口约定见 [`web/docs/api.md`](web/docs/api.md),权限说明见 [`web/docs/permission.md`](web/docs/permission.md)。接口联调时应以当前 Go 路由和实际响应为最终依据。 ## 关键配置 后端通过环境变量读取配置,Docker 开发示例位于 [`deploy/docker-compose.yml`](deploy/docker-compose.yml)。 | 环境变量 | 说明 | 开发默认行为 | | --- | --- | --- | | `APP_ENV` | 运行环境 | `development` | | `APP_MODE` | `single`、`saas` 或 `maintenance` | `saas` | | `APP_HTTP_ADDR` | API 监听地址 | `:8000` | | `HTTP_READ_HEADER_TIMEOUT` | HTTP 请求头读取超时 | `5s` | | `HTTP_READ_TIMEOUT` | HTTP 请求读取超时(含上传) | `5m` | | `HTTP_WRITE_TIMEOUT` | HTTP 响应写入超时 | `5m` | | `HTTP_IDLE_TIMEOUT` | Keep-Alive 空闲超时 | `60s` | | `HTTP_SHUTDOWN_TIMEOUT` | 优雅停机等待时间 | `10s` | | `DB_DRIVER` | `mysql` 或 `postgres` | 必须与 DSN 匹配 | | `DB_DSN` | 数据库连接串 | 必填 | | `DB_MAX_OPEN_CONNS` | 数据库最大打开连接数 | `50` | | `DB_MAX_IDLE_CONNS` | 数据库最大空闲连接数 | `10` | | `DB_CONN_MAX_LIFETIME` | 数据库连接最大生命周期 | `1h` | | `DB_CONN_MAX_IDLE_TIME` | 数据库连接最大空闲时间 | `15m` | | `DB_AUTO_MIGRATE` | 是否使用 GORM 自动迁移 | Docker 环境为 `false` | | `APP_BOOTSTRAP_DEMO` | 是否初始化演示租户和账号 | Docker 开发环境为 `true` | | `JWT_SECRET` | JWT 签名密钥 | 至少 32 个字符 | | `JWT_ACCESS_TTL` | Access Token 有效期 | 默认 2 小时 | | `JWT_REFRESH_TTL` | Refresh Token 有效期 | 默认 7 天 | | `PLATFORM_DOMAINS` | 平台域名列表 | `admin.localhost` | | `ALLOW_DEV_TENANT_HEADER` | 是否允许开发租户回退 | 仅开发环境使用 | | `DEFAULT_TENANT_ID` | 单租户或开发回退租户 ID | Docker 开发环境为 `1` | | `USER_IMPORT_DEFAULT_PASSWORD` | 用户导入默认密码 | 生产环境必须显式配置 | 生产环境下服务会强制关闭演示数据初始化和开发租户回退。密钥、密码和生产 DSN 应由部署平台的 Secret 管理能力注入,不应提交到 Git。 ## 开发与验证 ### 后端 ```bash make server-check ``` 该命令会依次执行 Go 格式化、静态检查、测试和构建: ```text gofmt → go vet → go test → go build api → go build pluginctl ``` ### 前端 ```bash make web-check ``` 该命令会使用锁文件安装依赖,然后执行类型检查、Vitest 测试和生产构建。 ### 全量检查 ```bash make check ``` ### 双数据库验证 ```bash make verify-databases ``` > **高风险提示:** `scripts/verify-databases.sh` 会分别启动 MySQL、PostgreSQL,并在每轮结束执行 `docker compose down -v`。这会删除该 Compose 项目的数据卷,只能用于可丢弃的本地验证环境,严禁直接用于保存了业务数据的环境。 ## 插件开发 校验插件包: ```bash make plugin-validate PACKAGE=/path/to/plugin.zip ``` 安装插件源码: ```bash make plugin-install PACKAGE=/path/to/plugin.zip ``` 插件安装后需要重新构建后端和受影响的前端应用。内置示例位于 [`server/plugins/example`](server/plugins/example)。 ## 通用插件配置与对外访问 插件 Manifest v2 可通过 `settings` 声明平台、租户和应用三级配置,运行时解析优先级为: ```text 应用配置 > 租户配置 > 平台默认配置 > Manifest 默认值 ``` 支持 `string`、`text`、`integer`、`number`、`boolean`、`select`、`url`、`secret` 和 `json` 类型。`secret` 使用 `PLUGIN_CONFIG_MASTER_KEY` 进行 AES-GCM 加密,读取 API 仅返回是否已配置,不返回明文。生产环境必须提供至少 32 字符的独立主密钥。 独立应用配置 `domainBindable: true` 后,可在租户域名管理中绑定独立域名。域名只有在 DNS TXT 实际验证通过后才会启用,验证失败原因和最后检查时间会被记录。 插件如需公开 API,必须在 Manifest 中显式设置 `publicApi.enabled: true` 并实现 Go 接口 `plugin.PublicRouteProvider`。统一前缀为: ```text /api/plugins/{pluginId}/{appId} ``` 公开 API 只允许从绑定到目标插件应用的域名访问,支持 `anonymous`、`api_key`、`signature` 三种认证方式,并统一提供请求体限制、进程内限流、CORS 白名单与访问审计。HMAC 签名模式需要传递时间戳、随机数和签名头。公开 API 默认关闭。 相关数据库升级脚本位于: - `server/migrations/mysql/004_plugin_config.sql` ~ `006_plugin_public_api.sql` - `server/migrations/postgres/004_plugin_config.sql` ~ `006_plugin_public_api.sql` 对应回滚 SQL 位于 `server/migrations/rollback/`。执行迁移或回滚前必须备份数据库,并先在同版本测试环境验证。 ## 常见问题 ### 登录返回 401:账号或密码错误 优先检查: 1. 真实 API 使用 `admin / admin123`,不是 Mock 的 `admin / 123456`; 2. 平台后台使用 `admin.localhost`,租户后台使用 `tenant.localhost`; 3. 请求地址为 `/admin/auth/login`; 4. 请求头包含 `Content-Type: application/json`; 5. 已有数据库中的密码是否被修改。 ### 登录返回 4291 同一账号连续登录失败 5 次后会锁定 15 分钟。停止继续尝试错误密码,等待锁定自动解除,或由有权限的管理员通过系统密码重置流程处理。 ### 返回“域名未绑定有效租户” 确认请求 Host 已绑定到有效租户,或在本地使用 `tenant.localhost`。生产环境不会使用开发租户回退。 ### 修改初始化密码后仍无法登录 初始化只负责创建不存在的账号,不会更新已有账号。修改源码中的初始化密码并重启服务,不会改变数据库内已经存在的密码。 ### 数据库表没有自动更新 Docker 开发环境设置了 `DB_AUTO_MIGRATE=false`,数据库结构由 `server/migrations/mysql` 或 `server/migrations/postgres` 下的脚本负责初始化。已有数据库的结构变更应通过可审阅、可回滚的迁移执行,而不是删除数据卷。 ## 更多文档 - [前端完整说明](web/README.md) - [API 约定](web/docs/api.md) - [权限设计](web/docs/permission.md) - [组件说明](web/docs/components.md) - [列表页约定](web/docs/list-page.md) - [表单弹窗约定](web/docs/form-dialog.md) - [主题配置](web/docs/theme.md) ## 安全建议 - 默认账号只用于本地演示,首次部署后立即修改密码。 - 生产环境禁止启用 `APP_BOOTSTRAP_DEMO` 和开发租户回退。 - 不要把 JWT Secret、数据库密码、Token 或生产 DSN 写入仓库。 - 密码仅保存 bcrypt 哈希,不应尝试读取或还原明文。 - 数据库变更先准备迁移与回滚方案,不直接修改生产数据。 - API 契约变更前评估前端、插件及其他调用方的兼容性。 ## License 仓库根目录代码许可见 [LICENSE](LICENSE)(Apache License 2.0)。第三方依赖及子项目如有独立许可声明,以其各自许可文件为准。