sync: 同步 v1.0.4 开源代码并脱敏

This commit is contained in:
MiFaZhan
2026-10-29 14:49:18 +08:00
parent f42c9b29f6
commit a8874ca6f2
101 changed files with 392 additions and 214 deletions
+1
View File
@@ -11,3 +11,4 @@
*.ttf binary *.ttf binary
*.pdf binary *.pdf binary
*.exe binary *.exe binary
*.go linguist-language=Go
+4
View File
@@ -0,0 +1,4 @@
# GoFrame Template For SingleRepo
Quick Start:
- https://goframe.org/quick
+9 -2
View File
@@ -27,8 +27,11 @@ type BatchSimSubscribeReq struct {
Remark string `json:"remark,omitempty"` Remark string `json:"remark,omitempty"`
} }
// RenewReq 历史批量续费兼容入口,与 /batch-sim-subscribe 共用 SubmitRenew 实现。
// 说明:g.Meta 的 deprecated 标签在 GoFrame v2.9.6 中不被解析,无任何运行时或文档生成效果,
// 不能替代对外废弃告知;对外说明见 openapi-docs「标准入口与兼容入口」一节。
type RenewReq struct { type RenewReq struct {
g.Meta `path:"/renew" method:"POST" tags:"V3 Common API" summary:"Renewal compatibility endpoint"` g.Meta `path:"/renew" method:"POST" tags:"V3 Compatibility API" summary:"Deprecated compatibility endpoint; use /change/batch-sim-subscribe"`
model.CommonRenewParam model.CommonRenewParam
} }
@@ -51,7 +54,11 @@ type BatchSimTrafficCutoffReq struct {
model.CommonTrafficCutoffConfigParam model.CommonTrafficCutoffConfigParam
} }
// TrafficCutoffConfigReq 历史批量达量断网变更入口,已决定下线:不登记资源、不授权,
// 调用返回 10014。与 /batch-sim-traffic-cutoff 的参数类型与实现完全相同,客户应改用标准入口。
// 路由与结构体保留以便可逆恢复(取消登记 SQL 文末注释即可),故不删除代码。
// 说明:deprecated 标签在 GoFrame v2.9.6 中不被解析,无运行时效果。
type TrafficCutoffConfigReq struct { type TrafficCutoffConfigReq struct {
g.Meta `path:"/traffic-cutoff-config" method:"POST" tags:"V3 Common API" summary:"Batch traffic cutoff compatibility endpoint"` g.Meta `path:"/traffic-cutoff-config" method:"POST" tags:"V3 Compatibility API" summary:"Deprecated write endpoint; use /change/batch-sim-traffic-cutoff"`
model.CommonTrafficCutoffConfigParam model.CommonTrafficCutoffConfigParam
} }
+9 -8
View File
@@ -1,5 +1,5 @@
FROM golang:1.25-alpine AS builder ARG BASE_REGISTRY=docker.io/library
FROM ${BASE_REGISTRY}/golang:1.25-alpine AS builder
LABEL maintainer="iotlcm-openapi" LABEL maintainer="iotlcm-openapi"
ARG GOPROXY=https://goproxy.cn,direct ARG GOPROXY=https://goproxy.cn,direct
@@ -7,14 +7,13 @@ ENV GOPROXY=${GOPROXY} \
GOSUMDB=off GOSUMDB=off
WORKDIR /app WORKDIR /app
ENV GO111MODULE=on \ ENV GO111MODULE=on \
CGO_ENABLED=0 \ CGO_ENABLED=0 \
GOOS=linux \ GOOS=linux \
GOARCH=amd64 GOARCH=amd64
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download || (go clean -modcache && go mod download)
ARG BuildVersion ARG BuildVersion
ARG BuildTime ARG BuildTime
@@ -23,21 +22,23 @@ ARG CommitID
COPY . . COPY . .
RUN go build -trimpath -ldflags="-s -w -X main.BuildVersion=${BuildVersion} -X main.BuildTime=${BuildTime} -X main.CommitID=${CommitID}" -o /app/bin/iotlcm-openapi . RUN go build -trimpath -ldflags="-s -w -X main.BuildVersion=${BuildVersion} -X main.BuildTime=${BuildTime} -X main.CommitID=${CommitID}" -o /app/bin/iotlcm-openapi .
FROM alpine:3.23 FROM ${BASE_REGISTRY}/alpine:3.23 AS alpine
LABEL maintainer="iotlcm-openapi" LABEL maintainer="iotlcm-openapi"
RUN apk add --no-cache ca-certificates tzdata && \ ARG ALPINE_MIRROR=mirrors.aliyun.com
RUN sed -i "s|dl-cdn.alpinelinux.org|${ALPINE_MIRROR}|g" /etc/apk/repositories && \
apk add --no-cache ca-certificates tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone echo "Asia/Shanghai" > /etc/timezone
ENV TZ=Asia/Shanghai \ ENV TZ=Asia/Shanghai \
WORKDIR=/app WORKDIR=/app
WORKDIR $WORKDIR
COPY --from=builder /app/bin/iotlcm-openapi $WORKDIR/main COPY --from=builder /app/bin/iotlcm-openapi $WORKDIR/main
COPY --from=builder /app/resource $WORKDIR/resource COPY --from=builder /app/resource $WORKDIR/resource
COPY --from=builder /app/manifest/i18n $WORKDIR/manifest/i18n COPY --from=builder /app/manifest/i18n $WORKDIR/manifest/i18n
COPY --from=builder /app/build/build_config.yaml $WORKDIR/config/config.yaml COPY --from=builder /app/build/config.example.yaml $WORKDIR/config/config.yaml
RUN mkdir -p $WORKDIR/config RUN mkdir -p $WORKDIR/config
RUN chmod +x $WORKDIR/main RUN chmod +x $WORKDIR/main
@@ -33,7 +33,7 @@ database:
level: "all" level: "all"
stdout: true stdout: true
default: default:
link: "mysql:${DB_USER}:${DB_PASSWORD}@tcp(${DB_HOST}:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" link: "${DB_DSN}"
debug: true debug: true
charset: "utf8mb4" charset: "utf8mb4"
dryRun: false dryRun: false
@@ -49,9 +49,9 @@ redis:
default: default:
mode: "single" mode: "single"
sentinelMasterName: "iotlcm-master" sentinelMasterName: "iotlcm-master"
address: "192.0.2.29:6379" address: "127.0.0.1:6379"
db: 0 db: 0
pass: "${REDIS_PASSWORD}" pass: "${SERVICE_PASSWORD}"
minIdle: 5 minIdle: 5
maxIdle: 30 maxIdle: 30
maxActive: 5000 maxActive: 5000
@@ -70,4 +70,4 @@ upstream:
rabbitmq: rabbitmq:
enabled: true enabled: true
dsn: "amqp://${MQ_USER}:${MQ_PASSWORD}@${MQ_HOST}/" dsn: "${SERVICE_DSN}"
+58
View File
@@ -0,0 +1,58 @@
# v1.0.4 权限修复上线说明
受保护的 V3 接口仅在资源已启用、API 账号已启用、账号已分配权限组且权限组绑定该资源时放行。未登记资源、资源停用、账号不可用、未绑定权限组一律拒绝,不降级放行。
## 错误码
| 码 | 含义 | 触发条件 | 排查方向 |
|---|---|---|---|
| `10014` | 没有权限 | 资源未登记、资源停用、账号停用/不存在、账号无权限组、权限组未绑定该资源 | 业务与授权配置问题:查 `t_api_resource`、`t_api`、`t_api_group_resource` |
| `10016` | 权限校验失败 | 权限数据查询本身出错(如 `t_api_resource` 查询失败) | **系统侧故障**:查数据库连通性与表结构,不要按授权问题处理 |
两个码必须区分:数据库抖动时若复用 `10014`,运维会把系统故障误判成客户未授权。
## 上线前
1. 执行资源登记脚本 `iotlcm-database/SQL/20261016_openapi_resource_register.sql`。共 24 条 V3 路由,扣除 2 条取 token 入口后为 22 条受保护路由:**登记 15 条**,另 7 条已决定下线(`/common/*` 6 条 + `/change/traffic-cutoff-config` 1 条)。脚本幂等可重复执行,且不改动既有 `status`、`api_code`、`method`、`path`。
执行顺序:只读核对 → 登记(第 1 段)→ 计数校验应为 15 → 按实际授权范围绑定(第 3 段)。
2. 检查正在使用接口的账号对应 `t_api.group_id`,以及 `t_api_group_resource` 绑定。按已确认的授权范围补齐,**不能将所有资源自动赋给所有权限组**——那是扩大授权,属于安全倒退。
3. 资源登记使用完整请求路径与正确方法(`method=1` 即 POST)。查询与变更的 `traffic-cutoff-config` 路径前缀不同,分别登记。
4. 在验证环境检查:已授权接口正常;未登记/未授权/停用资源拒绝返回 `10014`;账号停用或无权限组拒绝;权限数据查询失败返回 `10016`。确认全部在用账号与接口后再部署生产。
## 免登录路径
`/openapi/v3/query/token` 与 `/openapi/v3/query/operator-token` 由配置 `router.exceptLogin` 控制,中间件内已无硬编码白名单。部署配置必须保留这两条,否则取 token 接口自身会被鉴权拦截而无法调用。
已确认 dev / preview / preview2 / prod 四套配置均含这两条。
## 重复路由的处置决定
代码中存在 12 条功能重叠的路由(`/common` 与 `/change` 各 6 条为同义路径)。判定分两层:先看**对外文档是否发布过**(发布过的必须保住),再看**业务是否确认在用**(业务确认不用的才硬删除)。
| 路径 | 决定 | 依据 |
|---|---|---|
| `/change/traffic-cutoff-config` | **下线**(不登记) | 从未写入对外文档(原始 common.md 只发布 4 个接口);与 `/change/batch-sim-traffic-cutoff` 参数类型、实现完全相同,控制器代码逐行重复,客户迁移无需改报文体;尾路径与只读的 `/query/traffic-cutoff-config` 同名,最易误调 |
| `/common/*`(6 条) | **已删除**(代码级,返回 404) | 业务确认真实客户只走 `/change/`,从不使用 `/common/`;该前缀是新增 `/change` 分组时未删旧分组的遗留,从未作为对外接口发布(原始 `common.md` 只发布 4 个 `/change` 接口) |
| `/change/renew` | **保留,登记授权,待观察** | 08-21 建立、09-10 才新增标准入口,存在早期接入客户;且入参只收 `cards[]`,与 `batch-sim-subscribe`(兼容平铺 `iccid[]`)不等价,不能直接判定为重复 |
| `/change/sim-subscribe`、`/change/sim-traffic-cutoff`(单卡)与对应批量接口 | **保留** | 已对外文档化,且同步单卡与异步批次是两套实现,粒度不同,非重复 |
两种下线方式的差别:
| | `/common/*` | `/change/traffic-cutoff-config` |
|---|---|---|
| 手段 | 删除 `internal/router/common.go`,`router.go` 不再调用 `Common()` | 不登记资源、不授权 |
| 客户端表现 | `404`(路由不存在) | `10014`(没有权限) |
| 恢复成本 | 需重新发版恢复路由,并补登记 6 条资源与授权 | 执行 SQL 文末的恢复语句即可,无需发版 |
| 选择理由 | 业务已确认无客户,该前缀无文档包袱,继续保留只会放大接口表面积与登记/授权工作量 | 参数与标准入口完全一致,但缺少「无人在用」的确认,需保住可逆性 |
`/change/renew` 上线后查调用日志,确认无调用再走「不登记」方式下线。
注意:`g.Meta` 的 `deprecated` 标签在 GoFrame v2.9.6 中不被解析,**没有运行时或文档生成效果**,不能作为废弃告知手段。对外废弃说明由 `openapi-docs` 承担。
## 回归验证
```
go test ./internal/logic/middleware -count=1
```
测试使用内存 SQLite,覆盖:数字/文本方法登记、路径规范化与末尾斜杠、未登记资源、方法不匹配、资源停用、缺失权限绑定、兼容入口独立授权(登记但未授权仍拒绝)、账号停用/无权限组/不存在、token 路径不在中间件白名单内,以及权限数据查询失败必须返回错误而非静默放行。
+4 -2
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
@@ -34,8 +34,10 @@ var (
CodeLoginExpired = gcode.New(10012, "登录已过期", nil) CodeLoginExpired = gcode.New(10012, "登录已过期", nil)
// 部门下有子部门,不能删除 // 部门下有子部门,不能删除
CodeDeptHasSub = gcode.New(10013, "部门下有子部门,不能删除", nil) CodeDeptHasSub = gcode.New(10013, "部门下有子部门,不能删除", nil)
// 没有权限 // 没有权限(业务判定:资源未登记、资源停用、账号不可用或未授权)
CodeNoPermission = gcode.New(10014, "没有权限", nil) CodeNoPermission = gcode.New(10014, "没有权限", nil)
// 无效Token // 无效Token
CodeInvalidToken = gcode.New(10015, "无效Token", nil) CodeInvalidToken = gcode.New(10015, "无效Token", nil)
// 权限校验失败(系统侧故障:权限数据查询异常,区别于 10014 无权限,避免误判为授权问题)
CodePermissionCheckFailed = gcode.New(10016, "权限校验失败", nil)
) )
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts // Package consts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts package consts
+1 -1
View File
@@ -1,6 +1,6 @@
// Package bcache // Package bcache
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package bcache package bcache
+1 -1
View File
@@ -1,7 +1,7 @@
// Package cache // Package cache
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cache package cache
+1 -1
View File
@@ -1,7 +1,7 @@
// Package file // Package file
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package file package file
+1 -1
View File
@@ -1,7 +1,7 @@
// Package contexts // Package contexts
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package contexts package contexts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package mcache // Package mcache
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// 内存缓存管理 // 内存缓存管理
package mcache package mcache
+1 -1
View File
@@ -1,7 +1,7 @@
// package xgorm // package xgorm
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package xgorm package xgorm
+1 -1
View File
@@ -1,7 +1,7 @@
// package xgorm // package xgorm
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package xgorm package xgorm
@@ -1,7 +1,7 @@
// package gormmodel // package gormmodel
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package gormmodel package gormmodel
@@ -1,7 +1,7 @@
// package handler // package handler
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package handler package handler
@@ -1,7 +1,7 @@
// package handler // package handler
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package handler package handler
+1 -1
View File
@@ -1,7 +1,7 @@
// package handler // package handler
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package handler package handler
+1 -1
View File
@@ -1,7 +1,7 @@
// package handler // package handler
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package handler package handler
+1 -1
View File
@@ -1,7 +1,7 @@
// package hook // package hook
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package hook package hook
+34 -21
View File
@@ -2,6 +2,8 @@ package middleware
import ( import (
"context" "context"
"database/sql"
"errors"
"net/http" "net/http"
"slices" "slices"
"strconv" "strconv"
@@ -138,7 +140,13 @@ func (s *sMiddleware) ApiAuth(r *ghttp.Request) {
response.JsonExit(r, gcode.CodeNotAuthorized.Code(), consts.CodeLoginExpired.Message()) response.JsonExit(r, gcode.CodeNotAuthorized.Code(), consts.CodeLoginExpired.Message())
return return
} }
if !s.hasOpenApiPermission(ctx, r.Method, path) { allowed, err := s.hasOpenApiPermission(ctx, r.Method, path)
if err != nil {
g.Log().Errorf(ctx, "sMiddleware.ApiAuth permission check failed, method: %s, path: %s, err: %v", r.Method, path, err)
response.JsonExit(r, consts.CodePermissionCheckFailed.Code(), consts.CodePermissionCheckFailed.Message())
return
}
if !allowed {
response.JsonExit(r, consts.CodeNoPermission.Code(), consts.CodeNoPermission.Message()) response.JsonExit(r, consts.CodeNoPermission.Code(), consts.CodeNoPermission.Message())
return return
} }
@@ -162,33 +170,36 @@ func openApiMethodValues(method string) []string {
return values return values
} }
func (s *sMiddleware) hasOpenApiPermission(ctx context.Context, method, path string) bool { // hasOpenApiPermission 判定当前 API 账号对指定路由是否已授权。
// 返回值 error 仅代表权限数据查询本身的系统故障,与「无权限」(false, nil) 严格区分:
// 调用方对 error 返回系统异常码,对 false 返回无权限码,避免把数据库故障误报成授权问题。
// 未登记资源、资源停用、账号不可用、未绑定权限组均按无权限处理。
func (s *sMiddleware) hasOpenApiPermission(ctx context.Context, method, path string) (bool, error) {
agentUser := contexts.GetAgentUser(ctx) agentUser := contexts.GetAgentUser(ctx)
if agentUser == nil { if agentUser == nil {
return false return false, nil
}
if path == "/openapi/v3/query/token" {
return true
} }
path = strings.TrimSpace(path) path = strings.TrimSpace(path)
if path != "/" { if path != "/" {
path = strings.TrimRight(path, "/") path = strings.TrimRight(path, "/")
} }
// 每条受保护路由(含 /common 兼容前缀的别名路由)都必须显式登记资源并完成授权,
// 资源查询失败不得降级为放行。
var apiResource entity.TApiResource var apiResource entity.TApiResource
if err := dao.TApiResource.Ctx(ctx). err := dao.TApiResource.Ctx(ctx).
WhereIn(dao.TApiResource.Columns().Method, openApiMethodValues(method)). WhereIn(dao.TApiResource.Columns().Method, openApiMethodValues(method)).
Where(dao.TApiResource.Columns().Path, path). Where(dao.TApiResource.Columns().Path, path).
Scan(&apiResource); err != nil { Scan(&apiResource)
g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission resource not configured, method: %s, path: %s, err: %v", method, path, err) if err != nil && !errors.Is(err, sql.ErrNoRows) {
return true return false, gerror.Wrapf(err, "query t_api_resource failed, method: %s, path: %s", method, path)
} }
if apiResource.Id == 0 { if err != nil || apiResource.Id == 0 {
g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission resource not configured, method: %s, path: %s", method, path) g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission resource not configured, method: %s, path: %s", method, path)
return true return false, nil
} }
if apiResource.Status == 1 { if apiResource.Status == 1 {
return false return false, nil
} }
var tApi entity.TApi var tApi entity.TApi
@@ -199,19 +210,22 @@ func (s *sMiddleware) hasOpenApiPermission(ctx context.Context, method, path str
apiMod = apiMod.Where(dao.TApi.Columns().AppKey, agentUser.AppKey) apiMod = apiMod.Where(dao.TApi.Columns().AppKey, agentUser.AppKey)
} else { } else {
g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission api identity is empty, resourceApiId: %d, path: %s", apiResource.Id, path) g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission api identity is empty, resourceApiId: %d, path: %s", apiResource.Id, path)
return false return false, nil
} }
if err := apiMod.Scan(&tApi); err != nil { if err := apiMod.Scan(&tApi); err != nil {
g.Log().Errorf(ctx, "sMiddleware.hasOpenApiPermission scan t_api error: %v", err) if errors.Is(err, sql.ErrNoRows) {
return false g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission t_api not found, resourceApiId: %d, path: %s", apiResource.Id, path)
return false, nil
}
return false, gerror.Wrapf(err, "query t_api failed, resourceApiId: %d, path: %s", apiResource.Id, path)
} }
if tApi.Id == 0 || tApi.Status == 1 { if tApi.Id == 0 || tApi.Status == 1 {
g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission t_api unavailable, tApiId: %d, status: %d, resourceApiId: %d, path: %s", tApi.Id, tApi.Status, apiResource.Id, path) g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission t_api unavailable, tApiId: %d, status: %d, resourceApiId: %d, path: %s", tApi.Id, tApi.Status, apiResource.Id, path)
return false return false, nil
} }
if tApi.GroupId <= 0 { if tApi.GroupId <= 0 {
g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission groupId is empty, tApiId: %d, appKey: %s, resourceApiId: %d, path: %s", tApi.Id, tApi.AppKey, apiResource.Id, path) g.Log().Warningf(ctx, "sMiddleware.hasOpenApiPermission groupId is empty, tApiId: %d, appKey: %s, resourceApiId: %d, path: %s", tApi.Id, tApi.AppKey, apiResource.Id, path)
return false return false, nil
} }
count, err := dao.TApiGroupResource.Ctx(ctx). count, err := dao.TApiGroupResource.Ctx(ctx).
@@ -219,10 +233,9 @@ func (s *sMiddleware) hasOpenApiPermission(ctx context.Context, method, path str
Where(dao.TApiGroupResource.Columns().ApiId, apiResource.Id). Where(dao.TApiGroupResource.Columns().ApiId, apiResource.Id).
Count() Count()
if err != nil { if err != nil {
g.Log().Errorf(ctx, "sMiddleware.hasOpenApiPermission scan relation error: %v", err) return false, gerror.Wrapf(err, "query t_api_group_resource failed, groupId: %d, resourceApiId: %d, path: %s", tApi.GroupId, apiResource.Id, path)
return false
} }
return count > 0 return count > 0, nil
} }
func (m *sMiddleware) OldResponseHandler(r *ghttp.Request) { func (m *sMiddleware) OldResponseHandler(r *ghttp.Request) {
@@ -0,0 +1,117 @@
package middleware
import (
"context"
"testing"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model"
)
func TestOpenAPIPermission(t *testing.T) {
ctx := contexts.Set(context.Background(), &model.Context{
AgentUser: &model.BaseClaimsApi{ApiId: 1, AppKey: "test-key"},
})
if err := gdb.SetConfig(gdb.Config{"default": gdb.ConfigGroup{{Type: "sqlite", Link: "sqlite::@file(:memory:)", MaxOpenConnCount: 1}}}); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = g.DB().Close(ctx) })
if err := g.DB().GetCore().ClearTableFieldsAll(ctx); err != nil {
t.Fatal(err)
}
exec := func(sql string) {
t.Helper()
if _, err := g.DB().Exec(ctx, sql); err != nil {
t.Fatal(err)
}
}
exec(`CREATE TABLE t_api_resource (id INTEGER PRIMARY KEY, method TEXT, path TEXT, status INTEGER)`)
exec(`CREATE TABLE t_api (id INTEGER PRIMARY KEY, app_key TEXT, group_id INTEGER, status INTEGER)`)
exec(`CREATE TABLE t_api_group_resource (group_id INTEGER, api_id INTEGER)`)
exec(`INSERT INTO t_api VALUES (1, 'test-key', 7, 0)`)
exec(`INSERT INTO t_api_resource VALUES
(1, '1', '/openapi/v3/change/sim-subscribe', 0),
(2, 'POST', '/openapi/v3/query/sim-info', 0),
(3, '1', '/openapi/v3/query/sim-status', 1),
(4, '1', '/openapi/v3/query/sim-imei-batch', 0)`)
exec(`INSERT INTO t_api_group_resource VALUES (7, 1), (7, 2), (7, 3)`)
middleware := New()
check := func(t *testing.T, method, path string) (bool, error) {
t.Helper()
return middleware.hasOpenApiPermission(ctx, method, path)
}
for _, tc := range []struct {
name, method, path string
want bool
}{
{"authorized numeric method", "POST", "/openapi/v3/change/sim-subscribe", true},
{"authorized text method", "POST", "/openapi/v3/query/sim-info", true},
{"normalized path", "post", "/openapi/v3/query/sim-info/", true},
{"unregistered resource", "POST", "/openapi/v3/query/batch-status", false},
{"legacy alias path never inherits grants", "POST", "/openapi/v3/common/sim-subscribe", false},
{"wrong method", "GET", "/openapi/v3/change/sim-subscribe", false},
{"disabled resource", "POST", "/openapi/v3/query/sim-status", false},
{"missing group binding", "POST", "/openapi/v3/query/sim-imei-batch", false},
} {
t.Run(tc.name, func(t *testing.T) {
got, err := check(t, tc.method, tc.path)
if err != nil {
t.Fatalf("business denial must not report a system failure: %v", err)
}
if got != tc.want {
t.Fatalf("permission = %v, want %v", got, tc.want)
}
})
}
// Token endpoints are exempted by router.exceptLogin only; the middleware must not
// carry its own whitelist, otherwise the two lists drift apart.
if got, err := check(t, "POST", "/openapi/v3/query/token"); err != nil || got {
t.Fatalf("token path must not be whitelisted inside middleware, got=%v err=%v", got, err)
}
// The /common alias prefix has been removed from the router (router/common.go deleted).
// Keep the path-level guard anyway: if an alias is ever re-introduced, it must still be
// registered and granted on its own full path instead of inheriting /change permissions.
exec(`INSERT INTO t_api_resource VALUES (5, '1', '/openapi/v3/common/sim-subscribe', 0)`)
if got, err := check(t, "POST", "/openapi/v3/common/sim-subscribe"); err != nil || got {
t.Fatalf("registered compatibility route without grant must be denied, got=%v err=%v", got, err)
}
exec(`INSERT INTO t_api_group_resource VALUES (7, 5)`)
if got, err := check(t, "POST", "/openapi/v3/common/sim-subscribe"); err != nil || !got {
t.Fatalf("explicitly granted compatibility route must be allowed, got=%v err=%v", got, err)
}
// Unusable accounts are a business denial, not a system failure.
for _, sql := range []string{
`UPDATE t_api SET status = 1`,
`UPDATE t_api SET status = 0, group_id = 0`,
`DELETE FROM t_api`,
} {
exec(sql)
got, err := check(t, "POST", "/openapi/v3/query/sim-info")
if err != nil {
t.Fatalf("account rejection must not be reported as a system failure after %s: %v", sql, err)
}
if got {
t.Fatalf("invalid account allowed after %s", sql)
}
}
// A broken permission lookup is a system failure: it must deny AND surface the error,
// so callers can answer 10016 instead of misreporting it as 10014 no-permission.
exec(`DROP TABLE t_api_resource`)
got, err := check(t, "POST", "/openapi/v3/query/sim-info")
if err == nil {
t.Fatal("resource lookup failure must return an error")
}
if got {
t.Fatal("resource lookup failure must deny access")
}
}
-1
View File
@@ -22,7 +22,6 @@ import (
// setupImeiBatchDB 建一张最小可用的卡表并灌入覆盖各分支的样本数据。 // setupImeiBatchDB 建一张最小可用的卡表并灌入覆盖各分支的样本数据。
// //
// 样本设计(对齐 §7 测试场景): // 样本设计(对齐 §7 测试场景):
//
// CARD-A 有 imei → 正常命中 // CARD-A 有 imei → 正常命中
// CARD-B imei 为空 → 卡存在但上游未上报值 // CARD-B imei 为空 → 卡存在但上游未上报值
// CARD-C 有 imei → 正常命中(入库带的值) // CARD-C 有 imei → 正常命中(入库带的值)
+4 -4
View File
@@ -286,7 +286,7 @@ func (s *sQueryToken) GenerateToken(ctx context.Context, customer *model.CustomC
ets := g.Cfg().MustGet(ctx, "jwt.expiresTime", "3650d").String() ets := g.Cfg().MustGet(ctx, "jwt.expiresTime", "3650d").String()
bts := g.Cfg().MustGet(ctx, "jwt.bufferTime", "1d").String() bts := g.Cfg().MustGet(ctx, "jwt.bufferTime", "1d").String()
iss := g.Cfg().MustGet(ctx, "jwt.issuer", "JieIOTAPI").String() iss := g.Cfg().MustGet(ctx, "jwt.issuer", "JieIOTAPI").String()
sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "${JWT_SIGNING_KEY}").String() sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "49c54195e73304e74a8429b178965865").String()
et, _ := utils.ParseDuration(ets) et, _ := utils.ParseDuration(ets)
bt, _ := utils.ParseDuration(bts) bt, _ := utils.ParseDuration(bts)
g.Log().Infof(ctx, "GenerateToken: customer:%+v, et:%s, bt:%s, iss:%s", customer, et, bt, iss) g.Log().Infof(ctx, "GenerateToken: customer:%+v, et:%s, bt:%s, iss:%s", customer, et, bt, iss)
@@ -336,7 +336,7 @@ func (s *sQueryToken) GenerateToken(ctx context.Context, customer *model.CustomC
// GenerateShortToken 生成短令牌 // GenerateShortToken 生成短令牌
func (s *sQueryToken) GenerateShortToken(ctx context.Context, tokenUuid string) (token string, err error) { func (s *sQueryToken) GenerateShortToken(ctx context.Context, tokenUuid string) (token string, err error) {
sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "${JWT_SIGNING_KEY}").String() sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "49c54195e73304e74a8429b178965865").String()
shortToken := jwt.NewWithClaims(jwt.SigningMethodHS256, &model.ApiTokenClaims{ shortToken := jwt.NewWithClaims(jwt.SigningMethodHS256, &model.ApiTokenClaims{
UUID: tokenUuid, UUID: tokenUuid,
}) })
@@ -346,7 +346,7 @@ func (s *sQueryToken) GenerateShortToken(ctx context.Context, tokenUuid string)
// 解析Token // 解析Token
func (s *sQueryToken) ParseToken(ctx context.Context, token string) (claims *model.CustomClaimsApi, err error) { func (s *sQueryToken) ParseToken(ctx context.Context, token string) (claims *model.CustomClaimsApi, err error) {
sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "${JWT_SIGNING_KEY}").String() sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "49c54195e73304e74a8429b178965865").String()
t, err := jwt.ParseWithClaims(token, &model.ApiTokenClaims{}, func(token *jwt.Token) (interface{}, error) { t, err := jwt.ParseWithClaims(token, &model.ApiTokenClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(sk), nil return []byte(sk), nil
}) })
@@ -386,7 +386,7 @@ func (s *sQueryToken) ParseToken(ctx context.Context, token string) (claims *mod
// 删除Token // 删除Token
func (s *sQueryToken) DeleteToken(ctx context.Context, token string) (err error) { func (s *sQueryToken) DeleteToken(ctx context.Context, token string) (err error) {
sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "${JWT_SIGNING_KEY}").String() sk := g.Cfg().MustGet(ctx, "jwt.signingKey", "49c54195e73304e74a8429b178965865").String()
t, err := jwt.ParseWithClaims(token, &model.ApiTokenClaims{}, func(token *jwt.Token) (interface{}, error) { t, err := jwt.ParseWithClaims(token, &model.ApiTokenClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(sk), nil return []byte(sk), nil
}) })
@@ -4,11 +4,11 @@ import (
"context" "context"
"strings" "strings"
"github.com/gogf/gf/v2/errors/gerror"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model/entity" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model/entity"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/service" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/service"
"github.com/gogf/gf/v2/errors/gerror"
) )
const queryTrafficCutoffConfigMaxCards = 1000 const queryTrafficCutoffConfigMaxCards = 1000
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package genin package genin
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package request // package request
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package request package request
+1 -1
View File
@@ -1,7 +1,7 @@
// package response // package response
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package response package response
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// package model // package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package model // Package model
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package iotin // Package iotin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package iotin // Package iotin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package iot // Package iot
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,7 +1,7 @@
// Package genin // Package genin
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie // @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version // @AutoGenerate Version
package model package model
+1 -1
View File
@@ -1,6 +1,6 @@
// package packed // package packed
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package packed package packed
+1 -1
View File
@@ -1,7 +1,7 @@
// package response // package response
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package response package response
-15
View File
@@ -1,15 +0,0 @@
package router
import (
"context"
"git.5iot.com/iotlcm-public/iotlcm-openapi/internal/controller/common"
"github.com/gogf/gf/v2/net/ghttp"
)
func Common(ctx context.Context, group *ghttp.RouterGroup) {
group.Group("/common", func(group *ghttp.RouterGroup) {
group.Bind(common.NewV1())
})
}
-1
View File
@@ -15,7 +15,6 @@ func InitRouter(ctx context.Context, s *ghttp.Server) {
service.Middleware().ApiAuth, service.Middleware().ApiAuth,
service.Middleware().ResponseHandler, service.Middleware().ResponseHandler,
) )
Common(ctx, group)
Change(ctx, group) Change(ctx, group)
Query(ctx, group) Query(ctx, group)
}) })
@@ -33,7 +33,7 @@ database:
level: "all" level: "all"
stdout: true stdout: true
default: default:
link: "mysql:${DB_USER}:${DB_PASSWORD}@tcp(${DB_HOST}:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" link: "${DB_DSN}"
debug: true debug: true
charset: "utf8mb4" charset: "utf8mb4"
dryRun: false dryRun: false
@@ -49,9 +49,9 @@ redis:
default: default:
mode: "single" mode: "single"
sentinelMasterName: "iotlcm-master" sentinelMasterName: "iotlcm-master"
address: "192.0.2.29:6379" address: "127.0.0.1:6379"
db: 0 db: 0
pass: "${REDIS_PASSWORD}" pass: "${SERVICE_PASSWORD}"
minIdle: 5 minIdle: 5
maxIdle: 30 maxIdle: 30
maxActive: 5000 maxActive: 5000
@@ -73,4 +73,4 @@ upstream:
rabbitmq: rabbitmq:
enabled: true enabled: true
dsn: "amqp://${MQ_USER}:${MQ_PASSWORD}@${MQ_HOST}/" dsn: "${SERVICE_DSN}"
+1 -3
View File
@@ -1,9 +1,7 @@
# 基础镜像仓库。默认使用 Docker Hub 官方镜像;内网环境可替换为自己的仓库:
# docker build --build-arg BASE_REGISTRY=harbor.example.com/library ...
ARG BASE_REGISTRY=docker.io/library ARG BASE_REGISTRY=docker.io/library
FROM ${BASE_REGISTRY}/alpine:3.23 FROM ${BASE_REGISTRY}/alpine:3.23
RUN apk add --no-cache ca-certificates tzdata
############################################################################### ###############################################################################
# INSTALLATION # INSTALLATION
############################################################################### ###############################################################################
+1 -1
View File
@@ -1,7 +1,7 @@
// package convert // package convert
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package convert package convert
+1 -1
View File
@@ -1,7 +1,7 @@
// package excel // package excel
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package excel package excel
+1 -1
View File
@@ -31,7 +31,7 @@ type Redis struct {
// Config is redis configuration. // Config is redis configuration.
type Config struct { type Config struct {
// Address It supports single and cluster redis server. Multiple addresses joined with char ','. Eg: 192.168.1.1:6379, 192.168.1.2:6379. // Address It supports single and cluster redis server. Multiple addresses joined with char ','. Eg: 127.0.0.1:6379, 127.0.0.1:6379.
Address string `json:"address"` Address string `json:"address"`
Db int `json:"db"` // Redis db. Db int `json:"db"` // Redis db.
User string `json:"user"` // Username for AUTH. User string `json:"user"` // Username for AUTH.
+1 -1
View File
@@ -1,7 +1,7 @@
// package tree // package tree
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package tree package tree
+1 -1
View File
@@ -1,7 +1,7 @@
// package utility // package utility
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package utility package utility
+3 -9
View File
@@ -1,7 +1,7 @@
// package version // package version
// @Link https://github.com/xiujiecn/xiu-admin // @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie // @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn> // @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package version package version
@@ -24,20 +24,14 @@ func ShowLogo(buildVersion, buildTime, commitID string) {
CommitID = commitID CommitID = commitID
//版本号 //版本号
fmt.Println(` fmt.Println(" __ __ _ _ _ _ \n \\ \\/ /(_) _ _ / \\ __| | _ __ ___ (_) _ __ \n \\ / | || | | | / _ \\ / _` || '_ ` _ \\ | || '_ \\ \n / \\ | || |_| | / ___ \\| (_| || | | | | || || | | |\n /_/\\_\\|_| \\__,_| /_/ \\_\\\\__,_||_| |_| |_||_||_| |_|")
██╗██╗███████╗ ██╗ ██████╗ ████████╗
██║██║██╔════╝ ██║██╔═══██╗╚══██╔══╝
██║██║█████╗ ██║██║ ██║ ██║
██ ██║██║██╔══╝ ██║██║ ██║ ██║
╚█████╔╝██║███████╗ ██║╚██████╔╝ ██║
╚════╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝`)
fmt.Println("") fmt.Println("")
fmt.Println("Version :", buildVersion) fmt.Println("Version :", buildVersion)
fmt.Println("BuildTime :", buildTime) fmt.Println("BuildTime :", buildTime)
fmt.Println("CommitID :", commitID) fmt.Println("CommitID :", commitID)
fmt.Println("") fmt.Println("")
fmt.Println("Copyright:", "2026 The iotLCM Authors") fmt.Println("Copyright:", "XiuJieZhiLian Technology Co.,Ltd")
} }
func AppName(ctx context.Context) string { func AppName(ctx context.Context) string {