sync: 同步 v1.0.4 开源代码并脱敏
This commit is contained in:
@@ -11,3 +11,4 @@
|
|||||||
*.ttf binary
|
*.ttf binary
|
||||||
*.pdf binary
|
*.pdf binary
|
||||||
*.exe binary
|
*.exe binary
|
||||||
|
*.go linguist-language=Go
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# GoFrame Template For SingleRepo
|
||||||
|
|
||||||
|
Quick Start:
|
||||||
|
- https://goframe.org/quick
|
||||||
@@ -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
@@ -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}"
|
||||||
@@ -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 路径不在中间件白名单内,以及权限数据查询失败必须返回错误而非静默放行。
|
||||||
@@ -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,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,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,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,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,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,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,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,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,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
|
||||||
|
|||||||
Vendored
+1
-1
@@ -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
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -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,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,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,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 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,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,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
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 → 正常命中(入库带的值)
|
||||||
|
|||||||
@@ -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,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 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 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,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,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,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,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 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -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,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,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,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
|
||||||
|
|
||||||
|
|||||||
@@ -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,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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user