mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-04 07:22:13 +08:00
Compare commits
330 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dd83d3cf2 | ||
|
|
14e1aac9b5 | ||
|
|
aa4b102108 | ||
|
|
e4bc35151f | ||
|
|
56da498b7e | ||
|
|
1bba1a62b1 | ||
|
|
4a84ca9a02 | ||
|
|
a70d37a676 | ||
|
|
6892e84ad2 | ||
|
|
73f455745c | ||
|
|
021abfca18 | ||
|
|
7d66f7ff0d | ||
|
|
470b37be7e | ||
|
|
f6cfab9901 | ||
|
|
51572b5da0 | ||
|
|
91ca28b7e3 | ||
|
|
04cedce9a1 | ||
|
|
5e0d789440 | ||
|
|
149e4267cd | ||
|
|
9a479d1b55 | ||
|
|
fc095bf054 | ||
|
|
1af06aed96 | ||
|
|
9236936a55 | ||
|
|
125152460f | ||
|
|
6d90fb0bc3 | ||
|
|
b889d5017b | ||
|
|
72b08f9cc5 | ||
|
|
681950dadd | ||
|
|
a67d9337b8 | ||
|
|
2f1182e8a9 | ||
|
|
cbb4d854ab | ||
|
|
35598d5648 | ||
|
|
5c76b9e45a | ||
|
|
0b8fea4cb4 | ||
|
|
5fa93ebdc7 | ||
|
|
8aa0aed566 | ||
|
|
2eb32a0ed7 | ||
|
|
bac9e2bfd5 | ||
|
|
e4d74ae11d | ||
|
|
8a0a8558cf | ||
|
|
2185a3b674 | ||
|
|
9e3c306a5b | ||
|
|
b1c30df8e3 | ||
|
|
69816f8691 | ||
|
|
b4ec65785d | ||
|
|
3c93644146 | ||
|
|
fb58560d15 | ||
|
|
6ab77f5eb5 | ||
|
|
4f57d7f761 | ||
|
|
1563bd3dda | ||
|
|
df3346387f | ||
|
|
77b66653ed | ||
|
|
3077fd279d | ||
|
|
f3605ddc71 | ||
|
|
6aaa4aee6a | ||
|
|
e3748da860 | ||
|
|
36e6fb5fc8 | ||
|
|
86b503f87f | ||
|
|
50a783ff01 | ||
|
|
da9546ba24 | ||
|
|
1439eb39a9 | ||
|
|
e1a68497d6 | ||
|
|
c4615a1224 | ||
|
|
fa28dcbf32 | ||
|
|
2656320d04 | ||
|
|
5d4327eb14 | ||
|
|
b4f6c4f9d5 | ||
|
|
14c6c9321a | ||
|
|
386126b1b2 | ||
|
|
de0927289e | ||
|
|
edb0937024 | ||
|
|
43a4840daf | ||
|
|
5e98445b22 | ||
|
|
e617b45ba3 | ||
|
|
20283bb55b | ||
|
|
515dbf2c78 | ||
|
|
2887e280d6 | ||
|
|
8826705e71 | ||
|
|
8917afab2a | ||
|
|
49233ec26a | ||
|
|
1e1cbbee80 | ||
|
|
39a5b17d31 | ||
|
|
35a55e10aa | ||
|
|
9e80ed0fa8 | ||
|
|
5299f3dcf6 | ||
|
|
7b1564898b | ||
|
|
76d242e024 | ||
|
|
260c152166 | ||
|
|
9f4c1ef9f9 | ||
|
|
bd7fdb5e6c | ||
|
|
a381910e86 | ||
|
|
d182ef0391 | ||
|
|
7319122e92 | ||
|
|
4809fa4f19 | ||
|
|
ee01f80dc1 | ||
|
|
98671a73f4 | ||
|
|
f33a950103 | ||
|
|
132bf34b69 | ||
|
|
01b08e1e43 | ||
|
|
c6a456c7c7 | ||
|
|
cc2329d4fd | ||
|
|
84d0433cc3 | ||
|
|
a113dd4def | ||
|
|
98f793155f | ||
|
|
a38bd413ab | ||
|
|
9e1535e203 | ||
|
|
037a409919 | ||
|
|
571d1479a4 | ||
|
|
ae1934f7db | ||
|
|
39e05a2dad | ||
|
|
7b46bbb628 | ||
|
|
d2527e36eb | ||
|
|
029994a83b | ||
|
|
37047919ab | ||
|
|
0b45d48e85 | ||
|
|
0c660f8335 | ||
|
|
ce9a247a9d | ||
|
|
b4bd46d067 | ||
|
|
1d8b686446 | ||
|
|
2b192f7dca | ||
|
|
979114db45 | ||
|
|
6d0152c8e2 | ||
|
|
dabed96af4 | ||
|
|
36becd972a | ||
|
|
7498035d24 | ||
|
|
39a0359dd5 | ||
|
|
49a3c43741 | ||
|
|
fa3ea5ee4d | ||
|
|
05af95dade | ||
|
|
ae680d79ed | ||
|
|
97a5c1ac1d | ||
|
|
8f39754812 | ||
|
|
ac4371fa98 | ||
|
|
9985c4a344 | ||
|
|
fecfaae8dc | ||
|
|
804b6f2282 | ||
|
|
cb58daf38d | ||
|
|
a9398d210b | ||
|
|
df1c2383da | ||
|
|
ff8b1b4ae3 | ||
|
|
4cce21b125 | ||
|
|
6baf810885 | ||
|
|
9a48b2e942 | ||
|
|
c0c9c984d1 | ||
|
|
3fed478e4d | ||
|
|
0afc5d0b1a | ||
|
|
ba5a0d47eb | ||
|
|
be7bc658fc | ||
|
|
c89bbf5130 | ||
|
|
e59e3a9f00 | ||
|
|
6146be1474 | ||
|
|
730d2a9ad2 | ||
|
|
d008941cb3 | ||
|
|
df7a3e65ee | ||
|
|
0707f3d963 | ||
|
|
976d6fb03f | ||
|
|
f1aafbc06f | ||
|
|
7cb5444dbb | ||
|
|
3bede6e65f | ||
|
|
ad90bb4645 | ||
|
|
2220fd18ca | ||
|
|
bb3df5785a | ||
|
|
6e54eda41f | ||
|
|
df4c0adf0b | ||
|
|
7cbe4afdb8 | ||
|
|
16f150caae | ||
|
|
7229b41fc7 | ||
|
|
2cd5037878 | ||
|
|
53ee6383db | ||
|
|
a09478f374 | ||
|
|
d3c1d77a35 | ||
|
|
8824400c3e | ||
|
|
6e8eff9bb9 | ||
|
|
f5884d1608 | ||
|
|
56949a58bc | ||
|
|
7d256879c5 | ||
|
|
f9512fda58 | ||
|
|
beb63cb152 | ||
|
|
11ff73b578 | ||
|
|
0ed4a404e4 | ||
|
|
6c86501d11 | ||
|
|
2fe8932c1d | ||
|
|
0ab68aa9fb | ||
|
|
2f92b06869 | ||
|
|
03e94f9f53 | ||
|
|
606e29d390 | ||
|
|
3ecadf4aad | ||
|
|
0170d19fa7 | ||
|
|
ce1d2904c7 | ||
|
|
ea41f830fd | ||
|
|
e1a4a7b8c0 | ||
|
|
b381e8ee73 | ||
|
|
45e1429ae8 | ||
|
|
7b1d63a786 | ||
|
|
e204b4d81f | ||
|
|
325ed747d8 | ||
|
|
cbf3dba28d | ||
|
|
4329f72abf | ||
|
|
ad1cdba338 | ||
|
|
016c3915d7 | ||
|
|
79fa18132b | ||
|
|
673caf41a0 | ||
|
|
c441638fc0 | ||
|
|
ae18397ca6 | ||
|
|
426ce616c0 | ||
|
|
5cda979209 | ||
|
|
cc7e67b01a | ||
|
|
6999a9c011 | ||
|
|
bbdc8663d3 | ||
|
|
4bfeeecb05 | ||
|
|
bbc7b4aeed | ||
|
|
d3062b2e46 | ||
|
|
b7777fb46c | ||
|
|
35f39ca291 | ||
|
|
f2e206700c | ||
|
|
adb77af1d9 | ||
|
|
3a34746668 | ||
|
|
fe17058700 | ||
|
|
9bee0a2071 | ||
|
|
b7f69844e1 | ||
|
|
602bf9c017 | ||
|
|
c3d1891ccd | ||
|
|
4d8f2db924 | ||
|
|
6599b366dc | ||
|
|
ba16ace697 | ||
|
|
7ade9baa15 | ||
|
|
fa454b1b99 | ||
|
|
8375094c69 | ||
|
|
91079d3f15 | ||
|
|
63412a9fcc | ||
|
|
d98648f03b | ||
|
|
c37fe91672 | ||
|
|
4d40fb6b60 | ||
|
|
be3b788b8f | ||
|
|
723e54013a | ||
|
|
4d566f68b6 | ||
|
|
31f817d189 | ||
|
|
59231668c5 | ||
|
|
cadca752c4 | ||
|
|
edf215e6fd | ||
|
|
e12dd079fd | ||
|
|
04a509d45e | ||
|
|
269a659200 | ||
|
|
2c31bf46b5 | ||
|
|
5b787334c8 | ||
|
|
f761afb1ef | ||
|
|
8f6639f825 | ||
|
|
fc17d9d7df | ||
|
|
ab092e88a8 | ||
|
|
877c17251d | ||
|
|
ffe43f6098 | ||
|
|
66f49b67d6 | ||
|
|
08d6dc5227 | ||
|
|
56a1e29cdd | ||
|
|
7cea6b6fc9 | ||
|
|
4b57e80e6a | ||
|
|
0059a232a6 | ||
|
|
45676fdc8d | ||
|
|
a161fcc89b | ||
|
|
e32c5f534f | ||
|
|
426d691c95 | ||
|
|
e9a4c8ab97 | ||
|
|
a55cfebd09 | ||
|
|
34cc02f8c7 | ||
|
|
624d9fddb7 | ||
|
|
47fbe43324 | ||
|
|
1245f07a2d | ||
|
|
839975b0cf | ||
|
|
8c1233393f | ||
|
|
9cdb0568cc | ||
|
|
74e05b83ea | ||
|
|
4ded9e7d49 | ||
|
|
716272a1e2 | ||
|
|
9cc8352593 | ||
|
|
43a1031e38 | ||
|
|
a5547b2f30 | ||
|
|
b0aa23540b | ||
|
|
ffaa6c4a17 | ||
|
|
fbf72f0ec4 | ||
|
|
e316a923d4 | ||
|
|
fd0370c07a | ||
|
|
909b8a8f9c | ||
|
|
316f2fee21 | ||
|
|
4a0fe3b143 | ||
|
|
a1292fac81 | ||
|
|
7f98be4f91 | ||
|
|
fd73b8875d | ||
|
|
f9ab1daa3c | ||
|
|
d27b847442 | ||
|
|
3002c7a17f | ||
|
|
dac6bc2228 | ||
|
|
207e09500a | ||
|
|
52c745bc62 | ||
|
|
498c6cfae9 | ||
|
|
71f8b9e473 | ||
|
|
3a31fa4768 | ||
|
|
65e69738cc | ||
|
|
549c134bb8 | ||
|
|
d206721fc1 | ||
|
|
64795a03e3 | ||
|
|
c8e2f614fa | ||
|
|
86d63f919d | ||
|
|
c43aa22cdb | ||
|
|
d1a6303e49 | ||
|
|
c0347cde85 | ||
|
|
2f2e76f9c6 | ||
|
|
dd7f21244b | ||
|
|
49be9d08f3 | ||
|
|
bba5b3c037 | ||
|
|
26298c4a5f | ||
|
|
eb7d830296 | ||
|
|
02db4c7671 | ||
|
|
a05b8b56e3 | ||
|
|
eca3898410 | ||
|
|
6901b64fce | ||
|
|
32c47b1509 | ||
|
|
39e430018b | ||
|
|
6549a40cf4 | ||
|
|
4e75d8fda9 | ||
|
|
8917a3ea8f | ||
|
|
0c011b889b | ||
|
|
0962ba43c0 | ||
|
|
b8c48fb477 | ||
|
|
2a7d04fec4 | ||
|
|
bd854e1750 | ||
|
|
65fd0d15ae | ||
|
|
c11f14f3a0 | ||
|
|
98b65e67f2 | ||
|
|
c579439c1e | ||
|
|
46e5ac9672 |
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# 确保所有 SQL 迁移文件使用 LF 换行符
|
||||
backend/migrations/*.sql text eol=lf
|
||||
|
||||
# Go 源代码文件
|
||||
*.go text eol=lf
|
||||
|
||||
# Shell 脚本
|
||||
*.sh text eol=lf
|
||||
|
||||
# YAML/YML 配置文件
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
|
||||
# Dockerfile
|
||||
Dockerfile text eol=lf
|
||||
4
.github/workflows/backend-ci.yml
vendored
4
.github/workflows/backend-ci.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
cache: true
|
||||
- name: Verify Go version
|
||||
run: |
|
||||
go version | grep -q 'go1.25.5'
|
||||
go version | grep -q 'go1.25.7'
|
||||
- name: Unit tests
|
||||
working-directory: backend
|
||||
run: make test-unit
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
cache: true
|
||||
- name: Verify Go version
|
||||
run: |
|
||||
go version | grep -q 'go1.25.5'
|
||||
go version | grep -q 'go1.25.7'
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
with:
|
||||
|
||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -115,7 +115,7 @@ jobs:
|
||||
|
||||
- name: Verify Go version
|
||||
run: |
|
||||
go version | grep -q 'go1.25.5'
|
||||
go version | grep -q 'go1.25.7'
|
||||
|
||||
# Docker setup for GoReleaser
|
||||
- name: Set up QEMU
|
||||
@@ -222,8 +222,9 @@ jobs:
|
||||
REPO="${{ github.repository }}"
|
||||
GHCR_IMAGE="ghcr.io/${REPO,,}" # ${,,} converts to lowercase
|
||||
|
||||
# 获取 tag message 内容
|
||||
# 获取 tag message 内容并转义 Markdown 特殊字符
|
||||
TAG_MESSAGE='${{ steps.tag_message.outputs.message }}'
|
||||
TAG_MESSAGE=$(echo "$TAG_MESSAGE" | sed 's/\([_*`\[]\)/\\\1/g')
|
||||
|
||||
# 限制消息长度(Telegram 消息限制 4096 字符,预留空间给头尾固定内容)
|
||||
if [ ${#TAG_MESSAGE} -gt 3500 ]; then
|
||||
|
||||
2
.github/workflows/security-scan.yml
vendored
2
.github/workflows/security-scan.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
cache-dependency-path: backend/go.sum
|
||||
- name: Verify Go version
|
||||
run: |
|
||||
go version | grep -q 'go1.25.5'
|
||||
go version | grep -q 'go1.25.7'
|
||||
- name: Run govulncheck
|
||||
working-directory: backend
|
||||
run: |
|
||||
|
||||
323
DEV_GUIDE.md
Normal file
323
DEV_GUIDE.md
Normal file
@@ -0,0 +1,323 @@
|
||||
# sub2api 项目开发指南
|
||||
|
||||
> 本文档记录项目环境配置、常见坑点和注意事项,供 Claude Code 和团队成员参考。
|
||||
|
||||
## 一、项目基本信息
|
||||
|
||||
| 项目 | 说明 |
|
||||
|------|------|
|
||||
| **上游仓库** | Wei-Shaw/sub2api |
|
||||
| **Fork 仓库** | bayma888/sub2api-bmai |
|
||||
| **技术栈** | Go 后端 (Ent ORM + Gin) + Vue3 前端 (pnpm) |
|
||||
| **数据库** | PostgreSQL 16 + Redis |
|
||||
| **包管理** | 后端: go modules, 前端: **pnpm**(不是 npm) |
|
||||
|
||||
## 二、本地环境配置
|
||||
|
||||
### PostgreSQL 16 (Windows 服务)
|
||||
|
||||
| 配置项 | 值 |
|
||||
|--------|-----|
|
||||
| 端口 | 5432 |
|
||||
| psql 路径 | `C:\Program Files\PostgreSQL\16\bin\psql.exe` |
|
||||
| pg_hba.conf | `C:\Program Files\PostgreSQL\16\data\pg_hba.conf` |
|
||||
| 数据库凭据 | user=`sub2api`, password=`sub2api`, dbname=`sub2api` |
|
||||
| 超级用户 | user=`postgres`, password=`postgres` |
|
||||
|
||||
### Redis
|
||||
|
||||
| 配置项 | 值 |
|
||||
|--------|-----|
|
||||
| 端口 | 6379 |
|
||||
| 密码 | 无 |
|
||||
|
||||
### 开发工具
|
||||
|
||||
```bash
|
||||
# golangci-lint v2.7
|
||||
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.7
|
||||
|
||||
# pnpm (前端包管理)
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
## 三、CI/CD 流水线
|
||||
|
||||
### GitHub Actions Workflows
|
||||
|
||||
| Workflow | 触发条件 | 检查内容 |
|
||||
|----------|----------|----------|
|
||||
| **backend-ci.yml** | push, pull_request | 单元测试 + 集成测试 + golangci-lint v2.7 |
|
||||
| **security-scan.yml** | push, pull_request, 每周一 | govulncheck + gosec + pnpm audit |
|
||||
| **release.yml** | tag `v*` | 构建发布(PR 不触发) |
|
||||
|
||||
### CI 要求
|
||||
|
||||
- Go 版本必须是 **1.25.7**
|
||||
- 前端使用 `pnpm install --frozen-lockfile`,必须提交 `pnpm-lock.yaml`
|
||||
|
||||
### 本地测试命令
|
||||
|
||||
```bash
|
||||
# 后端单元测试
|
||||
cd backend && go test -tags=unit ./...
|
||||
|
||||
# 后端集成测试
|
||||
cd backend && go test -tags=integration ./...
|
||||
|
||||
# 代码质量检查
|
||||
cd backend && golangci-lint run ./...
|
||||
|
||||
# 前端依赖安装(必须用 pnpm)
|
||||
cd frontend && pnpm install
|
||||
```
|
||||
|
||||
## 四、常见坑点 & 解决方案
|
||||
|
||||
### 坑 1:pnpm-lock.yaml 必须同步提交
|
||||
|
||||
**问题**:`package.json` 新增依赖后,CI 的 `pnpm install --frozen-lockfile` 失败。
|
||||
|
||||
**原因**:上游 CI 使用 pnpm,lock 文件不同步会报错。
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
cd frontend
|
||||
pnpm install # 更新 pnpm-lock.yaml
|
||||
git add pnpm-lock.yaml
|
||||
git commit -m "chore: update pnpm-lock.yaml"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 2:npm 和 pnpm 的 node_modules 冲突
|
||||
|
||||
**问题**:之前用 npm 装过 `node_modules`,pnpm install 报 `EPERM` 错误。
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
cd frontend
|
||||
rm -rf node_modules # 或 PowerShell: Remove-Item -Recurse -Force node_modules
|
||||
pnpm install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 3:PowerShell 中 bcrypt hash 的 `$` 被转义
|
||||
|
||||
**问题**:bcrypt hash 格式如 `$2a$10$xxx...`,PowerShell 把 `$2a` 当变量解析,导致数据丢失。
|
||||
|
||||
**解决**:将 SQL 写入文件,用 `psql -f` 执行:
|
||||
```bash
|
||||
# 错误示范(PowerShell 会吃掉 $)
|
||||
psql -c "INSERT INTO users ... VALUES ('$2a$10$...')"
|
||||
|
||||
# 正确做法
|
||||
echo "INSERT INTO users ... VALUES ('\$2a\$10\$...')" > temp.sql
|
||||
psql -U sub2api -h 127.0.0.1 -d sub2api -f temp.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 4:psql 不支持中文路径
|
||||
|
||||
**问题**:`psql -f "D:\中文路径\file.sql"` 报错找不到文件。
|
||||
|
||||
**解决**:复制到纯英文路径再执行:
|
||||
```bash
|
||||
cp "D:\中文路径\file.sql" "C:\temp.sql"
|
||||
psql -f "C:\temp.sql"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 5:PostgreSQL 密码重置流程
|
||||
|
||||
**场景**:忘记 PostgreSQL 密码。
|
||||
|
||||
**步骤**:
|
||||
1. 修改 `C:\Program Files\PostgreSQL\16\data\pg_hba.conf`
|
||||
```
|
||||
# 将 scram-sha-256 改为 trust
|
||||
host all all 127.0.0.1/32 trust
|
||||
```
|
||||
2. 重启 PostgreSQL 服务
|
||||
```powershell
|
||||
Restart-Service postgresql-x64-16
|
||||
```
|
||||
3. 无密码登录并重置
|
||||
```bash
|
||||
psql -U postgres -h 127.0.0.1
|
||||
ALTER USER sub2api WITH PASSWORD 'sub2api';
|
||||
ALTER USER postgres WITH PASSWORD 'postgres';
|
||||
```
|
||||
4. 改回 `scram-sha-256` 并重启
|
||||
|
||||
---
|
||||
|
||||
### 坑 6:Go interface 新增方法后 test stub 必须补全
|
||||
|
||||
**问题**:给 interface 新增方法后,编译报错 `does not implement interface (missing method XXX)`。
|
||||
|
||||
**原因**:所有测试文件中实现该 interface 的 stub/mock 都必须补上新方法。
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 搜索所有实现该 interface 的 struct
|
||||
cd backend
|
||||
grep -r "type.*Stub.*struct" internal/
|
||||
grep -r "type.*Mock.*struct" internal/
|
||||
|
||||
# 逐一补全新方法
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 7:Windows 上 psql 连 localhost 的 IPv6 问题
|
||||
|
||||
**问题**:psql 连 `localhost` 先尝试 IPv6 (::1),可能报错后再回退 IPv4。
|
||||
|
||||
**建议**:直接用 `127.0.0.1` 代替 `localhost`。
|
||||
|
||||
---
|
||||
|
||||
### 坑 8:Windows 没有 make 命令
|
||||
|
||||
**问题**:CI 里用 `make test-unit`,本地 Windows 没有 make。
|
||||
|
||||
**解决**:直接用 Makefile 里的原始命令:
|
||||
```bash
|
||||
# 代替 make test-unit
|
||||
go test -tags=unit ./...
|
||||
|
||||
# 代替 make test-integration
|
||||
go test -tags=integration ./...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 9:Ent Schema 修改后必须重新生成
|
||||
|
||||
**问题**:修改 `ent/schema/*.go` 后,代码不生效。
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
cd backend
|
||||
go generate ./ent # 重新生成 ent 代码
|
||||
git add ent/ # 生成的文件也要提交
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 坑 10:PR 提交前检查清单
|
||||
|
||||
提交 PR 前务必本地验证:
|
||||
|
||||
- [ ] `go test -tags=unit ./...` 通过
|
||||
- [ ] `go test -tags=integration ./...` 通过
|
||||
- [ ] `golangci-lint run ./...` 无新增问题
|
||||
- [ ] `pnpm-lock.yaml` 已同步(如果改了 package.json)
|
||||
- [ ] 所有 test stub 补全新接口方法(如果改了 interface)
|
||||
- [ ] Ent 生成的代码已提交(如果改了 schema)
|
||||
|
||||
## 五、常用命令速查
|
||||
|
||||
### 数据库操作
|
||||
|
||||
```bash
|
||||
# 连接数据库
|
||||
psql -U sub2api -h 127.0.0.1 -d sub2api
|
||||
|
||||
# 查看所有用户
|
||||
psql -U postgres -h 127.0.0.1 -c "\du"
|
||||
|
||||
# 查看所有数据库
|
||||
psql -U postgres -h 127.0.0.1 -c "\l"
|
||||
|
||||
# 执行 SQL 文件
|
||||
psql -U sub2api -h 127.0.0.1 -d sub2api -f migration.sql
|
||||
```
|
||||
|
||||
### Git 操作
|
||||
|
||||
```bash
|
||||
# 同步上游
|
||||
git fetch upstream
|
||||
git checkout main
|
||||
git merge upstream/main
|
||||
git push origin main
|
||||
|
||||
# 创建功能分支
|
||||
git checkout -b feature/xxx
|
||||
|
||||
# Rebase 到最新 main
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
```
|
||||
|
||||
### 前端操作
|
||||
|
||||
```bash
|
||||
# 安装依赖(必须用 pnpm)
|
||||
cd frontend
|
||||
pnpm install
|
||||
|
||||
# 开发服务器
|
||||
pnpm dev
|
||||
|
||||
# 构建
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### 后端操作
|
||||
|
||||
```bash
|
||||
# 运行服务器
|
||||
cd backend
|
||||
go run ./cmd/server/
|
||||
|
||||
# 生成 Ent 代码
|
||||
go generate ./ent
|
||||
|
||||
# 运行测试
|
||||
go test -tags=unit ./...
|
||||
go test -tags=integration ./...
|
||||
|
||||
# Lint 检查
|
||||
golangci-lint run ./...
|
||||
```
|
||||
|
||||
## 六、项目结构速览
|
||||
|
||||
```
|
||||
sub2api-bmai/
|
||||
├── backend/
|
||||
│ ├── cmd/server/ # 主程序入口
|
||||
│ ├── ent/ # Ent ORM 生成代码
|
||||
│ │ └── schema/ # 数据库 Schema 定义
|
||||
│ ├── internal/
|
||||
│ │ ├── handler/ # HTTP 处理器
|
||||
│ │ ├── service/ # 业务逻辑
|
||||
│ │ ├── repository/ # 数据访问层
|
||||
│ │ └── server/ # 服务器配置
|
||||
│ ├── migrations/ # 数据库迁移脚本
|
||||
│ └── config.yaml # 配置文件
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # API 调用
|
||||
│ │ ├── components/ # Vue 组件
|
||||
│ │ ├── views/ # 页面视图
|
||||
│ │ ├── types/ # TypeScript 类型
|
||||
│ │ └── i18n/ # 国际化
|
||||
│ ├── package.json # 依赖配置
|
||||
│ └── pnpm-lock.yaml # pnpm 锁文件(必须提交)
|
||||
└── .claude/
|
||||
└── CLAUDE.md # 本文档
|
||||
```
|
||||
|
||||
## 七、参考资源
|
||||
|
||||
- [上游仓库](https://github.com/Wei-Shaw/sub2api)
|
||||
- [Ent 文档](https://entgo.io/docs/getting-started)
|
||||
- [Vue3 文档](https://vuejs.org/)
|
||||
- [pnpm 文档](https://pnpm.io/)
|
||||
@@ -7,7 +7,7 @@
|
||||
# =============================================================================
|
||||
|
||||
ARG NODE_IMAGE=node:24-alpine
|
||||
ARG GOLANG_IMAGE=golang:1.25.5-alpine
|
||||
ARG GOLANG_IMAGE=golang:1.25.7-alpine
|
||||
ARG ALPINE_IMAGE=alpine:3.20
|
||||
ARG GOPROXY=https://goproxy.cn,direct
|
||||
ARG GOSUMDB=sum.golang.google.cn
|
||||
|
||||
@@ -1,368 +0,0 @@
|
||||
# Linux DO Connect
|
||||
|
||||
OAuth(Open Authorization)是一个开放的网络授权标准,目前最新版本为 OAuth 2.0。我们日常使用的第三方登录(如 Google 账号登录)就采用了该标准。OAuth 允许用户授权第三方应用访问存储在其他服务提供商(如 Google)上的信息,无需在不同平台上重复填写注册信息。用户授权后,平台可以直接访问用户的账户信息进行身份验证,而用户无需向第三方应用提供密码。
|
||||
|
||||
目前系统已实现完整的 OAuth2 授权码(code)方式鉴权,但界面等配套功能还在持续完善中。让我们一起打造一个更完善的共享方案。
|
||||
|
||||
## 基本介绍
|
||||
|
||||
这是一套标准的 OAuth2 鉴权系统,可以让开发者共享论坛的用户基本信息。
|
||||
|
||||
- 可获取字段:
|
||||
|
||||
| 参数 | 说明 |
|
||||
| ----------------- | ------------------------------- |
|
||||
| `id` | 用户唯一标识(不可变) |
|
||||
| `username` | 论坛用户名 |
|
||||
| `name` | 论坛用户昵称(可变) |
|
||||
| `avatar_template` | 用户头像模板URL(支持多种尺寸) |
|
||||
| `active` | 账号活跃状态 |
|
||||
| `trust_level` | 信任等级(0-4) |
|
||||
| `silenced` | 禁言状态 |
|
||||
| `external_ids` | 外部ID关联信息 |
|
||||
| `api_key` | API访问密钥 |
|
||||
|
||||
通过这些信息,公益网站/接口可以实现:
|
||||
|
||||
1. 基于 `id` 的服务频率限制
|
||||
2. 基于 `trust_level` 的服务额度分配
|
||||
3. 基于用户信息的滥用举报机制
|
||||
|
||||
## 相关端点
|
||||
|
||||
- Authorize 端点: `https://connect.linux.do/oauth2/authorize`
|
||||
- Token 端点:`https://connect.linux.do/oauth2/token`
|
||||
- 用户信息 端点:`https://connect.linux.do/api/user`
|
||||
|
||||
## 申请使用
|
||||
|
||||
- 访问 [Connect.Linux.Do](https://connect.linux.do/) 申请接入你的应用。
|
||||
|
||||

|
||||
|
||||
- 点击 **`我的应用接入`** - **`申请新接入`**,填写相关信息。其中 **`回调地址`** 是你的应用接收用户信息的地址。
|
||||
|
||||

|
||||
|
||||
- 申请成功后,你将获得 **`Client Id`** 和 **`Client Secret`**,这是你应用的唯一身份凭证。
|
||||
|
||||

|
||||
|
||||
## 接入 Linux Do
|
||||
|
||||
JavaScript
|
||||
```JavaScript
|
||||
// 安装第三方请求库(或使用原生的 Fetch API),本例中使用 axios
|
||||
// npm install axios
|
||||
|
||||
// 通过 OAuth2 获取 Linux Do 用户信息的参考流程
|
||||
const axios = require('axios');
|
||||
const readline = require('readline');
|
||||
|
||||
// 配置信息(建议通过环境变量配置,避免使用硬编码)
|
||||
const CLIENT_ID = '你的 Client ID';
|
||||
const CLIENT_SECRET = '你的 Client Secret';
|
||||
const REDIRECT_URI = '你的回调地址';
|
||||
const AUTH_URL = 'https://connect.linux.do/oauth2/authorize';
|
||||
const TOKEN_URL = 'https://connect.linux.do/oauth2/token';
|
||||
const USER_INFO_URL = 'https://connect.linux.do/api/user';
|
||||
|
||||
// 第一步:生成授权 URL
|
||||
function getAuthUrl() {
|
||||
const params = new URLSearchParams({
|
||||
client_id: CLIENT_ID,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
response_type: 'code',
|
||||
scope: 'user'
|
||||
});
|
||||
|
||||
return `${AUTH_URL}?${params.toString()}`;
|
||||
}
|
||||
|
||||
// 第二步:获取 code 参数
|
||||
function getCode() {
|
||||
return new Promise((resolve) => {
|
||||
// 本例中使用终端输入来模拟流程,仅供本地测试
|
||||
// 请在实际应用中替换为真实的处理逻辑
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
rl.question('从回调 URL 中提取出 code,粘贴到此处并按回车:', (answer) => {
|
||||
rl.close();
|
||||
resolve(answer.trim());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 第三步:使用 code 参数获取访问令牌
|
||||
async function getAccessToken(code) {
|
||||
try {
|
||||
const form = new URLSearchParams({
|
||||
client_id: CLIENT_ID,
|
||||
client_secret: CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
grant_type: 'authorization_code'
|
||||
}).toString();
|
||||
|
||||
const response = await axios.post(TOKEN_URL, form, {
|
||||
// 提醒:需正确配置请求头,否则无法正常获取访问令牌
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error(`获取访问令牌失败:${error.response ? JSON.stringify(error.response.data) : error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 第四步:使用访问令牌获取用户信息
|
||||
async function getUserInfo(accessToken) {
|
||||
try {
|
||||
const response = await axios.get(USER_INFO_URL, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error(`获取用户信息失败:${error.response ? JSON.stringify(error.response.data) : error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 主流程
|
||||
async function main() {
|
||||
// 1. 生成授权 URL,前端引导用户访问授权页
|
||||
const authUrl = getAuthUrl();
|
||||
console.log(`请访问此 URL 授权:${authUrl}
|
||||
`);
|
||||
|
||||
// 2. 用户授权后,从回调 URL 获取 code 参数
|
||||
const code = await getCode();
|
||||
|
||||
try {
|
||||
// 3. 使用 code 参数获取访问令牌
|
||||
const tokenData = await getAccessToken(code);
|
||||
const accessToken = tokenData.access_token;
|
||||
|
||||
// 4. 使用访问令牌获取用户信息
|
||||
if (accessToken) {
|
||||
const userInfo = await getUserInfo(accessToken);
|
||||
console.log(`
|
||||
获取用户信息成功:${JSON.stringify(userInfo, null, 2)}`);
|
||||
} else {
|
||||
console.log(`
|
||||
获取访问令牌失败:${JSON.stringify(tokenData)}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发生错误:', error);
|
||||
}
|
||||
}
|
||||
```
|
||||
Python
|
||||
```python
|
||||
# 安装第三方请求库,本例中使用 requests
|
||||
# pip install requests
|
||||
|
||||
# 通过 OAuth2 获取 Linux Do 用户信息的参考流程
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 配置信息(建议通过环境变量配置,避免使用硬编码)
|
||||
CLIENT_ID = '你的 Client ID'
|
||||
CLIENT_SECRET = '你的 Client Secret'
|
||||
REDIRECT_URI = '你的回调地址'
|
||||
AUTH_URL = 'https://connect.linux.do/oauth2/authorize'
|
||||
TOKEN_URL = 'https://connect.linux.do/oauth2/token'
|
||||
USER_INFO_URL = 'https://connect.linux.do/api/user'
|
||||
|
||||
# 第一步:生成授权 URL
|
||||
def get_auth_url():
|
||||
params = {
|
||||
'client_id': CLIENT_ID,
|
||||
'redirect_uri': REDIRECT_URI,
|
||||
'response_type': 'code',
|
||||
'scope': 'user'
|
||||
}
|
||||
auth_url = f"{AUTH_URL}?{'&'.join(f'{k}={v}' for k, v in params.items())}"
|
||||
return auth_url
|
||||
|
||||
# 第二步:获取 code 参数
|
||||
def get_code():
|
||||
# 本例中使用终端输入来模拟流程,仅供本地测试
|
||||
# 请在实际应用中替换为真实的处理逻辑
|
||||
return input('从回调 URL 中提取出 code,粘贴到此处并按回车:').strip()
|
||||
|
||||
# 第三步:使用 code 参数获取访问令牌
|
||||
def get_access_token(code):
|
||||
try:
|
||||
data = {
|
||||
'client_id': CLIENT_ID,
|
||||
'client_secret': CLIENT_SECRET,
|
||||
'code': code,
|
||||
'redirect_uri': REDIRECT_URI,
|
||||
'grant_type': 'authorization_code'
|
||||
}
|
||||
# 提醒:需正确配置请求头,否则无法正常获取访问令牌
|
||||
headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
response = requests.post(TOKEN_URL, data=data, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"获取访问令牌失败:{e}")
|
||||
return None
|
||||
|
||||
# 第四步:使用访问令牌获取用户信息
|
||||
def get_user_info(access_token):
|
||||
try:
|
||||
headers = {
|
||||
'Authorization': f'Bearer {access_token}'
|
||||
}
|
||||
response = requests.get(USER_INFO_URL, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"获取用户信息失败:{e}")
|
||||
return None
|
||||
|
||||
# 主流程
|
||||
if __name__ == '__main__':
|
||||
# 1. 生成授权 URL,前端引导用户访问授权页
|
||||
auth_url = get_auth_url()
|
||||
print(f'请访问此 URL 授权:{auth_url}
|
||||
')
|
||||
|
||||
# 2. 用户授权后,从回调 URL 获取 code 参数
|
||||
code = get_code()
|
||||
|
||||
# 3. 使用 code 参数获取访问令牌
|
||||
token_data = get_access_token(code)
|
||||
if token_data:
|
||||
access_token = token_data.get('access_token')
|
||||
|
||||
# 4. 使用访问令牌获取用户信息
|
||||
if access_token:
|
||||
user_info = get_user_info(access_token)
|
||||
if user_info:
|
||||
print(f"
|
||||
获取用户信息成功:{json.dumps(user_info, indent=2)}")
|
||||
else:
|
||||
print("
|
||||
获取用户信息失败")
|
||||
else:
|
||||
print(f"
|
||||
获取访问令牌失败:{json.dumps(token_data, indent=2)}")
|
||||
else:
|
||||
print("
|
||||
获取访问令牌失败")
|
||||
```
|
||||
PHP
|
||||
```php
|
||||
// 通过 OAuth2 获取 Linux Do 用户信息的参考流程
|
||||
|
||||
// 配置信息
|
||||
$CLIENT_ID = '你的 Client ID';
|
||||
$CLIENT_SECRET = '你的 Client Secret';
|
||||
$REDIRECT_URI = '你的回调地址';
|
||||
$AUTH_URL = 'https://connect.linux.do/oauth2/authorize';
|
||||
$TOKEN_URL = 'https://connect.linux.do/oauth2/token';
|
||||
$USER_INFO_URL = 'https://connect.linux.do/api/user';
|
||||
|
||||
// 生成授权 URL
|
||||
function getAuthUrl($clientId, $redirectUri) {
|
||||
global $AUTH_URL;
|
||||
return $AUTH_URL . '?' . http_build_query([
|
||||
'client_id' => $clientId,
|
||||
'redirect_uri' => $redirectUri,
|
||||
'response_type' => 'code',
|
||||
'scope' => 'user'
|
||||
]);
|
||||
}
|
||||
|
||||
// 使用 code 参数获取用户信息(合并获取令牌和获取用户信息的步骤)
|
||||
function getUserInfoWithCode($code, $clientId, $clientSecret, $redirectUri) {
|
||||
global $TOKEN_URL, $USER_INFO_URL;
|
||||
|
||||
// 1. 获取访问令牌
|
||||
$ch = curl_init($TOKEN_URL);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||
'client_id' => $clientId,
|
||||
'client_secret' => $clientSecret,
|
||||
'code' => $code,
|
||||
'redirect_uri' => $redirectUri,
|
||||
'grant_type' => 'authorization_code'
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Accept: application/json'
|
||||
]);
|
||||
|
||||
$tokenResponse = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$tokenData = json_decode($tokenResponse, true);
|
||||
if (!isset($tokenData['access_token'])) {
|
||||
return ['error' => '获取访问令牌失败', 'details' => $tokenData];
|
||||
}
|
||||
|
||||
// 2. 获取用户信息
|
||||
$ch = curl_init($USER_INFO_URL);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Authorization: Bearer ' . $tokenData['access_token']
|
||||
]);
|
||||
|
||||
$userResponse = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return json_decode($userResponse, true);
|
||||
}
|
||||
|
||||
// 主流程
|
||||
// 1. 生成授权 URL
|
||||
$authUrl = getAuthUrl($CLIENT_ID, $REDIRECT_URI);
|
||||
echo "<a href='$authUrl'>使用 Linux Do 登录</a>";
|
||||
|
||||
// 2. 处理回调并获取用户信息
|
||||
if (isset($_GET['code'])) {
|
||||
$userInfo = getUserInfoWithCode(
|
||||
$_GET['code'],
|
||||
$CLIENT_ID,
|
||||
$CLIENT_SECRET,
|
||||
$REDIRECT_URI
|
||||
);
|
||||
|
||||
if (isset($userInfo['error'])) {
|
||||
echo '错误: ' . $userInfo['error'];
|
||||
} else {
|
||||
echo '欢迎, ' . $userInfo['name'] . '!';
|
||||
// 处理用户登录逻辑...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 授权流程
|
||||
|
||||
1. 用户点击应用中的’使用 Linux Do 登录’按钮
|
||||
2. 系统将用户重定向至 Linux Do 的授权页面
|
||||
3. 用户完成授权后,系统自动重定向回应用并携带授权码
|
||||
4. 应用使用授权码获取访问令牌
|
||||
5. 使用访问令牌获取用户信息
|
||||
|
||||
### 安全建议
|
||||
|
||||
- 切勿在前端代码中暴露 Client Secret
|
||||
- 对所有用户输入数据进行严格验证
|
||||
- 确保使用 HTTPS 协议传输数据
|
||||
- 定期更新并妥善保管 Client Secret
|
||||
@@ -1,164 +0,0 @@
|
||||
## 概述
|
||||
|
||||
全面增强运维监控系统(Ops)的错误日志管理和告警静默功能,优化前端 UI 组件代码质量和用户体验。本次更新重构了核心服务层和数据访问层,提升系统可维护性和运维效率。
|
||||
|
||||
## 主要改动
|
||||
|
||||
### 1. 错误日志查询优化
|
||||
|
||||
**功能特性:**
|
||||
- 新增 GetErrorLogByID 接口,支持按 ID 精确查询错误详情
|
||||
- 优化错误日志过滤逻辑,支持多维度筛选(平台、阶段、来源、所有者等)
|
||||
- 改进查询参数处理,简化代码结构
|
||||
- 增强错误分类和标准化处理
|
||||
- 支持错误解决状态追踪(resolved 字段)
|
||||
|
||||
**技术实现:**
|
||||
- `ops_handler.go` - 新增单条错误日志查询接口
|
||||
- `ops_repo.go` - 优化数据查询和过滤条件构建
|
||||
- `ops_models.go` - 扩展错误日志数据模型
|
||||
- 前端 API 接口同步更新
|
||||
|
||||
### 2. 告警静默功能
|
||||
|
||||
**功能特性:**
|
||||
- 支持按规则、平台、分组、区域等维度静默告警
|
||||
- 可设置静默时长和原因说明
|
||||
- 静默记录可追溯,记录创建人和创建时间
|
||||
- 自动过期机制,避免永久静默
|
||||
|
||||
**技术实现:**
|
||||
- `037_ops_alert_silences.sql` - 新增告警静默表
|
||||
- `ops_alerts.go` - 告警静默逻辑实现
|
||||
- `ops_alerts_handler.go` - 告警静默 API 接口
|
||||
- `OpsAlertEventsCard.vue` - 前端告警静默操作界面
|
||||
|
||||
**数据库结构:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| rule_id | BIGINT | 告警规则 ID |
|
||||
| platform | VARCHAR(64) | 平台标识 |
|
||||
| group_id | BIGINT | 分组 ID(可选) |
|
||||
| region | VARCHAR(64) | 区域(可选) |
|
||||
| until | TIMESTAMPTZ | 静默截止时间 |
|
||||
| reason | TEXT | 静默原因 |
|
||||
| created_by | BIGINT | 创建人 ID |
|
||||
|
||||
### 3. 错误分类标准化
|
||||
|
||||
**功能特性:**
|
||||
- 统一错误阶段分类(request|auth|routing|upstream|network|internal)
|
||||
- 规范错误归属分类(client|provider|platform)
|
||||
- 标准化错误来源分类(client_request|upstream_http|gateway)
|
||||
- 自动迁移历史数据到新分类体系
|
||||
|
||||
**技术实现:**
|
||||
- `038_ops_errors_resolution_retry_results_and_standardize_classification.sql` - 分类标准化迁移
|
||||
- 自动映射历史遗留分类到新标准
|
||||
- 自动解决已恢复的上游错误(客户端状态码 < 400)
|
||||
|
||||
### 4. Gateway 服务集成
|
||||
|
||||
**功能特性:**
|
||||
- 完善各 Gateway 服务的 Ops 集成
|
||||
- 统一错误日志记录接口
|
||||
- 增强上游错误追踪能力
|
||||
|
||||
**涉及服务:**
|
||||
- `antigravity_gateway_service.go` - Antigravity 网关集成
|
||||
- `gateway_service.go` - 通用网关集成
|
||||
- `gemini_messages_compat_service.go` - Gemini 兼容层集成
|
||||
- `openai_gateway_service.go` - OpenAI 网关集成
|
||||
|
||||
### 5. 前端 UI 优化
|
||||
|
||||
**代码重构:**
|
||||
- 大幅简化错误详情模态框代码(从 828 行优化到 450 行)
|
||||
- 优化错误日志表格组件,提升可读性
|
||||
- 清理未使用的 i18n 翻译,减少冗余
|
||||
- 统一组件代码风格和格式
|
||||
- 优化骨架屏组件,更好匹配实际看板布局
|
||||
|
||||
**布局改进:**
|
||||
- 修复模态框内容溢出和滚动问题
|
||||
- 优化表格布局,使用 flex 布局确保正确显示
|
||||
- 改进看板头部布局和交互
|
||||
- 提升响应式体验
|
||||
- 骨架屏支持全屏模式适配
|
||||
|
||||
**交互优化:**
|
||||
- 优化告警事件卡片功能和展示
|
||||
- 改进错误详情展示逻辑
|
||||
- 增强请求详情模态框
|
||||
- 完善运行时设置卡片
|
||||
- 改进加载动画效果
|
||||
|
||||
### 6. 国际化完善
|
||||
|
||||
**文案补充:**
|
||||
- 补充错误日志相关的英文翻译
|
||||
- 添加告警静默功能的中英文文案
|
||||
- 完善提示文本和错误信息
|
||||
- 统一术语翻译标准
|
||||
|
||||
## 文件变更
|
||||
|
||||
**后端(26 个文件):**
|
||||
- `backend/internal/handler/admin/ops_alerts_handler.go` - 告警接口增强
|
||||
- `backend/internal/handler/admin/ops_handler.go` - 错误日志接口优化
|
||||
- `backend/internal/handler/ops_error_logger.go` - 错误记录器增强
|
||||
- `backend/internal/repository/ops_repo.go` - 数据访问层重构
|
||||
- `backend/internal/repository/ops_repo_alerts.go` - 告警数据访问增强
|
||||
- `backend/internal/service/ops_*.go` - 核心服务层重构(10 个文件)
|
||||
- `backend/internal/service/*_gateway_service.go` - Gateway 集成(4 个文件)
|
||||
- `backend/internal/server/routes/admin.go` - 路由配置更新
|
||||
- `backend/migrations/*.sql` - 数据库迁移(2 个文件)
|
||||
- 测试文件更新(5 个文件)
|
||||
|
||||
**前端(13 个文件):**
|
||||
- `frontend/src/views/admin/ops/OpsDashboard.vue` - 看板主页优化
|
||||
- `frontend/src/views/admin/ops/components/*.vue` - 组件重构(10 个文件)
|
||||
- `frontend/src/api/admin/ops.ts` - API 接口扩展
|
||||
- `frontend/src/i18n/locales/*.ts` - 国际化文本(2 个文件)
|
||||
|
||||
## 代码统计
|
||||
|
||||
- 44 个文件修改
|
||||
- 3733 行新增
|
||||
- 995 行删除
|
||||
- 净增加 2738 行
|
||||
|
||||
## 核心改进
|
||||
|
||||
**可维护性提升:**
|
||||
- 重构核心服务层,职责更清晰
|
||||
- 简化前端组件代码,降低复杂度
|
||||
- 统一代码风格和命名规范
|
||||
- 清理冗余代码和未使用的翻译
|
||||
- 标准化错误分类体系
|
||||
|
||||
**功能完善:**
|
||||
- 告警静默功能,减少告警噪音
|
||||
- 错误日志查询优化,提升运维效率
|
||||
- Gateway 服务集成完善,统一监控能力
|
||||
- 错误解决状态追踪,便于问题管理
|
||||
|
||||
**用户体验优化:**
|
||||
- 修复多个 UI 布局问题
|
||||
- 优化交互流程
|
||||
- 完善国际化支持
|
||||
- 提升响应式体验
|
||||
- 改进加载状态展示
|
||||
|
||||
## 测试验证
|
||||
|
||||
- ✅ 错误日志查询和过滤功能
|
||||
- ✅ 告警静默创建和自动过期
|
||||
- ✅ 错误分类标准化迁移
|
||||
- ✅ Gateway 服务错误日志记录
|
||||
- ✅ 前端组件布局和交互
|
||||
- ✅ 骨架屏全屏模式适配
|
||||
- ✅ 国际化文本完整性
|
||||
- ✅ API 接口功能正确性
|
||||
- ✅ 数据库迁移执行成功
|
||||
134
README.md
134
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://golang.org/)
|
||||
[](https://golang.org/)
|
||||
[](https://vuejs.org/)
|
||||
[](https://www.postgresql.org/)
|
||||
[](https://redis.io/)
|
||||
@@ -18,7 +18,7 @@ English | [中文](README_CN.md)
|
||||
|
||||
## Demo
|
||||
|
||||
Try Sub2API online: **https://v2.pincc.ai/**
|
||||
Try Sub2API online: **https://demo.sub2api.org/**
|
||||
|
||||
Demo credentials (shared demo environment; **not** created automatically for self-hosted installs):
|
||||
|
||||
@@ -44,7 +44,7 @@ Sub2API is an AI API gateway platform designed to distribute and manage API quot
|
||||
|
||||
| Component | Technology |
|
||||
|-----------|------------|
|
||||
| Backend | Go 1.25.5, Gin, Ent |
|
||||
| Backend | Go 1.25.7, Gin, Ent |
|
||||
| Frontend | Vue 3.4+, Vite 5+, TailwindCSS |
|
||||
| Database | PostgreSQL 15+ |
|
||||
| Cache/Queue | Redis 7+ |
|
||||
@@ -128,7 +128,7 @@ curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install
|
||||
|
||||
---
|
||||
|
||||
### Method 2: Docker Compose
|
||||
### Method 2: Docker Compose (Recommended)
|
||||
|
||||
Deploy with Docker Compose, including PostgreSQL and Redis containers.
|
||||
|
||||
@@ -137,87 +137,157 @@ Deploy with Docker Compose, including PostgreSQL and Redis containers.
|
||||
- Docker 20.10+
|
||||
- Docker Compose v2+
|
||||
|
||||
#### Installation Steps
|
||||
#### Quick Start (One-Click Deployment)
|
||||
|
||||
Use the automated deployment script for easy setup:
|
||||
|
||||
```bash
|
||||
# Create deployment directory
|
||||
mkdir -p sub2api-deploy && cd sub2api-deploy
|
||||
|
||||
# Download and run deployment preparation script
|
||||
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
|
||||
|
||||
# Start services
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
|
||||
# View logs
|
||||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||||
```
|
||||
|
||||
**What the script does:**
|
||||
- Downloads `docker-compose.local.yml` and `.env.example`
|
||||
- Generates secure credentials (JWT_SECRET, TOTP_ENCRYPTION_KEY, POSTGRES_PASSWORD)
|
||||
- Creates `.env` file with auto-generated secrets
|
||||
- Creates data directories (uses local directories for easy backup/migration)
|
||||
- Displays generated credentials for your reference
|
||||
|
||||
#### Manual Deployment
|
||||
|
||||
If you prefer manual setup:
|
||||
|
||||
```bash
|
||||
# 1. Clone the repository
|
||||
git clone https://github.com/Wei-Shaw/sub2api.git
|
||||
cd sub2api
|
||||
cd sub2api/deploy
|
||||
|
||||
# 2. Enter the deploy directory
|
||||
cd deploy
|
||||
|
||||
# 3. Copy environment configuration
|
||||
# 2. Copy environment configuration
|
||||
cp .env.example .env
|
||||
|
||||
# 4. Edit configuration (set your passwords)
|
||||
# 3. Edit configuration (generate secure passwords)
|
||||
nano .env
|
||||
```
|
||||
|
||||
**Required configuration in `.env`:**
|
||||
|
||||
```bash
|
||||
# PostgreSQL password (REQUIRED - change this!)
|
||||
# PostgreSQL password (REQUIRED)
|
||||
POSTGRES_PASSWORD=your_secure_password_here
|
||||
|
||||
# JWT Secret (RECOMMENDED - keeps users logged in after restart)
|
||||
JWT_SECRET=your_jwt_secret_here
|
||||
|
||||
# TOTP Encryption Key (RECOMMENDED - preserves 2FA after restart)
|
||||
TOTP_ENCRYPTION_KEY=your_totp_key_here
|
||||
|
||||
# Optional: Admin account
|
||||
ADMIN_EMAIL=admin@example.com
|
||||
ADMIN_PASSWORD=your_admin_password
|
||||
|
||||
# Optional: Custom port
|
||||
SERVER_PORT=8080
|
||||
```
|
||||
|
||||
# Optional: Security configuration
|
||||
# Enable URL allowlist validation (false to skip allowlist checks, only basic format validation)
|
||||
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||
**Generate secure secrets:**
|
||||
```bash
|
||||
# Generate JWT_SECRET
|
||||
openssl rand -hex 32
|
||||
|
||||
# Allow insecure HTTP URLs when allowlist is disabled (default: false, requires https)
|
||||
# ⚠️ WARNING: Enabling this allows HTTP (plaintext) URLs which can expose API keys
|
||||
# Only recommended for:
|
||||
# - Development/testing environments
|
||||
# - Internal networks with trusted endpoints
|
||||
# - When using local test servers (http://localhost)
|
||||
# PRODUCTION: Keep this false or use HTTPS URLs only
|
||||
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=false
|
||||
# Generate TOTP_ENCRYPTION_KEY
|
||||
openssl rand -hex 32
|
||||
|
||||
# Allow private IP addresses for upstream/pricing/CRS (for internal deployments)
|
||||
SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=false
|
||||
# Generate POSTGRES_PASSWORD
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
```bash
|
||||
# 4. Create data directories (for local version)
|
||||
mkdir -p data postgres_data redis_data
|
||||
|
||||
# 5. Start all services
|
||||
# Option A: Local directory version (recommended - easy migration)
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
|
||||
# Option B: Named volumes version (simple setup)
|
||||
docker-compose up -d
|
||||
|
||||
# 6. Check status
|
||||
docker-compose ps
|
||||
docker-compose -f docker-compose.local.yml ps
|
||||
|
||||
# 7. View logs
|
||||
docker-compose logs -f sub2api
|
||||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||||
```
|
||||
|
||||
#### Deployment Versions
|
||||
|
||||
| Version | Data Storage | Migration | Best For |
|
||||
|---------|-------------|-----------|----------|
|
||||
| **docker-compose.local.yml** | Local directories | ✅ Easy (tar entire directory) | Production, frequent backups |
|
||||
| **docker-compose.yml** | Named volumes | ⚠️ Requires docker commands | Simple setup |
|
||||
|
||||
**Recommendation:** Use `docker-compose.local.yml` (deployed by script) for easier data management.
|
||||
|
||||
#### Access
|
||||
|
||||
Open `http://YOUR_SERVER_IP:8080` in your browser.
|
||||
|
||||
If admin password was auto-generated, find it in logs:
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml logs sub2api | grep "admin password"
|
||||
```
|
||||
|
||||
#### Upgrade
|
||||
|
||||
```bash
|
||||
# Pull latest image and recreate container
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker-compose -f docker-compose.local.yml pull
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
#### Easy Migration (Local Directory Version)
|
||||
|
||||
When using `docker-compose.local.yml`, migrate to a new server easily:
|
||||
|
||||
```bash
|
||||
# On source server
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
cd ..
|
||||
tar czf sub2api-complete.tar.gz sub2api-deploy/
|
||||
|
||||
# Transfer to new server
|
||||
scp sub2api-complete.tar.gz user@new-server:/path/
|
||||
|
||||
# On new server
|
||||
tar xzf sub2api-complete.tar.gz
|
||||
cd sub2api-deploy/
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
#### Useful Commands
|
||||
|
||||
```bash
|
||||
# Stop all services
|
||||
docker-compose down
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
|
||||
# Restart
|
||||
docker-compose restart
|
||||
docker-compose -f docker-compose.local.yml restart
|
||||
|
||||
# View all logs
|
||||
docker-compose logs -f
|
||||
docker-compose -f docker-compose.local.yml logs -f
|
||||
|
||||
# Remove all data (caution!)
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
rm -rf data/ postgres_data/ redis_data/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
132
README_CN.md
132
README_CN.md
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://golang.org/)
|
||||
[](https://golang.org/)
|
||||
[](https://vuejs.org/)
|
||||
[](https://www.postgresql.org/)
|
||||
[](https://redis.io/)
|
||||
@@ -44,7 +44,7 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅(
|
||||
|
||||
| 组件 | 技术 |
|
||||
|------|------|
|
||||
| 后端 | Go 1.25.5, Gin, Ent |
|
||||
| 后端 | Go 1.25.7, Gin, Ent |
|
||||
| 前端 | Vue 3.4+, Vite 5+, TailwindCSS |
|
||||
| 数据库 | PostgreSQL 15+ |
|
||||
| 缓存/队列 | Redis 7+ |
|
||||
@@ -135,7 +135,7 @@ curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install
|
||||
|
||||
---
|
||||
|
||||
### 方式二:Docker Compose
|
||||
### 方式二:Docker Compose(推荐)
|
||||
|
||||
使用 Docker Compose 部署,包含 PostgreSQL 和 Redis 容器。
|
||||
|
||||
@@ -144,87 +144,157 @@ curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install
|
||||
- Docker 20.10+
|
||||
- Docker Compose v2+
|
||||
|
||||
#### 安装步骤
|
||||
#### 快速开始(一键部署)
|
||||
|
||||
使用自动化部署脚本快速搭建:
|
||||
|
||||
```bash
|
||||
# 创建部署目录
|
||||
mkdir -p sub2api-deploy && cd sub2api-deploy
|
||||
|
||||
# 下载并运行部署准备脚本
|
||||
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
|
||||
|
||||
# 启动服务
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
|
||||
# 查看日志
|
||||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||||
```
|
||||
|
||||
**脚本功能:**
|
||||
- 下载 `docker-compose.local.yml` 和 `.env.example`
|
||||
- 自动生成安全凭证(JWT_SECRET、TOTP_ENCRYPTION_KEY、POSTGRES_PASSWORD)
|
||||
- 创建 `.env` 文件并填充自动生成的密钥
|
||||
- 创建数据目录(使用本地目录,便于备份和迁移)
|
||||
- 显示生成的凭证供你记录
|
||||
|
||||
#### 手动部署
|
||||
|
||||
如果你希望手动配置:
|
||||
|
||||
```bash
|
||||
# 1. 克隆仓库
|
||||
git clone https://github.com/Wei-Shaw/sub2api.git
|
||||
cd sub2api
|
||||
cd sub2api/deploy
|
||||
|
||||
# 2. 进入 deploy 目录
|
||||
cd deploy
|
||||
|
||||
# 3. 复制环境配置文件
|
||||
# 2. 复制环境配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 4. 编辑配置(设置密码等)
|
||||
# 3. 编辑配置(生成安全密码)
|
||||
nano .env
|
||||
```
|
||||
|
||||
**`.env` 必须配置项:**
|
||||
|
||||
```bash
|
||||
# PostgreSQL 密码(必须修改!)
|
||||
# PostgreSQL 密码(必需)
|
||||
POSTGRES_PASSWORD=your_secure_password_here
|
||||
|
||||
# JWT 密钥(推荐 - 重启后保持用户登录状态)
|
||||
JWT_SECRET=your_jwt_secret_here
|
||||
|
||||
# TOTP 加密密钥(推荐 - 重启后保留双因素认证)
|
||||
TOTP_ENCRYPTION_KEY=your_totp_key_here
|
||||
|
||||
# 可选:管理员账号
|
||||
ADMIN_EMAIL=admin@example.com
|
||||
ADMIN_PASSWORD=your_admin_password
|
||||
|
||||
# 可选:自定义端口
|
||||
SERVER_PORT=8080
|
||||
```
|
||||
|
||||
# 可选:安全配置
|
||||
# 启用 URL 白名单验证(false 则跳过白名单检查,仅做基本格式校验)
|
||||
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||
**生成安全密钥:**
|
||||
```bash
|
||||
# 生成 JWT_SECRET
|
||||
openssl rand -hex 32
|
||||
|
||||
# 关闭白名单时,是否允许 http:// URL(默认 false,只允许 https://)
|
||||
# ⚠️ 警告:允许 HTTP 会暴露 API 密钥(明文传输)
|
||||
# 仅建议在以下场景使用:
|
||||
# - 开发/测试环境
|
||||
# - 内部可信网络
|
||||
# - 本地测试服务器(http://localhost)
|
||||
# 生产环境:保持 false 或仅使用 HTTPS URL
|
||||
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=false
|
||||
# 生成 TOTP_ENCRYPTION_KEY
|
||||
openssl rand -hex 32
|
||||
|
||||
# 是否允许私有 IP 地址用于上游/定价/CRS(内网部署时使用)
|
||||
SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=false
|
||||
# 生成 POSTGRES_PASSWORD
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
```bash
|
||||
# 4. 创建数据目录(本地版)
|
||||
mkdir -p data postgres_data redis_data
|
||||
|
||||
# 5. 启动所有服务
|
||||
# 选项 A:本地目录版(推荐 - 易于迁移)
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
|
||||
# 选项 B:命名卷版(简单设置)
|
||||
docker-compose up -d
|
||||
|
||||
# 6. 查看状态
|
||||
docker-compose ps
|
||||
docker-compose -f docker-compose.local.yml ps
|
||||
|
||||
# 7. 查看日志
|
||||
docker-compose logs -f sub2api
|
||||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||||
```
|
||||
|
||||
#### 部署版本对比
|
||||
|
||||
| 版本 | 数据存储 | 迁移便利性 | 适用场景 |
|
||||
|------|---------|-----------|---------|
|
||||
| **docker-compose.local.yml** | 本地目录 | ✅ 简单(打包整个目录) | 生产环境、频繁备份 |
|
||||
| **docker-compose.yml** | 命名卷 | ⚠️ 需要 docker 命令 | 简单设置 |
|
||||
|
||||
**推荐:** 使用 `docker-compose.local.yml`(脚本部署)以便更轻松地管理数据。
|
||||
|
||||
#### 访问
|
||||
|
||||
在浏览器中打开 `http://你的服务器IP:8080`
|
||||
|
||||
如果管理员密码是自动生成的,在日志中查找:
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml logs sub2api | grep "admin password"
|
||||
```
|
||||
|
||||
#### 升级
|
||||
|
||||
```bash
|
||||
# 拉取最新镜像并重建容器
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker-compose -f docker-compose.local.yml pull
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
#### 轻松迁移(本地目录版)
|
||||
|
||||
使用 `docker-compose.local.yml` 时,可以轻松迁移到新服务器:
|
||||
|
||||
```bash
|
||||
# 源服务器
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
cd ..
|
||||
tar czf sub2api-complete.tar.gz sub2api-deploy/
|
||||
|
||||
# 传输到新服务器
|
||||
scp sub2api-complete.tar.gz user@new-server:/path/
|
||||
|
||||
# 新服务器
|
||||
tar xzf sub2api-complete.tar.gz
|
||||
cd sub2api-deploy/
|
||||
docker-compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
#### 常用命令
|
||||
|
||||
```bash
|
||||
# 停止所有服务
|
||||
docker-compose down
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
|
||||
# 重启
|
||||
docker-compose restart
|
||||
docker-compose -f docker-compose.local.yml restart
|
||||
|
||||
# 查看所有日志
|
||||
docker-compose logs -f
|
||||
docker-compose -f docker-compose.local.yml logs -f
|
||||
|
||||
# 删除所有数据(谨慎!)
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
rm -rf data/ postgres_data/ redis_data/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25.5-alpine
|
||||
FROM golang:1.25.7-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -15,7 +15,7 @@ RUN go mod download
|
||||
COPY . .
|
||||
|
||||
# 构建应用
|
||||
RUN go build -o main cmd/server/main.go
|
||||
RUN go build -o main ./cmd/server/
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8080
|
||||
|
||||
@@ -33,7 +33,7 @@ func main() {
|
||||
}()
|
||||
|
||||
userRepo := repository.NewUserRepository(client, sqlDB)
|
||||
authService := service.NewAuthService(userRepo, cfg, nil, nil, nil, nil, nil)
|
||||
authService := service.NewAuthService(userRepo, nil, nil, cfg, nil, nil, nil, nil, nil)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.46
|
||||
0.1.76
|
||||
@@ -70,6 +70,7 @@ func provideCleanup(
|
||||
schedulerSnapshot *service.SchedulerSnapshotService,
|
||||
tokenRefresh *service.TokenRefreshService,
|
||||
accountExpiry *service.AccountExpiryService,
|
||||
subscriptionExpiry *service.SubscriptionExpiryService,
|
||||
usageCleanup *service.UsageCleanupService,
|
||||
pricing *service.PricingService,
|
||||
emailQueue *service.EmailQueueService,
|
||||
@@ -138,6 +139,10 @@ func provideCleanup(
|
||||
accountExpiry.Stop()
|
||||
return nil
|
||||
}},
|
||||
{"SubscriptionExpiryService", func() error {
|
||||
subscriptionExpiry.Stop()
|
||||
return nil
|
||||
}},
|
||||
{"PricingService", func() error {
|
||||
pricing.Stop()
|
||||
return nil
|
||||
|
||||
@@ -43,9 +43,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
return nil, err
|
||||
}
|
||||
userRepository := repository.NewUserRepository(client, db)
|
||||
redeemCodeRepository := repository.NewRedeemCodeRepository(client)
|
||||
redisClient := repository.ProvideRedis(configConfig)
|
||||
refreshTokenCache := repository.NewRefreshTokenCache(redisClient)
|
||||
settingRepository := repository.NewSettingRepository(client)
|
||||
settingService := service.NewSettingService(settingRepository, configConfig)
|
||||
redisClient := repository.ProvideRedis(configConfig)
|
||||
emailCache := repository.NewEmailCache(redisClient)
|
||||
emailService := service.NewEmailService(settingRepository, emailCache)
|
||||
turnstileVerifier := repository.NewTurnstileVerifier()
|
||||
@@ -57,24 +59,34 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
billingCacheService := service.NewBillingCacheService(billingCache, userRepository, userSubscriptionRepository, configConfig)
|
||||
apiKeyRepository := repository.NewAPIKeyRepository(client)
|
||||
groupRepository := repository.NewGroupRepository(client, db)
|
||||
userGroupRateRepository := repository.NewUserGroupRateRepository(db)
|
||||
apiKeyCache := repository.NewAPIKeyCache(redisClient)
|
||||
apiKeyService := service.NewAPIKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
|
||||
apiKeyService := service.NewAPIKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, userGroupRateRepository, apiKeyCache, configConfig)
|
||||
apiKeyAuthCacheInvalidator := service.ProvideAPIKeyAuthCacheInvalidator(apiKeyService)
|
||||
promoService := service.NewPromoService(promoCodeRepository, userRepository, billingCacheService, client, apiKeyAuthCacheInvalidator)
|
||||
authService := service.NewAuthService(userRepository, configConfig, settingService, emailService, turnstileService, emailQueueService, promoService)
|
||||
authService := service.NewAuthService(userRepository, redeemCodeRepository, refreshTokenCache, configConfig, settingService, emailService, turnstileService, emailQueueService, promoService)
|
||||
userService := service.NewUserService(userRepository, apiKeyAuthCacheInvalidator)
|
||||
authHandler := handler.NewAuthHandler(configConfig, authService, userService, settingService, promoService)
|
||||
subscriptionService := service.NewSubscriptionService(groupRepository, userSubscriptionRepository, billingCacheService)
|
||||
redeemCache := repository.NewRedeemCache(redisClient)
|
||||
redeemService := service.NewRedeemService(redeemCodeRepository, userRepository, subscriptionService, redeemCache, billingCacheService, client, apiKeyAuthCacheInvalidator)
|
||||
secretEncryptor, err := repository.NewAESEncryptor(configConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
totpCache := repository.NewTotpCache(redisClient)
|
||||
totpService := service.NewTotpService(userRepository, secretEncryptor, totpCache, settingService, emailService, emailQueueService)
|
||||
authHandler := handler.NewAuthHandler(configConfig, authService, userService, settingService, promoService, redeemService, totpService)
|
||||
userHandler := handler.NewUserHandler(userService)
|
||||
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
|
||||
usageLogRepository := repository.NewUsageLogRepository(client, db)
|
||||
usageService := service.NewUsageService(usageLogRepository, userRepository, client, apiKeyAuthCacheInvalidator)
|
||||
usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
|
||||
redeemCodeRepository := repository.NewRedeemCodeRepository(client)
|
||||
subscriptionService := service.NewSubscriptionService(groupRepository, userSubscriptionRepository, billingCacheService)
|
||||
redeemCache := repository.NewRedeemCache(redisClient)
|
||||
redeemService := service.NewRedeemService(redeemCodeRepository, userRepository, subscriptionService, redeemCache, billingCacheService, client, apiKeyAuthCacheInvalidator)
|
||||
redeemHandler := handler.NewRedeemHandler(redeemService)
|
||||
subscriptionHandler := handler.NewSubscriptionHandler(subscriptionService)
|
||||
announcementRepository := repository.NewAnnouncementRepository(client)
|
||||
announcementReadRepository := repository.NewAnnouncementReadRepository(client)
|
||||
announcementService := service.NewAnnouncementService(announcementRepository, announcementReadRepository, userRepository, userSubscriptionRepository)
|
||||
announcementHandler := handler.NewAnnouncementHandler(announcementService)
|
||||
dashboardAggregationRepository := repository.NewDashboardAggregationRepository(db)
|
||||
dashboardStatsCache := repository.NewDashboardCache(redisClient, configConfig)
|
||||
dashboardService := service.NewDashboardService(usageLogRepository, dashboardAggregationRepository, dashboardStatsCache, configConfig)
|
||||
@@ -89,8 +101,10 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
proxyRepository := repository.NewProxyRepository(client, db)
|
||||
proxyExitInfoProber := repository.NewProxyExitInfoProber(configConfig)
|
||||
proxyLatencyCache := repository.NewProxyLatencyCache(redisClient)
|
||||
adminService := service.NewAdminService(userRepository, groupRepository, accountRepository, proxyRepository, apiKeyRepository, redeemCodeRepository, billingCacheService, proxyExitInfoProber, proxyLatencyCache, apiKeyAuthCacheInvalidator)
|
||||
adminUserHandler := admin.NewUserHandler(adminService)
|
||||
adminService := service.NewAdminService(userRepository, groupRepository, accountRepository, proxyRepository, apiKeyRepository, redeemCodeRepository, userGroupRateRepository, billingCacheService, proxyExitInfoProber, proxyLatencyCache, apiKeyAuthCacheInvalidator)
|
||||
concurrencyCache := repository.ProvideConcurrencyCache(redisClient, configConfig)
|
||||
concurrencyService := service.ProvideConcurrencyService(concurrencyCache, accountRepository, configConfig)
|
||||
adminUserHandler := admin.NewUserHandler(adminService, concurrencyService)
|
||||
groupHandler := admin.NewGroupHandler(adminService)
|
||||
claudeOAuthClient := repository.NewClaudeOAuthClient()
|
||||
oAuthService := service.NewOAuthService(proxyRepository, claudeOAuthClient)
|
||||
@@ -114,14 +128,15 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
accountUsageService := service.NewAccountUsageService(accountRepository, usageLogRepository, claudeUsageFetcher, geminiQuotaService, antigravityQuotaFetcher, usageCache, identityCache)
|
||||
geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
|
||||
gatewayCache := repository.NewGatewayCache(redisClient)
|
||||
schedulerOutboxRepository := repository.NewSchedulerOutboxRepository(db)
|
||||
schedulerSnapshotService := service.ProvideSchedulerSnapshotService(schedulerCache, schedulerOutboxRepository, accountRepository, groupRepository, configConfig)
|
||||
antigravityTokenProvider := service.NewAntigravityTokenProvider(accountRepository, geminiTokenCache, antigravityOAuthService)
|
||||
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, antigravityTokenProvider, rateLimitService, httpUpstream, settingService)
|
||||
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, schedulerSnapshotService, antigravityTokenProvider, rateLimitService, httpUpstream, settingService)
|
||||
accountTestService := service.NewAccountTestService(accountRepository, geminiTokenProvider, antigravityGatewayService, httpUpstream, configConfig)
|
||||
concurrencyCache := repository.ProvideConcurrencyCache(redisClient, configConfig)
|
||||
concurrencyService := service.ProvideConcurrencyService(concurrencyCache, accountRepository, configConfig)
|
||||
crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService, configConfig)
|
||||
sessionLimitCache := repository.ProvideSessionLimitCache(redisClient, configConfig)
|
||||
accountHandler := admin.NewAccountHandler(adminService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, rateLimitService, accountUsageService, accountTestService, concurrencyService, crsSyncService, sessionLimitCache, compositeTokenCacheInvalidator)
|
||||
adminAnnouncementHandler := admin.NewAnnouncementHandler(announcementService)
|
||||
oAuthHandler := admin.NewOAuthHandler(oAuthService)
|
||||
openAIOAuthHandler := admin.NewOpenAIOAuthHandler(openAIOAuthService, adminService)
|
||||
geminiOAuthHandler := admin.NewGeminiOAuthHandler(geminiOAuthService)
|
||||
@@ -130,8 +145,6 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
adminRedeemHandler := admin.NewRedeemHandler(adminService)
|
||||
promoHandler := admin.NewPromoHandler(promoService)
|
||||
opsRepository := repository.NewOpsRepository(db)
|
||||
schedulerOutboxRepository := repository.NewSchedulerOutboxRepository(db)
|
||||
schedulerSnapshotService := service.ProvideSchedulerSnapshotService(schedulerCache, schedulerOutboxRepository, accountRepository, groupRepository, configConfig)
|
||||
pricingRemoteClient := repository.ProvidePricingRemoteClient(configConfig)
|
||||
pricingService, err := service.ProvidePricingService(configConfig, pricingRemoteClient)
|
||||
if err != nil {
|
||||
@@ -141,11 +154,12 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
identityService := service.NewIdentityService(identityCache)
|
||||
deferredService := service.ProvideDeferredService(accountRepository, timingWheelService)
|
||||
claudeTokenProvider := service.NewClaudeTokenProvider(accountRepository, geminiTokenCache, oAuthService)
|
||||
gatewayService := service.NewGatewayService(accountRepository, groupRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, schedulerSnapshotService, concurrencyService, billingService, rateLimitService, billingCacheService, identityService, httpUpstream, deferredService, claudeTokenProvider, sessionLimitCache)
|
||||
digestSessionStore := service.NewDigestSessionStore()
|
||||
gatewayService := service.NewGatewayService(accountRepository, groupRepository, usageLogRepository, userRepository, userSubscriptionRepository, userGroupRateRepository, gatewayCache, configConfig, schedulerSnapshotService, concurrencyService, billingService, rateLimitService, billingCacheService, identityService, httpUpstream, deferredService, claudeTokenProvider, sessionLimitCache, digestSessionStore)
|
||||
openAITokenProvider := service.NewOpenAITokenProvider(accountRepository, geminiTokenCache, openAIOAuthService)
|
||||
openAIGatewayService := service.NewOpenAIGatewayService(accountRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, schedulerSnapshotService, concurrencyService, billingService, rateLimitService, billingCacheService, httpUpstream, deferredService, openAITokenProvider)
|
||||
geminiMessagesCompatService := service.NewGeminiMessagesCompatService(accountRepository, groupRepository, gatewayCache, schedulerSnapshotService, geminiTokenProvider, rateLimitService, httpUpstream, antigravityGatewayService, configConfig)
|
||||
opsService := service.NewOpsService(opsRepository, settingRepository, configConfig, accountRepository, concurrencyService, gatewayService, openAIGatewayService, geminiMessagesCompatService, antigravityGatewayService)
|
||||
opsService := service.NewOpsService(opsRepository, settingRepository, configConfig, accountRepository, userRepository, concurrencyService, gatewayService, openAIGatewayService, geminiMessagesCompatService, antigravityGatewayService)
|
||||
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService, opsService)
|
||||
opsHandler := admin.NewOpsHandler(opsService)
|
||||
updateCache := repository.NewUpdateCache(redisClient)
|
||||
@@ -161,11 +175,16 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
userAttributeValueRepository := repository.NewUserAttributeValueRepository(client)
|
||||
userAttributeService := service.NewUserAttributeService(userAttributeDefinitionRepository, userAttributeValueRepository)
|
||||
userAttributeHandler := admin.NewUserAttributeHandler(userAttributeService)
|
||||
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, promoHandler, settingHandler, opsHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler)
|
||||
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, configConfig)
|
||||
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, configConfig)
|
||||
errorPassthroughRepository := repository.NewErrorPassthroughRepository(client)
|
||||
errorPassthroughCache := repository.NewErrorPassthroughCache(redisClient)
|
||||
errorPassthroughService := service.NewErrorPassthroughService(errorPassthroughRepository, errorPassthroughCache)
|
||||
errorPassthroughHandler := admin.NewErrorPassthroughHandler(errorPassthroughService)
|
||||
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, adminAnnouncementHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, promoHandler, settingHandler, opsHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler, errorPassthroughHandler)
|
||||
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, usageService, apiKeyService, errorPassthroughService, configConfig)
|
||||
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, apiKeyService, errorPassthroughService, configConfig)
|
||||
handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
|
||||
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler)
|
||||
totpHandler := handler.NewTotpHandler(totpService)
|
||||
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, announcementHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler, totpHandler)
|
||||
jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService)
|
||||
adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService)
|
||||
apiKeyAuthMiddleware := middleware.NewAPIKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
|
||||
@@ -176,9 +195,10 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
opsAlertEvaluatorService := service.ProvideOpsAlertEvaluatorService(opsService, opsRepository, emailService, redisClient, configConfig)
|
||||
opsCleanupService := service.ProvideOpsCleanupService(opsRepository, db, redisClient, configConfig)
|
||||
opsScheduledReportService := service.ProvideOpsScheduledReportService(opsService, userService, emailService, redisClient, configConfig)
|
||||
tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, compositeTokenCacheInvalidator, configConfig)
|
||||
tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, compositeTokenCacheInvalidator, schedulerCache, configConfig)
|
||||
accountExpiryService := service.ProvideAccountExpiryService(accountRepository)
|
||||
v := provideCleanup(client, redisClient, opsMetricsCollector, opsAggregationService, opsAlertEvaluatorService, opsCleanupService, opsScheduledReportService, schedulerSnapshotService, tokenRefreshService, accountExpiryService, usageCleanupService, pricingService, emailQueueService, billingCacheService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService)
|
||||
subscriptionExpiryService := service.ProvideSubscriptionExpiryService(userSubscriptionRepository)
|
||||
v := provideCleanup(client, redisClient, opsMetricsCollector, opsAggregationService, opsAlertEvaluatorService, opsCleanupService, opsScheduledReportService, schedulerSnapshotService, tokenRefreshService, accountExpiryService, subscriptionExpiryService, usageCleanupService, pricingService, emailQueueService, billingCacheService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService)
|
||||
application := &Application{
|
||||
Server: httpServer,
|
||||
Cleanup: v,
|
||||
@@ -211,6 +231,7 @@ func provideCleanup(
|
||||
schedulerSnapshot *service.SchedulerSnapshotService,
|
||||
tokenRefresh *service.TokenRefreshService,
|
||||
accountExpiry *service.AccountExpiryService,
|
||||
subscriptionExpiry *service.SubscriptionExpiryService,
|
||||
usageCleanup *service.UsageCleanupService,
|
||||
pricing *service.PricingService,
|
||||
emailQueue *service.EmailQueueService,
|
||||
@@ -278,6 +299,10 @@ func provideCleanup(
|
||||
accountExpiry.Stop()
|
||||
return nil
|
||||
}},
|
||||
{"SubscriptionExpiryService", func() error {
|
||||
subscriptionExpiry.Stop()
|
||||
return nil
|
||||
}},
|
||||
{"PricingService", func() error {
|
||||
pricing.Stop()
|
||||
return nil
|
||||
|
||||
249
backend/ent/announcement.go
Normal file
249
backend/ent/announcement.go
Normal file
@@ -0,0 +1,249 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
)
|
||||
|
||||
// Announcement is the model entity for the Announcement schema.
|
||||
type Announcement struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// 公告标题
|
||||
Title string `json:"title,omitempty"`
|
||||
// 公告内容(支持 Markdown)
|
||||
Content string `json:"content,omitempty"`
|
||||
// 状态: draft, active, archived
|
||||
Status string `json:"status,omitempty"`
|
||||
// 展示条件(JSON 规则)
|
||||
Targeting domain.AnnouncementTargeting `json:"targeting,omitempty"`
|
||||
// 开始展示时间(为空表示立即生效)
|
||||
StartsAt *time.Time `json:"starts_at,omitempty"`
|
||||
// 结束展示时间(为空表示永久生效)
|
||||
EndsAt *time.Time `json:"ends_at,omitempty"`
|
||||
// 创建人用户ID(管理员)
|
||||
CreatedBy *int64 `json:"created_by,omitempty"`
|
||||
// 更新人用户ID(管理员)
|
||||
UpdatedBy *int64 `json:"updated_by,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AnnouncementQuery when eager-loading is set.
|
||||
Edges AnnouncementEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// AnnouncementEdges holds the relations/edges for other nodes in the graph.
|
||||
type AnnouncementEdges struct {
|
||||
// Reads holds the value of the reads edge.
|
||||
Reads []*AnnouncementRead `json:"reads,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [1]bool
|
||||
}
|
||||
|
||||
// ReadsOrErr returns the Reads value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e AnnouncementEdges) ReadsOrErr() ([]*AnnouncementRead, error) {
|
||||
if e.loadedTypes[0] {
|
||||
return e.Reads, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "reads"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*Announcement) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case announcement.FieldTargeting:
|
||||
values[i] = new([]byte)
|
||||
case announcement.FieldID, announcement.FieldCreatedBy, announcement.FieldUpdatedBy:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case announcement.FieldTitle, announcement.FieldContent, announcement.FieldStatus:
|
||||
values[i] = new(sql.NullString)
|
||||
case announcement.FieldStartsAt, announcement.FieldEndsAt, announcement.FieldCreatedAt, announcement.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the Announcement fields.
|
||||
func (_m *Announcement) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case announcement.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case announcement.FieldTitle:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field title", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Title = value.String
|
||||
}
|
||||
case announcement.FieldContent:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field content", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Content = value.String
|
||||
}
|
||||
case announcement.FieldStatus:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field status", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Status = value.String
|
||||
}
|
||||
case announcement.FieldTargeting:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field targeting", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.Targeting); err != nil {
|
||||
return fmt.Errorf("unmarshal field targeting: %w", err)
|
||||
}
|
||||
}
|
||||
case announcement.FieldStartsAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field starts_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.StartsAt = new(time.Time)
|
||||
*_m.StartsAt = value.Time
|
||||
}
|
||||
case announcement.FieldEndsAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field ends_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.EndsAt = new(time.Time)
|
||||
*_m.EndsAt = value.Time
|
||||
}
|
||||
case announcement.FieldCreatedBy:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_by", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedBy = new(int64)
|
||||
*_m.CreatedBy = value.Int64
|
||||
}
|
||||
case announcement.FieldUpdatedBy:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_by", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedBy = new(int64)
|
||||
*_m.UpdatedBy = value.Int64
|
||||
}
|
||||
case announcement.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case announcement.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the Announcement.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *Announcement) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryReads queries the "reads" edge of the Announcement entity.
|
||||
func (_m *Announcement) QueryReads() *AnnouncementReadQuery {
|
||||
return NewAnnouncementClient(_m.config).QueryReads(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this Announcement.
|
||||
// Note that you need to call Announcement.Unwrap() before calling this method if this Announcement
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *Announcement) Update() *AnnouncementUpdateOne {
|
||||
return NewAnnouncementClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the Announcement entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *Announcement) Unwrap() *Announcement {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: Announcement is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *Announcement) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("Announcement(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("title=")
|
||||
builder.WriteString(_m.Title)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("content=")
|
||||
builder.WriteString(_m.Content)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("status=")
|
||||
builder.WriteString(_m.Status)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("targeting=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Targeting))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.StartsAt; v != nil {
|
||||
builder.WriteString("starts_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.EndsAt; v != nil {
|
||||
builder.WriteString("ends_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.CreatedBy; v != nil {
|
||||
builder.WriteString("created_by=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.UpdatedBy; v != nil {
|
||||
builder.WriteString("updated_by=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// Announcements is a parsable slice of Announcement.
|
||||
type Announcements []*Announcement
|
||||
164
backend/ent/announcement/announcement.go
Normal file
164
backend/ent/announcement/announcement.go
Normal file
@@ -0,0 +1,164 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the announcement type in the database.
|
||||
Label = "announcement"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldTitle holds the string denoting the title field in the database.
|
||||
FieldTitle = "title"
|
||||
// FieldContent holds the string denoting the content field in the database.
|
||||
FieldContent = "content"
|
||||
// FieldStatus holds the string denoting the status field in the database.
|
||||
FieldStatus = "status"
|
||||
// FieldTargeting holds the string denoting the targeting field in the database.
|
||||
FieldTargeting = "targeting"
|
||||
// FieldStartsAt holds the string denoting the starts_at field in the database.
|
||||
FieldStartsAt = "starts_at"
|
||||
// FieldEndsAt holds the string denoting the ends_at field in the database.
|
||||
FieldEndsAt = "ends_at"
|
||||
// FieldCreatedBy holds the string denoting the created_by field in the database.
|
||||
FieldCreatedBy = "created_by"
|
||||
// FieldUpdatedBy holds the string denoting the updated_by field in the database.
|
||||
FieldUpdatedBy = "updated_by"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// EdgeReads holds the string denoting the reads edge name in mutations.
|
||||
EdgeReads = "reads"
|
||||
// Table holds the table name of the announcement in the database.
|
||||
Table = "announcements"
|
||||
// ReadsTable is the table that holds the reads relation/edge.
|
||||
ReadsTable = "announcement_reads"
|
||||
// ReadsInverseTable is the table name for the AnnouncementRead entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "announcementread" package.
|
||||
ReadsInverseTable = "announcement_reads"
|
||||
// ReadsColumn is the table column denoting the reads relation/edge.
|
||||
ReadsColumn = "announcement_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for announcement fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldTitle,
|
||||
FieldContent,
|
||||
FieldStatus,
|
||||
FieldTargeting,
|
||||
FieldStartsAt,
|
||||
FieldEndsAt,
|
||||
FieldCreatedBy,
|
||||
FieldUpdatedBy,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// TitleValidator is a validator for the "title" field. It is called by the builders before save.
|
||||
TitleValidator func(string) error
|
||||
// ContentValidator is a validator for the "content" field. It is called by the builders before save.
|
||||
ContentValidator func(string) error
|
||||
// DefaultStatus holds the default value on creation for the "status" field.
|
||||
DefaultStatus string
|
||||
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
StatusValidator func(string) error
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the Announcement queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTitle orders the results by the title field.
|
||||
func ByTitle(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTitle, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByContent orders the results by the content field.
|
||||
func ByContent(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldContent, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByStatus orders the results by the status field.
|
||||
func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByStartsAt orders the results by the starts_at field.
|
||||
func ByStartsAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldStartsAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByEndsAt orders the results by the ends_at field.
|
||||
func ByEndsAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldEndsAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedBy orders the results by the created_by field.
|
||||
func ByCreatedBy(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedBy, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedBy orders the results by the updated_by field.
|
||||
func ByUpdatedBy(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedBy, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByReadsCount orders the results by reads count.
|
||||
func ByReadsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newReadsStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByReads orders the results by reads terms.
|
||||
func ByReads(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newReadsStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
func newReadsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(ReadsInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, ReadsTable, ReadsColumn),
|
||||
)
|
||||
}
|
||||
624
backend/ent/announcement/where.go
Normal file
624
backend/ent/announcement/where.go
Normal file
@@ -0,0 +1,624 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// Title applies equality check predicate on the "title" field. It's identical to TitleEQ.
|
||||
func Title(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldTitle, v))
|
||||
}
|
||||
|
||||
// Content applies equality check predicate on the "content" field. It's identical to ContentEQ.
|
||||
func Content(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldContent, v))
|
||||
}
|
||||
|
||||
// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
|
||||
func Status(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StartsAt applies equality check predicate on the "starts_at" field. It's identical to StartsAtEQ.
|
||||
func StartsAt(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// EndsAt applies equality check predicate on the "ends_at" field. It's identical to EndsAtEQ.
|
||||
func EndsAt(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// CreatedBy applies equality check predicate on the "created_by" field. It's identical to CreatedByEQ.
|
||||
func CreatedBy(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedBy applies equality check predicate on the "updated_by" field. It's identical to UpdatedByEQ.
|
||||
func UpdatedBy(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// TitleEQ applies the EQ predicate on the "title" field.
|
||||
func TitleEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleNEQ applies the NEQ predicate on the "title" field.
|
||||
func TitleNEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleIn applies the In predicate on the "title" field.
|
||||
func TitleIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldTitle, vs...))
|
||||
}
|
||||
|
||||
// TitleNotIn applies the NotIn predicate on the "title" field.
|
||||
func TitleNotIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldTitle, vs...))
|
||||
}
|
||||
|
||||
// TitleGT applies the GT predicate on the "title" field.
|
||||
func TitleGT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleGTE applies the GTE predicate on the "title" field.
|
||||
func TitleGTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleLT applies the LT predicate on the "title" field.
|
||||
func TitleLT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleLTE applies the LTE predicate on the "title" field.
|
||||
func TitleLTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleContains applies the Contains predicate on the "title" field.
|
||||
func TitleContains(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContains(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleHasPrefix applies the HasPrefix predicate on the "title" field.
|
||||
func TitleHasPrefix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasPrefix(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleHasSuffix applies the HasSuffix predicate on the "title" field.
|
||||
func TitleHasSuffix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasSuffix(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleEqualFold applies the EqualFold predicate on the "title" field.
|
||||
func TitleEqualFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEqualFold(FieldTitle, v))
|
||||
}
|
||||
|
||||
// TitleContainsFold applies the ContainsFold predicate on the "title" field.
|
||||
func TitleContainsFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContainsFold(FieldTitle, v))
|
||||
}
|
||||
|
||||
// ContentEQ applies the EQ predicate on the "content" field.
|
||||
func ContentEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentNEQ applies the NEQ predicate on the "content" field.
|
||||
func ContentNEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentIn applies the In predicate on the "content" field.
|
||||
func ContentIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldContent, vs...))
|
||||
}
|
||||
|
||||
// ContentNotIn applies the NotIn predicate on the "content" field.
|
||||
func ContentNotIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldContent, vs...))
|
||||
}
|
||||
|
||||
// ContentGT applies the GT predicate on the "content" field.
|
||||
func ContentGT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentGTE applies the GTE predicate on the "content" field.
|
||||
func ContentGTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentLT applies the LT predicate on the "content" field.
|
||||
func ContentLT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentLTE applies the LTE predicate on the "content" field.
|
||||
func ContentLTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentContains applies the Contains predicate on the "content" field.
|
||||
func ContentContains(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContains(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentHasPrefix applies the HasPrefix predicate on the "content" field.
|
||||
func ContentHasPrefix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasPrefix(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentHasSuffix applies the HasSuffix predicate on the "content" field.
|
||||
func ContentHasSuffix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasSuffix(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentEqualFold applies the EqualFold predicate on the "content" field.
|
||||
func ContentEqualFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEqualFold(FieldContent, v))
|
||||
}
|
||||
|
||||
// ContentContainsFold applies the ContainsFold predicate on the "content" field.
|
||||
func ContentContainsFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContainsFold(FieldContent, v))
|
||||
}
|
||||
|
||||
// StatusEQ applies the EQ predicate on the "status" field.
|
||||
func StatusEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusNEQ applies the NEQ predicate on the "status" field.
|
||||
func StatusNEQ(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusIn applies the In predicate on the "status" field.
|
||||
func StatusIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldStatus, vs...))
|
||||
}
|
||||
|
||||
// StatusNotIn applies the NotIn predicate on the "status" field.
|
||||
func StatusNotIn(vs ...string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldStatus, vs...))
|
||||
}
|
||||
|
||||
// StatusGT applies the GT predicate on the "status" field.
|
||||
func StatusGT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusGTE applies the GTE predicate on the "status" field.
|
||||
func StatusGTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusLT applies the LT predicate on the "status" field.
|
||||
func StatusLT(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusLTE applies the LTE predicate on the "status" field.
|
||||
func StatusLTE(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusContains applies the Contains predicate on the "status" field.
|
||||
func StatusContains(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContains(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusHasPrefix applies the HasPrefix predicate on the "status" field.
|
||||
func StatusHasPrefix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasPrefix(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusHasSuffix applies the HasSuffix predicate on the "status" field.
|
||||
func StatusHasSuffix(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldHasSuffix(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusEqualFold applies the EqualFold predicate on the "status" field.
|
||||
func StatusEqualFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEqualFold(FieldStatus, v))
|
||||
}
|
||||
|
||||
// StatusContainsFold applies the ContainsFold predicate on the "status" field.
|
||||
func StatusContainsFold(v string) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldContainsFold(FieldStatus, v))
|
||||
}
|
||||
|
||||
// TargetingIsNil applies the IsNil predicate on the "targeting" field.
|
||||
func TargetingIsNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIsNull(FieldTargeting))
|
||||
}
|
||||
|
||||
// TargetingNotNil applies the NotNil predicate on the "targeting" field.
|
||||
func TargetingNotNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotNull(FieldTargeting))
|
||||
}
|
||||
|
||||
// StartsAtEQ applies the EQ predicate on the "starts_at" field.
|
||||
func StartsAtEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtNEQ applies the NEQ predicate on the "starts_at" field.
|
||||
func StartsAtNEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtIn applies the In predicate on the "starts_at" field.
|
||||
func StartsAtIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldStartsAt, vs...))
|
||||
}
|
||||
|
||||
// StartsAtNotIn applies the NotIn predicate on the "starts_at" field.
|
||||
func StartsAtNotIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldStartsAt, vs...))
|
||||
}
|
||||
|
||||
// StartsAtGT applies the GT predicate on the "starts_at" field.
|
||||
func StartsAtGT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtGTE applies the GTE predicate on the "starts_at" field.
|
||||
func StartsAtGTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtLT applies the LT predicate on the "starts_at" field.
|
||||
func StartsAtLT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtLTE applies the LTE predicate on the "starts_at" field.
|
||||
func StartsAtLTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldStartsAt, v))
|
||||
}
|
||||
|
||||
// StartsAtIsNil applies the IsNil predicate on the "starts_at" field.
|
||||
func StartsAtIsNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIsNull(FieldStartsAt))
|
||||
}
|
||||
|
||||
// StartsAtNotNil applies the NotNil predicate on the "starts_at" field.
|
||||
func StartsAtNotNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotNull(FieldStartsAt))
|
||||
}
|
||||
|
||||
// EndsAtEQ applies the EQ predicate on the "ends_at" field.
|
||||
func EndsAtEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtNEQ applies the NEQ predicate on the "ends_at" field.
|
||||
func EndsAtNEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtIn applies the In predicate on the "ends_at" field.
|
||||
func EndsAtIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldEndsAt, vs...))
|
||||
}
|
||||
|
||||
// EndsAtNotIn applies the NotIn predicate on the "ends_at" field.
|
||||
func EndsAtNotIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldEndsAt, vs...))
|
||||
}
|
||||
|
||||
// EndsAtGT applies the GT predicate on the "ends_at" field.
|
||||
func EndsAtGT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtGTE applies the GTE predicate on the "ends_at" field.
|
||||
func EndsAtGTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtLT applies the LT predicate on the "ends_at" field.
|
||||
func EndsAtLT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtLTE applies the LTE predicate on the "ends_at" field.
|
||||
func EndsAtLTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldEndsAt, v))
|
||||
}
|
||||
|
||||
// EndsAtIsNil applies the IsNil predicate on the "ends_at" field.
|
||||
func EndsAtIsNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIsNull(FieldEndsAt))
|
||||
}
|
||||
|
||||
// EndsAtNotNil applies the NotNil predicate on the "ends_at" field.
|
||||
func EndsAtNotNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotNull(FieldEndsAt))
|
||||
}
|
||||
|
||||
// CreatedByEQ applies the EQ predicate on the "created_by" field.
|
||||
func CreatedByEQ(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByNEQ applies the NEQ predicate on the "created_by" field.
|
||||
func CreatedByNEQ(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByIn applies the In predicate on the "created_by" field.
|
||||
func CreatedByIn(vs ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldCreatedBy, vs...))
|
||||
}
|
||||
|
||||
// CreatedByNotIn applies the NotIn predicate on the "created_by" field.
|
||||
func CreatedByNotIn(vs ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldCreatedBy, vs...))
|
||||
}
|
||||
|
||||
// CreatedByGT applies the GT predicate on the "created_by" field.
|
||||
func CreatedByGT(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByGTE applies the GTE predicate on the "created_by" field.
|
||||
func CreatedByGTE(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByLT applies the LT predicate on the "created_by" field.
|
||||
func CreatedByLT(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByLTE applies the LTE predicate on the "created_by" field.
|
||||
func CreatedByLTE(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldCreatedBy, v))
|
||||
}
|
||||
|
||||
// CreatedByIsNil applies the IsNil predicate on the "created_by" field.
|
||||
func CreatedByIsNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIsNull(FieldCreatedBy))
|
||||
}
|
||||
|
||||
// CreatedByNotNil applies the NotNil predicate on the "created_by" field.
|
||||
func CreatedByNotNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotNull(FieldCreatedBy))
|
||||
}
|
||||
|
||||
// UpdatedByEQ applies the EQ predicate on the "updated_by" field.
|
||||
func UpdatedByEQ(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByNEQ applies the NEQ predicate on the "updated_by" field.
|
||||
func UpdatedByNEQ(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByIn applies the In predicate on the "updated_by" field.
|
||||
func UpdatedByIn(vs ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldUpdatedBy, vs...))
|
||||
}
|
||||
|
||||
// UpdatedByNotIn applies the NotIn predicate on the "updated_by" field.
|
||||
func UpdatedByNotIn(vs ...int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldUpdatedBy, vs...))
|
||||
}
|
||||
|
||||
// UpdatedByGT applies the GT predicate on the "updated_by" field.
|
||||
func UpdatedByGT(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByGTE applies the GTE predicate on the "updated_by" field.
|
||||
func UpdatedByGTE(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByLT applies the LT predicate on the "updated_by" field.
|
||||
func UpdatedByLT(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByLTE applies the LTE predicate on the "updated_by" field.
|
||||
func UpdatedByLTE(v int64) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldUpdatedBy, v))
|
||||
}
|
||||
|
||||
// UpdatedByIsNil applies the IsNil predicate on the "updated_by" field.
|
||||
func UpdatedByIsNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIsNull(FieldUpdatedBy))
|
||||
}
|
||||
|
||||
// UpdatedByNotNil applies the NotNil predicate on the "updated_by" field.
|
||||
func UpdatedByNotNil() predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotNull(FieldUpdatedBy))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.Announcement {
|
||||
return predicate.Announcement(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// HasReads applies the HasEdge predicate on the "reads" edge.
|
||||
func HasReads() predicate.Announcement {
|
||||
return predicate.Announcement(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, ReadsTable, ReadsColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasReadsWith applies the HasEdge predicate on the "reads" edge with a given conditions (other predicates).
|
||||
func HasReadsWith(preds ...predicate.AnnouncementRead) predicate.Announcement {
|
||||
return predicate.Announcement(func(s *sql.Selector) {
|
||||
step := newReadsStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.Announcement) predicate.Announcement {
|
||||
return predicate.Announcement(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.Announcement) predicate.Announcement {
|
||||
return predicate.Announcement(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.Announcement) predicate.Announcement {
|
||||
return predicate.Announcement(sql.NotPredicates(p))
|
||||
}
|
||||
1159
backend/ent/announcement_create.go
Normal file
1159
backend/ent/announcement_create.go
Normal file
File diff suppressed because it is too large
Load Diff
88
backend/ent/announcement_delete.go
Normal file
88
backend/ent/announcement_delete.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AnnouncementDelete is the builder for deleting a Announcement entity.
|
||||
type AnnouncementDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AnnouncementMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementDelete builder.
|
||||
func (_d *AnnouncementDelete) Where(ps ...predicate.Announcement) *AnnouncementDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *AnnouncementDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AnnouncementDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *AnnouncementDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(announcement.Table, sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// AnnouncementDeleteOne is the builder for deleting a single Announcement entity.
|
||||
type AnnouncementDeleteOne struct {
|
||||
_d *AnnouncementDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementDelete builder.
|
||||
func (_d *AnnouncementDeleteOne) Where(ps ...predicate.Announcement) *AnnouncementDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *AnnouncementDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{announcement.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AnnouncementDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
643
backend/ent/announcement_query.go
Normal file
643
backend/ent/announcement_query.go
Normal file
@@ -0,0 +1,643 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AnnouncementQuery is the builder for querying Announcement entities.
|
||||
type AnnouncementQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []announcement.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.Announcement
|
||||
withReads *AnnouncementReadQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the AnnouncementQuery builder.
|
||||
func (_q *AnnouncementQuery) Where(ps ...predicate.Announcement) *AnnouncementQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *AnnouncementQuery) Limit(limit int) *AnnouncementQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *AnnouncementQuery) Offset(offset int) *AnnouncementQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *AnnouncementQuery) Unique(unique bool) *AnnouncementQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *AnnouncementQuery) Order(o ...announcement.OrderOption) *AnnouncementQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryReads chains the current query on the "reads" edge.
|
||||
func (_q *AnnouncementQuery) QueryReads() *AnnouncementReadQuery {
|
||||
query := (&AnnouncementReadClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcement.Table, announcement.FieldID, selector),
|
||||
sqlgraph.To(announcementread.Table, announcementread.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, announcement.ReadsTable, announcement.ReadsColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first Announcement entity from the query.
|
||||
// Returns a *NotFoundError when no Announcement was found.
|
||||
func (_q *AnnouncementQuery) First(ctx context.Context) (*Announcement, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{announcement.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) FirstX(ctx context.Context) *Announcement {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first Announcement ID from the query.
|
||||
// Returns a *NotFoundError when no Announcement ID was found.
|
||||
func (_q *AnnouncementQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{announcement.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single Announcement entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one Announcement entity is found.
|
||||
// Returns a *NotFoundError when no Announcement entities are found.
|
||||
func (_q *AnnouncementQuery) Only(ctx context.Context) (*Announcement, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{announcement.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{announcement.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) OnlyX(ctx context.Context) *Announcement {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only Announcement ID in the query.
|
||||
// Returns a *NotSingularError when more than one Announcement ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *AnnouncementQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{announcement.Label}
|
||||
default:
|
||||
err = &NotSingularError{announcement.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of Announcements.
|
||||
func (_q *AnnouncementQuery) All(ctx context.Context) ([]*Announcement, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*Announcement, *AnnouncementQuery]()
|
||||
return withInterceptors[[]*Announcement](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) AllX(ctx context.Context) []*Announcement {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of Announcement IDs.
|
||||
func (_q *AnnouncementQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(announcement.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *AnnouncementQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*AnnouncementQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *AnnouncementQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *AnnouncementQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the AnnouncementQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *AnnouncementQuery) Clone() *AnnouncementQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &AnnouncementQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]announcement.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.Announcement{}, _q.predicates...),
|
||||
withReads: _q.withReads.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithReads tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "reads" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AnnouncementQuery) WithReads(opts ...func(*AnnouncementReadQuery)) *AnnouncementQuery {
|
||||
query := (&AnnouncementReadClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withReads = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// Title string `json:"title,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.Announcement.Query().
|
||||
// GroupBy(announcement.FieldTitle).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AnnouncementQuery) GroupBy(field string, fields ...string) *AnnouncementGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &AnnouncementGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = announcement.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// Title string `json:"title,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.Announcement.Query().
|
||||
// Select(announcement.FieldTitle).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AnnouncementQuery) Select(fields ...string) *AnnouncementSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &AnnouncementSelect{AnnouncementQuery: _q}
|
||||
sbuild.label = announcement.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a AnnouncementSelect configured with the given aggregations.
|
||||
func (_q *AnnouncementQuery) Aggregate(fns ...AggregateFunc) *AnnouncementSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !announcement.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Announcement, error) {
|
||||
var (
|
||||
nodes = []*Announcement{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [1]bool{
|
||||
_q.withReads != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*Announcement).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &Announcement{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withReads; query != nil {
|
||||
if err := _q.loadReads(ctx, query, nodes,
|
||||
func(n *Announcement) { n.Edges.Reads = []*AnnouncementRead{} },
|
||||
func(n *Announcement, e *AnnouncementRead) { n.Edges.Reads = append(n.Edges.Reads, e) }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) loadReads(ctx context.Context, query *AnnouncementReadQuery, nodes []*Announcement, init func(*Announcement), assign func(*Announcement, *AnnouncementRead)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*Announcement)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(announcementread.FieldAnnouncementID)
|
||||
}
|
||||
query.Where(predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(announcement.ReadsColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.AnnouncementID
|
||||
node, ok := nodeids[fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "announcement_id" returned %v for node %v`, fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(announcement.Table, announcement.Columns, sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, announcement.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != announcement.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *AnnouncementQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(announcement.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = announcement.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *AnnouncementQuery) ForUpdate(opts ...sql.LockOption) *AnnouncementQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *AnnouncementQuery) ForShare(opts ...sql.LockOption) *AnnouncementQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// AnnouncementGroupBy is the group-by builder for Announcement entities.
|
||||
type AnnouncementGroupBy struct {
|
||||
selector
|
||||
build *AnnouncementQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *AnnouncementGroupBy) Aggregate(fns ...AggregateFunc) *AnnouncementGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *AnnouncementGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AnnouncementQuery, *AnnouncementGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *AnnouncementGroupBy) sqlScan(ctx context.Context, root *AnnouncementQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// AnnouncementSelect is the builder for selecting fields of Announcement entities.
|
||||
type AnnouncementSelect struct {
|
||||
*AnnouncementQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *AnnouncementSelect) Aggregate(fns ...AggregateFunc) *AnnouncementSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *AnnouncementSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AnnouncementQuery, *AnnouncementSelect](ctx, _s.AnnouncementQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *AnnouncementSelect) sqlScan(ctx context.Context, root *AnnouncementQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
824
backend/ent/announcement_update.go
Normal file
824
backend/ent/announcement_update.go
Normal file
@@ -0,0 +1,824 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
)
|
||||
|
||||
// AnnouncementUpdate is the builder for updating Announcement entities.
|
||||
type AnnouncementUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AnnouncementMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementUpdate builder.
|
||||
func (_u *AnnouncementUpdate) Where(ps ...predicate.Announcement) *AnnouncementUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTitle sets the "title" field.
|
||||
func (_u *AnnouncementUpdate) SetTitle(v string) *AnnouncementUpdate {
|
||||
_u.mutation.SetTitle(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTitle sets the "title" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableTitle(v *string) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetTitle(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetContent sets the "content" field.
|
||||
func (_u *AnnouncementUpdate) SetContent(v string) *AnnouncementUpdate {
|
||||
_u.mutation.SetContent(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableContent sets the "content" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableContent(v *string) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetContent(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (_u *AnnouncementUpdate) SetStatus(v string) *AnnouncementUpdate {
|
||||
_u.mutation.SetStatus(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableStatus sets the "status" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableStatus(v *string) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetStatus(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTargeting sets the "targeting" field.
|
||||
func (_u *AnnouncementUpdate) SetTargeting(v domain.AnnouncementTargeting) *AnnouncementUpdate {
|
||||
_u.mutation.SetTargeting(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTargeting sets the "targeting" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableTargeting(v *domain.AnnouncementTargeting) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetTargeting(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTargeting clears the value of the "targeting" field.
|
||||
func (_u *AnnouncementUpdate) ClearTargeting() *AnnouncementUpdate {
|
||||
_u.mutation.ClearTargeting()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStartsAt sets the "starts_at" field.
|
||||
func (_u *AnnouncementUpdate) SetStartsAt(v time.Time) *AnnouncementUpdate {
|
||||
_u.mutation.SetStartsAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableStartsAt sets the "starts_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableStartsAt(v *time.Time) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetStartsAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearStartsAt clears the value of the "starts_at" field.
|
||||
func (_u *AnnouncementUpdate) ClearStartsAt() *AnnouncementUpdate {
|
||||
_u.mutation.ClearStartsAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetEndsAt sets the "ends_at" field.
|
||||
func (_u *AnnouncementUpdate) SetEndsAt(v time.Time) *AnnouncementUpdate {
|
||||
_u.mutation.SetEndsAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableEndsAt sets the "ends_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableEndsAt(v *time.Time) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetEndsAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearEndsAt clears the value of the "ends_at" field.
|
||||
func (_u *AnnouncementUpdate) ClearEndsAt() *AnnouncementUpdate {
|
||||
_u.mutation.ClearEndsAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetCreatedBy sets the "created_by" field.
|
||||
func (_u *AnnouncementUpdate) SetCreatedBy(v int64) *AnnouncementUpdate {
|
||||
_u.mutation.ResetCreatedBy()
|
||||
_u.mutation.SetCreatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableCreatedBy sets the "created_by" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableCreatedBy(v *int64) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetCreatedBy(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddCreatedBy adds value to the "created_by" field.
|
||||
func (_u *AnnouncementUpdate) AddCreatedBy(v int64) *AnnouncementUpdate {
|
||||
_u.mutation.AddCreatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearCreatedBy clears the value of the "created_by" field.
|
||||
func (_u *AnnouncementUpdate) ClearCreatedBy() *AnnouncementUpdate {
|
||||
_u.mutation.ClearCreatedBy()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedBy sets the "updated_by" field.
|
||||
func (_u *AnnouncementUpdate) SetUpdatedBy(v int64) *AnnouncementUpdate {
|
||||
_u.mutation.ResetUpdatedBy()
|
||||
_u.mutation.SetUpdatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUpdatedBy sets the "updated_by" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdate) SetNillableUpdatedBy(v *int64) *AnnouncementUpdate {
|
||||
if v != nil {
|
||||
_u.SetUpdatedBy(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddUpdatedBy adds value to the "updated_by" field.
|
||||
func (_u *AnnouncementUpdate) AddUpdatedBy(v int64) *AnnouncementUpdate {
|
||||
_u.mutation.AddUpdatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearUpdatedBy clears the value of the "updated_by" field.
|
||||
func (_u *AnnouncementUpdate) ClearUpdatedBy() *AnnouncementUpdate {
|
||||
_u.mutation.ClearUpdatedBy()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AnnouncementUpdate) SetUpdatedAt(v time.Time) *AnnouncementUpdate {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddReadIDs adds the "reads" edge to the AnnouncementRead entity by IDs.
|
||||
func (_u *AnnouncementUpdate) AddReadIDs(ids ...int64) *AnnouncementUpdate {
|
||||
_u.mutation.AddReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddReads adds the "reads" edges to the AnnouncementRead entity.
|
||||
func (_u *AnnouncementUpdate) AddReads(v ...*AnnouncementRead) *AnnouncementUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddReadIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the AnnouncementMutation object of the builder.
|
||||
func (_u *AnnouncementUpdate) Mutation() *AnnouncementMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearReads clears all "reads" edges to the AnnouncementRead entity.
|
||||
func (_u *AnnouncementUpdate) ClearReads() *AnnouncementUpdate {
|
||||
_u.mutation.ClearReads()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveReadIDs removes the "reads" edge to AnnouncementRead entities by IDs.
|
||||
func (_u *AnnouncementUpdate) RemoveReadIDs(ids ...int64) *AnnouncementUpdate {
|
||||
_u.mutation.RemoveReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveReads removes "reads" edges to AnnouncementRead entities.
|
||||
func (_u *AnnouncementUpdate) RemoveReads(v ...*AnnouncementRead) *AnnouncementUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveReadIDs(ids...)
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *AnnouncementUpdate) Save(ctx context.Context) (int, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AnnouncementUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *AnnouncementUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AnnouncementUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AnnouncementUpdate) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := announcement.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AnnouncementUpdate) check() error {
|
||||
if v, ok := _u.mutation.Title(); ok {
|
||||
if err := announcement.TitleValidator(v); err != nil {
|
||||
return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Announcement.title": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Content(); ok {
|
||||
if err := announcement.ContentValidator(v); err != nil {
|
||||
return &ValidationError{Name: "content", err: fmt.Errorf(`ent: validator failed for field "Announcement.content": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Status(); ok {
|
||||
if err := announcement.StatusValidator(v); err != nil {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Announcement.status": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AnnouncementUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(announcement.Table, announcement.Columns, sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.Title(); ok {
|
||||
_spec.SetField(announcement.FieldTitle, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Content(); ok {
|
||||
_spec.SetField(announcement.FieldContent, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Status(); ok {
|
||||
_spec.SetField(announcement.FieldStatus, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Targeting(); ok {
|
||||
_spec.SetField(announcement.FieldTargeting, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.TargetingCleared() {
|
||||
_spec.ClearField(announcement.FieldTargeting, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.StartsAt(); ok {
|
||||
_spec.SetField(announcement.FieldStartsAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.StartsAtCleared() {
|
||||
_spec.ClearField(announcement.FieldStartsAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.EndsAt(); ok {
|
||||
_spec.SetField(announcement.FieldEndsAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.EndsAtCleared() {
|
||||
_spec.ClearField(announcement.FieldEndsAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.CreatedBy(); ok {
|
||||
_spec.SetField(announcement.FieldCreatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedCreatedBy(); ok {
|
||||
_spec.AddField(announcement.FieldCreatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.CreatedByCleared() {
|
||||
_spec.ClearField(announcement.FieldCreatedBy, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedBy(); ok {
|
||||
_spec.SetField(announcement.FieldUpdatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedUpdatedBy(); ok {
|
||||
_spec.AddField(announcement.FieldUpdatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.UpdatedByCleared() {
|
||||
_spec.ClearField(announcement.FieldUpdatedBy, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(announcement.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.ReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedReadsIDs(); len(nodes) > 0 && !_u.mutation.ReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.ReadsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{announcement.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// AnnouncementUpdateOne is the builder for updating a single Announcement entity.
|
||||
type AnnouncementUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *AnnouncementMutation
|
||||
}
|
||||
|
||||
// SetTitle sets the "title" field.
|
||||
func (_u *AnnouncementUpdateOne) SetTitle(v string) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetTitle(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTitle sets the "title" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableTitle(v *string) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetTitle(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetContent sets the "content" field.
|
||||
func (_u *AnnouncementUpdateOne) SetContent(v string) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetContent(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableContent sets the "content" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableContent(v *string) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetContent(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (_u *AnnouncementUpdateOne) SetStatus(v string) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetStatus(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableStatus sets the "status" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableStatus(v *string) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetStatus(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTargeting sets the "targeting" field.
|
||||
func (_u *AnnouncementUpdateOne) SetTargeting(v domain.AnnouncementTargeting) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetTargeting(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTargeting sets the "targeting" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableTargeting(v *domain.AnnouncementTargeting) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetTargeting(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTargeting clears the value of the "targeting" field.
|
||||
func (_u *AnnouncementUpdateOne) ClearTargeting() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearTargeting()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStartsAt sets the "starts_at" field.
|
||||
func (_u *AnnouncementUpdateOne) SetStartsAt(v time.Time) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetStartsAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableStartsAt sets the "starts_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableStartsAt(v *time.Time) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetStartsAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearStartsAt clears the value of the "starts_at" field.
|
||||
func (_u *AnnouncementUpdateOne) ClearStartsAt() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearStartsAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetEndsAt sets the "ends_at" field.
|
||||
func (_u *AnnouncementUpdateOne) SetEndsAt(v time.Time) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetEndsAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableEndsAt sets the "ends_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableEndsAt(v *time.Time) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetEndsAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearEndsAt clears the value of the "ends_at" field.
|
||||
func (_u *AnnouncementUpdateOne) ClearEndsAt() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearEndsAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetCreatedBy sets the "created_by" field.
|
||||
func (_u *AnnouncementUpdateOne) SetCreatedBy(v int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.ResetCreatedBy()
|
||||
_u.mutation.SetCreatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableCreatedBy sets the "created_by" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableCreatedBy(v *int64) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetCreatedBy(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddCreatedBy adds value to the "created_by" field.
|
||||
func (_u *AnnouncementUpdateOne) AddCreatedBy(v int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.AddCreatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearCreatedBy clears the value of the "created_by" field.
|
||||
func (_u *AnnouncementUpdateOne) ClearCreatedBy() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearCreatedBy()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedBy sets the "updated_by" field.
|
||||
func (_u *AnnouncementUpdateOne) SetUpdatedBy(v int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.ResetUpdatedBy()
|
||||
_u.mutation.SetUpdatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUpdatedBy sets the "updated_by" field if the given value is not nil.
|
||||
func (_u *AnnouncementUpdateOne) SetNillableUpdatedBy(v *int64) *AnnouncementUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetUpdatedBy(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddUpdatedBy adds value to the "updated_by" field.
|
||||
func (_u *AnnouncementUpdateOne) AddUpdatedBy(v int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.AddUpdatedBy(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearUpdatedBy clears the value of the "updated_by" field.
|
||||
func (_u *AnnouncementUpdateOne) ClearUpdatedBy() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearUpdatedBy()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AnnouncementUpdateOne) SetUpdatedAt(v time.Time) *AnnouncementUpdateOne {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddReadIDs adds the "reads" edge to the AnnouncementRead entity by IDs.
|
||||
func (_u *AnnouncementUpdateOne) AddReadIDs(ids ...int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.AddReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddReads adds the "reads" edges to the AnnouncementRead entity.
|
||||
func (_u *AnnouncementUpdateOne) AddReads(v ...*AnnouncementRead) *AnnouncementUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddReadIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the AnnouncementMutation object of the builder.
|
||||
func (_u *AnnouncementUpdateOne) Mutation() *AnnouncementMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearReads clears all "reads" edges to the AnnouncementRead entity.
|
||||
func (_u *AnnouncementUpdateOne) ClearReads() *AnnouncementUpdateOne {
|
||||
_u.mutation.ClearReads()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveReadIDs removes the "reads" edge to AnnouncementRead entities by IDs.
|
||||
func (_u *AnnouncementUpdateOne) RemoveReadIDs(ids ...int64) *AnnouncementUpdateOne {
|
||||
_u.mutation.RemoveReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveReads removes "reads" edges to AnnouncementRead entities.
|
||||
func (_u *AnnouncementUpdateOne) RemoveReads(v ...*AnnouncementRead) *AnnouncementUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveReadIDs(ids...)
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementUpdate builder.
|
||||
func (_u *AnnouncementUpdateOne) Where(ps ...predicate.Announcement) *AnnouncementUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *AnnouncementUpdateOne) Select(field string, fields ...string) *AnnouncementUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated Announcement entity.
|
||||
func (_u *AnnouncementUpdateOne) Save(ctx context.Context) (*Announcement, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AnnouncementUpdateOne) SaveX(ctx context.Context) *Announcement {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *AnnouncementUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AnnouncementUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AnnouncementUpdateOne) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := announcement.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AnnouncementUpdateOne) check() error {
|
||||
if v, ok := _u.mutation.Title(); ok {
|
||||
if err := announcement.TitleValidator(v); err != nil {
|
||||
return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Announcement.title": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Content(); ok {
|
||||
if err := announcement.ContentValidator(v); err != nil {
|
||||
return &ValidationError{Name: "content", err: fmt.Errorf(`ent: validator failed for field "Announcement.content": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Status(); ok {
|
||||
if err := announcement.StatusValidator(v); err != nil {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Announcement.status": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AnnouncementUpdateOne) sqlSave(ctx context.Context) (_node *Announcement, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(announcement.Table, announcement.Columns, sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Announcement.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, announcement.FieldID)
|
||||
for _, f := range fields {
|
||||
if !announcement.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != announcement.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.Title(); ok {
|
||||
_spec.SetField(announcement.FieldTitle, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Content(); ok {
|
||||
_spec.SetField(announcement.FieldContent, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Status(); ok {
|
||||
_spec.SetField(announcement.FieldStatus, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Targeting(); ok {
|
||||
_spec.SetField(announcement.FieldTargeting, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.TargetingCleared() {
|
||||
_spec.ClearField(announcement.FieldTargeting, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.StartsAt(); ok {
|
||||
_spec.SetField(announcement.FieldStartsAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.StartsAtCleared() {
|
||||
_spec.ClearField(announcement.FieldStartsAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.EndsAt(); ok {
|
||||
_spec.SetField(announcement.FieldEndsAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.EndsAtCleared() {
|
||||
_spec.ClearField(announcement.FieldEndsAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.CreatedBy(); ok {
|
||||
_spec.SetField(announcement.FieldCreatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedCreatedBy(); ok {
|
||||
_spec.AddField(announcement.FieldCreatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.CreatedByCleared() {
|
||||
_spec.ClearField(announcement.FieldCreatedBy, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedBy(); ok {
|
||||
_spec.SetField(announcement.FieldUpdatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedUpdatedBy(); ok {
|
||||
_spec.AddField(announcement.FieldUpdatedBy, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.UpdatedByCleared() {
|
||||
_spec.ClearField(announcement.FieldUpdatedBy, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(announcement.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.ReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedReadsIDs(); len(nodes) > 0 && !_u.mutation.ReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.ReadsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: announcement.ReadsTable,
|
||||
Columns: []string{announcement.ReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &Announcement{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{announcement.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
185
backend/ent/announcementread.go
Normal file
185
backend/ent/announcementread.go
Normal file
@@ -0,0 +1,185 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AnnouncementRead is the model entity for the AnnouncementRead schema.
|
||||
type AnnouncementRead struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// AnnouncementID holds the value of the "announcement_id" field.
|
||||
AnnouncementID int64 `json:"announcement_id,omitempty"`
|
||||
// UserID holds the value of the "user_id" field.
|
||||
UserID int64 `json:"user_id,omitempty"`
|
||||
// 用户首次已读时间
|
||||
ReadAt time.Time `json:"read_at,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AnnouncementReadQuery when eager-loading is set.
|
||||
Edges AnnouncementReadEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// AnnouncementReadEdges holds the relations/edges for other nodes in the graph.
|
||||
type AnnouncementReadEdges struct {
|
||||
// Announcement holds the value of the announcement edge.
|
||||
Announcement *Announcement `json:"announcement,omitempty"`
|
||||
// User holds the value of the user edge.
|
||||
User *User `json:"user,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [2]bool
|
||||
}
|
||||
|
||||
// AnnouncementOrErr returns the Announcement value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e AnnouncementReadEdges) AnnouncementOrErr() (*Announcement, error) {
|
||||
if e.Announcement != nil {
|
||||
return e.Announcement, nil
|
||||
} else if e.loadedTypes[0] {
|
||||
return nil, &NotFoundError{label: announcement.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "announcement"}
|
||||
}
|
||||
|
||||
// UserOrErr returns the User value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e AnnouncementReadEdges) UserOrErr() (*User, error) {
|
||||
if e.User != nil {
|
||||
return e.User, nil
|
||||
} else if e.loadedTypes[1] {
|
||||
return nil, &NotFoundError{label: user.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "user"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*AnnouncementRead) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case announcementread.FieldID, announcementread.FieldAnnouncementID, announcementread.FieldUserID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case announcementread.FieldReadAt, announcementread.FieldCreatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the AnnouncementRead fields.
|
||||
func (_m *AnnouncementRead) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case announcementread.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case announcementread.FieldAnnouncementID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field announcement_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.AnnouncementID = value.Int64
|
||||
}
|
||||
case announcementread.FieldUserID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field user_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UserID = value.Int64
|
||||
}
|
||||
case announcementread.FieldReadAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field read_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ReadAt = value.Time
|
||||
}
|
||||
case announcementread.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the AnnouncementRead.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *AnnouncementRead) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryAnnouncement queries the "announcement" edge of the AnnouncementRead entity.
|
||||
func (_m *AnnouncementRead) QueryAnnouncement() *AnnouncementQuery {
|
||||
return NewAnnouncementReadClient(_m.config).QueryAnnouncement(_m)
|
||||
}
|
||||
|
||||
// QueryUser queries the "user" edge of the AnnouncementRead entity.
|
||||
func (_m *AnnouncementRead) QueryUser() *UserQuery {
|
||||
return NewAnnouncementReadClient(_m.config).QueryUser(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this AnnouncementRead.
|
||||
// Note that you need to call AnnouncementRead.Unwrap() before calling this method if this AnnouncementRead
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *AnnouncementRead) Update() *AnnouncementReadUpdateOne {
|
||||
return NewAnnouncementReadClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the AnnouncementRead entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *AnnouncementRead) Unwrap() *AnnouncementRead {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: AnnouncementRead is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *AnnouncementRead) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("AnnouncementRead(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("announcement_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.AnnouncementID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("user_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.UserID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("read_at=")
|
||||
builder.WriteString(_m.ReadAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// AnnouncementReads is a parsable slice of AnnouncementRead.
|
||||
type AnnouncementReads []*AnnouncementRead
|
||||
127
backend/ent/announcementread/announcementread.go
Normal file
127
backend/ent/announcementread/announcementread.go
Normal file
@@ -0,0 +1,127 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package announcementread
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the announcementread type in the database.
|
||||
Label = "announcement_read"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldAnnouncementID holds the string denoting the announcement_id field in the database.
|
||||
FieldAnnouncementID = "announcement_id"
|
||||
// FieldUserID holds the string denoting the user_id field in the database.
|
||||
FieldUserID = "user_id"
|
||||
// FieldReadAt holds the string denoting the read_at field in the database.
|
||||
FieldReadAt = "read_at"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// EdgeAnnouncement holds the string denoting the announcement edge name in mutations.
|
||||
EdgeAnnouncement = "announcement"
|
||||
// EdgeUser holds the string denoting the user edge name in mutations.
|
||||
EdgeUser = "user"
|
||||
// Table holds the table name of the announcementread in the database.
|
||||
Table = "announcement_reads"
|
||||
// AnnouncementTable is the table that holds the announcement relation/edge.
|
||||
AnnouncementTable = "announcement_reads"
|
||||
// AnnouncementInverseTable is the table name for the Announcement entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "announcement" package.
|
||||
AnnouncementInverseTable = "announcements"
|
||||
// AnnouncementColumn is the table column denoting the announcement relation/edge.
|
||||
AnnouncementColumn = "announcement_id"
|
||||
// UserTable is the table that holds the user relation/edge.
|
||||
UserTable = "announcement_reads"
|
||||
// UserInverseTable is the table name for the User entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "user" package.
|
||||
UserInverseTable = "users"
|
||||
// UserColumn is the table column denoting the user relation/edge.
|
||||
UserColumn = "user_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for announcementread fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldAnnouncementID,
|
||||
FieldUserID,
|
||||
FieldReadAt,
|
||||
FieldCreatedAt,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultReadAt holds the default value on creation for the "read_at" field.
|
||||
DefaultReadAt func() time.Time
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the AnnouncementRead queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAnnouncementID orders the results by the announcement_id field.
|
||||
func ByAnnouncementID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldAnnouncementID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUserID orders the results by the user_id field.
|
||||
func ByUserID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUserID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByReadAt orders the results by the read_at field.
|
||||
func ByReadAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldReadAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAnnouncementField orders the results by announcement field.
|
||||
func ByAnnouncementField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newAnnouncementStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
|
||||
// ByUserField orders the results by user field.
|
||||
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
func newAnnouncementStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(AnnouncementInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, AnnouncementTable, AnnouncementColumn),
|
||||
)
|
||||
}
|
||||
func newUserStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(UserInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
||||
)
|
||||
}
|
||||
257
backend/ent/announcementread/where.go
Normal file
257
backend/ent/announcementread/where.go
Normal file
@@ -0,0 +1,257 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package announcementread
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// AnnouncementID applies equality check predicate on the "announcement_id" field. It's identical to AnnouncementIDEQ.
|
||||
func AnnouncementID(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldAnnouncementID, v))
|
||||
}
|
||||
|
||||
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
|
||||
func UserID(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// ReadAt applies equality check predicate on the "read_at" field. It's identical to ReadAtEQ.
|
||||
func ReadAt(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// AnnouncementIDEQ applies the EQ predicate on the "announcement_id" field.
|
||||
func AnnouncementIDEQ(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldAnnouncementID, v))
|
||||
}
|
||||
|
||||
// AnnouncementIDNEQ applies the NEQ predicate on the "announcement_id" field.
|
||||
func AnnouncementIDNEQ(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNEQ(FieldAnnouncementID, v))
|
||||
}
|
||||
|
||||
// AnnouncementIDIn applies the In predicate on the "announcement_id" field.
|
||||
func AnnouncementIDIn(vs ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldIn(FieldAnnouncementID, vs...))
|
||||
}
|
||||
|
||||
// AnnouncementIDNotIn applies the NotIn predicate on the "announcement_id" field.
|
||||
func AnnouncementIDNotIn(vs ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNotIn(FieldAnnouncementID, vs...))
|
||||
}
|
||||
|
||||
// UserIDEQ applies the EQ predicate on the "user_id" field.
|
||||
func UserIDEQ(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
|
||||
func UserIDNEQ(v int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// UserIDIn applies the In predicate on the "user_id" field.
|
||||
func UserIDIn(vs ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldIn(FieldUserID, vs...))
|
||||
}
|
||||
|
||||
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
|
||||
func UserIDNotIn(vs ...int64) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNotIn(FieldUserID, vs...))
|
||||
}
|
||||
|
||||
// ReadAtEQ applies the EQ predicate on the "read_at" field.
|
||||
func ReadAtEQ(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// ReadAtNEQ applies the NEQ predicate on the "read_at" field.
|
||||
func ReadAtNEQ(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNEQ(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// ReadAtIn applies the In predicate on the "read_at" field.
|
||||
func ReadAtIn(vs ...time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldIn(FieldReadAt, vs...))
|
||||
}
|
||||
|
||||
// ReadAtNotIn applies the NotIn predicate on the "read_at" field.
|
||||
func ReadAtNotIn(vs ...time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNotIn(FieldReadAt, vs...))
|
||||
}
|
||||
|
||||
// ReadAtGT applies the GT predicate on the "read_at" field.
|
||||
func ReadAtGT(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGT(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// ReadAtGTE applies the GTE predicate on the "read_at" field.
|
||||
func ReadAtGTE(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGTE(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// ReadAtLT applies the LT predicate on the "read_at" field.
|
||||
func ReadAtLT(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLT(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// ReadAtLTE applies the LTE predicate on the "read_at" field.
|
||||
func ReadAtLTE(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLTE(FieldReadAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// HasAnnouncement applies the HasEdge predicate on the "announcement" edge.
|
||||
func HasAnnouncement() predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, AnnouncementTable, AnnouncementColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasAnnouncementWith applies the HasEdge predicate on the "announcement" edge with a given conditions (other predicates).
|
||||
func HasAnnouncementWith(preds ...predicate.Announcement) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
step := newAnnouncementStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasUser applies the HasEdge predicate on the "user" edge.
|
||||
func HasUser() predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
|
||||
func HasUserWith(preds ...predicate.User) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
step := newUserStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.AnnouncementRead) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.AnnouncementRead) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.AnnouncementRead) predicate.AnnouncementRead {
|
||||
return predicate.AnnouncementRead(sql.NotPredicates(p))
|
||||
}
|
||||
660
backend/ent/announcementread_create.go
Normal file
660
backend/ent/announcementread_create.go
Normal file
@@ -0,0 +1,660 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AnnouncementReadCreate is the builder for creating a AnnouncementRead entity.
|
||||
type AnnouncementReadCreate struct {
|
||||
config
|
||||
mutation *AnnouncementReadMutation
|
||||
hooks []Hook
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (_c *AnnouncementReadCreate) SetAnnouncementID(v int64) *AnnouncementReadCreate {
|
||||
_c.mutation.SetAnnouncementID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (_c *AnnouncementReadCreate) SetUserID(v int64) *AnnouncementReadCreate {
|
||||
_c.mutation.SetUserID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (_c *AnnouncementReadCreate) SetReadAt(v time.Time) *AnnouncementReadCreate {
|
||||
_c.mutation.SetReadAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableReadAt sets the "read_at" field if the given value is not nil.
|
||||
func (_c *AnnouncementReadCreate) SetNillableReadAt(v *time.Time) *AnnouncementReadCreate {
|
||||
if v != nil {
|
||||
_c.SetReadAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (_c *AnnouncementReadCreate) SetCreatedAt(v time.Time) *AnnouncementReadCreate {
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (_c *AnnouncementReadCreate) SetNillableCreatedAt(v *time.Time) *AnnouncementReadCreate {
|
||||
if v != nil {
|
||||
_c.SetCreatedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetAnnouncement sets the "announcement" edge to the Announcement entity.
|
||||
func (_c *AnnouncementReadCreate) SetAnnouncement(v *Announcement) *AnnouncementReadCreate {
|
||||
return _c.SetAnnouncementID(v.ID)
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_c *AnnouncementReadCreate) SetUser(v *User) *AnnouncementReadCreate {
|
||||
return _c.SetUserID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AnnouncementReadMutation object of the builder.
|
||||
func (_c *AnnouncementReadCreate) Mutation() *AnnouncementReadMutation {
|
||||
return _c.mutation
|
||||
}
|
||||
|
||||
// Save creates the AnnouncementRead in the database.
|
||||
func (_c *AnnouncementReadCreate) Save(ctx context.Context) (*AnnouncementRead, error) {
|
||||
_c.defaults()
|
||||
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (_c *AnnouncementReadCreate) SaveX(ctx context.Context) *AnnouncementRead {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *AnnouncementReadCreate) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *AnnouncementReadCreate) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_c *AnnouncementReadCreate) defaults() {
|
||||
if _, ok := _c.mutation.ReadAt(); !ok {
|
||||
v := announcementread.DefaultReadAt()
|
||||
_c.mutation.SetReadAt(v)
|
||||
}
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
v := announcementread.DefaultCreatedAt()
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_c *AnnouncementReadCreate) check() error {
|
||||
if _, ok := _c.mutation.AnnouncementID(); !ok {
|
||||
return &ValidationError{Name: "announcement_id", err: errors.New(`ent: missing required field "AnnouncementRead.announcement_id"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.UserID(); !ok {
|
||||
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "AnnouncementRead.user_id"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.ReadAt(); !ok {
|
||||
return &ValidationError{Name: "read_at", err: errors.New(`ent: missing required field "AnnouncementRead.read_at"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "AnnouncementRead.created_at"`)}
|
||||
}
|
||||
if len(_c.mutation.AnnouncementIDs()) == 0 {
|
||||
return &ValidationError{Name: "announcement", err: errors.New(`ent: missing required edge "AnnouncementRead.announcement"`)}
|
||||
}
|
||||
if len(_c.mutation.UserIDs()) == 0 {
|
||||
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "AnnouncementRead.user"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_c *AnnouncementReadCreate) sqlSave(ctx context.Context) (*AnnouncementRead, error) {
|
||||
if err := _c.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_node, _spec := _c.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
id := _spec.ID.Value.(int64)
|
||||
_node.ID = int64(id)
|
||||
_c.mutation.id = &_node.ID
|
||||
_c.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (_c *AnnouncementReadCreate) createSpec() (*AnnouncementRead, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &AnnouncementRead{config: _c.config}
|
||||
_spec = sqlgraph.NewCreateSpec(announcementread.Table, sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64))
|
||||
)
|
||||
_spec.OnConflict = _c.conflict
|
||||
if value, ok := _c.mutation.ReadAt(); ok {
|
||||
_spec.SetField(announcementread.FieldReadAt, field.TypeTime, value)
|
||||
_node.ReadAt = value
|
||||
}
|
||||
if value, ok := _c.mutation.CreatedAt(); ok {
|
||||
_spec.SetField(announcementread.FieldCreatedAt, field.TypeTime, value)
|
||||
_node.CreatedAt = value
|
||||
}
|
||||
if nodes := _c.mutation.AnnouncementIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.AnnouncementTable,
|
||||
Columns: []string{announcementread.AnnouncementColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.AnnouncementID = nodes[0]
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.UserTable,
|
||||
Columns: []string{announcementread.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.UserID = nodes[0]
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// SetAnnouncementID(v).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.AnnouncementReadUpsert) {
|
||||
// SetAnnouncementID(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *AnnouncementReadCreate) OnConflict(opts ...sql.ConflictOption) *AnnouncementReadUpsertOne {
|
||||
_c.conflict = opts
|
||||
return &AnnouncementReadUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *AnnouncementReadCreate) OnConflictColumns(columns ...string) *AnnouncementReadUpsertOne {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &AnnouncementReadUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// AnnouncementReadUpsertOne is the builder for "upsert"-ing
|
||||
// one AnnouncementRead node.
|
||||
AnnouncementReadUpsertOne struct {
|
||||
create *AnnouncementReadCreate
|
||||
}
|
||||
|
||||
// AnnouncementReadUpsert is the "OnConflict" setter.
|
||||
AnnouncementReadUpsert struct {
|
||||
*sql.UpdateSet
|
||||
}
|
||||
)
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (u *AnnouncementReadUpsert) SetAnnouncementID(v int64) *AnnouncementReadUpsert {
|
||||
u.Set(announcementread.FieldAnnouncementID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateAnnouncementID sets the "announcement_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsert) UpdateAnnouncementID() *AnnouncementReadUpsert {
|
||||
u.SetExcluded(announcementread.FieldAnnouncementID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (u *AnnouncementReadUpsert) SetUserID(v int64) *AnnouncementReadUpsert {
|
||||
u.Set(announcementread.FieldUserID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsert) UpdateUserID() *AnnouncementReadUpsert {
|
||||
u.SetExcluded(announcementread.FieldUserID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (u *AnnouncementReadUpsert) SetReadAt(v time.Time) *AnnouncementReadUpsert {
|
||||
u.Set(announcementread.FieldReadAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateReadAt sets the "read_at" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsert) UpdateReadAt() *AnnouncementReadUpsert {
|
||||
u.SetExcluded(announcementread.FieldReadAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AnnouncementReadUpsertOne) UpdateNewValues() *AnnouncementReadUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(announcementread.FieldCreatedAt)
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AnnouncementReadUpsertOne) Ignore() *AnnouncementReadUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *AnnouncementReadUpsertOne) DoNothing() *AnnouncementReadUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AnnouncementReadCreate.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AnnouncementReadUpsertOne) Update(set func(*AnnouncementReadUpsert)) *AnnouncementReadUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AnnouncementReadUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (u *AnnouncementReadUpsertOne) SetAnnouncementID(v int64) *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetAnnouncementID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAnnouncementID sets the "announcement_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertOne) UpdateAnnouncementID() *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateAnnouncementID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (u *AnnouncementReadUpsertOne) SetUserID(v int64) *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetUserID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertOne) UpdateUserID() *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateUserID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (u *AnnouncementReadUpsertOne) SetReadAt(v time.Time) *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetReadAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateReadAt sets the "read_at" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertOne) UpdateReadAt() *AnnouncementReadUpsertOne {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateReadAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AnnouncementReadUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AnnouncementReadCreate.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AnnouncementReadUpsertOne) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
||||
func (u *AnnouncementReadUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
||||
node, err := u.create.Save(ctx)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return node.ID, nil
|
||||
}
|
||||
|
||||
// IDX is like ID, but panics if an error occurs.
|
||||
func (u *AnnouncementReadUpsertOne) IDX(ctx context.Context) int64 {
|
||||
id, err := u.ID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// AnnouncementReadCreateBulk is the builder for creating many AnnouncementRead entities in bulk.
|
||||
type AnnouncementReadCreateBulk struct {
|
||||
config
|
||||
err error
|
||||
builders []*AnnouncementReadCreate
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// Save creates the AnnouncementRead entities in the database.
|
||||
func (_c *AnnouncementReadCreateBulk) Save(ctx context.Context) ([]*AnnouncementRead, error) {
|
||||
if _c.err != nil {
|
||||
return nil, _c.err
|
||||
}
|
||||
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
|
||||
nodes := make([]*AnnouncementRead, len(_c.builders))
|
||||
mutators := make([]Mutator, len(_c.builders))
|
||||
for i := range _c.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := _c.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*AnnouncementReadMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err := builder.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.mutation = mutation
|
||||
var err error
|
||||
nodes[i], specs[i] = builder.createSpec()
|
||||
if i < len(mutators)-1 {
|
||||
_, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
spec.OnConflict = _c.conflict
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &nodes[i].ID
|
||||
if specs[i].ID.Value != nil {
|
||||
id := specs[i].ID.Value.(int64)
|
||||
nodes[i].ID = int64(id)
|
||||
}
|
||||
mutation.done = true
|
||||
return nodes[i], nil
|
||||
})
|
||||
for i := len(builder.hooks) - 1; i >= 0; i-- {
|
||||
mut = builder.hooks[i](mut)
|
||||
}
|
||||
mutators[i] = mut
|
||||
}(i, ctx)
|
||||
}
|
||||
if len(mutators) > 0 {
|
||||
if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_c *AnnouncementReadCreateBulk) SaveX(ctx context.Context) []*AnnouncementRead {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *AnnouncementReadCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *AnnouncementReadCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.AnnouncementRead.CreateBulk(builders...).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.AnnouncementReadUpsert) {
|
||||
// SetAnnouncementID(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *AnnouncementReadCreateBulk) OnConflict(opts ...sql.ConflictOption) *AnnouncementReadUpsertBulk {
|
||||
_c.conflict = opts
|
||||
return &AnnouncementReadUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *AnnouncementReadCreateBulk) OnConflictColumns(columns ...string) *AnnouncementReadUpsertBulk {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &AnnouncementReadUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// AnnouncementReadUpsertBulk is the builder for "upsert"-ing
|
||||
// a bulk of AnnouncementRead nodes.
|
||||
type AnnouncementReadUpsertBulk struct {
|
||||
create *AnnouncementReadCreateBulk
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that
|
||||
// were set on create. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AnnouncementReadUpsertBulk) UpdateNewValues() *AnnouncementReadUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
for _, b := range u.create.builders {
|
||||
if _, exists := b.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(announcementread.FieldCreatedAt)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AnnouncementRead.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AnnouncementReadUpsertBulk) Ignore() *AnnouncementReadUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *AnnouncementReadUpsertBulk) DoNothing() *AnnouncementReadUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AnnouncementReadCreateBulk.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AnnouncementReadUpsertBulk) Update(set func(*AnnouncementReadUpsert)) *AnnouncementReadUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AnnouncementReadUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (u *AnnouncementReadUpsertBulk) SetAnnouncementID(v int64) *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetAnnouncementID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAnnouncementID sets the "announcement_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertBulk) UpdateAnnouncementID() *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateAnnouncementID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (u *AnnouncementReadUpsertBulk) SetUserID(v int64) *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetUserID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertBulk) UpdateUserID() *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateUserID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (u *AnnouncementReadUpsertBulk) SetReadAt(v time.Time) *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.SetReadAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateReadAt sets the "read_at" field to the value that was provided on create.
|
||||
func (u *AnnouncementReadUpsertBulk) UpdateReadAt() *AnnouncementReadUpsertBulk {
|
||||
return u.Update(func(s *AnnouncementReadUpsert) {
|
||||
s.UpdateReadAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AnnouncementReadUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
return u.create.err
|
||||
}
|
||||
for i, b := range u.create.builders {
|
||||
if len(b.conflict) != 0 {
|
||||
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the AnnouncementReadCreateBulk instead", i)
|
||||
}
|
||||
}
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AnnouncementReadCreateBulk.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AnnouncementReadUpsertBulk) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
88
backend/ent/announcementread_delete.go
Normal file
88
backend/ent/announcementread_delete.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AnnouncementReadDelete is the builder for deleting a AnnouncementRead entity.
|
||||
type AnnouncementReadDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AnnouncementReadMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementReadDelete builder.
|
||||
func (_d *AnnouncementReadDelete) Where(ps ...predicate.AnnouncementRead) *AnnouncementReadDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *AnnouncementReadDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AnnouncementReadDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *AnnouncementReadDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(announcementread.Table, sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// AnnouncementReadDeleteOne is the builder for deleting a single AnnouncementRead entity.
|
||||
type AnnouncementReadDeleteOne struct {
|
||||
_d *AnnouncementReadDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementReadDelete builder.
|
||||
func (_d *AnnouncementReadDeleteOne) Where(ps ...predicate.AnnouncementRead) *AnnouncementReadDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *AnnouncementReadDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{announcementread.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AnnouncementReadDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
718
backend/ent/announcementread_query.go
Normal file
718
backend/ent/announcementread_query.go
Normal file
@@ -0,0 +1,718 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AnnouncementReadQuery is the builder for querying AnnouncementRead entities.
|
||||
type AnnouncementReadQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []announcementread.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.AnnouncementRead
|
||||
withAnnouncement *AnnouncementQuery
|
||||
withUser *UserQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the AnnouncementReadQuery builder.
|
||||
func (_q *AnnouncementReadQuery) Where(ps ...predicate.AnnouncementRead) *AnnouncementReadQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *AnnouncementReadQuery) Limit(limit int) *AnnouncementReadQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *AnnouncementReadQuery) Offset(offset int) *AnnouncementReadQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *AnnouncementReadQuery) Unique(unique bool) *AnnouncementReadQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *AnnouncementReadQuery) Order(o ...announcementread.OrderOption) *AnnouncementReadQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryAnnouncement chains the current query on the "announcement" edge.
|
||||
func (_q *AnnouncementReadQuery) QueryAnnouncement() *AnnouncementQuery {
|
||||
query := (&AnnouncementClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcementread.Table, announcementread.FieldID, selector),
|
||||
sqlgraph.To(announcement.Table, announcement.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, announcementread.AnnouncementTable, announcementread.AnnouncementColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryUser chains the current query on the "user" edge.
|
||||
func (_q *AnnouncementReadQuery) QueryUser() *UserQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcementread.Table, announcementread.FieldID, selector),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, announcementread.UserTable, announcementread.UserColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first AnnouncementRead entity from the query.
|
||||
// Returns a *NotFoundError when no AnnouncementRead was found.
|
||||
func (_q *AnnouncementReadQuery) First(ctx context.Context) (*AnnouncementRead, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{announcementread.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) FirstX(ctx context.Context) *AnnouncementRead {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first AnnouncementRead ID from the query.
|
||||
// Returns a *NotFoundError when no AnnouncementRead ID was found.
|
||||
func (_q *AnnouncementReadQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{announcementread.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single AnnouncementRead entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one AnnouncementRead entity is found.
|
||||
// Returns a *NotFoundError when no AnnouncementRead entities are found.
|
||||
func (_q *AnnouncementReadQuery) Only(ctx context.Context) (*AnnouncementRead, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{announcementread.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{announcementread.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) OnlyX(ctx context.Context) *AnnouncementRead {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only AnnouncementRead ID in the query.
|
||||
// Returns a *NotSingularError when more than one AnnouncementRead ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *AnnouncementReadQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{announcementread.Label}
|
||||
default:
|
||||
err = &NotSingularError{announcementread.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of AnnouncementReads.
|
||||
func (_q *AnnouncementReadQuery) All(ctx context.Context) ([]*AnnouncementRead, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*AnnouncementRead, *AnnouncementReadQuery]()
|
||||
return withInterceptors[[]*AnnouncementRead](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) AllX(ctx context.Context) []*AnnouncementRead {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of AnnouncementRead IDs.
|
||||
func (_q *AnnouncementReadQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(announcementread.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *AnnouncementReadQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*AnnouncementReadQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *AnnouncementReadQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *AnnouncementReadQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the AnnouncementReadQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *AnnouncementReadQuery) Clone() *AnnouncementReadQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &AnnouncementReadQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]announcementread.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.AnnouncementRead{}, _q.predicates...),
|
||||
withAnnouncement: _q.withAnnouncement.Clone(),
|
||||
withUser: _q.withUser.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithAnnouncement tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "announcement" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AnnouncementReadQuery) WithAnnouncement(opts ...func(*AnnouncementQuery)) *AnnouncementReadQuery {
|
||||
query := (&AnnouncementClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withAnnouncement = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithUser tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AnnouncementReadQuery) WithUser(opts ...func(*UserQuery)) *AnnouncementReadQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withUser = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// AnnouncementID int64 `json:"announcement_id,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AnnouncementRead.Query().
|
||||
// GroupBy(announcementread.FieldAnnouncementID).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AnnouncementReadQuery) GroupBy(field string, fields ...string) *AnnouncementReadGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &AnnouncementReadGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = announcementread.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// AnnouncementID int64 `json:"announcement_id,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AnnouncementRead.Query().
|
||||
// Select(announcementread.FieldAnnouncementID).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AnnouncementReadQuery) Select(fields ...string) *AnnouncementReadSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &AnnouncementReadSelect{AnnouncementReadQuery: _q}
|
||||
sbuild.label = announcementread.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a AnnouncementReadSelect configured with the given aggregations.
|
||||
func (_q *AnnouncementReadQuery) Aggregate(fns ...AggregateFunc) *AnnouncementReadSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !announcementread.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AnnouncementRead, error) {
|
||||
var (
|
||||
nodes = []*AnnouncementRead{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [2]bool{
|
||||
_q.withAnnouncement != nil,
|
||||
_q.withUser != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*AnnouncementRead).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &AnnouncementRead{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withAnnouncement; query != nil {
|
||||
if err := _q.loadAnnouncement(ctx, query, nodes, nil,
|
||||
func(n *AnnouncementRead, e *Announcement) { n.Edges.Announcement = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withUser; query != nil {
|
||||
if err := _q.loadUser(ctx, query, nodes, nil,
|
||||
func(n *AnnouncementRead, e *User) { n.Edges.User = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) loadAnnouncement(ctx context.Context, query *AnnouncementQuery, nodes []*AnnouncementRead, init func(*AnnouncementRead), assign func(*AnnouncementRead, *Announcement)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*AnnouncementRead)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].AnnouncementID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(announcement.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "announcement_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *AnnouncementReadQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*AnnouncementRead, init func(*AnnouncementRead), assign func(*AnnouncementRead, *User)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*AnnouncementRead)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].UserID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(user.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "user_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(announcementread.Table, announcementread.Columns, sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, announcementread.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != announcementread.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if _q.withAnnouncement != nil {
|
||||
_spec.Node.AddColumnOnce(announcementread.FieldAnnouncementID)
|
||||
}
|
||||
if _q.withUser != nil {
|
||||
_spec.Node.AddColumnOnce(announcementread.FieldUserID)
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *AnnouncementReadQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(announcementread.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = announcementread.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *AnnouncementReadQuery) ForUpdate(opts ...sql.LockOption) *AnnouncementReadQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *AnnouncementReadQuery) ForShare(opts ...sql.LockOption) *AnnouncementReadQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// AnnouncementReadGroupBy is the group-by builder for AnnouncementRead entities.
|
||||
type AnnouncementReadGroupBy struct {
|
||||
selector
|
||||
build *AnnouncementReadQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *AnnouncementReadGroupBy) Aggregate(fns ...AggregateFunc) *AnnouncementReadGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *AnnouncementReadGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AnnouncementReadQuery, *AnnouncementReadGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *AnnouncementReadGroupBy) sqlScan(ctx context.Context, root *AnnouncementReadQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// AnnouncementReadSelect is the builder for selecting fields of AnnouncementRead entities.
|
||||
type AnnouncementReadSelect struct {
|
||||
*AnnouncementReadQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *AnnouncementReadSelect) Aggregate(fns ...AggregateFunc) *AnnouncementReadSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *AnnouncementReadSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AnnouncementReadQuery, *AnnouncementReadSelect](ctx, _s.AnnouncementReadQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *AnnouncementReadSelect) sqlScan(ctx context.Context, root *AnnouncementReadQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
456
backend/ent/announcementread_update.go
Normal file
456
backend/ent/announcementread_update.go
Normal file
@@ -0,0 +1,456 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AnnouncementReadUpdate is the builder for updating AnnouncementRead entities.
|
||||
type AnnouncementReadUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AnnouncementReadMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementReadUpdate builder.
|
||||
func (_u *AnnouncementReadUpdate) Where(ps ...predicate.AnnouncementRead) *AnnouncementReadUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (_u *AnnouncementReadUpdate) SetAnnouncementID(v int64) *AnnouncementReadUpdate {
|
||||
_u.mutation.SetAnnouncementID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAnnouncementID sets the "announcement_id" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdate) SetNillableAnnouncementID(v *int64) *AnnouncementReadUpdate {
|
||||
if v != nil {
|
||||
_u.SetAnnouncementID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (_u *AnnouncementReadUpdate) SetUserID(v int64) *AnnouncementReadUpdate {
|
||||
_u.mutation.SetUserID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdate) SetNillableUserID(v *int64) *AnnouncementReadUpdate {
|
||||
if v != nil {
|
||||
_u.SetUserID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (_u *AnnouncementReadUpdate) SetReadAt(v time.Time) *AnnouncementReadUpdate {
|
||||
_u.mutation.SetReadAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableReadAt sets the "read_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdate) SetNillableReadAt(v *time.Time) *AnnouncementReadUpdate {
|
||||
if v != nil {
|
||||
_u.SetReadAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAnnouncement sets the "announcement" edge to the Announcement entity.
|
||||
func (_u *AnnouncementReadUpdate) SetAnnouncement(v *Announcement) *AnnouncementReadUpdate {
|
||||
return _u.SetAnnouncementID(v.ID)
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *AnnouncementReadUpdate) SetUser(v *User) *AnnouncementReadUpdate {
|
||||
return _u.SetUserID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AnnouncementReadMutation object of the builder.
|
||||
func (_u *AnnouncementReadUpdate) Mutation() *AnnouncementReadMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearAnnouncement clears the "announcement" edge to the Announcement entity.
|
||||
func (_u *AnnouncementReadUpdate) ClearAnnouncement() *AnnouncementReadUpdate {
|
||||
_u.mutation.ClearAnnouncement()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearUser clears the "user" edge to the User entity.
|
||||
func (_u *AnnouncementReadUpdate) ClearUser() *AnnouncementReadUpdate {
|
||||
_u.mutation.ClearUser()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *AnnouncementReadUpdate) Save(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AnnouncementReadUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *AnnouncementReadUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AnnouncementReadUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AnnouncementReadUpdate) check() error {
|
||||
if _u.mutation.AnnouncementCleared() && len(_u.mutation.AnnouncementIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AnnouncementRead.announcement"`)
|
||||
}
|
||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AnnouncementRead.user"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AnnouncementReadUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(announcementread.Table, announcementread.Columns, sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.ReadAt(); ok {
|
||||
_spec.SetField(announcementread.FieldReadAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.AnnouncementCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.AnnouncementTable,
|
||||
Columns: []string{announcementread.AnnouncementColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AnnouncementIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.AnnouncementTable,
|
||||
Columns: []string{announcementread.AnnouncementColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.UserTable,
|
||||
Columns: []string{announcementread.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.UserTable,
|
||||
Columns: []string{announcementread.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{announcementread.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// AnnouncementReadUpdateOne is the builder for updating a single AnnouncementRead entity.
|
||||
type AnnouncementReadUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *AnnouncementReadMutation
|
||||
}
|
||||
|
||||
// SetAnnouncementID sets the "announcement_id" field.
|
||||
func (_u *AnnouncementReadUpdateOne) SetAnnouncementID(v int64) *AnnouncementReadUpdateOne {
|
||||
_u.mutation.SetAnnouncementID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAnnouncementID sets the "announcement_id" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdateOne) SetNillableAnnouncementID(v *int64) *AnnouncementReadUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetAnnouncementID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (_u *AnnouncementReadUpdateOne) SetUserID(v int64) *AnnouncementReadUpdateOne {
|
||||
_u.mutation.SetUserID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdateOne) SetNillableUserID(v *int64) *AnnouncementReadUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetUserID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetReadAt sets the "read_at" field.
|
||||
func (_u *AnnouncementReadUpdateOne) SetReadAt(v time.Time) *AnnouncementReadUpdateOne {
|
||||
_u.mutation.SetReadAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableReadAt sets the "read_at" field if the given value is not nil.
|
||||
func (_u *AnnouncementReadUpdateOne) SetNillableReadAt(v *time.Time) *AnnouncementReadUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetReadAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAnnouncement sets the "announcement" edge to the Announcement entity.
|
||||
func (_u *AnnouncementReadUpdateOne) SetAnnouncement(v *Announcement) *AnnouncementReadUpdateOne {
|
||||
return _u.SetAnnouncementID(v.ID)
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *AnnouncementReadUpdateOne) SetUser(v *User) *AnnouncementReadUpdateOne {
|
||||
return _u.SetUserID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AnnouncementReadMutation object of the builder.
|
||||
func (_u *AnnouncementReadUpdateOne) Mutation() *AnnouncementReadMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearAnnouncement clears the "announcement" edge to the Announcement entity.
|
||||
func (_u *AnnouncementReadUpdateOne) ClearAnnouncement() *AnnouncementReadUpdateOne {
|
||||
_u.mutation.ClearAnnouncement()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearUser clears the "user" edge to the User entity.
|
||||
func (_u *AnnouncementReadUpdateOne) ClearUser() *AnnouncementReadUpdateOne {
|
||||
_u.mutation.ClearUser()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AnnouncementReadUpdate builder.
|
||||
func (_u *AnnouncementReadUpdateOne) Where(ps ...predicate.AnnouncementRead) *AnnouncementReadUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *AnnouncementReadUpdateOne) Select(field string, fields ...string) *AnnouncementReadUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated AnnouncementRead entity.
|
||||
func (_u *AnnouncementReadUpdateOne) Save(ctx context.Context) (*AnnouncementRead, error) {
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AnnouncementReadUpdateOne) SaveX(ctx context.Context) *AnnouncementRead {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *AnnouncementReadUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AnnouncementReadUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AnnouncementReadUpdateOne) check() error {
|
||||
if _u.mutation.AnnouncementCleared() && len(_u.mutation.AnnouncementIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AnnouncementRead.announcement"`)
|
||||
}
|
||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AnnouncementRead.user"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AnnouncementReadUpdateOne) sqlSave(ctx context.Context) (_node *AnnouncementRead, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(announcementread.Table, announcementread.Columns, sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AnnouncementRead.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, announcementread.FieldID)
|
||||
for _, f := range fields {
|
||||
if !announcementread.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != announcementread.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.ReadAt(); ok {
|
||||
_spec.SetField(announcementread.FieldReadAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.AnnouncementCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.AnnouncementTable,
|
||||
Columns: []string{announcementread.AnnouncementColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AnnouncementIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.AnnouncementTable,
|
||||
Columns: []string{announcementread.AnnouncementColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcement.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.UserTable,
|
||||
Columns: []string{announcementread.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: announcementread.UserTable,
|
||||
Columns: []string{announcementread.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &AnnouncementRead{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{announcementread.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
@@ -40,6 +40,12 @@ type APIKey struct {
|
||||
IPWhitelist []string `json:"ip_whitelist,omitempty"`
|
||||
// Blocked IPs/CIDRs
|
||||
IPBlacklist []string `json:"ip_blacklist,omitempty"`
|
||||
// Quota limit in USD for this API key (0 = unlimited)
|
||||
Quota float64 `json:"quota,omitempty"`
|
||||
// Used quota amount in USD
|
||||
QuotaUsed float64 `json:"quota_used,omitempty"`
|
||||
// Expiration time for this API key (null = never expires)
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the APIKeyQuery when eager-loading is set.
|
||||
Edges APIKeyEdges `json:"edges"`
|
||||
@@ -97,11 +103,13 @@ func (*APIKey) scanValues(columns []string) ([]any, error) {
|
||||
switch columns[i] {
|
||||
case apikey.FieldIPWhitelist, apikey.FieldIPBlacklist:
|
||||
values[i] = new([]byte)
|
||||
case apikey.FieldQuota, apikey.FieldQuotaUsed:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
case apikey.FieldID, apikey.FieldUserID, apikey.FieldGroupID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case apikey.FieldKey, apikey.FieldName, apikey.FieldStatus:
|
||||
values[i] = new(sql.NullString)
|
||||
case apikey.FieldCreatedAt, apikey.FieldUpdatedAt, apikey.FieldDeletedAt:
|
||||
case apikey.FieldCreatedAt, apikey.FieldUpdatedAt, apikey.FieldDeletedAt, apikey.FieldExpiresAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
@@ -190,6 +198,25 @@ func (_m *APIKey) assignValues(columns []string, values []any) error {
|
||||
return fmt.Errorf("unmarshal field ip_blacklist: %w", err)
|
||||
}
|
||||
}
|
||||
case apikey.FieldQuota:
|
||||
if value, ok := values[i].(*sql.NullFloat64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field quota", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Quota = value.Float64
|
||||
}
|
||||
case apikey.FieldQuotaUsed:
|
||||
if value, ok := values[i].(*sql.NullFloat64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field quota_used", values[i])
|
||||
} else if value.Valid {
|
||||
_m.QuotaUsed = value.Float64
|
||||
}
|
||||
case apikey.FieldExpiresAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field expires_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ExpiresAt = new(time.Time)
|
||||
*_m.ExpiresAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
@@ -274,6 +301,17 @@ func (_m *APIKey) String() string {
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("ip_blacklist=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.IPBlacklist))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("quota=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Quota))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("quota_used=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.QuotaUsed))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.ExpiresAt; v != nil {
|
||||
builder.WriteString("expires_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ const (
|
||||
FieldIPWhitelist = "ip_whitelist"
|
||||
// FieldIPBlacklist holds the string denoting the ip_blacklist field in the database.
|
||||
FieldIPBlacklist = "ip_blacklist"
|
||||
// FieldQuota holds the string denoting the quota field in the database.
|
||||
FieldQuota = "quota"
|
||||
// FieldQuotaUsed holds the string denoting the quota_used field in the database.
|
||||
FieldQuotaUsed = "quota_used"
|
||||
// FieldExpiresAt holds the string denoting the expires_at field in the database.
|
||||
FieldExpiresAt = "expires_at"
|
||||
// EdgeUser holds the string denoting the user edge name in mutations.
|
||||
EdgeUser = "user"
|
||||
// EdgeGroup holds the string denoting the group edge name in mutations.
|
||||
@@ -79,6 +85,9 @@ var Columns = []string{
|
||||
FieldStatus,
|
||||
FieldIPWhitelist,
|
||||
FieldIPBlacklist,
|
||||
FieldQuota,
|
||||
FieldQuotaUsed,
|
||||
FieldExpiresAt,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
@@ -113,6 +122,10 @@ var (
|
||||
DefaultStatus string
|
||||
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
StatusValidator func(string) error
|
||||
// DefaultQuota holds the default value on creation for the "quota" field.
|
||||
DefaultQuota float64
|
||||
// DefaultQuotaUsed holds the default value on creation for the "quota_used" field.
|
||||
DefaultQuotaUsed float64
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the APIKey queries.
|
||||
@@ -163,6 +176,21 @@ func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByQuota orders the results by the quota field.
|
||||
func ByQuota(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldQuota, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByQuotaUsed orders the results by the quota_used field.
|
||||
func ByQuotaUsed(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldQuotaUsed, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByExpiresAt orders the results by the expires_at field.
|
||||
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldExpiresAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUserField orders the results by user field.
|
||||
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
|
||||
@@ -95,6 +95,21 @@ func Status(v string) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
|
||||
}
|
||||
|
||||
// Quota applies equality check predicate on the "quota" field. It's identical to QuotaEQ.
|
||||
func Quota(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaUsed applies equality check predicate on the "quota_used" field. It's identical to QuotaUsedEQ.
|
||||
func QuotaUsed(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// ExpiresAt applies equality check predicate on the "expires_at" field. It's identical to ExpiresAtEQ.
|
||||
func ExpiresAt(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldCreatedAt, v))
|
||||
@@ -490,6 +505,136 @@ func IPBlacklistNotNil() predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNotNull(FieldIPBlacklist))
|
||||
}
|
||||
|
||||
// QuotaEQ applies the EQ predicate on the "quota" field.
|
||||
func QuotaEQ(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaNEQ applies the NEQ predicate on the "quota" field.
|
||||
func QuotaNEQ(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNEQ(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaIn applies the In predicate on the "quota" field.
|
||||
func QuotaIn(vs ...float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldIn(FieldQuota, vs...))
|
||||
}
|
||||
|
||||
// QuotaNotIn applies the NotIn predicate on the "quota" field.
|
||||
func QuotaNotIn(vs ...float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNotIn(FieldQuota, vs...))
|
||||
}
|
||||
|
||||
// QuotaGT applies the GT predicate on the "quota" field.
|
||||
func QuotaGT(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGT(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaGTE applies the GTE predicate on the "quota" field.
|
||||
func QuotaGTE(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGTE(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaLT applies the LT predicate on the "quota" field.
|
||||
func QuotaLT(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLT(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaLTE applies the LTE predicate on the "quota" field.
|
||||
func QuotaLTE(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLTE(FieldQuota, v))
|
||||
}
|
||||
|
||||
// QuotaUsedEQ applies the EQ predicate on the "quota_used" field.
|
||||
func QuotaUsedEQ(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// QuotaUsedNEQ applies the NEQ predicate on the "quota_used" field.
|
||||
func QuotaUsedNEQ(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNEQ(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// QuotaUsedIn applies the In predicate on the "quota_used" field.
|
||||
func QuotaUsedIn(vs ...float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldIn(FieldQuotaUsed, vs...))
|
||||
}
|
||||
|
||||
// QuotaUsedNotIn applies the NotIn predicate on the "quota_used" field.
|
||||
func QuotaUsedNotIn(vs ...float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNotIn(FieldQuotaUsed, vs...))
|
||||
}
|
||||
|
||||
// QuotaUsedGT applies the GT predicate on the "quota_used" field.
|
||||
func QuotaUsedGT(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGT(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// QuotaUsedGTE applies the GTE predicate on the "quota_used" field.
|
||||
func QuotaUsedGTE(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGTE(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// QuotaUsedLT applies the LT predicate on the "quota_used" field.
|
||||
func QuotaUsedLT(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLT(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// QuotaUsedLTE applies the LTE predicate on the "quota_used" field.
|
||||
func QuotaUsedLTE(v float64) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLTE(FieldQuotaUsed, v))
|
||||
}
|
||||
|
||||
// ExpiresAtEQ applies the EQ predicate on the "expires_at" field.
|
||||
func ExpiresAtEQ(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldEQ(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtNEQ applies the NEQ predicate on the "expires_at" field.
|
||||
func ExpiresAtNEQ(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNEQ(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtIn applies the In predicate on the "expires_at" field.
|
||||
func ExpiresAtIn(vs ...time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldIn(FieldExpiresAt, vs...))
|
||||
}
|
||||
|
||||
// ExpiresAtNotIn applies the NotIn predicate on the "expires_at" field.
|
||||
func ExpiresAtNotIn(vs ...time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNotIn(FieldExpiresAt, vs...))
|
||||
}
|
||||
|
||||
// ExpiresAtGT applies the GT predicate on the "expires_at" field.
|
||||
func ExpiresAtGT(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGT(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtGTE applies the GTE predicate on the "expires_at" field.
|
||||
func ExpiresAtGTE(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldGTE(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtLT applies the LT predicate on the "expires_at" field.
|
||||
func ExpiresAtLT(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLT(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtLTE applies the LTE predicate on the "expires_at" field.
|
||||
func ExpiresAtLTE(v time.Time) predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldLTE(FieldExpiresAt, v))
|
||||
}
|
||||
|
||||
// ExpiresAtIsNil applies the IsNil predicate on the "expires_at" field.
|
||||
func ExpiresAtIsNil() predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldIsNull(FieldExpiresAt))
|
||||
}
|
||||
|
||||
// ExpiresAtNotNil applies the NotNil predicate on the "expires_at" field.
|
||||
func ExpiresAtNotNil() predicate.APIKey {
|
||||
return predicate.APIKey(sql.FieldNotNull(FieldExpiresAt))
|
||||
}
|
||||
|
||||
// HasUser applies the HasEdge predicate on the "user" edge.
|
||||
func HasUser() predicate.APIKey {
|
||||
return predicate.APIKey(func(s *sql.Selector) {
|
||||
|
||||
@@ -125,6 +125,48 @@ func (_c *APIKeyCreate) SetIPBlacklist(v []string) *APIKeyCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (_c *APIKeyCreate) SetQuota(v float64) *APIKeyCreate {
|
||||
_c.mutation.SetQuota(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableQuota sets the "quota" field if the given value is not nil.
|
||||
func (_c *APIKeyCreate) SetNillableQuota(v *float64) *APIKeyCreate {
|
||||
if v != nil {
|
||||
_c.SetQuota(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (_c *APIKeyCreate) SetQuotaUsed(v float64) *APIKeyCreate {
|
||||
_c.mutation.SetQuotaUsed(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
|
||||
func (_c *APIKeyCreate) SetNillableQuotaUsed(v *float64) *APIKeyCreate {
|
||||
if v != nil {
|
||||
_c.SetQuotaUsed(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (_c *APIKeyCreate) SetExpiresAt(v time.Time) *APIKeyCreate {
|
||||
_c.mutation.SetExpiresAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||
func (_c *APIKeyCreate) SetNillableExpiresAt(v *time.Time) *APIKeyCreate {
|
||||
if v != nil {
|
||||
_c.SetExpiresAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_c *APIKeyCreate) SetUser(v *User) *APIKeyCreate {
|
||||
return _c.SetUserID(v.ID)
|
||||
@@ -205,6 +247,14 @@ func (_c *APIKeyCreate) defaults() error {
|
||||
v := apikey.DefaultStatus
|
||||
_c.mutation.SetStatus(v)
|
||||
}
|
||||
if _, ok := _c.mutation.Quota(); !ok {
|
||||
v := apikey.DefaultQuota
|
||||
_c.mutation.SetQuota(v)
|
||||
}
|
||||
if _, ok := _c.mutation.QuotaUsed(); !ok {
|
||||
v := apikey.DefaultQuotaUsed
|
||||
_c.mutation.SetQuotaUsed(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -243,6 +293,12 @@ func (_c *APIKeyCreate) check() error {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.Quota(); !ok {
|
||||
return &ValidationError{Name: "quota", err: errors.New(`ent: missing required field "APIKey.quota"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.QuotaUsed(); !ok {
|
||||
return &ValidationError{Name: "quota_used", err: errors.New(`ent: missing required field "APIKey.quota_used"`)}
|
||||
}
|
||||
if len(_c.mutation.UserIDs()) == 0 {
|
||||
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "APIKey.user"`)}
|
||||
}
|
||||
@@ -305,6 +361,18 @@ func (_c *APIKeyCreate) createSpec() (*APIKey, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(apikey.FieldIPBlacklist, field.TypeJSON, value)
|
||||
_node.IPBlacklist = value
|
||||
}
|
||||
if value, ok := _c.mutation.Quota(); ok {
|
||||
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
|
||||
_node.Quota = value
|
||||
}
|
||||
if value, ok := _c.mutation.QuotaUsed(); ok {
|
||||
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
|
||||
_node.QuotaUsed = value
|
||||
}
|
||||
if value, ok := _c.mutation.ExpiresAt(); ok {
|
||||
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
|
||||
_node.ExpiresAt = &value
|
||||
}
|
||||
if nodes := _c.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
@@ -539,6 +607,60 @@ func (u *APIKeyUpsert) ClearIPBlacklist() *APIKeyUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (u *APIKeyUpsert) SetQuota(v float64) *APIKeyUpsert {
|
||||
u.Set(apikey.FieldQuota, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateQuota sets the "quota" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsert) UpdateQuota() *APIKeyUpsert {
|
||||
u.SetExcluded(apikey.FieldQuota)
|
||||
return u
|
||||
}
|
||||
|
||||
// AddQuota adds v to the "quota" field.
|
||||
func (u *APIKeyUpsert) AddQuota(v float64) *APIKeyUpsert {
|
||||
u.Add(apikey.FieldQuota, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (u *APIKeyUpsert) SetQuotaUsed(v float64) *APIKeyUpsert {
|
||||
u.Set(apikey.FieldQuotaUsed, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsert) UpdateQuotaUsed() *APIKeyUpsert {
|
||||
u.SetExcluded(apikey.FieldQuotaUsed)
|
||||
return u
|
||||
}
|
||||
|
||||
// AddQuotaUsed adds v to the "quota_used" field.
|
||||
func (u *APIKeyUpsert) AddQuotaUsed(v float64) *APIKeyUpsert {
|
||||
u.Add(apikey.FieldQuotaUsed, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (u *APIKeyUpsert) SetExpiresAt(v time.Time) *APIKeyUpsert {
|
||||
u.Set(apikey.FieldExpiresAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsert) UpdateExpiresAt() *APIKeyUpsert {
|
||||
u.SetExcluded(apikey.FieldExpiresAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||
func (u *APIKeyUpsert) ClearExpiresAt() *APIKeyUpsert {
|
||||
u.SetNull(apikey.FieldExpiresAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
@@ -738,6 +860,69 @@ func (u *APIKeyUpsertOne) ClearIPBlacklist() *APIKeyUpsertOne {
|
||||
})
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (u *APIKeyUpsertOne) SetQuota(v float64) *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetQuota(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddQuota adds v to the "quota" field.
|
||||
func (u *APIKeyUpsertOne) AddQuota(v float64) *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.AddQuota(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateQuota sets the "quota" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertOne) UpdateQuota() *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateQuota()
|
||||
})
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (u *APIKeyUpsertOne) SetQuotaUsed(v float64) *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetQuotaUsed(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddQuotaUsed adds v to the "quota_used" field.
|
||||
func (u *APIKeyUpsertOne) AddQuotaUsed(v float64) *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.AddQuotaUsed(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertOne) UpdateQuotaUsed() *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateQuotaUsed()
|
||||
})
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (u *APIKeyUpsertOne) SetExpiresAt(v time.Time) *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetExpiresAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertOne) UpdateExpiresAt() *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateExpiresAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||
func (u *APIKeyUpsertOne) ClearExpiresAt() *APIKeyUpsertOne {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.ClearExpiresAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *APIKeyUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
@@ -1103,6 +1288,69 @@ func (u *APIKeyUpsertBulk) ClearIPBlacklist() *APIKeyUpsertBulk {
|
||||
})
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (u *APIKeyUpsertBulk) SetQuota(v float64) *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetQuota(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddQuota adds v to the "quota" field.
|
||||
func (u *APIKeyUpsertBulk) AddQuota(v float64) *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.AddQuota(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateQuota sets the "quota" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertBulk) UpdateQuota() *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateQuota()
|
||||
})
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (u *APIKeyUpsertBulk) SetQuotaUsed(v float64) *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetQuotaUsed(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddQuotaUsed adds v to the "quota_used" field.
|
||||
func (u *APIKeyUpsertBulk) AddQuotaUsed(v float64) *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.AddQuotaUsed(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertBulk) UpdateQuotaUsed() *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateQuotaUsed()
|
||||
})
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (u *APIKeyUpsertBulk) SetExpiresAt(v time.Time) *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.SetExpiresAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||
func (u *APIKeyUpsertBulk) UpdateExpiresAt() *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.UpdateExpiresAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||
func (u *APIKeyUpsertBulk) ClearExpiresAt() *APIKeyUpsertBulk {
|
||||
return u.Update(func(s *APIKeyUpsert) {
|
||||
s.ClearExpiresAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *APIKeyUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
|
||||
@@ -170,6 +170,68 @@ func (_u *APIKeyUpdate) ClearIPBlacklist() *APIKeyUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (_u *APIKeyUpdate) SetQuota(v float64) *APIKeyUpdate {
|
||||
_u.mutation.ResetQuota()
|
||||
_u.mutation.SetQuota(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableQuota sets the "quota" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdate) SetNillableQuota(v *float64) *APIKeyUpdate {
|
||||
if v != nil {
|
||||
_u.SetQuota(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddQuota adds value to the "quota" field.
|
||||
func (_u *APIKeyUpdate) AddQuota(v float64) *APIKeyUpdate {
|
||||
_u.mutation.AddQuota(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (_u *APIKeyUpdate) SetQuotaUsed(v float64) *APIKeyUpdate {
|
||||
_u.mutation.ResetQuotaUsed()
|
||||
_u.mutation.SetQuotaUsed(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdate) SetNillableQuotaUsed(v *float64) *APIKeyUpdate {
|
||||
if v != nil {
|
||||
_u.SetQuotaUsed(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddQuotaUsed adds value to the "quota_used" field.
|
||||
func (_u *APIKeyUpdate) AddQuotaUsed(v float64) *APIKeyUpdate {
|
||||
_u.mutation.AddQuotaUsed(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (_u *APIKeyUpdate) SetExpiresAt(v time.Time) *APIKeyUpdate {
|
||||
_u.mutation.SetExpiresAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdate) SetNillableExpiresAt(v *time.Time) *APIKeyUpdate {
|
||||
if v != nil {
|
||||
_u.SetExpiresAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||
func (_u *APIKeyUpdate) ClearExpiresAt() *APIKeyUpdate {
|
||||
_u.mutation.ClearExpiresAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *APIKeyUpdate) SetUser(v *User) *APIKeyUpdate {
|
||||
return _u.SetUserID(v.ID)
|
||||
@@ -350,6 +412,24 @@ func (_u *APIKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if _u.mutation.IPBlacklistCleared() {
|
||||
_spec.ClearField(apikey.FieldIPBlacklist, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Quota(); ok {
|
||||
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedQuota(); ok {
|
||||
_spec.AddField(apikey.FieldQuota, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.QuotaUsed(); ok {
|
||||
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedQuotaUsed(); ok {
|
||||
_spec.AddField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ExpiresAt(); ok {
|
||||
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.ExpiresAtCleared() {
|
||||
_spec.ClearField(apikey.FieldExpiresAt, field.TypeTime)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
@@ -611,6 +691,68 @@ func (_u *APIKeyUpdateOne) ClearIPBlacklist() *APIKeyUpdateOne {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetQuota sets the "quota" field.
|
||||
func (_u *APIKeyUpdateOne) SetQuota(v float64) *APIKeyUpdateOne {
|
||||
_u.mutation.ResetQuota()
|
||||
_u.mutation.SetQuota(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableQuota sets the "quota" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdateOne) SetNillableQuota(v *float64) *APIKeyUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetQuota(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddQuota adds value to the "quota" field.
|
||||
func (_u *APIKeyUpdateOne) AddQuota(v float64) *APIKeyUpdateOne {
|
||||
_u.mutation.AddQuota(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetQuotaUsed sets the "quota_used" field.
|
||||
func (_u *APIKeyUpdateOne) SetQuotaUsed(v float64) *APIKeyUpdateOne {
|
||||
_u.mutation.ResetQuotaUsed()
|
||||
_u.mutation.SetQuotaUsed(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdateOne) SetNillableQuotaUsed(v *float64) *APIKeyUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetQuotaUsed(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddQuotaUsed adds value to the "quota_used" field.
|
||||
func (_u *APIKeyUpdateOne) AddQuotaUsed(v float64) *APIKeyUpdateOne {
|
||||
_u.mutation.AddQuotaUsed(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetExpiresAt sets the "expires_at" field.
|
||||
func (_u *APIKeyUpdateOne) SetExpiresAt(v time.Time) *APIKeyUpdateOne {
|
||||
_u.mutation.SetExpiresAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||
func (_u *APIKeyUpdateOne) SetNillableExpiresAt(v *time.Time) *APIKeyUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetExpiresAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||
func (_u *APIKeyUpdateOne) ClearExpiresAt() *APIKeyUpdateOne {
|
||||
_u.mutation.ClearExpiresAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *APIKeyUpdateOne) SetUser(v *User) *APIKeyUpdateOne {
|
||||
return _u.SetUserID(v.ID)
|
||||
@@ -821,6 +963,24 @@ func (_u *APIKeyUpdateOne) sqlSave(ctx context.Context) (_node *APIKey, err erro
|
||||
if _u.mutation.IPBlacklistCleared() {
|
||||
_spec.ClearField(apikey.FieldIPBlacklist, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Quota(); ok {
|
||||
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedQuota(); ok {
|
||||
_spec.AddField(apikey.FieldQuota, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.QuotaUsed(); ok {
|
||||
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedQuotaUsed(); ok {
|
||||
_spec.AddField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ExpiresAt(); ok {
|
||||
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.ExpiresAtCleared() {
|
||||
_spec.ClearField(apikey.FieldExpiresAt, field.TypeTime)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
||||
@@ -17,7 +17,10 @@ import (
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/account"
|
||||
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
@@ -46,6 +49,12 @@ type Client struct {
|
||||
Account *AccountClient
|
||||
// AccountGroup is the client for interacting with the AccountGroup builders.
|
||||
AccountGroup *AccountGroupClient
|
||||
// Announcement is the client for interacting with the Announcement builders.
|
||||
Announcement *AnnouncementClient
|
||||
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
|
||||
AnnouncementRead *AnnouncementReadClient
|
||||
// ErrorPassthroughRule is the client for interacting with the ErrorPassthroughRule builders.
|
||||
ErrorPassthroughRule *ErrorPassthroughRuleClient
|
||||
// Group is the client for interacting with the Group builders.
|
||||
Group *GroupClient
|
||||
// PromoCode is the client for interacting with the PromoCode builders.
|
||||
@@ -86,6 +95,9 @@ func (c *Client) init() {
|
||||
c.APIKey = NewAPIKeyClient(c.config)
|
||||
c.Account = NewAccountClient(c.config)
|
||||
c.AccountGroup = NewAccountGroupClient(c.config)
|
||||
c.Announcement = NewAnnouncementClient(c.config)
|
||||
c.AnnouncementRead = NewAnnouncementReadClient(c.config)
|
||||
c.ErrorPassthroughRule = NewErrorPassthroughRuleClient(c.config)
|
||||
c.Group = NewGroupClient(c.config)
|
||||
c.PromoCode = NewPromoCodeClient(c.config)
|
||||
c.PromoCodeUsage = NewPromoCodeUsageClient(c.config)
|
||||
@@ -194,6 +206,9 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
@@ -229,6 +244,9 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
@@ -271,8 +289,9 @@ func (c *Client) Close() error {
|
||||
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
|
||||
func (c *Client) Use(hooks ...Hook) {
|
||||
for _, n := range []interface{ Use(...Hook) }{
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Group, c.PromoCode, c.PromoCodeUsage,
|
||||
c.Proxy, c.RedeemCode, c.Setting, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
|
||||
c.ErrorPassthroughRule, c.Group, c.PromoCode, c.PromoCodeUsage, c.Proxy,
|
||||
c.RedeemCode, c.Setting, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.UserSubscription,
|
||||
} {
|
||||
@@ -284,8 +303,9 @@ func (c *Client) Use(hooks ...Hook) {
|
||||
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
|
||||
func (c *Client) Intercept(interceptors ...Interceptor) {
|
||||
for _, n := range []interface{ Intercept(...Interceptor) }{
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Group, c.PromoCode, c.PromoCodeUsage,
|
||||
c.Proxy, c.RedeemCode, c.Setting, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
|
||||
c.ErrorPassthroughRule, c.Group, c.PromoCode, c.PromoCodeUsage, c.Proxy,
|
||||
c.RedeemCode, c.Setting, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.UserSubscription,
|
||||
} {
|
||||
@@ -302,6 +322,12 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
||||
return c.Account.mutate(ctx, m)
|
||||
case *AccountGroupMutation:
|
||||
return c.AccountGroup.mutate(ctx, m)
|
||||
case *AnnouncementMutation:
|
||||
return c.Announcement.mutate(ctx, m)
|
||||
case *AnnouncementReadMutation:
|
||||
return c.AnnouncementRead.mutate(ctx, m)
|
||||
case *ErrorPassthroughRuleMutation:
|
||||
return c.ErrorPassthroughRule.mutate(ctx, m)
|
||||
case *GroupMutation:
|
||||
return c.Group.mutate(ctx, m)
|
||||
case *PromoCodeMutation:
|
||||
@@ -831,6 +857,453 @@ func (c *AccountGroupClient) mutate(ctx context.Context, m *AccountGroupMutation
|
||||
}
|
||||
}
|
||||
|
||||
// AnnouncementClient is a client for the Announcement schema.
|
||||
type AnnouncementClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewAnnouncementClient returns a client for the Announcement from the given config.
|
||||
func NewAnnouncementClient(c config) *AnnouncementClient {
|
||||
return &AnnouncementClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `announcement.Hooks(f(g(h())))`.
|
||||
func (c *AnnouncementClient) Use(hooks ...Hook) {
|
||||
c.hooks.Announcement = append(c.hooks.Announcement, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `announcement.Intercept(f(g(h())))`.
|
||||
func (c *AnnouncementClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.Announcement = append(c.inters.Announcement, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a Announcement entity.
|
||||
func (c *AnnouncementClient) Create() *AnnouncementCreate {
|
||||
mutation := newAnnouncementMutation(c.config, OpCreate)
|
||||
return &AnnouncementCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of Announcement entities.
|
||||
func (c *AnnouncementClient) CreateBulk(builders ...*AnnouncementCreate) *AnnouncementCreateBulk {
|
||||
return &AnnouncementCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
|
||||
// a builder and applies setFunc on it.
|
||||
func (c *AnnouncementClient) MapCreateBulk(slice any, setFunc func(*AnnouncementCreate, int)) *AnnouncementCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &AnnouncementCreateBulk{err: fmt.Errorf("calling to AnnouncementClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*AnnouncementCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &AnnouncementCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for Announcement.
|
||||
func (c *AnnouncementClient) Update() *AnnouncementUpdate {
|
||||
mutation := newAnnouncementMutation(c.config, OpUpdate)
|
||||
return &AnnouncementUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *AnnouncementClient) UpdateOne(_m *Announcement) *AnnouncementUpdateOne {
|
||||
mutation := newAnnouncementMutation(c.config, OpUpdateOne, withAnnouncement(_m))
|
||||
return &AnnouncementUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *AnnouncementClient) UpdateOneID(id int64) *AnnouncementUpdateOne {
|
||||
mutation := newAnnouncementMutation(c.config, OpUpdateOne, withAnnouncementID(id))
|
||||
return &AnnouncementUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for Announcement.
|
||||
func (c *AnnouncementClient) Delete() *AnnouncementDelete {
|
||||
mutation := newAnnouncementMutation(c.config, OpDelete)
|
||||
return &AnnouncementDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *AnnouncementClient) DeleteOne(_m *Announcement) *AnnouncementDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *AnnouncementClient) DeleteOneID(id int64) *AnnouncementDeleteOne {
|
||||
builder := c.Delete().Where(announcement.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &AnnouncementDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for Announcement.
|
||||
func (c *AnnouncementClient) Query() *AnnouncementQuery {
|
||||
return &AnnouncementQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeAnnouncement},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a Announcement entity by its id.
|
||||
func (c *AnnouncementClient) Get(ctx context.Context, id int64) (*Announcement, error) {
|
||||
return c.Query().Where(announcement.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *AnnouncementClient) GetX(ctx context.Context, id int64) *Announcement {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryReads queries the reads edge of a Announcement.
|
||||
func (c *AnnouncementClient) QueryReads(_m *Announcement) *AnnouncementReadQuery {
|
||||
query := (&AnnouncementReadClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcement.Table, announcement.FieldID, id),
|
||||
sqlgraph.To(announcementread.Table, announcementread.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, announcement.ReadsTable, announcement.ReadsColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *AnnouncementClient) Hooks() []Hook {
|
||||
return c.hooks.Announcement
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *AnnouncementClient) Interceptors() []Interceptor {
|
||||
return c.inters.Announcement
|
||||
}
|
||||
|
||||
func (c *AnnouncementClient) mutate(ctx context.Context, m *AnnouncementMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&AnnouncementCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&AnnouncementUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&AnnouncementUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&AnnouncementDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown Announcement mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// AnnouncementReadClient is a client for the AnnouncementRead schema.
|
||||
type AnnouncementReadClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewAnnouncementReadClient returns a client for the AnnouncementRead from the given config.
|
||||
func NewAnnouncementReadClient(c config) *AnnouncementReadClient {
|
||||
return &AnnouncementReadClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `announcementread.Hooks(f(g(h())))`.
|
||||
func (c *AnnouncementReadClient) Use(hooks ...Hook) {
|
||||
c.hooks.AnnouncementRead = append(c.hooks.AnnouncementRead, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `announcementread.Intercept(f(g(h())))`.
|
||||
func (c *AnnouncementReadClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.AnnouncementRead = append(c.inters.AnnouncementRead, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a AnnouncementRead entity.
|
||||
func (c *AnnouncementReadClient) Create() *AnnouncementReadCreate {
|
||||
mutation := newAnnouncementReadMutation(c.config, OpCreate)
|
||||
return &AnnouncementReadCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of AnnouncementRead entities.
|
||||
func (c *AnnouncementReadClient) CreateBulk(builders ...*AnnouncementReadCreate) *AnnouncementReadCreateBulk {
|
||||
return &AnnouncementReadCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
|
||||
// a builder and applies setFunc on it.
|
||||
func (c *AnnouncementReadClient) MapCreateBulk(slice any, setFunc func(*AnnouncementReadCreate, int)) *AnnouncementReadCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &AnnouncementReadCreateBulk{err: fmt.Errorf("calling to AnnouncementReadClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*AnnouncementReadCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &AnnouncementReadCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for AnnouncementRead.
|
||||
func (c *AnnouncementReadClient) Update() *AnnouncementReadUpdate {
|
||||
mutation := newAnnouncementReadMutation(c.config, OpUpdate)
|
||||
return &AnnouncementReadUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *AnnouncementReadClient) UpdateOne(_m *AnnouncementRead) *AnnouncementReadUpdateOne {
|
||||
mutation := newAnnouncementReadMutation(c.config, OpUpdateOne, withAnnouncementRead(_m))
|
||||
return &AnnouncementReadUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *AnnouncementReadClient) UpdateOneID(id int64) *AnnouncementReadUpdateOne {
|
||||
mutation := newAnnouncementReadMutation(c.config, OpUpdateOne, withAnnouncementReadID(id))
|
||||
return &AnnouncementReadUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for AnnouncementRead.
|
||||
func (c *AnnouncementReadClient) Delete() *AnnouncementReadDelete {
|
||||
mutation := newAnnouncementReadMutation(c.config, OpDelete)
|
||||
return &AnnouncementReadDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *AnnouncementReadClient) DeleteOne(_m *AnnouncementRead) *AnnouncementReadDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *AnnouncementReadClient) DeleteOneID(id int64) *AnnouncementReadDeleteOne {
|
||||
builder := c.Delete().Where(announcementread.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &AnnouncementReadDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for AnnouncementRead.
|
||||
func (c *AnnouncementReadClient) Query() *AnnouncementReadQuery {
|
||||
return &AnnouncementReadQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeAnnouncementRead},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a AnnouncementRead entity by its id.
|
||||
func (c *AnnouncementReadClient) Get(ctx context.Context, id int64) (*AnnouncementRead, error) {
|
||||
return c.Query().Where(announcementread.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *AnnouncementReadClient) GetX(ctx context.Context, id int64) *AnnouncementRead {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryAnnouncement queries the announcement edge of a AnnouncementRead.
|
||||
func (c *AnnouncementReadClient) QueryAnnouncement(_m *AnnouncementRead) *AnnouncementQuery {
|
||||
query := (&AnnouncementClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcementread.Table, announcementread.FieldID, id),
|
||||
sqlgraph.To(announcement.Table, announcement.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, announcementread.AnnouncementTable, announcementread.AnnouncementColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryUser queries the user edge of a AnnouncementRead.
|
||||
func (c *AnnouncementReadClient) QueryUser(_m *AnnouncementRead) *UserQuery {
|
||||
query := (&UserClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(announcementread.Table, announcementread.FieldID, id),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, announcementread.UserTable, announcementread.UserColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *AnnouncementReadClient) Hooks() []Hook {
|
||||
return c.hooks.AnnouncementRead
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *AnnouncementReadClient) Interceptors() []Interceptor {
|
||||
return c.inters.AnnouncementRead
|
||||
}
|
||||
|
||||
func (c *AnnouncementReadClient) mutate(ctx context.Context, m *AnnouncementReadMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&AnnouncementReadCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&AnnouncementReadUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&AnnouncementReadUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&AnnouncementReadDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown AnnouncementRead mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleClient is a client for the ErrorPassthroughRule schema.
|
||||
type ErrorPassthroughRuleClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewErrorPassthroughRuleClient returns a client for the ErrorPassthroughRule from the given config.
|
||||
func NewErrorPassthroughRuleClient(c config) *ErrorPassthroughRuleClient {
|
||||
return &ErrorPassthroughRuleClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `errorpassthroughrule.Hooks(f(g(h())))`.
|
||||
func (c *ErrorPassthroughRuleClient) Use(hooks ...Hook) {
|
||||
c.hooks.ErrorPassthroughRule = append(c.hooks.ErrorPassthroughRule, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `errorpassthroughrule.Intercept(f(g(h())))`.
|
||||
func (c *ErrorPassthroughRuleClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.ErrorPassthroughRule = append(c.inters.ErrorPassthroughRule, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a ErrorPassthroughRule entity.
|
||||
func (c *ErrorPassthroughRuleClient) Create() *ErrorPassthroughRuleCreate {
|
||||
mutation := newErrorPassthroughRuleMutation(c.config, OpCreate)
|
||||
return &ErrorPassthroughRuleCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of ErrorPassthroughRule entities.
|
||||
func (c *ErrorPassthroughRuleClient) CreateBulk(builders ...*ErrorPassthroughRuleCreate) *ErrorPassthroughRuleCreateBulk {
|
||||
return &ErrorPassthroughRuleCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
|
||||
// a builder and applies setFunc on it.
|
||||
func (c *ErrorPassthroughRuleClient) MapCreateBulk(slice any, setFunc func(*ErrorPassthroughRuleCreate, int)) *ErrorPassthroughRuleCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &ErrorPassthroughRuleCreateBulk{err: fmt.Errorf("calling to ErrorPassthroughRuleClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*ErrorPassthroughRuleCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &ErrorPassthroughRuleCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for ErrorPassthroughRule.
|
||||
func (c *ErrorPassthroughRuleClient) Update() *ErrorPassthroughRuleUpdate {
|
||||
mutation := newErrorPassthroughRuleMutation(c.config, OpUpdate)
|
||||
return &ErrorPassthroughRuleUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *ErrorPassthroughRuleClient) UpdateOne(_m *ErrorPassthroughRule) *ErrorPassthroughRuleUpdateOne {
|
||||
mutation := newErrorPassthroughRuleMutation(c.config, OpUpdateOne, withErrorPassthroughRule(_m))
|
||||
return &ErrorPassthroughRuleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *ErrorPassthroughRuleClient) UpdateOneID(id int64) *ErrorPassthroughRuleUpdateOne {
|
||||
mutation := newErrorPassthroughRuleMutation(c.config, OpUpdateOne, withErrorPassthroughRuleID(id))
|
||||
return &ErrorPassthroughRuleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for ErrorPassthroughRule.
|
||||
func (c *ErrorPassthroughRuleClient) Delete() *ErrorPassthroughRuleDelete {
|
||||
mutation := newErrorPassthroughRuleMutation(c.config, OpDelete)
|
||||
return &ErrorPassthroughRuleDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *ErrorPassthroughRuleClient) DeleteOne(_m *ErrorPassthroughRule) *ErrorPassthroughRuleDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *ErrorPassthroughRuleClient) DeleteOneID(id int64) *ErrorPassthroughRuleDeleteOne {
|
||||
builder := c.Delete().Where(errorpassthroughrule.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &ErrorPassthroughRuleDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for ErrorPassthroughRule.
|
||||
func (c *ErrorPassthroughRuleClient) Query() *ErrorPassthroughRuleQuery {
|
||||
return &ErrorPassthroughRuleQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeErrorPassthroughRule},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a ErrorPassthroughRule entity by its id.
|
||||
func (c *ErrorPassthroughRuleClient) Get(ctx context.Context, id int64) (*ErrorPassthroughRule, error) {
|
||||
return c.Query().Where(errorpassthroughrule.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *ErrorPassthroughRuleClient) GetX(ctx context.Context, id int64) *ErrorPassthroughRule {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *ErrorPassthroughRuleClient) Hooks() []Hook {
|
||||
return c.hooks.ErrorPassthroughRule
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *ErrorPassthroughRuleClient) Interceptors() []Interceptor {
|
||||
return c.inters.ErrorPassthroughRule
|
||||
}
|
||||
|
||||
func (c *ErrorPassthroughRuleClient) mutate(ctx context.Context, m *ErrorPassthroughRuleMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&ErrorPassthroughRuleCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&ErrorPassthroughRuleUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&ErrorPassthroughRuleUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&ErrorPassthroughRuleDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown ErrorPassthroughRule mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// GroupClient is a client for the Group schema.
|
||||
type GroupClient struct {
|
||||
config
|
||||
@@ -2375,6 +2848,22 @@ func (c *UserClient) QueryAssignedSubscriptions(_m *User) *UserSubscriptionQuery
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAnnouncementReads queries the announcement_reads edge of a User.
|
||||
func (c *UserClient) QueryAnnouncementReads(_m *User) *AnnouncementReadQuery {
|
||||
query := (&AnnouncementReadClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, id),
|
||||
sqlgraph.To(announcementread.Table, announcementread.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.AnnouncementReadsTable, user.AnnouncementReadsColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAllowedGroups queries the allowed_groups edge of a User.
|
||||
func (c *UserClient) QueryAllowedGroups(_m *User) *GroupQuery {
|
||||
query := (&GroupClient{config: c.config}).Query()
|
||||
@@ -3116,13 +3605,15 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription
|
||||
// hooks and interceptors per client, for fast access.
|
||||
type (
|
||||
hooks struct {
|
||||
APIKey, Account, AccountGroup, Group, PromoCode, PromoCodeUsage, Proxy,
|
||||
RedeemCode, Setting, UsageCleanupTask, UsageLog, User, UserAllowedGroup,
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
|
||||
ErrorPassthroughRule, Group, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
|
||||
Setting, UsageCleanupTask, UsageLog, User, UserAllowedGroup,
|
||||
UserAttributeDefinition, UserAttributeValue, UserSubscription []ent.Hook
|
||||
}
|
||||
inters struct {
|
||||
APIKey, Account, AccountGroup, Group, PromoCode, PromoCodeUsage, Proxy,
|
||||
RedeemCode, Setting, UsageCleanupTask, UsageLog, User, UserAllowedGroup,
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
|
||||
ErrorPassthroughRule, Group, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
|
||||
Setting, UsageCleanupTask, UsageLog, User, UserAllowedGroup,
|
||||
UserAttributeDefinition, UserAttributeValue, UserSubscription []ent.Interceptor
|
||||
}
|
||||
)
|
||||
|
||||
@@ -14,7 +14,10 @@ import (
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/account"
|
||||
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
@@ -91,6 +94,9 @@ func checkColumn(t, c string) error {
|
||||
apikey.Table: apikey.ValidColumn,
|
||||
account.Table: account.ValidColumn,
|
||||
accountgroup.Table: accountgroup.ValidColumn,
|
||||
announcement.Table: announcement.ValidColumn,
|
||||
announcementread.Table: announcementread.ValidColumn,
|
||||
errorpassthroughrule.Table: errorpassthroughrule.ValidColumn,
|
||||
group.Table: group.ValidColumn,
|
||||
promocode.Table: promocode.ValidColumn,
|
||||
promocodeusage.Table: promocodeusage.ValidColumn,
|
||||
|
||||
269
backend/ent/errorpassthroughrule.go
Normal file
269
backend/ent/errorpassthroughrule.go
Normal file
@@ -0,0 +1,269 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
)
|
||||
|
||||
// ErrorPassthroughRule is the model entity for the ErrorPassthroughRule schema.
|
||||
type ErrorPassthroughRule struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// Name holds the value of the "name" field.
|
||||
Name string `json:"name,omitempty"`
|
||||
// Enabled holds the value of the "enabled" field.
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
// Priority holds the value of the "priority" field.
|
||||
Priority int `json:"priority,omitempty"`
|
||||
// ErrorCodes holds the value of the "error_codes" field.
|
||||
ErrorCodes []int `json:"error_codes,omitempty"`
|
||||
// Keywords holds the value of the "keywords" field.
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
// MatchMode holds the value of the "match_mode" field.
|
||||
MatchMode string `json:"match_mode,omitempty"`
|
||||
// Platforms holds the value of the "platforms" field.
|
||||
Platforms []string `json:"platforms,omitempty"`
|
||||
// PassthroughCode holds the value of the "passthrough_code" field.
|
||||
PassthroughCode bool `json:"passthrough_code,omitempty"`
|
||||
// ResponseCode holds the value of the "response_code" field.
|
||||
ResponseCode *int `json:"response_code,omitempty"`
|
||||
// PassthroughBody holds the value of the "passthrough_body" field.
|
||||
PassthroughBody bool `json:"passthrough_body,omitempty"`
|
||||
// CustomMessage holds the value of the "custom_message" field.
|
||||
CustomMessage *string `json:"custom_message,omitempty"`
|
||||
// Description holds the value of the "description" field.
|
||||
Description *string `json:"description,omitempty"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*ErrorPassthroughRule) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case errorpassthroughrule.FieldErrorCodes, errorpassthroughrule.FieldKeywords, errorpassthroughrule.FieldPlatforms:
|
||||
values[i] = new([]byte)
|
||||
case errorpassthroughrule.FieldEnabled, errorpassthroughrule.FieldPassthroughCode, errorpassthroughrule.FieldPassthroughBody:
|
||||
values[i] = new(sql.NullBool)
|
||||
case errorpassthroughrule.FieldID, errorpassthroughrule.FieldPriority, errorpassthroughrule.FieldResponseCode:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case errorpassthroughrule.FieldName, errorpassthroughrule.FieldMatchMode, errorpassthroughrule.FieldCustomMessage, errorpassthroughrule.FieldDescription:
|
||||
values[i] = new(sql.NullString)
|
||||
case errorpassthroughrule.FieldCreatedAt, errorpassthroughrule.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the ErrorPassthroughRule fields.
|
||||
func (_m *ErrorPassthroughRule) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case errorpassthroughrule.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case errorpassthroughrule.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case errorpassthroughrule.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
case errorpassthroughrule.FieldName:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field name", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Name = value.String
|
||||
}
|
||||
case errorpassthroughrule.FieldEnabled:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field enabled", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Enabled = value.Bool
|
||||
}
|
||||
case errorpassthroughrule.FieldPriority:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field priority", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Priority = int(value.Int64)
|
||||
}
|
||||
case errorpassthroughrule.FieldErrorCodes:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field error_codes", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.ErrorCodes); err != nil {
|
||||
return fmt.Errorf("unmarshal field error_codes: %w", err)
|
||||
}
|
||||
}
|
||||
case errorpassthroughrule.FieldKeywords:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field keywords", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.Keywords); err != nil {
|
||||
return fmt.Errorf("unmarshal field keywords: %w", err)
|
||||
}
|
||||
}
|
||||
case errorpassthroughrule.FieldMatchMode:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field match_mode", values[i])
|
||||
} else if value.Valid {
|
||||
_m.MatchMode = value.String
|
||||
}
|
||||
case errorpassthroughrule.FieldPlatforms:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field platforms", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.Platforms); err != nil {
|
||||
return fmt.Errorf("unmarshal field platforms: %w", err)
|
||||
}
|
||||
}
|
||||
case errorpassthroughrule.FieldPassthroughCode:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field passthrough_code", values[i])
|
||||
} else if value.Valid {
|
||||
_m.PassthroughCode = value.Bool
|
||||
}
|
||||
case errorpassthroughrule.FieldResponseCode:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field response_code", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ResponseCode = new(int)
|
||||
*_m.ResponseCode = int(value.Int64)
|
||||
}
|
||||
case errorpassthroughrule.FieldPassthroughBody:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field passthrough_body", values[i])
|
||||
} else if value.Valid {
|
||||
_m.PassthroughBody = value.Bool
|
||||
}
|
||||
case errorpassthroughrule.FieldCustomMessage:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field custom_message", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CustomMessage = new(string)
|
||||
*_m.CustomMessage = value.String
|
||||
}
|
||||
case errorpassthroughrule.FieldDescription:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field description", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Description = new(string)
|
||||
*_m.Description = value.String
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the ErrorPassthroughRule.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *ErrorPassthroughRule) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this ErrorPassthroughRule.
|
||||
// Note that you need to call ErrorPassthroughRule.Unwrap() before calling this method if this ErrorPassthroughRule
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *ErrorPassthroughRule) Update() *ErrorPassthroughRuleUpdateOne {
|
||||
return NewErrorPassthroughRuleClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the ErrorPassthroughRule entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *ErrorPassthroughRule) Unwrap() *ErrorPassthroughRule {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: ErrorPassthroughRule is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *ErrorPassthroughRule) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("ErrorPassthroughRule(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("name=")
|
||||
builder.WriteString(_m.Name)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("enabled=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Enabled))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("priority=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Priority))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("error_codes=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.ErrorCodes))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("keywords=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Keywords))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("match_mode=")
|
||||
builder.WriteString(_m.MatchMode)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("platforms=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Platforms))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("passthrough_code=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.PassthroughCode))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.ResponseCode; v != nil {
|
||||
builder.WriteString("response_code=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("passthrough_body=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.PassthroughBody))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.CustomMessage; v != nil {
|
||||
builder.WriteString("custom_message=")
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.Description; v != nil {
|
||||
builder.WriteString("description=")
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// ErrorPassthroughRules is a parsable slice of ErrorPassthroughRule.
|
||||
type ErrorPassthroughRules []*ErrorPassthroughRule
|
||||
161
backend/ent/errorpassthroughrule/errorpassthroughrule.go
Normal file
161
backend/ent/errorpassthroughrule/errorpassthroughrule.go
Normal file
@@ -0,0 +1,161 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package errorpassthroughrule
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the errorpassthroughrule type in the database.
|
||||
Label = "error_passthrough_rule"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldName holds the string denoting the name field in the database.
|
||||
FieldName = "name"
|
||||
// FieldEnabled holds the string denoting the enabled field in the database.
|
||||
FieldEnabled = "enabled"
|
||||
// FieldPriority holds the string denoting the priority field in the database.
|
||||
FieldPriority = "priority"
|
||||
// FieldErrorCodes holds the string denoting the error_codes field in the database.
|
||||
FieldErrorCodes = "error_codes"
|
||||
// FieldKeywords holds the string denoting the keywords field in the database.
|
||||
FieldKeywords = "keywords"
|
||||
// FieldMatchMode holds the string denoting the match_mode field in the database.
|
||||
FieldMatchMode = "match_mode"
|
||||
// FieldPlatforms holds the string denoting the platforms field in the database.
|
||||
FieldPlatforms = "platforms"
|
||||
// FieldPassthroughCode holds the string denoting the passthrough_code field in the database.
|
||||
FieldPassthroughCode = "passthrough_code"
|
||||
// FieldResponseCode holds the string denoting the response_code field in the database.
|
||||
FieldResponseCode = "response_code"
|
||||
// FieldPassthroughBody holds the string denoting the passthrough_body field in the database.
|
||||
FieldPassthroughBody = "passthrough_body"
|
||||
// FieldCustomMessage holds the string denoting the custom_message field in the database.
|
||||
FieldCustomMessage = "custom_message"
|
||||
// FieldDescription holds the string denoting the description field in the database.
|
||||
FieldDescription = "description"
|
||||
// Table holds the table name of the errorpassthroughrule in the database.
|
||||
Table = "error_passthrough_rules"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for errorpassthroughrule fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldName,
|
||||
FieldEnabled,
|
||||
FieldPriority,
|
||||
FieldErrorCodes,
|
||||
FieldKeywords,
|
||||
FieldMatchMode,
|
||||
FieldPlatforms,
|
||||
FieldPassthroughCode,
|
||||
FieldResponseCode,
|
||||
FieldPassthroughBody,
|
||||
FieldCustomMessage,
|
||||
FieldDescription,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
// NameValidator is a validator for the "name" field. It is called by the builders before save.
|
||||
NameValidator func(string) error
|
||||
// DefaultEnabled holds the default value on creation for the "enabled" field.
|
||||
DefaultEnabled bool
|
||||
// DefaultPriority holds the default value on creation for the "priority" field.
|
||||
DefaultPriority int
|
||||
// DefaultMatchMode holds the default value on creation for the "match_mode" field.
|
||||
DefaultMatchMode string
|
||||
// MatchModeValidator is a validator for the "match_mode" field. It is called by the builders before save.
|
||||
MatchModeValidator func(string) error
|
||||
// DefaultPassthroughCode holds the default value on creation for the "passthrough_code" field.
|
||||
DefaultPassthroughCode bool
|
||||
// DefaultPassthroughBody holds the default value on creation for the "passthrough_body" field.
|
||||
DefaultPassthroughBody bool
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the ErrorPassthroughRule queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByName orders the results by the name field.
|
||||
func ByName(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldName, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByEnabled orders the results by the enabled field.
|
||||
func ByEnabled(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldEnabled, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPriority orders the results by the priority field.
|
||||
func ByPriority(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldPriority, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByMatchMode orders the results by the match_mode field.
|
||||
func ByMatchMode(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldMatchMode, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPassthroughCode orders the results by the passthrough_code field.
|
||||
func ByPassthroughCode(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldPassthroughCode, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByResponseCode orders the results by the response_code field.
|
||||
func ByResponseCode(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldResponseCode, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPassthroughBody orders the results by the passthrough_body field.
|
||||
func ByPassthroughBody(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldPassthroughBody, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCustomMessage orders the results by the custom_message field.
|
||||
func ByCustomMessage(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCustomMessage, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByDescription orders the results by the description field.
|
||||
func ByDescription(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldDescription, opts...).ToFunc()
|
||||
}
|
||||
635
backend/ent/errorpassthroughrule/where.go
Normal file
635
backend/ent/errorpassthroughrule/where.go
Normal file
@@ -0,0 +1,635 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package errorpassthroughrule
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
|
||||
func Name(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldName, v))
|
||||
}
|
||||
|
||||
// Enabled applies equality check predicate on the "enabled" field. It's identical to EnabledEQ.
|
||||
func Enabled(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldEnabled, v))
|
||||
}
|
||||
|
||||
// Priority applies equality check predicate on the "priority" field. It's identical to PriorityEQ.
|
||||
func Priority(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPriority, v))
|
||||
}
|
||||
|
||||
// MatchMode applies equality check predicate on the "match_mode" field. It's identical to MatchModeEQ.
|
||||
func MatchMode(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// PassthroughCode applies equality check predicate on the "passthrough_code" field. It's identical to PassthroughCodeEQ.
|
||||
func PassthroughCode(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPassthroughCode, v))
|
||||
}
|
||||
|
||||
// ResponseCode applies equality check predicate on the "response_code" field. It's identical to ResponseCodeEQ.
|
||||
func ResponseCode(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// PassthroughBody applies equality check predicate on the "passthrough_body" field. It's identical to PassthroughBodyEQ.
|
||||
func PassthroughBody(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPassthroughBody, v))
|
||||
}
|
||||
|
||||
// CustomMessage applies equality check predicate on the "custom_message" field. It's identical to CustomMessageEQ.
|
||||
func CustomMessage(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ.
|
||||
func Description(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldDescription, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// NameEQ applies the EQ predicate on the "name" field.
|
||||
func NameEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldName, v))
|
||||
}
|
||||
|
||||
// NameNEQ applies the NEQ predicate on the "name" field.
|
||||
func NameNEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldName, v))
|
||||
}
|
||||
|
||||
// NameIn applies the In predicate on the "name" field.
|
||||
func NameIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldName, vs...))
|
||||
}
|
||||
|
||||
// NameNotIn applies the NotIn predicate on the "name" field.
|
||||
func NameNotIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldName, vs...))
|
||||
}
|
||||
|
||||
// NameGT applies the GT predicate on the "name" field.
|
||||
func NameGT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldName, v))
|
||||
}
|
||||
|
||||
// NameGTE applies the GTE predicate on the "name" field.
|
||||
func NameGTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldName, v))
|
||||
}
|
||||
|
||||
// NameLT applies the LT predicate on the "name" field.
|
||||
func NameLT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldName, v))
|
||||
}
|
||||
|
||||
// NameLTE applies the LTE predicate on the "name" field.
|
||||
func NameLTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldName, v))
|
||||
}
|
||||
|
||||
// NameContains applies the Contains predicate on the "name" field.
|
||||
func NameContains(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContains(FieldName, v))
|
||||
}
|
||||
|
||||
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
|
||||
func NameHasPrefix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasPrefix(FieldName, v))
|
||||
}
|
||||
|
||||
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
|
||||
func NameHasSuffix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasSuffix(FieldName, v))
|
||||
}
|
||||
|
||||
// NameEqualFold applies the EqualFold predicate on the "name" field.
|
||||
func NameEqualFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEqualFold(FieldName, v))
|
||||
}
|
||||
|
||||
// NameContainsFold applies the ContainsFold predicate on the "name" field.
|
||||
func NameContainsFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContainsFold(FieldName, v))
|
||||
}
|
||||
|
||||
// EnabledEQ applies the EQ predicate on the "enabled" field.
|
||||
func EnabledEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldEnabled, v))
|
||||
}
|
||||
|
||||
// EnabledNEQ applies the NEQ predicate on the "enabled" field.
|
||||
func EnabledNEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldEnabled, v))
|
||||
}
|
||||
|
||||
// PriorityEQ applies the EQ predicate on the "priority" field.
|
||||
func PriorityEQ(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPriority, v))
|
||||
}
|
||||
|
||||
// PriorityNEQ applies the NEQ predicate on the "priority" field.
|
||||
func PriorityNEQ(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldPriority, v))
|
||||
}
|
||||
|
||||
// PriorityIn applies the In predicate on the "priority" field.
|
||||
func PriorityIn(vs ...int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldPriority, vs...))
|
||||
}
|
||||
|
||||
// PriorityNotIn applies the NotIn predicate on the "priority" field.
|
||||
func PriorityNotIn(vs ...int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldPriority, vs...))
|
||||
}
|
||||
|
||||
// PriorityGT applies the GT predicate on the "priority" field.
|
||||
func PriorityGT(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldPriority, v))
|
||||
}
|
||||
|
||||
// PriorityGTE applies the GTE predicate on the "priority" field.
|
||||
func PriorityGTE(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldPriority, v))
|
||||
}
|
||||
|
||||
// PriorityLT applies the LT predicate on the "priority" field.
|
||||
func PriorityLT(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldPriority, v))
|
||||
}
|
||||
|
||||
// PriorityLTE applies the LTE predicate on the "priority" field.
|
||||
func PriorityLTE(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldPriority, v))
|
||||
}
|
||||
|
||||
// ErrorCodesIsNil applies the IsNil predicate on the "error_codes" field.
|
||||
func ErrorCodesIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldErrorCodes))
|
||||
}
|
||||
|
||||
// ErrorCodesNotNil applies the NotNil predicate on the "error_codes" field.
|
||||
func ErrorCodesNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldErrorCodes))
|
||||
}
|
||||
|
||||
// KeywordsIsNil applies the IsNil predicate on the "keywords" field.
|
||||
func KeywordsIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldKeywords))
|
||||
}
|
||||
|
||||
// KeywordsNotNil applies the NotNil predicate on the "keywords" field.
|
||||
func KeywordsNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldKeywords))
|
||||
}
|
||||
|
||||
// MatchModeEQ applies the EQ predicate on the "match_mode" field.
|
||||
func MatchModeEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeNEQ applies the NEQ predicate on the "match_mode" field.
|
||||
func MatchModeNEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeIn applies the In predicate on the "match_mode" field.
|
||||
func MatchModeIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldMatchMode, vs...))
|
||||
}
|
||||
|
||||
// MatchModeNotIn applies the NotIn predicate on the "match_mode" field.
|
||||
func MatchModeNotIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldMatchMode, vs...))
|
||||
}
|
||||
|
||||
// MatchModeGT applies the GT predicate on the "match_mode" field.
|
||||
func MatchModeGT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeGTE applies the GTE predicate on the "match_mode" field.
|
||||
func MatchModeGTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeLT applies the LT predicate on the "match_mode" field.
|
||||
func MatchModeLT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeLTE applies the LTE predicate on the "match_mode" field.
|
||||
func MatchModeLTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeContains applies the Contains predicate on the "match_mode" field.
|
||||
func MatchModeContains(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContains(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeHasPrefix applies the HasPrefix predicate on the "match_mode" field.
|
||||
func MatchModeHasPrefix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasPrefix(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeHasSuffix applies the HasSuffix predicate on the "match_mode" field.
|
||||
func MatchModeHasSuffix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasSuffix(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeEqualFold applies the EqualFold predicate on the "match_mode" field.
|
||||
func MatchModeEqualFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEqualFold(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// MatchModeContainsFold applies the ContainsFold predicate on the "match_mode" field.
|
||||
func MatchModeContainsFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContainsFold(FieldMatchMode, v))
|
||||
}
|
||||
|
||||
// PlatformsIsNil applies the IsNil predicate on the "platforms" field.
|
||||
func PlatformsIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldPlatforms))
|
||||
}
|
||||
|
||||
// PlatformsNotNil applies the NotNil predicate on the "platforms" field.
|
||||
func PlatformsNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldPlatforms))
|
||||
}
|
||||
|
||||
// PassthroughCodeEQ applies the EQ predicate on the "passthrough_code" field.
|
||||
func PassthroughCodeEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPassthroughCode, v))
|
||||
}
|
||||
|
||||
// PassthroughCodeNEQ applies the NEQ predicate on the "passthrough_code" field.
|
||||
func PassthroughCodeNEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldPassthroughCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeEQ applies the EQ predicate on the "response_code" field.
|
||||
func ResponseCodeEQ(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeNEQ applies the NEQ predicate on the "response_code" field.
|
||||
func ResponseCodeNEQ(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeIn applies the In predicate on the "response_code" field.
|
||||
func ResponseCodeIn(vs ...int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldResponseCode, vs...))
|
||||
}
|
||||
|
||||
// ResponseCodeNotIn applies the NotIn predicate on the "response_code" field.
|
||||
func ResponseCodeNotIn(vs ...int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldResponseCode, vs...))
|
||||
}
|
||||
|
||||
// ResponseCodeGT applies the GT predicate on the "response_code" field.
|
||||
func ResponseCodeGT(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeGTE applies the GTE predicate on the "response_code" field.
|
||||
func ResponseCodeGTE(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeLT applies the LT predicate on the "response_code" field.
|
||||
func ResponseCodeLT(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeLTE applies the LTE predicate on the "response_code" field.
|
||||
func ResponseCodeLTE(v int) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldResponseCode, v))
|
||||
}
|
||||
|
||||
// ResponseCodeIsNil applies the IsNil predicate on the "response_code" field.
|
||||
func ResponseCodeIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldResponseCode))
|
||||
}
|
||||
|
||||
// ResponseCodeNotNil applies the NotNil predicate on the "response_code" field.
|
||||
func ResponseCodeNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldResponseCode))
|
||||
}
|
||||
|
||||
// PassthroughBodyEQ applies the EQ predicate on the "passthrough_body" field.
|
||||
func PassthroughBodyEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldPassthroughBody, v))
|
||||
}
|
||||
|
||||
// PassthroughBodyNEQ applies the NEQ predicate on the "passthrough_body" field.
|
||||
func PassthroughBodyNEQ(v bool) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldPassthroughBody, v))
|
||||
}
|
||||
|
||||
// CustomMessageEQ applies the EQ predicate on the "custom_message" field.
|
||||
func CustomMessageEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageNEQ applies the NEQ predicate on the "custom_message" field.
|
||||
func CustomMessageNEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageIn applies the In predicate on the "custom_message" field.
|
||||
func CustomMessageIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldCustomMessage, vs...))
|
||||
}
|
||||
|
||||
// CustomMessageNotIn applies the NotIn predicate on the "custom_message" field.
|
||||
func CustomMessageNotIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldCustomMessage, vs...))
|
||||
}
|
||||
|
||||
// CustomMessageGT applies the GT predicate on the "custom_message" field.
|
||||
func CustomMessageGT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageGTE applies the GTE predicate on the "custom_message" field.
|
||||
func CustomMessageGTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageLT applies the LT predicate on the "custom_message" field.
|
||||
func CustomMessageLT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageLTE applies the LTE predicate on the "custom_message" field.
|
||||
func CustomMessageLTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageContains applies the Contains predicate on the "custom_message" field.
|
||||
func CustomMessageContains(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContains(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageHasPrefix applies the HasPrefix predicate on the "custom_message" field.
|
||||
func CustomMessageHasPrefix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasPrefix(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageHasSuffix applies the HasSuffix predicate on the "custom_message" field.
|
||||
func CustomMessageHasSuffix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasSuffix(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageIsNil applies the IsNil predicate on the "custom_message" field.
|
||||
func CustomMessageIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldCustomMessage))
|
||||
}
|
||||
|
||||
// CustomMessageNotNil applies the NotNil predicate on the "custom_message" field.
|
||||
func CustomMessageNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldCustomMessage))
|
||||
}
|
||||
|
||||
// CustomMessageEqualFold applies the EqualFold predicate on the "custom_message" field.
|
||||
func CustomMessageEqualFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEqualFold(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// CustomMessageContainsFold applies the ContainsFold predicate on the "custom_message" field.
|
||||
func CustomMessageContainsFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContainsFold(FieldCustomMessage, v))
|
||||
}
|
||||
|
||||
// DescriptionEQ applies the EQ predicate on the "description" field.
|
||||
func DescriptionEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEQ(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionNEQ applies the NEQ predicate on the "description" field.
|
||||
func DescriptionNEQ(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNEQ(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionIn applies the In predicate on the "description" field.
|
||||
func DescriptionIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIn(FieldDescription, vs...))
|
||||
}
|
||||
|
||||
// DescriptionNotIn applies the NotIn predicate on the "description" field.
|
||||
func DescriptionNotIn(vs ...string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotIn(FieldDescription, vs...))
|
||||
}
|
||||
|
||||
// DescriptionGT applies the GT predicate on the "description" field.
|
||||
func DescriptionGT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGT(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionGTE applies the GTE predicate on the "description" field.
|
||||
func DescriptionGTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldGTE(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionLT applies the LT predicate on the "description" field.
|
||||
func DescriptionLT(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLT(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionLTE applies the LTE predicate on the "description" field.
|
||||
func DescriptionLTE(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldLTE(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionContains applies the Contains predicate on the "description" field.
|
||||
func DescriptionContains(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContains(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field.
|
||||
func DescriptionHasPrefix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasPrefix(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field.
|
||||
func DescriptionHasSuffix(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldHasSuffix(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionIsNil applies the IsNil predicate on the "description" field.
|
||||
func DescriptionIsNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldIsNull(FieldDescription))
|
||||
}
|
||||
|
||||
// DescriptionNotNil applies the NotNil predicate on the "description" field.
|
||||
func DescriptionNotNil() predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldNotNull(FieldDescription))
|
||||
}
|
||||
|
||||
// DescriptionEqualFold applies the EqualFold predicate on the "description" field.
|
||||
func DescriptionEqualFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldEqualFold(FieldDescription, v))
|
||||
}
|
||||
|
||||
// DescriptionContainsFold applies the ContainsFold predicate on the "description" field.
|
||||
func DescriptionContainsFold(v string) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.FieldContainsFold(FieldDescription, v))
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.ErrorPassthroughRule) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.ErrorPassthroughRule) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.ErrorPassthroughRule) predicate.ErrorPassthroughRule {
|
||||
return predicate.ErrorPassthroughRule(sql.NotPredicates(p))
|
||||
}
|
||||
1382
backend/ent/errorpassthroughrule_create.go
Normal file
1382
backend/ent/errorpassthroughrule_create.go
Normal file
File diff suppressed because it is too large
Load Diff
88
backend/ent/errorpassthroughrule_delete.go
Normal file
88
backend/ent/errorpassthroughrule_delete.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ErrorPassthroughRuleDelete is the builder for deleting a ErrorPassthroughRule entity.
|
||||
type ErrorPassthroughRuleDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *ErrorPassthroughRuleMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ErrorPassthroughRuleDelete builder.
|
||||
func (_d *ErrorPassthroughRuleDelete) Where(ps ...predicate.ErrorPassthroughRule) *ErrorPassthroughRuleDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *ErrorPassthroughRuleDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *ErrorPassthroughRuleDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *ErrorPassthroughRuleDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(errorpassthroughrule.Table, sqlgraph.NewFieldSpec(errorpassthroughrule.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleDeleteOne is the builder for deleting a single ErrorPassthroughRule entity.
|
||||
type ErrorPassthroughRuleDeleteOne struct {
|
||||
_d *ErrorPassthroughRuleDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ErrorPassthroughRuleDelete builder.
|
||||
func (_d *ErrorPassthroughRuleDeleteOne) Where(ps ...predicate.ErrorPassthroughRule) *ErrorPassthroughRuleDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *ErrorPassthroughRuleDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{errorpassthroughrule.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *ErrorPassthroughRuleDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
564
backend/ent/errorpassthroughrule_query.go
Normal file
564
backend/ent/errorpassthroughrule_query.go
Normal file
@@ -0,0 +1,564 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ErrorPassthroughRuleQuery is the builder for querying ErrorPassthroughRule entities.
|
||||
type ErrorPassthroughRuleQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []errorpassthroughrule.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.ErrorPassthroughRule
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the ErrorPassthroughRuleQuery builder.
|
||||
func (_q *ErrorPassthroughRuleQuery) Where(ps ...predicate.ErrorPassthroughRule) *ErrorPassthroughRuleQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *ErrorPassthroughRuleQuery) Limit(limit int) *ErrorPassthroughRuleQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *ErrorPassthroughRuleQuery) Offset(offset int) *ErrorPassthroughRuleQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *ErrorPassthroughRuleQuery) Unique(unique bool) *ErrorPassthroughRuleQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *ErrorPassthroughRuleQuery) Order(o ...errorpassthroughrule.OrderOption) *ErrorPassthroughRuleQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// First returns the first ErrorPassthroughRule entity from the query.
|
||||
// Returns a *NotFoundError when no ErrorPassthroughRule was found.
|
||||
func (_q *ErrorPassthroughRuleQuery) First(ctx context.Context) (*ErrorPassthroughRule, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{errorpassthroughrule.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) FirstX(ctx context.Context) *ErrorPassthroughRule {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first ErrorPassthroughRule ID from the query.
|
||||
// Returns a *NotFoundError when no ErrorPassthroughRule ID was found.
|
||||
func (_q *ErrorPassthroughRuleQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{errorpassthroughrule.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single ErrorPassthroughRule entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one ErrorPassthroughRule entity is found.
|
||||
// Returns a *NotFoundError when no ErrorPassthroughRule entities are found.
|
||||
func (_q *ErrorPassthroughRuleQuery) Only(ctx context.Context) (*ErrorPassthroughRule, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{errorpassthroughrule.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{errorpassthroughrule.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) OnlyX(ctx context.Context) *ErrorPassthroughRule {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only ErrorPassthroughRule ID in the query.
|
||||
// Returns a *NotSingularError when more than one ErrorPassthroughRule ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *ErrorPassthroughRuleQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{errorpassthroughrule.Label}
|
||||
default:
|
||||
err = &NotSingularError{errorpassthroughrule.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of ErrorPassthroughRules.
|
||||
func (_q *ErrorPassthroughRuleQuery) All(ctx context.Context) ([]*ErrorPassthroughRule, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*ErrorPassthroughRule, *ErrorPassthroughRuleQuery]()
|
||||
return withInterceptors[[]*ErrorPassthroughRule](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) AllX(ctx context.Context) []*ErrorPassthroughRule {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of ErrorPassthroughRule IDs.
|
||||
func (_q *ErrorPassthroughRuleQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(errorpassthroughrule.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *ErrorPassthroughRuleQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*ErrorPassthroughRuleQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *ErrorPassthroughRuleQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *ErrorPassthroughRuleQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the ErrorPassthroughRuleQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *ErrorPassthroughRuleQuery) Clone() *ErrorPassthroughRuleQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &ErrorPassthroughRuleQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]errorpassthroughrule.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.ErrorPassthroughRule{}, _q.predicates...),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.ErrorPassthroughRule.Query().
|
||||
// GroupBy(errorpassthroughrule.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *ErrorPassthroughRuleQuery) GroupBy(field string, fields ...string) *ErrorPassthroughRuleGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &ErrorPassthroughRuleGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = errorpassthroughrule.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.ErrorPassthroughRule.Query().
|
||||
// Select(errorpassthroughrule.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *ErrorPassthroughRuleQuery) Select(fields ...string) *ErrorPassthroughRuleSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &ErrorPassthroughRuleSelect{ErrorPassthroughRuleQuery: _q}
|
||||
sbuild.label = errorpassthroughrule.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a ErrorPassthroughRuleSelect configured with the given aggregations.
|
||||
func (_q *ErrorPassthroughRuleQuery) Aggregate(fns ...AggregateFunc) *ErrorPassthroughRuleSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *ErrorPassthroughRuleQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !errorpassthroughrule.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *ErrorPassthroughRuleQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ErrorPassthroughRule, error) {
|
||||
var (
|
||||
nodes = []*ErrorPassthroughRule{}
|
||||
_spec = _q.querySpec()
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*ErrorPassthroughRule).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &ErrorPassthroughRule{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *ErrorPassthroughRuleQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *ErrorPassthroughRuleQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(errorpassthroughrule.Table, errorpassthroughrule.Columns, sqlgraph.NewFieldSpec(errorpassthroughrule.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, errorpassthroughrule.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != errorpassthroughrule.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *ErrorPassthroughRuleQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(errorpassthroughrule.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = errorpassthroughrule.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *ErrorPassthroughRuleQuery) ForUpdate(opts ...sql.LockOption) *ErrorPassthroughRuleQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *ErrorPassthroughRuleQuery) ForShare(opts ...sql.LockOption) *ErrorPassthroughRuleQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleGroupBy is the group-by builder for ErrorPassthroughRule entities.
|
||||
type ErrorPassthroughRuleGroupBy struct {
|
||||
selector
|
||||
build *ErrorPassthroughRuleQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *ErrorPassthroughRuleGroupBy) Aggregate(fns ...AggregateFunc) *ErrorPassthroughRuleGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *ErrorPassthroughRuleGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*ErrorPassthroughRuleQuery, *ErrorPassthroughRuleGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *ErrorPassthroughRuleGroupBy) sqlScan(ctx context.Context, root *ErrorPassthroughRuleQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleSelect is the builder for selecting fields of ErrorPassthroughRule entities.
|
||||
type ErrorPassthroughRuleSelect struct {
|
||||
*ErrorPassthroughRuleQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *ErrorPassthroughRuleSelect) Aggregate(fns ...AggregateFunc) *ErrorPassthroughRuleSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *ErrorPassthroughRuleSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*ErrorPassthroughRuleQuery, *ErrorPassthroughRuleSelect](ctx, _s.ErrorPassthroughRuleQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *ErrorPassthroughRuleSelect) sqlScan(ctx context.Context, root *ErrorPassthroughRuleQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
823
backend/ent/errorpassthroughrule_update.go
Normal file
823
backend/ent/errorpassthroughrule_update.go
Normal file
@@ -0,0 +1,823 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/dialect/sql/sqljson"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ErrorPassthroughRuleUpdate is the builder for updating ErrorPassthroughRule entities.
|
||||
type ErrorPassthroughRuleUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *ErrorPassthroughRuleMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ErrorPassthroughRuleUpdate builder.
|
||||
func (_u *ErrorPassthroughRuleUpdate) Where(ps ...predicate.ErrorPassthroughRule) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetUpdatedAt(v time.Time) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetName(v string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetName(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableName sets the "name" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableName(v *string) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetName(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetEnabled sets the "enabled" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetEnabled(v bool) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetEnabled(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableEnabled sets the "enabled" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableEnabled(v *bool) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetEnabled(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPriority sets the "priority" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetPriority(v int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ResetPriority()
|
||||
_u.mutation.SetPriority(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePriority sets the "priority" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillablePriority(v *int) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetPriority(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddPriority adds value to the "priority" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) AddPriority(v int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.AddPriority(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetErrorCodes sets the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetErrorCodes(v []int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetErrorCodes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendErrorCodes appends value to the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) AppendErrorCodes(v []int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.AppendErrorCodes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearErrorCodes clears the value of the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearErrorCodes() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearErrorCodes()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetKeywords sets the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetKeywords(v []string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetKeywords(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendKeywords appends value to the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) AppendKeywords(v []string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.AppendKeywords(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearKeywords clears the value of the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearKeywords() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearKeywords()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMatchMode sets the "match_mode" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetMatchMode(v string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetMatchMode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableMatchMode sets the "match_mode" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableMatchMode(v *string) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetMatchMode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPlatforms sets the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetPlatforms(v []string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetPlatforms(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendPlatforms appends value to the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) AppendPlatforms(v []string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.AppendPlatforms(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearPlatforms clears the value of the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearPlatforms() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearPlatforms()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPassthroughCode sets the "passthrough_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetPassthroughCode(v bool) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetPassthroughCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePassthroughCode sets the "passthrough_code" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillablePassthroughCode(v *bool) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetPassthroughCode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetResponseCode sets the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetResponseCode(v int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ResetResponseCode()
|
||||
_u.mutation.SetResponseCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableResponseCode sets the "response_code" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableResponseCode(v *int) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetResponseCode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddResponseCode adds value to the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) AddResponseCode(v int) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.AddResponseCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearResponseCode clears the value of the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearResponseCode() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearResponseCode()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPassthroughBody sets the "passthrough_body" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetPassthroughBody(v bool) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetPassthroughBody(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePassthroughBody sets the "passthrough_body" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillablePassthroughBody(v *bool) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetPassthroughBody(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetCustomMessage sets the "custom_message" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetCustomMessage(v string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetCustomMessage(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableCustomMessage sets the "custom_message" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableCustomMessage(v *string) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetCustomMessage(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearCustomMessage clears the value of the "custom_message" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearCustomMessage() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearCustomMessage()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetDescription sets the "description" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetDescription(v string) *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.SetDescription(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableDescription sets the "description" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SetNillableDescription(v *string) *ErrorPassthroughRuleUpdate {
|
||||
if v != nil {
|
||||
_u.SetDescription(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearDescription clears the value of the "description" field.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ClearDescription() *ErrorPassthroughRuleUpdate {
|
||||
_u.mutation.ClearDescription()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Mutation returns the ErrorPassthroughRuleMutation object of the builder.
|
||||
func (_u *ErrorPassthroughRuleUpdate) Mutation() *ErrorPassthroughRuleMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *ErrorPassthroughRuleUpdate) Save(ctx context.Context) (int, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *ErrorPassthroughRuleUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *ErrorPassthroughRuleUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *ErrorPassthroughRuleUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *ErrorPassthroughRuleUpdate) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := errorpassthroughrule.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *ErrorPassthroughRuleUpdate) check() error {
|
||||
if v, ok := _u.mutation.Name(); ok {
|
||||
if err := errorpassthroughrule.NameValidator(v); err != nil {
|
||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ErrorPassthroughRule.name": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.MatchMode(); ok {
|
||||
if err := errorpassthroughrule.MatchModeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "match_mode", err: fmt.Errorf(`ent: validator failed for field "ErrorPassthroughRule.match_mode": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *ErrorPassthroughRuleUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(errorpassthroughrule.Table, errorpassthroughrule.Columns, sqlgraph.NewFieldSpec(errorpassthroughrule.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Name(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldName, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Enabled(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Priority(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPriority, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedPriority(); ok {
|
||||
_spec.AddField(errorpassthroughrule.FieldPriority, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ErrorCodes(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldErrorCodes, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedErrorCodes(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldErrorCodes, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.ErrorCodesCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldErrorCodes, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Keywords(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldKeywords, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedKeywords(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldKeywords, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.KeywordsCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldKeywords, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.MatchMode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldMatchMode, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Platforms(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPlatforms, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedPlatforms(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldPlatforms, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.PlatformsCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldPlatforms, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.PassthroughCode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPassthroughCode, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ResponseCode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldResponseCode, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedResponseCode(); ok {
|
||||
_spec.AddField(errorpassthroughrule.FieldResponseCode, field.TypeInt, value)
|
||||
}
|
||||
if _u.mutation.ResponseCodeCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldResponseCode, field.TypeInt)
|
||||
}
|
||||
if value, ok := _u.mutation.PassthroughBody(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPassthroughBody, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.CustomMessage(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldCustomMessage, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.CustomMessageCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldCustomMessage, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.Description(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldDescription, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.DescriptionCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldDescription, field.TypeString)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{errorpassthroughrule.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleUpdateOne is the builder for updating a single ErrorPassthroughRule entity.
|
||||
type ErrorPassthroughRuleUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *ErrorPassthroughRuleMutation
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetUpdatedAt(v time.Time) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetName(v string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetName(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableName sets the "name" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableName(v *string) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetName(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetEnabled sets the "enabled" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetEnabled(v bool) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetEnabled(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableEnabled sets the "enabled" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableEnabled(v *bool) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetEnabled(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPriority sets the "priority" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetPriority(v int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ResetPriority()
|
||||
_u.mutation.SetPriority(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePriority sets the "priority" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillablePriority(v *int) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetPriority(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddPriority adds value to the "priority" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) AddPriority(v int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.AddPriority(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetErrorCodes sets the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetErrorCodes(v []int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetErrorCodes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendErrorCodes appends value to the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) AppendErrorCodes(v []int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.AppendErrorCodes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearErrorCodes clears the value of the "error_codes" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearErrorCodes() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearErrorCodes()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetKeywords sets the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetKeywords(v []string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetKeywords(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendKeywords appends value to the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) AppendKeywords(v []string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.AppendKeywords(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearKeywords clears the value of the "keywords" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearKeywords() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearKeywords()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMatchMode sets the "match_mode" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetMatchMode(v string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetMatchMode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableMatchMode sets the "match_mode" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableMatchMode(v *string) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetMatchMode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPlatforms sets the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetPlatforms(v []string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetPlatforms(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendPlatforms appends value to the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) AppendPlatforms(v []string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.AppendPlatforms(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearPlatforms clears the value of the "platforms" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearPlatforms() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearPlatforms()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPassthroughCode sets the "passthrough_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetPassthroughCode(v bool) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetPassthroughCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePassthroughCode sets the "passthrough_code" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillablePassthroughCode(v *bool) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetPassthroughCode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetResponseCode sets the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetResponseCode(v int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ResetResponseCode()
|
||||
_u.mutation.SetResponseCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableResponseCode sets the "response_code" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableResponseCode(v *int) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetResponseCode(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddResponseCode adds value to the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) AddResponseCode(v int) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.AddResponseCode(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearResponseCode clears the value of the "response_code" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearResponseCode() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearResponseCode()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPassthroughBody sets the "passthrough_body" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetPassthroughBody(v bool) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetPassthroughBody(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePassthroughBody sets the "passthrough_body" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillablePassthroughBody(v *bool) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetPassthroughBody(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetCustomMessage sets the "custom_message" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetCustomMessage(v string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetCustomMessage(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableCustomMessage sets the "custom_message" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableCustomMessage(v *string) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetCustomMessage(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearCustomMessage clears the value of the "custom_message" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearCustomMessage() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearCustomMessage()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetDescription sets the "description" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetDescription(v string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.SetDescription(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableDescription sets the "description" field if the given value is not nil.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SetNillableDescription(v *string) *ErrorPassthroughRuleUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetDescription(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearDescription clears the value of the "description" field.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ClearDescription() *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.ClearDescription()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Mutation returns the ErrorPassthroughRuleMutation object of the builder.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) Mutation() *ErrorPassthroughRuleMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ErrorPassthroughRuleUpdate builder.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) Where(ps ...predicate.ErrorPassthroughRule) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) Select(field string, fields ...string) *ErrorPassthroughRuleUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated ErrorPassthroughRule entity.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) Save(ctx context.Context) (*ErrorPassthroughRule, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) SaveX(ctx context.Context) *ErrorPassthroughRule {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := errorpassthroughrule.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) check() error {
|
||||
if v, ok := _u.mutation.Name(); ok {
|
||||
if err := errorpassthroughrule.NameValidator(v); err != nil {
|
||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ErrorPassthroughRule.name": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.MatchMode(); ok {
|
||||
if err := errorpassthroughrule.MatchModeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "match_mode", err: fmt.Errorf(`ent: validator failed for field "ErrorPassthroughRule.match_mode": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *ErrorPassthroughRuleUpdateOne) sqlSave(ctx context.Context) (_node *ErrorPassthroughRule, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(errorpassthroughrule.Table, errorpassthroughrule.Columns, sqlgraph.NewFieldSpec(errorpassthroughrule.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ErrorPassthroughRule.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, errorpassthroughrule.FieldID)
|
||||
for _, f := range fields {
|
||||
if !errorpassthroughrule.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != errorpassthroughrule.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Name(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldName, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Enabled(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Priority(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPriority, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedPriority(); ok {
|
||||
_spec.AddField(errorpassthroughrule.FieldPriority, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ErrorCodes(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldErrorCodes, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedErrorCodes(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldErrorCodes, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.ErrorCodesCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldErrorCodes, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Keywords(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldKeywords, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedKeywords(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldKeywords, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.KeywordsCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldKeywords, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.MatchMode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldMatchMode, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Platforms(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPlatforms, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedPlatforms(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, errorpassthroughrule.FieldPlatforms, value)
|
||||
})
|
||||
}
|
||||
if _u.mutation.PlatformsCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldPlatforms, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.PassthroughCode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPassthroughCode, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ResponseCode(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldResponseCode, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedResponseCode(); ok {
|
||||
_spec.AddField(errorpassthroughrule.FieldResponseCode, field.TypeInt, value)
|
||||
}
|
||||
if _u.mutation.ResponseCodeCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldResponseCode, field.TypeInt)
|
||||
}
|
||||
if value, ok := _u.mutation.PassthroughBody(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldPassthroughBody, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.CustomMessage(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldCustomMessage, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.CustomMessageCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldCustomMessage, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.Description(); ok {
|
||||
_spec.SetField(errorpassthroughrule.FieldDescription, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.DescriptionCleared() {
|
||||
_spec.ClearField(errorpassthroughrule.FieldDescription, field.TypeString)
|
||||
}
|
||||
_node = &ErrorPassthroughRule{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{errorpassthroughrule.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
@@ -56,10 +56,18 @@ type Group struct {
|
||||
ClaudeCodeOnly bool `json:"claude_code_only,omitempty"`
|
||||
// 非 Claude Code 请求降级使用的分组 ID
|
||||
FallbackGroupID *int64 `json:"fallback_group_id,omitempty"`
|
||||
// 无效请求兜底使用的分组 ID
|
||||
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request,omitempty"`
|
||||
// 模型路由配置:模型模式 -> 优先账号ID列表
|
||||
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
||||
// 是否启用模型路由配置
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled,omitempty"`
|
||||
// 是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)
|
||||
McpXMLInject bool `json:"mcp_xml_inject,omitempty"`
|
||||
// 支持的模型系列:claude, gemini_text, gemini_image
|
||||
SupportedModelScopes []string `json:"supported_model_scopes,omitempty"`
|
||||
// 分组显示排序,数值越小越靠前
|
||||
SortOrder int `json:"sort_order,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the GroupQuery when eager-loading is set.
|
||||
Edges GroupEdges `json:"edges"`
|
||||
@@ -166,13 +174,13 @@ func (*Group) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case group.FieldModelRouting:
|
||||
case group.FieldModelRouting, group.FieldSupportedModelScopes:
|
||||
values[i] = new([]byte)
|
||||
case group.FieldIsExclusive, group.FieldClaudeCodeOnly, group.FieldModelRoutingEnabled:
|
||||
case group.FieldIsExclusive, group.FieldClaudeCodeOnly, group.FieldModelRoutingEnabled, group.FieldMcpXMLInject:
|
||||
values[i] = new(sql.NullBool)
|
||||
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd, group.FieldImagePrice1k, group.FieldImagePrice2k, group.FieldImagePrice4k:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
case group.FieldID, group.FieldDefaultValidityDays, group.FieldFallbackGroupID:
|
||||
case group.FieldID, group.FieldDefaultValidityDays, group.FieldFallbackGroupID, group.FieldFallbackGroupIDOnInvalidRequest, group.FieldSortOrder:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case group.FieldName, group.FieldDescription, group.FieldStatus, group.FieldPlatform, group.FieldSubscriptionType:
|
||||
values[i] = new(sql.NullString)
|
||||
@@ -322,6 +330,13 @@ func (_m *Group) assignValues(columns []string, values []any) error {
|
||||
_m.FallbackGroupID = new(int64)
|
||||
*_m.FallbackGroupID = value.Int64
|
||||
}
|
||||
case group.FieldFallbackGroupIDOnInvalidRequest:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field fallback_group_id_on_invalid_request", values[i])
|
||||
} else if value.Valid {
|
||||
_m.FallbackGroupIDOnInvalidRequest = new(int64)
|
||||
*_m.FallbackGroupIDOnInvalidRequest = value.Int64
|
||||
}
|
||||
case group.FieldModelRouting:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field model_routing", values[i])
|
||||
@@ -336,6 +351,26 @@ func (_m *Group) assignValues(columns []string, values []any) error {
|
||||
} else if value.Valid {
|
||||
_m.ModelRoutingEnabled = value.Bool
|
||||
}
|
||||
case group.FieldMcpXMLInject:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field mcp_xml_inject", values[i])
|
||||
} else if value.Valid {
|
||||
_m.McpXMLInject = value.Bool
|
||||
}
|
||||
case group.FieldSupportedModelScopes:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field supported_model_scopes", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.SupportedModelScopes); err != nil {
|
||||
return fmt.Errorf("unmarshal field supported_model_scopes: %w", err)
|
||||
}
|
||||
}
|
||||
case group.FieldSortOrder:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field sort_order", values[i])
|
||||
} else if value.Valid {
|
||||
_m.SortOrder = int(value.Int64)
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
@@ -487,11 +522,25 @@ func (_m *Group) String() string {
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.FallbackGroupIDOnInvalidRequest; v != nil {
|
||||
builder.WriteString("fallback_group_id_on_invalid_request=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("model_routing=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.ModelRouting))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("model_routing_enabled=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.ModelRoutingEnabled))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("mcp_xml_inject=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.McpXMLInject))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("supported_model_scopes=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.SupportedModelScopes))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("sort_order=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.SortOrder))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -53,10 +53,18 @@ const (
|
||||
FieldClaudeCodeOnly = "claude_code_only"
|
||||
// FieldFallbackGroupID holds the string denoting the fallback_group_id field in the database.
|
||||
FieldFallbackGroupID = "fallback_group_id"
|
||||
// FieldFallbackGroupIDOnInvalidRequest holds the string denoting the fallback_group_id_on_invalid_request field in the database.
|
||||
FieldFallbackGroupIDOnInvalidRequest = "fallback_group_id_on_invalid_request"
|
||||
// FieldModelRouting holds the string denoting the model_routing field in the database.
|
||||
FieldModelRouting = "model_routing"
|
||||
// FieldModelRoutingEnabled holds the string denoting the model_routing_enabled field in the database.
|
||||
FieldModelRoutingEnabled = "model_routing_enabled"
|
||||
// FieldMcpXMLInject holds the string denoting the mcp_xml_inject field in the database.
|
||||
FieldMcpXMLInject = "mcp_xml_inject"
|
||||
// FieldSupportedModelScopes holds the string denoting the supported_model_scopes field in the database.
|
||||
FieldSupportedModelScopes = "supported_model_scopes"
|
||||
// FieldSortOrder holds the string denoting the sort_order field in the database.
|
||||
FieldSortOrder = "sort_order"
|
||||
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
|
||||
EdgeAPIKeys = "api_keys"
|
||||
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
||||
@@ -151,8 +159,12 @@ var Columns = []string{
|
||||
FieldImagePrice4k,
|
||||
FieldClaudeCodeOnly,
|
||||
FieldFallbackGroupID,
|
||||
FieldFallbackGroupIDOnInvalidRequest,
|
||||
FieldModelRouting,
|
||||
FieldModelRoutingEnabled,
|
||||
FieldMcpXMLInject,
|
||||
FieldSupportedModelScopes,
|
||||
FieldSortOrder,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -212,6 +224,12 @@ var (
|
||||
DefaultClaudeCodeOnly bool
|
||||
// DefaultModelRoutingEnabled holds the default value on creation for the "model_routing_enabled" field.
|
||||
DefaultModelRoutingEnabled bool
|
||||
// DefaultMcpXMLInject holds the default value on creation for the "mcp_xml_inject" field.
|
||||
DefaultMcpXMLInject bool
|
||||
// DefaultSupportedModelScopes holds the default value on creation for the "supported_model_scopes" field.
|
||||
DefaultSupportedModelScopes []string
|
||||
// DefaultSortOrder holds the default value on creation for the "sort_order" field.
|
||||
DefaultSortOrder int
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the Group queries.
|
||||
@@ -317,11 +335,26 @@ func ByFallbackGroupID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldFallbackGroupID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByFallbackGroupIDOnInvalidRequest orders the results by the fallback_group_id_on_invalid_request field.
|
||||
func ByFallbackGroupIDOnInvalidRequest(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldFallbackGroupIDOnInvalidRequest, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByModelRoutingEnabled orders the results by the model_routing_enabled field.
|
||||
func ByModelRoutingEnabled(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldModelRoutingEnabled, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByMcpXMLInject orders the results by the mcp_xml_inject field.
|
||||
func ByMcpXMLInject(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldMcpXMLInject, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySortOrder orders the results by the sort_order field.
|
||||
func BySortOrder(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSortOrder, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAPIKeysCount orders the results by api_keys count.
|
||||
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
|
||||
@@ -150,11 +150,26 @@ func FallbackGroupID(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldFallbackGroupID, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequest applies equality check predicate on the "fallback_group_id_on_invalid_request" field. It's identical to FallbackGroupIDOnInvalidRequestEQ.
|
||||
func FallbackGroupIDOnInvalidRequest(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// ModelRoutingEnabled applies equality check predicate on the "model_routing_enabled" field. It's identical to ModelRoutingEnabledEQ.
|
||||
func ModelRoutingEnabled(v bool) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldModelRoutingEnabled, v))
|
||||
}
|
||||
|
||||
// McpXMLInject applies equality check predicate on the "mcp_xml_inject" field. It's identical to McpXMLInjectEQ.
|
||||
func McpXMLInject(v bool) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldMcpXMLInject, v))
|
||||
}
|
||||
|
||||
// SortOrder applies equality check predicate on the "sort_order" field. It's identical to SortOrderEQ.
|
||||
func SortOrder(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
|
||||
@@ -1070,6 +1085,56 @@ func FallbackGroupIDNotNil() predicate.Group {
|
||||
return predicate.Group(sql.FieldNotNull(FieldFallbackGroupID))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestEQ applies the EQ predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestEQ(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestNEQ applies the NEQ predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestNEQ(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldNEQ(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestIn applies the In predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestIn(vs ...int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldIn(FieldFallbackGroupIDOnInvalidRequest, vs...))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestNotIn applies the NotIn predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestNotIn(vs ...int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldNotIn(FieldFallbackGroupIDOnInvalidRequest, vs...))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestGT applies the GT predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestGT(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldGT(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestGTE applies the GTE predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestGTE(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldGTE(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestLT applies the LT predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestLT(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldLT(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestLTE applies the LTE predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestLTE(v int64) predicate.Group {
|
||||
return predicate.Group(sql.FieldLTE(FieldFallbackGroupIDOnInvalidRequest, v))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestIsNil applies the IsNil predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestIsNil() predicate.Group {
|
||||
return predicate.Group(sql.FieldIsNull(FieldFallbackGroupIDOnInvalidRequest))
|
||||
}
|
||||
|
||||
// FallbackGroupIDOnInvalidRequestNotNil applies the NotNil predicate on the "fallback_group_id_on_invalid_request" field.
|
||||
func FallbackGroupIDOnInvalidRequestNotNil() predicate.Group {
|
||||
return predicate.Group(sql.FieldNotNull(FieldFallbackGroupIDOnInvalidRequest))
|
||||
}
|
||||
|
||||
// ModelRoutingIsNil applies the IsNil predicate on the "model_routing" field.
|
||||
func ModelRoutingIsNil() predicate.Group {
|
||||
return predicate.Group(sql.FieldIsNull(FieldModelRouting))
|
||||
@@ -1090,6 +1155,56 @@ func ModelRoutingEnabledNEQ(v bool) predicate.Group {
|
||||
return predicate.Group(sql.FieldNEQ(FieldModelRoutingEnabled, v))
|
||||
}
|
||||
|
||||
// McpXMLInjectEQ applies the EQ predicate on the "mcp_xml_inject" field.
|
||||
func McpXMLInjectEQ(v bool) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldMcpXMLInject, v))
|
||||
}
|
||||
|
||||
// McpXMLInjectNEQ applies the NEQ predicate on the "mcp_xml_inject" field.
|
||||
func McpXMLInjectNEQ(v bool) predicate.Group {
|
||||
return predicate.Group(sql.FieldNEQ(FieldMcpXMLInject, v))
|
||||
}
|
||||
|
||||
// SortOrderEQ applies the EQ predicate on the "sort_order" field.
|
||||
func SortOrderEQ(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldEQ(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// SortOrderNEQ applies the NEQ predicate on the "sort_order" field.
|
||||
func SortOrderNEQ(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldNEQ(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// SortOrderIn applies the In predicate on the "sort_order" field.
|
||||
func SortOrderIn(vs ...int) predicate.Group {
|
||||
return predicate.Group(sql.FieldIn(FieldSortOrder, vs...))
|
||||
}
|
||||
|
||||
// SortOrderNotIn applies the NotIn predicate on the "sort_order" field.
|
||||
func SortOrderNotIn(vs ...int) predicate.Group {
|
||||
return predicate.Group(sql.FieldNotIn(FieldSortOrder, vs...))
|
||||
}
|
||||
|
||||
// SortOrderGT applies the GT predicate on the "sort_order" field.
|
||||
func SortOrderGT(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldGT(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// SortOrderGTE applies the GTE predicate on the "sort_order" field.
|
||||
func SortOrderGTE(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldGTE(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// SortOrderLT applies the LT predicate on the "sort_order" field.
|
||||
func SortOrderLT(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldLT(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// SortOrderLTE applies the LTE predicate on the "sort_order" field.
|
||||
func SortOrderLTE(v int) predicate.Group {
|
||||
return predicate.Group(sql.FieldLTE(FieldSortOrder, v))
|
||||
}
|
||||
|
||||
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
|
||||
func HasAPIKeys() predicate.Group {
|
||||
return predicate.Group(func(s *sql.Selector) {
|
||||
|
||||
@@ -286,6 +286,20 @@ func (_c *GroupCreate) SetNillableFallbackGroupID(v *int64) *GroupCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (_c *GroupCreate) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupCreate {
|
||||
_c.mutation.SetFallbackGroupIDOnInvalidRequest(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
|
||||
func (_c *GroupCreate) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupCreate {
|
||||
if v != nil {
|
||||
_c.SetFallbackGroupIDOnInvalidRequest(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (_c *GroupCreate) SetModelRouting(v map[string][]int64) *GroupCreate {
|
||||
_c.mutation.SetModelRouting(v)
|
||||
@@ -306,6 +320,40 @@ func (_c *GroupCreate) SetNillableModelRoutingEnabled(v *bool) *GroupCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (_c *GroupCreate) SetMcpXMLInject(v bool) *GroupCreate {
|
||||
_c.mutation.SetMcpXMLInject(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
|
||||
func (_c *GroupCreate) SetNillableMcpXMLInject(v *bool) *GroupCreate {
|
||||
if v != nil {
|
||||
_c.SetMcpXMLInject(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (_c *GroupCreate) SetSupportedModelScopes(v []string) *GroupCreate {
|
||||
_c.mutation.SetSupportedModelScopes(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (_c *GroupCreate) SetSortOrder(v int) *GroupCreate {
|
||||
_c.mutation.SetSortOrder(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
|
||||
func (_c *GroupCreate) SetNillableSortOrder(v *int) *GroupCreate {
|
||||
if v != nil {
|
||||
_c.SetSortOrder(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
||||
_c.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -479,6 +527,18 @@ func (_c *GroupCreate) defaults() error {
|
||||
v := group.DefaultModelRoutingEnabled
|
||||
_c.mutation.SetModelRoutingEnabled(v)
|
||||
}
|
||||
if _, ok := _c.mutation.McpXMLInject(); !ok {
|
||||
v := group.DefaultMcpXMLInject
|
||||
_c.mutation.SetMcpXMLInject(v)
|
||||
}
|
||||
if _, ok := _c.mutation.SupportedModelScopes(); !ok {
|
||||
v := group.DefaultSupportedModelScopes
|
||||
_c.mutation.SetSupportedModelScopes(v)
|
||||
}
|
||||
if _, ok := _c.mutation.SortOrder(); !ok {
|
||||
v := group.DefaultSortOrder
|
||||
_c.mutation.SetSortOrder(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -537,6 +597,15 @@ func (_c *GroupCreate) check() error {
|
||||
if _, ok := _c.mutation.ModelRoutingEnabled(); !ok {
|
||||
return &ValidationError{Name: "model_routing_enabled", err: errors.New(`ent: missing required field "Group.model_routing_enabled"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.McpXMLInject(); !ok {
|
||||
return &ValidationError{Name: "mcp_xml_inject", err: errors.New(`ent: missing required field "Group.mcp_xml_inject"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.SupportedModelScopes(); !ok {
|
||||
return &ValidationError{Name: "supported_model_scopes", err: errors.New(`ent: missing required field "Group.supported_model_scopes"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.SortOrder(); !ok {
|
||||
return &ValidationError{Name: "sort_order", err: errors.New(`ent: missing required field "Group.sort_order"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -640,6 +709,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(group.FieldFallbackGroupID, field.TypeInt64, value)
|
||||
_node.FallbackGroupID = &value
|
||||
}
|
||||
if value, ok := _c.mutation.FallbackGroupIDOnInvalidRequest(); ok {
|
||||
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
|
||||
_node.FallbackGroupIDOnInvalidRequest = &value
|
||||
}
|
||||
if value, ok := _c.mutation.ModelRouting(); ok {
|
||||
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
|
||||
_node.ModelRouting = value
|
||||
@@ -648,6 +721,18 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
||||
_node.ModelRoutingEnabled = value
|
||||
}
|
||||
if value, ok := _c.mutation.McpXMLInject(); ok {
|
||||
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
|
||||
_node.McpXMLInject = value
|
||||
}
|
||||
if value, ok := _c.mutation.SupportedModelScopes(); ok {
|
||||
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
|
||||
_node.SupportedModelScopes = value
|
||||
}
|
||||
if value, ok := _c.mutation.SortOrder(); ok {
|
||||
_spec.SetField(group.FieldSortOrder, field.TypeInt, value)
|
||||
_node.SortOrder = value
|
||||
}
|
||||
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -1128,6 +1213,30 @@ func (u *GroupUpsert) ClearFallbackGroupID() *GroupUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsert) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsert {
|
||||
u.Set(group.FieldFallbackGroupIDOnInvalidRequest, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
|
||||
func (u *GroupUpsert) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsert {
|
||||
u.SetExcluded(group.FieldFallbackGroupIDOnInvalidRequest)
|
||||
return u
|
||||
}
|
||||
|
||||
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsert) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsert {
|
||||
u.Add(group.FieldFallbackGroupIDOnInvalidRequest, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsert) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsert {
|
||||
u.SetNull(group.FieldFallbackGroupIDOnInvalidRequest)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (u *GroupUpsert) SetModelRouting(v map[string][]int64) *GroupUpsert {
|
||||
u.Set(group.FieldModelRouting, v)
|
||||
@@ -1158,6 +1267,48 @@ func (u *GroupUpsert) UpdateModelRoutingEnabled() *GroupUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (u *GroupUpsert) SetMcpXMLInject(v bool) *GroupUpsert {
|
||||
u.Set(group.FieldMcpXMLInject, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
|
||||
func (u *GroupUpsert) UpdateMcpXMLInject() *GroupUpsert {
|
||||
u.SetExcluded(group.FieldMcpXMLInject)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (u *GroupUpsert) SetSupportedModelScopes(v []string) *GroupUpsert {
|
||||
u.Set(group.FieldSupportedModelScopes, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
|
||||
func (u *GroupUpsert) UpdateSupportedModelScopes() *GroupUpsert {
|
||||
u.SetExcluded(group.FieldSupportedModelScopes)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (u *GroupUpsert) SetSortOrder(v int) *GroupUpsert {
|
||||
u.Set(group.FieldSortOrder, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
|
||||
func (u *GroupUpsert) UpdateSortOrder() *GroupUpsert {
|
||||
u.SetExcluded(group.FieldSortOrder)
|
||||
return u
|
||||
}
|
||||
|
||||
// AddSortOrder adds v to the "sort_order" field.
|
||||
func (u *GroupUpsert) AddSortOrder(v int) *GroupUpsert {
|
||||
u.Add(group.FieldSortOrder, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
@@ -1581,6 +1732,34 @@ func (u *GroupUpsertOne) ClearFallbackGroupID() *GroupUpsertOne {
|
||||
})
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertOne) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetFallbackGroupIDOnInvalidRequest(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertOne) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.AddFallbackGroupIDOnInvalidRequest(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
|
||||
func (u *GroupUpsertOne) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateFallbackGroupIDOnInvalidRequest()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertOne) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.ClearFallbackGroupIDOnInvalidRequest()
|
||||
})
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (u *GroupUpsertOne) SetModelRouting(v map[string][]int64) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
@@ -1616,6 +1795,55 @@ func (u *GroupUpsertOne) UpdateModelRoutingEnabled() *GroupUpsertOne {
|
||||
})
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (u *GroupUpsertOne) SetMcpXMLInject(v bool) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetMcpXMLInject(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
|
||||
func (u *GroupUpsertOne) UpdateMcpXMLInject() *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateMcpXMLInject()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (u *GroupUpsertOne) SetSupportedModelScopes(v []string) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetSupportedModelScopes(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
|
||||
func (u *GroupUpsertOne) UpdateSupportedModelScopes() *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateSupportedModelScopes()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (u *GroupUpsertOne) SetSortOrder(v int) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetSortOrder(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddSortOrder adds v to the "sort_order" field.
|
||||
func (u *GroupUpsertOne) AddSortOrder(v int) *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.AddSortOrder(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
|
||||
func (u *GroupUpsertOne) UpdateSortOrder() *GroupUpsertOne {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateSortOrder()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
@@ -2205,6 +2433,34 @@ func (u *GroupUpsertBulk) ClearFallbackGroupID() *GroupUpsertBulk {
|
||||
})
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertBulk) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetFallbackGroupIDOnInvalidRequest(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertBulk) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.AddFallbackGroupIDOnInvalidRequest(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
|
||||
func (u *GroupUpsertBulk) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateFallbackGroupIDOnInvalidRequest()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
|
||||
func (u *GroupUpsertBulk) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.ClearFallbackGroupIDOnInvalidRequest()
|
||||
})
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (u *GroupUpsertBulk) SetModelRouting(v map[string][]int64) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
@@ -2240,6 +2496,55 @@ func (u *GroupUpsertBulk) UpdateModelRoutingEnabled() *GroupUpsertBulk {
|
||||
})
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (u *GroupUpsertBulk) SetMcpXMLInject(v bool) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetMcpXMLInject(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
|
||||
func (u *GroupUpsertBulk) UpdateMcpXMLInject() *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateMcpXMLInject()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (u *GroupUpsertBulk) SetSupportedModelScopes(v []string) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetSupportedModelScopes(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
|
||||
func (u *GroupUpsertBulk) UpdateSupportedModelScopes() *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateSupportedModelScopes()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (u *GroupUpsertBulk) SetSortOrder(v int) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.SetSortOrder(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddSortOrder adds v to the "sort_order" field.
|
||||
func (u *GroupUpsertBulk) AddSortOrder(v int) *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.AddSortOrder(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
|
||||
func (u *GroupUpsertBulk) UpdateSortOrder() *GroupUpsertBulk {
|
||||
return u.Update(func(s *GroupUpsert) {
|
||||
s.UpdateSortOrder()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/dialect/sql/sqljson"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/account"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
@@ -395,6 +396,33 @@ func (_u *GroupUpdate) ClearFallbackGroupID() *GroupUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdate) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdate {
|
||||
_u.mutation.ResetFallbackGroupIDOnInvalidRequest()
|
||||
_u.mutation.SetFallbackGroupIDOnInvalidRequest(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
|
||||
func (_u *GroupUpdate) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupUpdate {
|
||||
if v != nil {
|
||||
_u.SetFallbackGroupIDOnInvalidRequest(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddFallbackGroupIDOnInvalidRequest adds value to the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdate) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdate {
|
||||
_u.mutation.AddFallbackGroupIDOnInvalidRequest(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdate) ClearFallbackGroupIDOnInvalidRequest() *GroupUpdate {
|
||||
_u.mutation.ClearFallbackGroupIDOnInvalidRequest()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (_u *GroupUpdate) SetModelRouting(v map[string][]int64) *GroupUpdate {
|
||||
_u.mutation.SetModelRouting(v)
|
||||
@@ -421,6 +449,53 @@ func (_u *GroupUpdate) SetNillableModelRoutingEnabled(v *bool) *GroupUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (_u *GroupUpdate) SetMcpXMLInject(v bool) *GroupUpdate {
|
||||
_u.mutation.SetMcpXMLInject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
|
||||
func (_u *GroupUpdate) SetNillableMcpXMLInject(v *bool) *GroupUpdate {
|
||||
if v != nil {
|
||||
_u.SetMcpXMLInject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (_u *GroupUpdate) SetSupportedModelScopes(v []string) *GroupUpdate {
|
||||
_u.mutation.SetSupportedModelScopes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendSupportedModelScopes appends value to the "supported_model_scopes" field.
|
||||
func (_u *GroupUpdate) AppendSupportedModelScopes(v []string) *GroupUpdate {
|
||||
_u.mutation.AppendSupportedModelScopes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (_u *GroupUpdate) SetSortOrder(v int) *GroupUpdate {
|
||||
_u.mutation.ResetSortOrder()
|
||||
_u.mutation.SetSortOrder(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
|
||||
func (_u *GroupUpdate) SetNillableSortOrder(v *int) *GroupUpdate {
|
||||
if v != nil {
|
||||
_u.SetSortOrder(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddSortOrder adds value to the "sort_order" field.
|
||||
func (_u *GroupUpdate) AddSortOrder(v int) *GroupUpdate {
|
||||
_u.mutation.AddSortOrder(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -829,6 +904,15 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if _u.mutation.FallbackGroupIDCleared() {
|
||||
_spec.ClearField(group.FieldFallbackGroupID, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.FallbackGroupIDOnInvalidRequest(); ok {
|
||||
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedFallbackGroupIDOnInvalidRequest(); ok {
|
||||
_spec.AddField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.FallbackGroupIDOnInvalidRequestCleared() {
|
||||
_spec.ClearField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.ModelRouting(); ok {
|
||||
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
|
||||
}
|
||||
@@ -838,6 +922,23 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
|
||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.McpXMLInject(); ok {
|
||||
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.SupportedModelScopes(); ok {
|
||||
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedSupportedModelScopes(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, group.FieldSupportedModelScopes, value)
|
||||
})
|
||||
}
|
||||
if value, ok := _u.mutation.SortOrder(); ok {
|
||||
_spec.SetField(group.FieldSortOrder, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedSortOrder(); ok {
|
||||
_spec.AddField(group.FieldSortOrder, field.TypeInt, value)
|
||||
}
|
||||
if _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -1513,6 +1614,33 @@ func (_u *GroupUpdateOne) ClearFallbackGroupID() *GroupUpdateOne {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdateOne) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdateOne {
|
||||
_u.mutation.ResetFallbackGroupIDOnInvalidRequest()
|
||||
_u.mutation.SetFallbackGroupIDOnInvalidRequest(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
|
||||
func (_u *GroupUpdateOne) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetFallbackGroupIDOnInvalidRequest(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddFallbackGroupIDOnInvalidRequest adds value to the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdateOne) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdateOne {
|
||||
_u.mutation.AddFallbackGroupIDOnInvalidRequest(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
|
||||
func (_u *GroupUpdateOne) ClearFallbackGroupIDOnInvalidRequest() *GroupUpdateOne {
|
||||
_u.mutation.ClearFallbackGroupIDOnInvalidRequest()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetModelRouting sets the "model_routing" field.
|
||||
func (_u *GroupUpdateOne) SetModelRouting(v map[string][]int64) *GroupUpdateOne {
|
||||
_u.mutation.SetModelRouting(v)
|
||||
@@ -1539,6 +1667,53 @@ func (_u *GroupUpdateOne) SetNillableModelRoutingEnabled(v *bool) *GroupUpdateOn
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (_u *GroupUpdateOne) SetMcpXMLInject(v bool) *GroupUpdateOne {
|
||||
_u.mutation.SetMcpXMLInject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
|
||||
func (_u *GroupUpdateOne) SetNillableMcpXMLInject(v *bool) *GroupUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetMcpXMLInject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSupportedModelScopes sets the "supported_model_scopes" field.
|
||||
func (_u *GroupUpdateOne) SetSupportedModelScopes(v []string) *GroupUpdateOne {
|
||||
_u.mutation.SetSupportedModelScopes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AppendSupportedModelScopes appends value to the "supported_model_scopes" field.
|
||||
func (_u *GroupUpdateOne) AppendSupportedModelScopes(v []string) *GroupUpdateOne {
|
||||
_u.mutation.AppendSupportedModelScopes(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSortOrder sets the "sort_order" field.
|
||||
func (_u *GroupUpdateOne) SetSortOrder(v int) *GroupUpdateOne {
|
||||
_u.mutation.ResetSortOrder()
|
||||
_u.mutation.SetSortOrder(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
|
||||
func (_u *GroupUpdateOne) SetNillableSortOrder(v *int) *GroupUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetSortOrder(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddSortOrder adds value to the "sort_order" field.
|
||||
func (_u *GroupUpdateOne) AddSortOrder(v int) *GroupUpdateOne {
|
||||
_u.mutation.AddSortOrder(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -1977,6 +2152,15 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
|
||||
if _u.mutation.FallbackGroupIDCleared() {
|
||||
_spec.ClearField(group.FieldFallbackGroupID, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.FallbackGroupIDOnInvalidRequest(); ok {
|
||||
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedFallbackGroupIDOnInvalidRequest(); ok {
|
||||
_spec.AddField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
|
||||
}
|
||||
if _u.mutation.FallbackGroupIDOnInvalidRequestCleared() {
|
||||
_spec.ClearField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64)
|
||||
}
|
||||
if value, ok := _u.mutation.ModelRouting(); ok {
|
||||
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
|
||||
}
|
||||
@@ -1986,6 +2170,23 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
|
||||
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
|
||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.McpXMLInject(); ok {
|
||||
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.SupportedModelScopes(); ok {
|
||||
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AppendedSupportedModelScopes(); ok {
|
||||
_spec.AddModifier(func(u *sql.UpdateBuilder) {
|
||||
sqljson.Append(u, group.FieldSupportedModelScopes, value)
|
||||
})
|
||||
}
|
||||
if value, ok := _u.mutation.SortOrder(); ok {
|
||||
_spec.SetField(group.FieldSortOrder, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AddedSortOrder(); ok {
|
||||
_spec.AddField(group.FieldSortOrder, field.TypeInt, value)
|
||||
}
|
||||
if _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
|
||||
@@ -45,6 +45,42 @@ func (f AccountGroupFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AccountGroupMutation", m)
|
||||
}
|
||||
|
||||
// The AnnouncementFunc type is an adapter to allow the use of ordinary
|
||||
// function as Announcement mutator.
|
||||
type AnnouncementFunc func(context.Context, *ent.AnnouncementMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f AnnouncementFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.AnnouncementMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AnnouncementMutation", m)
|
||||
}
|
||||
|
||||
// The AnnouncementReadFunc type is an adapter to allow the use of ordinary
|
||||
// function as AnnouncementRead mutator.
|
||||
type AnnouncementReadFunc func(context.Context, *ent.AnnouncementReadMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f AnnouncementReadFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.AnnouncementReadMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AnnouncementReadMutation", m)
|
||||
}
|
||||
|
||||
// The ErrorPassthroughRuleFunc type is an adapter to allow the use of ordinary
|
||||
// function as ErrorPassthroughRule mutator.
|
||||
type ErrorPassthroughRuleFunc func(context.Context, *ent.ErrorPassthroughRuleMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f ErrorPassthroughRuleFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.ErrorPassthroughRuleMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ErrorPassthroughRuleMutation", m)
|
||||
}
|
||||
|
||||
// The GroupFunc type is an adapter to allow the use of ordinary
|
||||
// function as Group mutator.
|
||||
type GroupFunc func(context.Context, *ent.GroupMutation) (ent.Value, error)
|
||||
|
||||
@@ -10,7 +10,10 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/ent/account"
|
||||
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
@@ -164,6 +167,87 @@ func (f TraverseAccountGroup) Traverse(ctx context.Context, q ent.Query) error {
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AccountGroupQuery", q)
|
||||
}
|
||||
|
||||
// The AnnouncementFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type AnnouncementFunc func(context.Context, *ent.AnnouncementQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f AnnouncementFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.AnnouncementQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.AnnouncementQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseAnnouncement type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseAnnouncement func(context.Context, *ent.AnnouncementQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseAnnouncement) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseAnnouncement) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.AnnouncementQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AnnouncementQuery", q)
|
||||
}
|
||||
|
||||
// The AnnouncementReadFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type AnnouncementReadFunc func(context.Context, *ent.AnnouncementReadQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f AnnouncementReadFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.AnnouncementReadQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.AnnouncementReadQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseAnnouncementRead type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseAnnouncementRead func(context.Context, *ent.AnnouncementReadQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseAnnouncementRead) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseAnnouncementRead) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.AnnouncementReadQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AnnouncementReadQuery", q)
|
||||
}
|
||||
|
||||
// The ErrorPassthroughRuleFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type ErrorPassthroughRuleFunc func(context.Context, *ent.ErrorPassthroughRuleQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f ErrorPassthroughRuleFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.ErrorPassthroughRuleQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.ErrorPassthroughRuleQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseErrorPassthroughRule type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseErrorPassthroughRule func(context.Context, *ent.ErrorPassthroughRuleQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseErrorPassthroughRule) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseErrorPassthroughRule) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.ErrorPassthroughRuleQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.ErrorPassthroughRuleQuery", q)
|
||||
}
|
||||
|
||||
// The GroupFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type GroupFunc func(context.Context, *ent.GroupQuery) (ent.Value, error)
|
||||
|
||||
@@ -524,6 +608,12 @@ func NewQuery(q ent.Query) (Query, error) {
|
||||
return &query[*ent.AccountQuery, predicate.Account, account.OrderOption]{typ: ent.TypeAccount, tq: q}, nil
|
||||
case *ent.AccountGroupQuery:
|
||||
return &query[*ent.AccountGroupQuery, predicate.AccountGroup, accountgroup.OrderOption]{typ: ent.TypeAccountGroup, tq: q}, nil
|
||||
case *ent.AnnouncementQuery:
|
||||
return &query[*ent.AnnouncementQuery, predicate.Announcement, announcement.OrderOption]{typ: ent.TypeAnnouncement, tq: q}, nil
|
||||
case *ent.AnnouncementReadQuery:
|
||||
return &query[*ent.AnnouncementReadQuery, predicate.AnnouncementRead, announcementread.OrderOption]{typ: ent.TypeAnnouncementRead, tq: q}, nil
|
||||
case *ent.ErrorPassthroughRuleQuery:
|
||||
return &query[*ent.ErrorPassthroughRuleQuery, predicate.ErrorPassthroughRule, errorpassthroughrule.OrderOption]{typ: ent.TypeErrorPassthroughRule, tq: q}, nil
|
||||
case *ent.GroupQuery:
|
||||
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
|
||||
case *ent.PromoCodeQuery:
|
||||
|
||||
@@ -20,6 +20,9 @@ var (
|
||||
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
|
||||
{Name: "ip_whitelist", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "ip_blacklist", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "quota", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
{Name: "quota_used", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
{Name: "expires_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "user_id", Type: field.TypeInt64},
|
||||
}
|
||||
@@ -31,13 +34,13 @@ var (
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "api_keys_groups_api_keys",
|
||||
Columns: []*schema.Column{APIKeysColumns[9]},
|
||||
Columns: []*schema.Column{APIKeysColumns[12]},
|
||||
RefColumns: []*schema.Column{GroupsColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
{
|
||||
Symbol: "api_keys_users_api_keys",
|
||||
Columns: []*schema.Column{APIKeysColumns[10]},
|
||||
Columns: []*schema.Column{APIKeysColumns[13]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
},
|
||||
@@ -46,12 +49,12 @@ var (
|
||||
{
|
||||
Name: "apikey_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[10]},
|
||||
Columns: []*schema.Column{APIKeysColumns[13]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_group_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[9]},
|
||||
Columns: []*schema.Column{APIKeysColumns[12]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_status",
|
||||
@@ -63,6 +66,16 @@ var (
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_quota_quota_used",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[9], APIKeysColumns[10]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_expires_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[11]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// AccountsColumns holds the columns for the "accounts" table.
|
||||
@@ -204,6 +217,134 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
// AnnouncementsColumns holds the columns for the "announcements" table.
|
||||
AnnouncementsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
{Name: "title", Type: field.TypeString, Size: 200},
|
||||
{Name: "content", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "status", Type: field.TypeString, Size: 20, Default: "draft"},
|
||||
{Name: "targeting", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "starts_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "ends_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "created_by", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "updated_by", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
}
|
||||
// AnnouncementsTable holds the schema information for the "announcements" table.
|
||||
AnnouncementsTable = &schema.Table{
|
||||
Name: "announcements",
|
||||
Columns: AnnouncementsColumns,
|
||||
PrimaryKey: []*schema.Column{AnnouncementsColumns[0]},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "announcement_status",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementsColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "announcement_created_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementsColumns[9]},
|
||||
},
|
||||
{
|
||||
Name: "announcement_starts_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementsColumns[5]},
|
||||
},
|
||||
{
|
||||
Name: "announcement_ends_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementsColumns[6]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// AnnouncementReadsColumns holds the columns for the "announcement_reads" table.
|
||||
AnnouncementReadsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
{Name: "read_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "announcement_id", Type: field.TypeInt64},
|
||||
{Name: "user_id", Type: field.TypeInt64},
|
||||
}
|
||||
// AnnouncementReadsTable holds the schema information for the "announcement_reads" table.
|
||||
AnnouncementReadsTable = &schema.Table{
|
||||
Name: "announcement_reads",
|
||||
Columns: AnnouncementReadsColumns,
|
||||
PrimaryKey: []*schema.Column{AnnouncementReadsColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "announcement_reads_announcements_reads",
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[3]},
|
||||
RefColumns: []*schema.Column{AnnouncementsColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
},
|
||||
{
|
||||
Symbol: "announcement_reads_users_announcement_reads",
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[4]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "announcementread_announcement_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "announcementread_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[4]},
|
||||
},
|
||||
{
|
||||
Name: "announcementread_read_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[1]},
|
||||
},
|
||||
{
|
||||
Name: "announcementread_announcement_id_user_id",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{AnnouncementReadsColumns[3], AnnouncementReadsColumns[4]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// ErrorPassthroughRulesColumns holds the columns for the "error_passthrough_rules" table.
|
||||
ErrorPassthroughRulesColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "name", Type: field.TypeString, Size: 100},
|
||||
{Name: "enabled", Type: field.TypeBool, Default: true},
|
||||
{Name: "priority", Type: field.TypeInt, Default: 0},
|
||||
{Name: "error_codes", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "keywords", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "match_mode", Type: field.TypeString, Size: 10, Default: "any"},
|
||||
{Name: "platforms", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "passthrough_code", Type: field.TypeBool, Default: true},
|
||||
{Name: "response_code", Type: field.TypeInt, Nullable: true},
|
||||
{Name: "passthrough_body", Type: field.TypeBool, Default: true},
|
||||
{Name: "custom_message", Type: field.TypeString, Nullable: true, Size: 2147483647},
|
||||
{Name: "description", Type: field.TypeString, Nullable: true, Size: 2147483647},
|
||||
}
|
||||
// ErrorPassthroughRulesTable holds the schema information for the "error_passthrough_rules" table.
|
||||
ErrorPassthroughRulesTable = &schema.Table{
|
||||
Name: "error_passthrough_rules",
|
||||
Columns: ErrorPassthroughRulesColumns,
|
||||
PrimaryKey: []*schema.Column{ErrorPassthroughRulesColumns[0]},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "errorpassthroughrule_enabled",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{ErrorPassthroughRulesColumns[4]},
|
||||
},
|
||||
{
|
||||
Name: "errorpassthroughrule_priority",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{ErrorPassthroughRulesColumns[5]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// GroupsColumns holds the columns for the "groups" table.
|
||||
GroupsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
@@ -226,8 +367,12 @@ var (
|
||||
{Name: "image_price_4k", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
{Name: "claude_code_only", Type: field.TypeBool, Default: false},
|
||||
{Name: "fallback_group_id", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "fallback_group_id_on_invalid_request", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "model_routing", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "model_routing_enabled", Type: field.TypeBool, Default: false},
|
||||
{Name: "mcp_xml_inject", Type: field.TypeBool, Default: true},
|
||||
{Name: "supported_model_scopes", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "sort_order", Type: field.TypeInt, Default: 0},
|
||||
}
|
||||
// GroupsTable holds the schema information for the "groups" table.
|
||||
GroupsTable = &schema.Table{
|
||||
@@ -260,6 +405,11 @@ var (
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{GroupsColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "group_sort_order",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{GroupsColumns[25]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// PromoCodesColumns holds the columns for the "promo_codes" table.
|
||||
@@ -610,6 +760,9 @@ var (
|
||||
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
|
||||
{Name: "username", Type: field.TypeString, Size: 100, Default: ""},
|
||||
{Name: "notes", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "totp_secret_encrypted", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "totp_enabled", Type: field.TypeBool, Default: false},
|
||||
{Name: "totp_enabled_at", Type: field.TypeTime, Nullable: true},
|
||||
}
|
||||
// UsersTable holds the schema information for the "users" table.
|
||||
UsersTable = &schema.Table{
|
||||
@@ -837,6 +990,9 @@ var (
|
||||
APIKeysTable,
|
||||
AccountsTable,
|
||||
AccountGroupsTable,
|
||||
AnnouncementsTable,
|
||||
AnnouncementReadsTable,
|
||||
ErrorPassthroughRulesTable,
|
||||
GroupsTable,
|
||||
PromoCodesTable,
|
||||
PromoCodeUsagesTable,
|
||||
@@ -868,6 +1024,17 @@ func init() {
|
||||
AccountGroupsTable.Annotation = &entsql.Annotation{
|
||||
Table: "account_groups",
|
||||
}
|
||||
AnnouncementsTable.Annotation = &entsql.Annotation{
|
||||
Table: "announcements",
|
||||
}
|
||||
AnnouncementReadsTable.ForeignKeys[0].RefTable = AnnouncementsTable
|
||||
AnnouncementReadsTable.ForeignKeys[1].RefTable = UsersTable
|
||||
AnnouncementReadsTable.Annotation = &entsql.Annotation{
|
||||
Table: "announcement_reads",
|
||||
}
|
||||
ErrorPassthroughRulesTable.Annotation = &entsql.Annotation{
|
||||
Table: "error_passthrough_rules",
|
||||
}
|
||||
GroupsTable.Annotation = &entsql.Annotation{
|
||||
Table: "groups",
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,15 @@ type Account func(*sql.Selector)
|
||||
// AccountGroup is the predicate function for accountgroup builders.
|
||||
type AccountGroup func(*sql.Selector)
|
||||
|
||||
// Announcement is the predicate function for announcement builders.
|
||||
type Announcement func(*sql.Selector)
|
||||
|
||||
// AnnouncementRead is the predicate function for announcementread builders.
|
||||
type AnnouncementRead func(*sql.Selector)
|
||||
|
||||
// ErrorPassthroughRule is the predicate function for errorpassthroughrule builders.
|
||||
type ErrorPassthroughRule func(*sql.Selector)
|
||||
|
||||
// Group is the predicate function for group builders.
|
||||
type Group func(*sql.Selector)
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ import (
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/account"
|
||||
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
@@ -89,6 +92,14 @@ func init() {
|
||||
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
|
||||
// apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error)
|
||||
// apikeyDescQuota is the schema descriptor for quota field.
|
||||
apikeyDescQuota := apikeyFields[7].Descriptor()
|
||||
// apikey.DefaultQuota holds the default value on creation for the quota field.
|
||||
apikey.DefaultQuota = apikeyDescQuota.Default.(float64)
|
||||
// apikeyDescQuotaUsed is the schema descriptor for quota_used field.
|
||||
apikeyDescQuotaUsed := apikeyFields[8].Descriptor()
|
||||
// apikey.DefaultQuotaUsed holds the default value on creation for the quota_used field.
|
||||
apikey.DefaultQuotaUsed = apikeyDescQuotaUsed.Default.(float64)
|
||||
accountMixin := schema.Account{}.Mixin()
|
||||
accountMixinHooks1 := accountMixin[1].Hooks()
|
||||
account.Hooks[0] = accountMixinHooks1[0]
|
||||
@@ -210,6 +221,111 @@ func init() {
|
||||
accountgroupDescCreatedAt := accountgroupFields[3].Descriptor()
|
||||
// accountgroup.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
accountgroup.DefaultCreatedAt = accountgroupDescCreatedAt.Default.(func() time.Time)
|
||||
announcementFields := schema.Announcement{}.Fields()
|
||||
_ = announcementFields
|
||||
// announcementDescTitle is the schema descriptor for title field.
|
||||
announcementDescTitle := announcementFields[0].Descriptor()
|
||||
// announcement.TitleValidator is a validator for the "title" field. It is called by the builders before save.
|
||||
announcement.TitleValidator = func() func(string) error {
|
||||
validators := announcementDescTitle.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
}
|
||||
return func(title string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(title); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// announcementDescContent is the schema descriptor for content field.
|
||||
announcementDescContent := announcementFields[1].Descriptor()
|
||||
// announcement.ContentValidator is a validator for the "content" field. It is called by the builders before save.
|
||||
announcement.ContentValidator = announcementDescContent.Validators[0].(func(string) error)
|
||||
// announcementDescStatus is the schema descriptor for status field.
|
||||
announcementDescStatus := announcementFields[2].Descriptor()
|
||||
// announcement.DefaultStatus holds the default value on creation for the status field.
|
||||
announcement.DefaultStatus = announcementDescStatus.Default.(string)
|
||||
// announcement.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
announcement.StatusValidator = announcementDescStatus.Validators[0].(func(string) error)
|
||||
// announcementDescCreatedAt is the schema descriptor for created_at field.
|
||||
announcementDescCreatedAt := announcementFields[8].Descriptor()
|
||||
// announcement.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
announcement.DefaultCreatedAt = announcementDescCreatedAt.Default.(func() time.Time)
|
||||
// announcementDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
announcementDescUpdatedAt := announcementFields[9].Descriptor()
|
||||
// announcement.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
announcement.DefaultUpdatedAt = announcementDescUpdatedAt.Default.(func() time.Time)
|
||||
// announcement.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
announcement.UpdateDefaultUpdatedAt = announcementDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
announcementreadFields := schema.AnnouncementRead{}.Fields()
|
||||
_ = announcementreadFields
|
||||
// announcementreadDescReadAt is the schema descriptor for read_at field.
|
||||
announcementreadDescReadAt := announcementreadFields[2].Descriptor()
|
||||
// announcementread.DefaultReadAt holds the default value on creation for the read_at field.
|
||||
announcementread.DefaultReadAt = announcementreadDescReadAt.Default.(func() time.Time)
|
||||
// announcementreadDescCreatedAt is the schema descriptor for created_at field.
|
||||
announcementreadDescCreatedAt := announcementreadFields[3].Descriptor()
|
||||
// announcementread.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
announcementread.DefaultCreatedAt = announcementreadDescCreatedAt.Default.(func() time.Time)
|
||||
errorpassthroughruleMixin := schema.ErrorPassthroughRule{}.Mixin()
|
||||
errorpassthroughruleMixinFields0 := errorpassthroughruleMixin[0].Fields()
|
||||
_ = errorpassthroughruleMixinFields0
|
||||
errorpassthroughruleFields := schema.ErrorPassthroughRule{}.Fields()
|
||||
_ = errorpassthroughruleFields
|
||||
// errorpassthroughruleDescCreatedAt is the schema descriptor for created_at field.
|
||||
errorpassthroughruleDescCreatedAt := errorpassthroughruleMixinFields0[0].Descriptor()
|
||||
// errorpassthroughrule.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
errorpassthroughrule.DefaultCreatedAt = errorpassthroughruleDescCreatedAt.Default.(func() time.Time)
|
||||
// errorpassthroughruleDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
errorpassthroughruleDescUpdatedAt := errorpassthroughruleMixinFields0[1].Descriptor()
|
||||
// errorpassthroughrule.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
errorpassthroughrule.DefaultUpdatedAt = errorpassthroughruleDescUpdatedAt.Default.(func() time.Time)
|
||||
// errorpassthroughrule.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
errorpassthroughrule.UpdateDefaultUpdatedAt = errorpassthroughruleDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
// errorpassthroughruleDescName is the schema descriptor for name field.
|
||||
errorpassthroughruleDescName := errorpassthroughruleFields[0].Descriptor()
|
||||
// errorpassthroughrule.NameValidator is a validator for the "name" field. It is called by the builders before save.
|
||||
errorpassthroughrule.NameValidator = func() func(string) error {
|
||||
validators := errorpassthroughruleDescName.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
}
|
||||
return func(name string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// errorpassthroughruleDescEnabled is the schema descriptor for enabled field.
|
||||
errorpassthroughruleDescEnabled := errorpassthroughruleFields[1].Descriptor()
|
||||
// errorpassthroughrule.DefaultEnabled holds the default value on creation for the enabled field.
|
||||
errorpassthroughrule.DefaultEnabled = errorpassthroughruleDescEnabled.Default.(bool)
|
||||
// errorpassthroughruleDescPriority is the schema descriptor for priority field.
|
||||
errorpassthroughruleDescPriority := errorpassthroughruleFields[2].Descriptor()
|
||||
// errorpassthroughrule.DefaultPriority holds the default value on creation for the priority field.
|
||||
errorpassthroughrule.DefaultPriority = errorpassthroughruleDescPriority.Default.(int)
|
||||
// errorpassthroughruleDescMatchMode is the schema descriptor for match_mode field.
|
||||
errorpassthroughruleDescMatchMode := errorpassthroughruleFields[5].Descriptor()
|
||||
// errorpassthroughrule.DefaultMatchMode holds the default value on creation for the match_mode field.
|
||||
errorpassthroughrule.DefaultMatchMode = errorpassthroughruleDescMatchMode.Default.(string)
|
||||
// errorpassthroughrule.MatchModeValidator is a validator for the "match_mode" field. It is called by the builders before save.
|
||||
errorpassthroughrule.MatchModeValidator = errorpassthroughruleDescMatchMode.Validators[0].(func(string) error)
|
||||
// errorpassthroughruleDescPassthroughCode is the schema descriptor for passthrough_code field.
|
||||
errorpassthroughruleDescPassthroughCode := errorpassthroughruleFields[7].Descriptor()
|
||||
// errorpassthroughrule.DefaultPassthroughCode holds the default value on creation for the passthrough_code field.
|
||||
errorpassthroughrule.DefaultPassthroughCode = errorpassthroughruleDescPassthroughCode.Default.(bool)
|
||||
// errorpassthroughruleDescPassthroughBody is the schema descriptor for passthrough_body field.
|
||||
errorpassthroughruleDescPassthroughBody := errorpassthroughruleFields[9].Descriptor()
|
||||
// errorpassthroughrule.DefaultPassthroughBody holds the default value on creation for the passthrough_body field.
|
||||
errorpassthroughrule.DefaultPassthroughBody = errorpassthroughruleDescPassthroughBody.Default.(bool)
|
||||
groupMixin := schema.Group{}.Mixin()
|
||||
groupMixinHooks1 := groupMixin[1].Hooks()
|
||||
group.Hooks[0] = groupMixinHooks1[0]
|
||||
@@ -282,9 +398,21 @@ func init() {
|
||||
// group.DefaultClaudeCodeOnly holds the default value on creation for the claude_code_only field.
|
||||
group.DefaultClaudeCodeOnly = groupDescClaudeCodeOnly.Default.(bool)
|
||||
// groupDescModelRoutingEnabled is the schema descriptor for model_routing_enabled field.
|
||||
groupDescModelRoutingEnabled := groupFields[17].Descriptor()
|
||||
groupDescModelRoutingEnabled := groupFields[18].Descriptor()
|
||||
// group.DefaultModelRoutingEnabled holds the default value on creation for the model_routing_enabled field.
|
||||
group.DefaultModelRoutingEnabled = groupDescModelRoutingEnabled.Default.(bool)
|
||||
// groupDescMcpXMLInject is the schema descriptor for mcp_xml_inject field.
|
||||
groupDescMcpXMLInject := groupFields[19].Descriptor()
|
||||
// group.DefaultMcpXMLInject holds the default value on creation for the mcp_xml_inject field.
|
||||
group.DefaultMcpXMLInject = groupDescMcpXMLInject.Default.(bool)
|
||||
// groupDescSupportedModelScopes is the schema descriptor for supported_model_scopes field.
|
||||
groupDescSupportedModelScopes := groupFields[20].Descriptor()
|
||||
// group.DefaultSupportedModelScopes holds the default value on creation for the supported_model_scopes field.
|
||||
group.DefaultSupportedModelScopes = groupDescSupportedModelScopes.Default.([]string)
|
||||
// groupDescSortOrder is the schema descriptor for sort_order field.
|
||||
groupDescSortOrder := groupFields[21].Descriptor()
|
||||
// group.DefaultSortOrder holds the default value on creation for the sort_order field.
|
||||
group.DefaultSortOrder = groupDescSortOrder.Default.(int)
|
||||
promocodeFields := schema.PromoCode{}.Fields()
|
||||
_ = promocodeFields
|
||||
// promocodeDescCode is the schema descriptor for code field.
|
||||
@@ -736,6 +864,10 @@ func init() {
|
||||
userDescNotes := userFields[7].Descriptor()
|
||||
// user.DefaultNotes holds the default value on creation for the notes field.
|
||||
user.DefaultNotes = userDescNotes.Default.(string)
|
||||
// userDescTotpEnabled is the schema descriptor for totp_enabled field.
|
||||
userDescTotpEnabled := userFields[9].Descriptor()
|
||||
// user.DefaultTotpEnabled holds the default value on creation for the totp_enabled field.
|
||||
user.DefaultTotpEnabled = userDescTotpEnabled.Default.(bool)
|
||||
userallowedgroupFields := schema.UserAllowedGroup{}.Fields()
|
||||
_ = userallowedgroupFields
|
||||
// userallowedgroupDescCreatedAt is the schema descriptor for created_at field.
|
||||
|
||||
@@ -4,7 +4,7 @@ package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -111,7 +111,7 @@ func (Account) Fields() []ent.Field {
|
||||
// status: 账户状态,如 "active", "error", "disabled"
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.StatusActive),
|
||||
Default(domain.StatusActive),
|
||||
|
||||
// error_message: 错误信息,记录账户异常时的详细信息
|
||||
field.String("error_message").
|
||||
|
||||
90
backend/ent/schema/announcement.go
Normal file
90
backend/ent/schema/announcement.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// Announcement holds the schema definition for the Announcement entity.
|
||||
//
|
||||
// 删除策略:硬删除(已读记录通过外键级联删除)
|
||||
type Announcement struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (Announcement) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "announcements"},
|
||||
}
|
||||
}
|
||||
|
||||
func (Announcement) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.String("title").
|
||||
MaxLen(200).
|
||||
NotEmpty().
|
||||
Comment("公告标题"),
|
||||
field.String("content").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}).
|
||||
NotEmpty().
|
||||
Comment("公告内容(支持 Markdown)"),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(domain.AnnouncementStatusDraft).
|
||||
Comment("状态: draft, active, archived"),
|
||||
field.JSON("targeting", domain.AnnouncementTargeting{}).
|
||||
Optional().
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}).
|
||||
Comment("展示条件(JSON 规则)"),
|
||||
field.Time("starts_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
|
||||
Comment("开始展示时间(为空表示立即生效)"),
|
||||
field.Time("ends_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
|
||||
Comment("结束展示时间(为空表示永久生效)"),
|
||||
field.Int64("created_by").
|
||||
Optional().
|
||||
Nillable().
|
||||
Comment("创建人用户ID(管理员)"),
|
||||
field.Int64("updated_by").
|
||||
Optional().
|
||||
Nillable().
|
||||
Comment("更新人用户ID(管理员)"),
|
||||
field.Time("created_at").
|
||||
Immutable().
|
||||
Default(time.Now).
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("updated_at").
|
||||
Default(time.Now).
|
||||
UpdateDefault(time.Now).
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (Announcement) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.To("reads", AnnouncementRead.Type),
|
||||
}
|
||||
}
|
||||
|
||||
func (Announcement) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("status"),
|
||||
index.Fields("created_at"),
|
||||
index.Fields("starts_at"),
|
||||
index.Fields("ends_at"),
|
||||
}
|
||||
}
|
||||
65
backend/ent/schema/announcement_read.go
Normal file
65
backend/ent/schema/announcement_read.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// AnnouncementRead holds the schema definition for the AnnouncementRead entity.
|
||||
//
|
||||
// 记录用户对公告的已读状态(首次已读时间)。
|
||||
type AnnouncementRead struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (AnnouncementRead) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "announcement_reads"},
|
||||
}
|
||||
}
|
||||
|
||||
func (AnnouncementRead) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int64("announcement_id"),
|
||||
field.Int64("user_id"),
|
||||
field.Time("read_at").
|
||||
Default(time.Now).
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
|
||||
Comment("用户首次已读时间"),
|
||||
field.Time("created_at").
|
||||
Immutable().
|
||||
Default(time.Now).
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (AnnouncementRead) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("announcement", Announcement.Type).
|
||||
Ref("reads").
|
||||
Field("announcement_id").
|
||||
Unique().
|
||||
Required(),
|
||||
edge.From("user", User.Type).
|
||||
Ref("announcement_reads").
|
||||
Field("user_id").
|
||||
Unique().
|
||||
Required(),
|
||||
}
|
||||
}
|
||||
|
||||
func (AnnouncementRead) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("announcement_id"),
|
||||
index.Fields("user_id"),
|
||||
index.Fields("read_at"),
|
||||
index.Fields("announcement_id", "user_id").Unique(),
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
@@ -45,13 +46,30 @@ func (APIKey) Fields() []ent.Field {
|
||||
Nillable(),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.StatusActive),
|
||||
Default(domain.StatusActive),
|
||||
field.JSON("ip_whitelist", []string{}).
|
||||
Optional().
|
||||
Comment("Allowed IPs/CIDRs, e.g. [\"192.168.1.100\", \"10.0.0.0/8\"]"),
|
||||
field.JSON("ip_blacklist", []string{}).
|
||||
Optional().
|
||||
Comment("Blocked IPs/CIDRs"),
|
||||
|
||||
// ========== Quota fields ==========
|
||||
// Quota limit in USD (0 = unlimited)
|
||||
field.Float("quota").
|
||||
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
|
||||
Default(0).
|
||||
Comment("Quota limit in USD for this API key (0 = unlimited)"),
|
||||
// Used quota amount
|
||||
field.Float("quota_used").
|
||||
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
|
||||
Default(0).
|
||||
Comment("Used quota amount in USD"),
|
||||
// Expiration time (nil = never expires)
|
||||
field.Time("expires_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
Comment("Expiration time for this API key (null = never expires)"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,5 +95,8 @@ func (APIKey) Indexes() []ent.Index {
|
||||
index.Fields("group_id"),
|
||||
index.Fields("status"),
|
||||
index.Fields("deleted_at"),
|
||||
// Index for quota queries
|
||||
index.Fields("quota", "quota_used"),
|
||||
index.Fields("expires_at"),
|
||||
}
|
||||
}
|
||||
|
||||
121
backend/ent/schema/error_passthrough_rule.go
Normal file
121
backend/ent/schema/error_passthrough_rule.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Package schema 定义 Ent ORM 的数据库 schema。
|
||||
package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// ErrorPassthroughRule 定义全局错误透传规则的 schema。
|
||||
//
|
||||
// 错误透传规则用于控制上游错误如何返回给客户端:
|
||||
// - 匹配条件:错误码 + 关键词组合
|
||||
// - 响应行为:透传原始信息 或 自定义错误信息
|
||||
// - 响应状态码:可指定返回给客户端的状态码
|
||||
// - 平台范围:规则适用的平台(Anthropic、OpenAI、Gemini、Antigravity)
|
||||
type ErrorPassthroughRule struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
// Annotations 返回 schema 的注解配置。
|
||||
func (ErrorPassthroughRule) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "error_passthrough_rules"},
|
||||
}
|
||||
}
|
||||
|
||||
// Mixin 返回该 schema 使用的混入组件。
|
||||
func (ErrorPassthroughRule) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
mixins.TimeMixin{},
|
||||
}
|
||||
}
|
||||
|
||||
// Fields 定义错误透传规则实体的所有字段。
|
||||
func (ErrorPassthroughRule) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
// name: 规则名称,用于在界面中标识规则
|
||||
field.String("name").
|
||||
MaxLen(100).
|
||||
NotEmpty(),
|
||||
|
||||
// enabled: 是否启用该规则
|
||||
field.Bool("enabled").
|
||||
Default(true),
|
||||
|
||||
// priority: 规则优先级,数值越小优先级越高
|
||||
// 匹配时按优先级顺序检查,命中第一个匹配的规则
|
||||
field.Int("priority").
|
||||
Default(0),
|
||||
|
||||
// error_codes: 匹配的错误码列表(OR关系)
|
||||
// 例如:[422, 400] 表示匹配 422 或 400 错误码
|
||||
field.JSON("error_codes", []int{}).
|
||||
Optional().
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
|
||||
// keywords: 匹配的关键词列表(OR关系)
|
||||
// 例如:["context limit", "model not supported"]
|
||||
// 关键词匹配不区分大小写
|
||||
field.JSON("keywords", []string{}).
|
||||
Optional().
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
|
||||
// match_mode: 匹配模式
|
||||
// - "any": 错误码匹配 OR 关键词匹配(任一条件满足即可)
|
||||
// - "all": 错误码匹配 AND 关键词匹配(所有条件都必须满足)
|
||||
field.String("match_mode").
|
||||
MaxLen(10).
|
||||
Default("any"),
|
||||
|
||||
// platforms: 适用平台列表
|
||||
// 例如:["anthropic", "openai", "gemini", "antigravity"]
|
||||
// 空列表表示适用于所有平台
|
||||
field.JSON("platforms", []string{}).
|
||||
Optional().
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
|
||||
// passthrough_code: 是否透传上游原始状态码
|
||||
// true: 使用上游返回的状态码
|
||||
// false: 使用 response_code 指定的状态码
|
||||
field.Bool("passthrough_code").
|
||||
Default(true),
|
||||
|
||||
// response_code: 自定义响应状态码
|
||||
// 当 passthrough_code=false 时使用此状态码
|
||||
field.Int("response_code").
|
||||
Optional().
|
||||
Nillable(),
|
||||
|
||||
// passthrough_body: 是否透传上游原始错误信息
|
||||
// true: 使用上游返回的错误信息
|
||||
// false: 使用 custom_message 指定的错误信息
|
||||
field.Bool("passthrough_body").
|
||||
Default(true),
|
||||
|
||||
// custom_message: 自定义错误信息
|
||||
// 当 passthrough_body=false 时使用此错误信息
|
||||
field.Text("custom_message").
|
||||
Optional().
|
||||
Nillable(),
|
||||
|
||||
// description: 规则描述,用于说明规则的用途
|
||||
field.Text("description").
|
||||
Optional().
|
||||
Nillable(),
|
||||
}
|
||||
}
|
||||
|
||||
// Indexes 定义数据库索引,优化查询性能。
|
||||
func (ErrorPassthroughRule) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("enabled"), // 筛选启用的规则
|
||||
index.Fields("priority"), // 按优先级排序
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -49,15 +49,15 @@ func (Group) Fields() []ent.Field {
|
||||
Default(false),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.StatusActive),
|
||||
Default(domain.StatusActive),
|
||||
|
||||
// Subscription-related fields (added by migration 003)
|
||||
field.String("platform").
|
||||
MaxLen(50).
|
||||
Default(service.PlatformAnthropic),
|
||||
Default(domain.PlatformAnthropic),
|
||||
field.String("subscription_type").
|
||||
MaxLen(20).
|
||||
Default(service.SubscriptionTypeStandard),
|
||||
Default(domain.SubscriptionTypeStandard),
|
||||
field.Float("daily_limit_usd").
|
||||
Optional().
|
||||
Nillable().
|
||||
@@ -95,6 +95,10 @@ func (Group) Fields() []ent.Field {
|
||||
Optional().
|
||||
Nillable().
|
||||
Comment("非 Claude Code 请求降级使用的分组 ID"),
|
||||
field.Int64("fallback_group_id_on_invalid_request").
|
||||
Optional().
|
||||
Nillable().
|
||||
Comment("无效请求兜底使用的分组 ID"),
|
||||
|
||||
// 模型路由配置 (added by migration 040)
|
||||
field.JSON("model_routing", map[string][]int64{}).
|
||||
@@ -106,6 +110,22 @@ func (Group) Fields() []ent.Field {
|
||||
field.Bool("model_routing_enabled").
|
||||
Default(false).
|
||||
Comment("是否启用模型路由配置"),
|
||||
|
||||
// MCP XML 协议注入开关 (added by migration 042)
|
||||
field.Bool("mcp_xml_inject").
|
||||
Default(true).
|
||||
Comment("是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)"),
|
||||
|
||||
// 支持的模型系列 (added by migration 046)
|
||||
field.JSON("supported_model_scopes", []string{}).
|
||||
Default([]string{"claude", "gemini_text", "gemini_image"}).
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}).
|
||||
Comment("支持的模型系列:claude, gemini_text, gemini_image"),
|
||||
|
||||
// 分组排序 (added by migration 052)
|
||||
field.Int("sort_order").
|
||||
Default(0).
|
||||
Comment("分组显示排序,数值越小越靠前"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,5 +154,6 @@ func (Group) Indexes() []ent.Index {
|
||||
index.Fields("subscription_type"),
|
||||
index.Fields("is_exclusive"),
|
||||
index.Fields("deleted_at"),
|
||||
index.Fields("sort_order"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package schema
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -49,7 +49,7 @@ func (PromoCode) Fields() []ent.Field {
|
||||
Comment("已使用次数"),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.PromoCodeStatusActive).
|
||||
Default(domain.PromoCodeStatusActive).
|
||||
Comment("状态: active, disabled"),
|
||||
field.Time("expires_at").
|
||||
Optional().
|
||||
|
||||
@@ -3,7 +3,7 @@ package schema
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -41,13 +41,13 @@ func (RedeemCode) Fields() []ent.Field {
|
||||
Unique(),
|
||||
field.String("type").
|
||||
MaxLen(20).
|
||||
Default(service.RedeemTypeBalance),
|
||||
Default(domain.RedeemTypeBalance),
|
||||
field.Float("value").
|
||||
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
|
||||
Default(0),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.StatusUnused),
|
||||
Default(domain.StatusUnused),
|
||||
field.Int64("used_by").
|
||||
Optional().
|
||||
Nillable(),
|
||||
|
||||
@@ -2,7 +2,7 @@ package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -43,7 +43,7 @@ func (User) Fields() []ent.Field {
|
||||
NotEmpty(),
|
||||
field.String("role").
|
||||
MaxLen(20).
|
||||
Default(service.RoleUser),
|
||||
Default(domain.RoleUser),
|
||||
field.Float("balance").
|
||||
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
|
||||
Default(0),
|
||||
@@ -51,7 +51,7 @@ func (User) Fields() []ent.Field {
|
||||
Default(5),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.StatusActive),
|
||||
Default(domain.StatusActive),
|
||||
|
||||
// Optional profile fields (added later; default '' in DB migration)
|
||||
field.String("username").
|
||||
@@ -61,6 +61,17 @@ func (User) Fields() []ent.Field {
|
||||
field.String("notes").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}).
|
||||
Default(""),
|
||||
|
||||
// TOTP 双因素认证字段
|
||||
field.String("totp_secret_encrypted").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}).
|
||||
Optional().
|
||||
Nillable(),
|
||||
field.Bool("totp_enabled").
|
||||
Default(false),
|
||||
field.Time("totp_enabled_at").
|
||||
Optional().
|
||||
Nillable(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +81,7 @@ func (User) Edges() []ent.Edge {
|
||||
edge.To("redeem_codes", RedeemCode.Type),
|
||||
edge.To("subscriptions", UserSubscription.Type),
|
||||
edge.To("assigned_subscriptions", UserSubscription.Type),
|
||||
edge.To("announcement_reads", AnnouncementRead.Type),
|
||||
edge.To("allowed_groups", Group.Type).
|
||||
Through("user_allowed_groups", UserAllowedGroup.Type),
|
||||
edge.To("usage_logs", UsageLog.Type),
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
@@ -44,7 +44,7 @@ func (UserSubscription) Fields() []ent.Field {
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.String("status").
|
||||
MaxLen(20).
|
||||
Default(service.SubscriptionStatusActive),
|
||||
Default(domain.SubscriptionStatusActive),
|
||||
|
||||
field.Time("daily_window_start").
|
||||
Optional().
|
||||
|
||||
@@ -20,6 +20,12 @@ type Tx struct {
|
||||
Account *AccountClient
|
||||
// AccountGroup is the client for interacting with the AccountGroup builders.
|
||||
AccountGroup *AccountGroupClient
|
||||
// Announcement is the client for interacting with the Announcement builders.
|
||||
Announcement *AnnouncementClient
|
||||
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
|
||||
AnnouncementRead *AnnouncementReadClient
|
||||
// ErrorPassthroughRule is the client for interacting with the ErrorPassthroughRule builders.
|
||||
ErrorPassthroughRule *ErrorPassthroughRuleClient
|
||||
// Group is the client for interacting with the Group builders.
|
||||
Group *GroupClient
|
||||
// PromoCode is the client for interacting with the PromoCode builders.
|
||||
@@ -180,6 +186,9 @@ func (tx *Tx) init() {
|
||||
tx.APIKey = NewAPIKeyClient(tx.config)
|
||||
tx.Account = NewAccountClient(tx.config)
|
||||
tx.AccountGroup = NewAccountGroupClient(tx.config)
|
||||
tx.Announcement = NewAnnouncementClient(tx.config)
|
||||
tx.AnnouncementRead = NewAnnouncementReadClient(tx.config)
|
||||
tx.ErrorPassthroughRule = NewErrorPassthroughRuleClient(tx.config)
|
||||
tx.Group = NewGroupClient(tx.config)
|
||||
tx.PromoCode = NewPromoCodeClient(tx.config)
|
||||
tx.PromoCodeUsage = NewPromoCodeUsageClient(tx.config)
|
||||
|
||||
@@ -39,6 +39,12 @@ type User struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
// Notes holds the value of the "notes" field.
|
||||
Notes string `json:"notes,omitempty"`
|
||||
// TotpSecretEncrypted holds the value of the "totp_secret_encrypted" field.
|
||||
TotpSecretEncrypted *string `json:"totp_secret_encrypted,omitempty"`
|
||||
// TotpEnabled holds the value of the "totp_enabled" field.
|
||||
TotpEnabled bool `json:"totp_enabled,omitempty"`
|
||||
// TotpEnabledAt holds the value of the "totp_enabled_at" field.
|
||||
TotpEnabledAt *time.Time `json:"totp_enabled_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the UserQuery when eager-loading is set.
|
||||
Edges UserEdges `json:"edges"`
|
||||
@@ -55,6 +61,8 @@ type UserEdges struct {
|
||||
Subscriptions []*UserSubscription `json:"subscriptions,omitempty"`
|
||||
// AssignedSubscriptions holds the value of the assigned_subscriptions edge.
|
||||
AssignedSubscriptions []*UserSubscription `json:"assigned_subscriptions,omitempty"`
|
||||
// AnnouncementReads holds the value of the announcement_reads edge.
|
||||
AnnouncementReads []*AnnouncementRead `json:"announcement_reads,omitempty"`
|
||||
// AllowedGroups holds the value of the allowed_groups edge.
|
||||
AllowedGroups []*Group `json:"allowed_groups,omitempty"`
|
||||
// UsageLogs holds the value of the usage_logs edge.
|
||||
@@ -67,7 +75,7 @@ type UserEdges struct {
|
||||
UserAllowedGroups []*UserAllowedGroup `json:"user_allowed_groups,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [9]bool
|
||||
loadedTypes [10]bool
|
||||
}
|
||||
|
||||
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
||||
@@ -106,10 +114,19 @@ func (e UserEdges) AssignedSubscriptionsOrErr() ([]*UserSubscription, error) {
|
||||
return nil, &NotLoadedError{edge: "assigned_subscriptions"}
|
||||
}
|
||||
|
||||
// AnnouncementReadsOrErr returns the AnnouncementReads value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) AnnouncementReadsOrErr() ([]*AnnouncementRead, error) {
|
||||
if e.loadedTypes[4] {
|
||||
return e.AnnouncementReads, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "announcement_reads"}
|
||||
}
|
||||
|
||||
// AllowedGroupsOrErr returns the AllowedGroups value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) AllowedGroupsOrErr() ([]*Group, error) {
|
||||
if e.loadedTypes[4] {
|
||||
if e.loadedTypes[5] {
|
||||
return e.AllowedGroups, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "allowed_groups"}
|
||||
@@ -118,7 +135,7 @@ func (e UserEdges) AllowedGroupsOrErr() ([]*Group, error) {
|
||||
// UsageLogsOrErr returns the UsageLogs value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) UsageLogsOrErr() ([]*UsageLog, error) {
|
||||
if e.loadedTypes[5] {
|
||||
if e.loadedTypes[6] {
|
||||
return e.UsageLogs, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "usage_logs"}
|
||||
@@ -127,7 +144,7 @@ func (e UserEdges) UsageLogsOrErr() ([]*UsageLog, error) {
|
||||
// AttributeValuesOrErr returns the AttributeValues value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) AttributeValuesOrErr() ([]*UserAttributeValue, error) {
|
||||
if e.loadedTypes[6] {
|
||||
if e.loadedTypes[7] {
|
||||
return e.AttributeValues, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "attribute_values"}
|
||||
@@ -136,7 +153,7 @@ func (e UserEdges) AttributeValuesOrErr() ([]*UserAttributeValue, error) {
|
||||
// PromoCodeUsagesOrErr returns the PromoCodeUsages value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) PromoCodeUsagesOrErr() ([]*PromoCodeUsage, error) {
|
||||
if e.loadedTypes[7] {
|
||||
if e.loadedTypes[8] {
|
||||
return e.PromoCodeUsages, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "promo_code_usages"}
|
||||
@@ -145,7 +162,7 @@ func (e UserEdges) PromoCodeUsagesOrErr() ([]*PromoCodeUsage, error) {
|
||||
// UserAllowedGroupsOrErr returns the UserAllowedGroups value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) UserAllowedGroupsOrErr() ([]*UserAllowedGroup, error) {
|
||||
if e.loadedTypes[8] {
|
||||
if e.loadedTypes[9] {
|
||||
return e.UserAllowedGroups, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "user_allowed_groups"}
|
||||
@@ -156,13 +173,15 @@ func (*User) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case user.FieldTotpEnabled:
|
||||
values[i] = new(sql.NullBool)
|
||||
case user.FieldBalance:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
case user.FieldID, user.FieldConcurrency:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case user.FieldEmail, user.FieldPasswordHash, user.FieldRole, user.FieldStatus, user.FieldUsername, user.FieldNotes:
|
||||
case user.FieldEmail, user.FieldPasswordHash, user.FieldRole, user.FieldStatus, user.FieldUsername, user.FieldNotes, user.FieldTotpSecretEncrypted:
|
||||
values[i] = new(sql.NullString)
|
||||
case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldDeletedAt:
|
||||
case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldDeletedAt, user.FieldTotpEnabledAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
@@ -252,6 +271,26 @@ func (_m *User) assignValues(columns []string, values []any) error {
|
||||
} else if value.Valid {
|
||||
_m.Notes = value.String
|
||||
}
|
||||
case user.FieldTotpSecretEncrypted:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field totp_secret_encrypted", values[i])
|
||||
} else if value.Valid {
|
||||
_m.TotpSecretEncrypted = new(string)
|
||||
*_m.TotpSecretEncrypted = value.String
|
||||
}
|
||||
case user.FieldTotpEnabled:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field totp_enabled", values[i])
|
||||
} else if value.Valid {
|
||||
_m.TotpEnabled = value.Bool
|
||||
}
|
||||
case user.FieldTotpEnabledAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field totp_enabled_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.TotpEnabledAt = new(time.Time)
|
||||
*_m.TotpEnabledAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
@@ -285,6 +324,11 @@ func (_m *User) QueryAssignedSubscriptions() *UserSubscriptionQuery {
|
||||
return NewUserClient(_m.config).QueryAssignedSubscriptions(_m)
|
||||
}
|
||||
|
||||
// QueryAnnouncementReads queries the "announcement_reads" edge of the User entity.
|
||||
func (_m *User) QueryAnnouncementReads() *AnnouncementReadQuery {
|
||||
return NewUserClient(_m.config).QueryAnnouncementReads(_m)
|
||||
}
|
||||
|
||||
// QueryAllowedGroups queries the "allowed_groups" edge of the User entity.
|
||||
func (_m *User) QueryAllowedGroups() *GroupQuery {
|
||||
return NewUserClient(_m.config).QueryAllowedGroups(_m)
|
||||
@@ -367,6 +411,19 @@ func (_m *User) String() string {
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("notes=")
|
||||
builder.WriteString(_m.Notes)
|
||||
builder.WriteString(", ")
|
||||
if v := _m.TotpSecretEncrypted; v != nil {
|
||||
builder.WriteString("totp_secret_encrypted=")
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("totp_enabled=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.TotpEnabled))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.TotpEnabledAt; v != nil {
|
||||
builder.WriteString("totp_enabled_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@ const (
|
||||
FieldUsername = "username"
|
||||
// FieldNotes holds the string denoting the notes field in the database.
|
||||
FieldNotes = "notes"
|
||||
// FieldTotpSecretEncrypted holds the string denoting the totp_secret_encrypted field in the database.
|
||||
FieldTotpSecretEncrypted = "totp_secret_encrypted"
|
||||
// FieldTotpEnabled holds the string denoting the totp_enabled field in the database.
|
||||
FieldTotpEnabled = "totp_enabled"
|
||||
// FieldTotpEnabledAt holds the string denoting the totp_enabled_at field in the database.
|
||||
FieldTotpEnabledAt = "totp_enabled_at"
|
||||
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
|
||||
EdgeAPIKeys = "api_keys"
|
||||
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
||||
@@ -45,6 +51,8 @@ const (
|
||||
EdgeSubscriptions = "subscriptions"
|
||||
// EdgeAssignedSubscriptions holds the string denoting the assigned_subscriptions edge name in mutations.
|
||||
EdgeAssignedSubscriptions = "assigned_subscriptions"
|
||||
// EdgeAnnouncementReads holds the string denoting the announcement_reads edge name in mutations.
|
||||
EdgeAnnouncementReads = "announcement_reads"
|
||||
// EdgeAllowedGroups holds the string denoting the allowed_groups edge name in mutations.
|
||||
EdgeAllowedGroups = "allowed_groups"
|
||||
// EdgeUsageLogs holds the string denoting the usage_logs edge name in mutations.
|
||||
@@ -85,6 +93,13 @@ const (
|
||||
AssignedSubscriptionsInverseTable = "user_subscriptions"
|
||||
// AssignedSubscriptionsColumn is the table column denoting the assigned_subscriptions relation/edge.
|
||||
AssignedSubscriptionsColumn = "assigned_by"
|
||||
// AnnouncementReadsTable is the table that holds the announcement_reads relation/edge.
|
||||
AnnouncementReadsTable = "announcement_reads"
|
||||
// AnnouncementReadsInverseTable is the table name for the AnnouncementRead entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "announcementread" package.
|
||||
AnnouncementReadsInverseTable = "announcement_reads"
|
||||
// AnnouncementReadsColumn is the table column denoting the announcement_reads relation/edge.
|
||||
AnnouncementReadsColumn = "user_id"
|
||||
// AllowedGroupsTable is the table that holds the allowed_groups relation/edge. The primary key declared below.
|
||||
AllowedGroupsTable = "user_allowed_groups"
|
||||
// AllowedGroupsInverseTable is the table name for the Group entity.
|
||||
@@ -134,6 +149,9 @@ var Columns = []string{
|
||||
FieldStatus,
|
||||
FieldUsername,
|
||||
FieldNotes,
|
||||
FieldTotpSecretEncrypted,
|
||||
FieldTotpEnabled,
|
||||
FieldTotpEnabledAt,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -188,6 +206,8 @@ var (
|
||||
UsernameValidator func(string) error
|
||||
// DefaultNotes holds the default value on creation for the "notes" field.
|
||||
DefaultNotes string
|
||||
// DefaultTotpEnabled holds the default value on creation for the "totp_enabled" field.
|
||||
DefaultTotpEnabled bool
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the User queries.
|
||||
@@ -253,6 +273,21 @@ func ByNotes(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldNotes, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTotpSecretEncrypted orders the results by the totp_secret_encrypted field.
|
||||
func ByTotpSecretEncrypted(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTotpSecretEncrypted, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTotpEnabled orders the results by the totp_enabled field.
|
||||
func ByTotpEnabled(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTotpEnabled, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTotpEnabledAt orders the results by the totp_enabled_at field.
|
||||
func ByTotpEnabledAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTotpEnabledAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAPIKeysCount orders the results by api_keys count.
|
||||
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
@@ -309,6 +344,20 @@ func ByAssignedSubscriptions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOp
|
||||
}
|
||||
}
|
||||
|
||||
// ByAnnouncementReadsCount orders the results by announcement_reads count.
|
||||
func ByAnnouncementReadsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newAnnouncementReadsStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByAnnouncementReads orders the results by announcement_reads terms.
|
||||
func ByAnnouncementReads(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newAnnouncementReadsStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByAllowedGroupsCount orders the results by allowed_groups count.
|
||||
func ByAllowedGroupsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
@@ -406,6 +455,13 @@ func newAssignedSubscriptionsStep() *sqlgraph.Step {
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AssignedSubscriptionsTable, AssignedSubscriptionsColumn),
|
||||
)
|
||||
}
|
||||
func newAnnouncementReadsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(AnnouncementReadsInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AnnouncementReadsTable, AnnouncementReadsColumn),
|
||||
)
|
||||
}
|
||||
func newAllowedGroupsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
|
||||
@@ -110,6 +110,21 @@ func Notes(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldNotes, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncrypted applies equality check predicate on the "totp_secret_encrypted" field. It's identical to TotpSecretEncryptedEQ.
|
||||
func TotpSecretEncrypted(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpEnabled applies equality check predicate on the "totp_enabled" field. It's identical to TotpEnabledEQ.
|
||||
func TotpEnabled(v bool) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpEnabled, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAt applies equality check predicate on the "totp_enabled_at" field. It's identical to TotpEnabledAtEQ.
|
||||
func TotpEnabledAt(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldCreatedAt, v))
|
||||
@@ -710,6 +725,141 @@ func NotesContainsFold(v string) predicate.User {
|
||||
return predicate.User(sql.FieldContainsFold(FieldNotes, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedEQ applies the EQ predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedEQ(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedNEQ applies the NEQ predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedNEQ(v string) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedIn applies the In predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedIn(vs ...string) predicate.User {
|
||||
return predicate.User(sql.FieldIn(FieldTotpSecretEncrypted, vs...))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedNotIn applies the NotIn predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedNotIn(vs ...string) predicate.User {
|
||||
return predicate.User(sql.FieldNotIn(FieldTotpSecretEncrypted, vs...))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedGT applies the GT predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedGT(v string) predicate.User {
|
||||
return predicate.User(sql.FieldGT(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedGTE applies the GTE predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedGTE(v string) predicate.User {
|
||||
return predicate.User(sql.FieldGTE(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedLT applies the LT predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedLT(v string) predicate.User {
|
||||
return predicate.User(sql.FieldLT(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedLTE applies the LTE predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedLTE(v string) predicate.User {
|
||||
return predicate.User(sql.FieldLTE(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedContains applies the Contains predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedContains(v string) predicate.User {
|
||||
return predicate.User(sql.FieldContains(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedHasPrefix applies the HasPrefix predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedHasPrefix(v string) predicate.User {
|
||||
return predicate.User(sql.FieldHasPrefix(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedHasSuffix applies the HasSuffix predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedHasSuffix(v string) predicate.User {
|
||||
return predicate.User(sql.FieldHasSuffix(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedIsNil applies the IsNil predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedIsNil() predicate.User {
|
||||
return predicate.User(sql.FieldIsNull(FieldTotpSecretEncrypted))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedNotNil applies the NotNil predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedNotNil() predicate.User {
|
||||
return predicate.User(sql.FieldNotNull(FieldTotpSecretEncrypted))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedEqualFold applies the EqualFold predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedEqualFold(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEqualFold(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpSecretEncryptedContainsFold applies the ContainsFold predicate on the "totp_secret_encrypted" field.
|
||||
func TotpSecretEncryptedContainsFold(v string) predicate.User {
|
||||
return predicate.User(sql.FieldContainsFold(FieldTotpSecretEncrypted, v))
|
||||
}
|
||||
|
||||
// TotpEnabledEQ applies the EQ predicate on the "totp_enabled" field.
|
||||
func TotpEnabledEQ(v bool) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpEnabled, v))
|
||||
}
|
||||
|
||||
// TotpEnabledNEQ applies the NEQ predicate on the "totp_enabled" field.
|
||||
func TotpEnabledNEQ(v bool) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldTotpEnabled, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtEQ applies the EQ predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtNEQ applies the NEQ predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtNEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtIn applies the In predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldIn(FieldTotpEnabledAt, vs...))
|
||||
}
|
||||
|
||||
// TotpEnabledAtNotIn applies the NotIn predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtNotIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNotIn(FieldTotpEnabledAt, vs...))
|
||||
}
|
||||
|
||||
// TotpEnabledAtGT applies the GT predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtGT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGT(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtGTE applies the GTE predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtGTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGTE(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtLT applies the LT predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtLT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLT(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtLTE applies the LTE predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtLTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLTE(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// TotpEnabledAtIsNil applies the IsNil predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtIsNil() predicate.User {
|
||||
return predicate.User(sql.FieldIsNull(FieldTotpEnabledAt))
|
||||
}
|
||||
|
||||
// TotpEnabledAtNotNil applies the NotNil predicate on the "totp_enabled_at" field.
|
||||
func TotpEnabledAtNotNil() predicate.User {
|
||||
return predicate.User(sql.FieldNotNull(FieldTotpEnabledAt))
|
||||
}
|
||||
|
||||
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
|
||||
func HasAPIKeys() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
@@ -802,6 +952,29 @@ func HasAssignedSubscriptionsWith(preds ...predicate.UserSubscription) predicate
|
||||
})
|
||||
}
|
||||
|
||||
// HasAnnouncementReads applies the HasEdge predicate on the "announcement_reads" edge.
|
||||
func HasAnnouncementReads() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AnnouncementReadsTable, AnnouncementReadsColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasAnnouncementReadsWith applies the HasEdge predicate on the "announcement_reads" edge with a given conditions (other predicates).
|
||||
func HasAnnouncementReadsWith(preds ...predicate.AnnouncementRead) predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := newAnnouncementReadsStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasAllowedGroups applies the HasEdge predicate on the "allowed_groups" edge.
|
||||
func HasAllowedGroups() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
@@ -167,6 +168,48 @@ func (_c *UserCreate) SetNillableNotes(v *string) *UserCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (_c *UserCreate) SetTotpSecretEncrypted(v string) *UserCreate {
|
||||
_c.mutation.SetTotpSecretEncrypted(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableTotpSecretEncrypted sets the "totp_secret_encrypted" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableTotpSecretEncrypted(v *string) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetTotpSecretEncrypted(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (_c *UserCreate) SetTotpEnabled(v bool) *UserCreate {
|
||||
_c.mutation.SetTotpEnabled(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabled sets the "totp_enabled" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableTotpEnabled(v *bool) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetTotpEnabled(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (_c *UserCreate) SetTotpEnabledAt(v time.Time) *UserCreate {
|
||||
_c.mutation.SetTotpEnabledAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabledAt sets the "totp_enabled_at" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableTotpEnabledAt(v *time.Time) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetTotpEnabledAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_c *UserCreate) AddAPIKeyIDs(ids ...int64) *UserCreate {
|
||||
_c.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -227,6 +270,21 @@ func (_c *UserCreate) AddAssignedSubscriptions(v ...*UserSubscription) *UserCrea
|
||||
return _c.AddAssignedSubscriptionIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
|
||||
func (_c *UserCreate) AddAnnouncementReadIDs(ids ...int64) *UserCreate {
|
||||
_c.mutation.AddAnnouncementReadIDs(ids...)
|
||||
return _c
|
||||
}
|
||||
|
||||
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
|
||||
func (_c *UserCreate) AddAnnouncementReads(v ...*AnnouncementRead) *UserCreate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _c.AddAnnouncementReadIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
|
||||
func (_c *UserCreate) AddAllowedGroupIDs(ids ...int64) *UserCreate {
|
||||
_c.mutation.AddAllowedGroupIDs(ids...)
|
||||
@@ -362,6 +420,10 @@ func (_c *UserCreate) defaults() error {
|
||||
v := user.DefaultNotes
|
||||
_c.mutation.SetNotes(v)
|
||||
}
|
||||
if _, ok := _c.mutation.TotpEnabled(); !ok {
|
||||
v := user.DefaultTotpEnabled
|
||||
_c.mutation.SetTotpEnabled(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -422,6 +484,9 @@ func (_c *UserCreate) check() error {
|
||||
if _, ok := _c.mutation.Notes(); !ok {
|
||||
return &ValidationError{Name: "notes", err: errors.New(`ent: missing required field "User.notes"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.TotpEnabled(); !ok {
|
||||
return &ValidationError{Name: "totp_enabled", err: errors.New(`ent: missing required field "User.totp_enabled"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -493,6 +558,18 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(user.FieldNotes, field.TypeString, value)
|
||||
_node.Notes = value
|
||||
}
|
||||
if value, ok := _c.mutation.TotpSecretEncrypted(); ok {
|
||||
_spec.SetField(user.FieldTotpSecretEncrypted, field.TypeString, value)
|
||||
_node.TotpSecretEncrypted = &value
|
||||
}
|
||||
if value, ok := _c.mutation.TotpEnabled(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabled, field.TypeBool, value)
|
||||
_node.TotpEnabled = value
|
||||
}
|
||||
if value, ok := _c.mutation.TotpEnabledAt(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabledAt, field.TypeTime, value)
|
||||
_node.TotpEnabledAt = &value
|
||||
}
|
||||
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -557,6 +634,22 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
|
||||
}
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.AllowedGroupsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2M,
|
||||
@@ -815,6 +908,54 @@ func (u *UserUpsert) UpdateNotes() *UserUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsert) SetTotpSecretEncrypted(v string) *UserUpsert {
|
||||
u.Set(user.FieldTotpSecretEncrypted, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateTotpSecretEncrypted sets the "totp_secret_encrypted" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateTotpSecretEncrypted() *UserUpsert {
|
||||
u.SetExcluded(user.FieldTotpSecretEncrypted)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearTotpSecretEncrypted clears the value of the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsert) ClearTotpSecretEncrypted() *UserUpsert {
|
||||
u.SetNull(user.FieldTotpSecretEncrypted)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (u *UserUpsert) SetTotpEnabled(v bool) *UserUpsert {
|
||||
u.Set(user.FieldTotpEnabled, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateTotpEnabled sets the "totp_enabled" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateTotpEnabled() *UserUpsert {
|
||||
u.SetExcluded(user.FieldTotpEnabled)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (u *UserUpsert) SetTotpEnabledAt(v time.Time) *UserUpsert {
|
||||
u.Set(user.FieldTotpEnabledAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateTotpEnabledAt sets the "totp_enabled_at" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateTotpEnabledAt() *UserUpsert {
|
||||
u.SetExcluded(user.FieldTotpEnabledAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearTotpEnabledAt clears the value of the "totp_enabled_at" field.
|
||||
func (u *UserUpsert) ClearTotpEnabledAt() *UserUpsert {
|
||||
u.SetNull(user.FieldTotpEnabledAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
@@ -1021,6 +1162,62 @@ func (u *UserUpsertOne) UpdateNotes() *UserUpsertOne {
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsertOne) SetTotpSecretEncrypted(v string) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpSecretEncrypted(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpSecretEncrypted sets the "totp_secret_encrypted" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateTotpSecretEncrypted() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpSecretEncrypted()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearTotpSecretEncrypted clears the value of the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsertOne) ClearTotpSecretEncrypted() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearTotpSecretEncrypted()
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (u *UserUpsertOne) SetTotpEnabled(v bool) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpEnabled(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpEnabled sets the "totp_enabled" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateTotpEnabled() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpEnabled()
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (u *UserUpsertOne) SetTotpEnabledAt(v time.Time) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpEnabledAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpEnabledAt sets the "totp_enabled_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateTotpEnabledAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpEnabledAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearTotpEnabledAt clears the value of the "totp_enabled_at" field.
|
||||
func (u *UserUpsertOne) ClearTotpEnabledAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearTotpEnabledAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *UserUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
@@ -1393,6 +1590,62 @@ func (u *UserUpsertBulk) UpdateNotes() *UserUpsertBulk {
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsertBulk) SetTotpSecretEncrypted(v string) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpSecretEncrypted(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpSecretEncrypted sets the "totp_secret_encrypted" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateTotpSecretEncrypted() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpSecretEncrypted()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearTotpSecretEncrypted clears the value of the "totp_secret_encrypted" field.
|
||||
func (u *UserUpsertBulk) ClearTotpSecretEncrypted() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearTotpSecretEncrypted()
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (u *UserUpsertBulk) SetTotpEnabled(v bool) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpEnabled(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpEnabled sets the "totp_enabled" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateTotpEnabled() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpEnabled()
|
||||
})
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (u *UserUpsertBulk) SetTotpEnabledAt(v time.Time) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetTotpEnabledAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTotpEnabledAt sets the "totp_enabled_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateTotpEnabledAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateTotpEnabledAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearTotpEnabledAt clears the value of the "totp_enabled_at" field.
|
||||
func (u *UserUpsertBulk) ClearTotpEnabledAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearTotpEnabledAt()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *UserUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
@@ -36,6 +37,7 @@ type UserQuery struct {
|
||||
withRedeemCodes *RedeemCodeQuery
|
||||
withSubscriptions *UserSubscriptionQuery
|
||||
withAssignedSubscriptions *UserSubscriptionQuery
|
||||
withAnnouncementReads *AnnouncementReadQuery
|
||||
withAllowedGroups *GroupQuery
|
||||
withUsageLogs *UsageLogQuery
|
||||
withAttributeValues *UserAttributeValueQuery
|
||||
@@ -166,6 +168,28 @@ func (_q *UserQuery) QueryAssignedSubscriptions() *UserSubscriptionQuery {
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAnnouncementReads chains the current query on the "announcement_reads" edge.
|
||||
func (_q *UserQuery) QueryAnnouncementReads() *AnnouncementReadQuery {
|
||||
query := (&AnnouncementReadClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, selector),
|
||||
sqlgraph.To(announcementread.Table, announcementread.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.AnnouncementReadsTable, user.AnnouncementReadsColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAllowedGroups chains the current query on the "allowed_groups" edge.
|
||||
func (_q *UserQuery) QueryAllowedGroups() *GroupQuery {
|
||||
query := (&GroupClient{config: _q.config}).Query()
|
||||
@@ -472,6 +496,7 @@ func (_q *UserQuery) Clone() *UserQuery {
|
||||
withRedeemCodes: _q.withRedeemCodes.Clone(),
|
||||
withSubscriptions: _q.withSubscriptions.Clone(),
|
||||
withAssignedSubscriptions: _q.withAssignedSubscriptions.Clone(),
|
||||
withAnnouncementReads: _q.withAnnouncementReads.Clone(),
|
||||
withAllowedGroups: _q.withAllowedGroups.Clone(),
|
||||
withUsageLogs: _q.withUsageLogs.Clone(),
|
||||
withAttributeValues: _q.withAttributeValues.Clone(),
|
||||
@@ -527,6 +552,17 @@ func (_q *UserQuery) WithAssignedSubscriptions(opts ...func(*UserSubscriptionQue
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithAnnouncementReads tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "announcement_reads" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *UserQuery) WithAnnouncementReads(opts ...func(*AnnouncementReadQuery)) *UserQuery {
|
||||
query := (&AnnouncementReadClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withAnnouncementReads = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithAllowedGroups tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "allowed_groups" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *UserQuery) WithAllowedGroups(opts ...func(*GroupQuery)) *UserQuery {
|
||||
@@ -660,11 +696,12 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
||||
var (
|
||||
nodes = []*User{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [9]bool{
|
||||
loadedTypes = [10]bool{
|
||||
_q.withAPIKeys != nil,
|
||||
_q.withRedeemCodes != nil,
|
||||
_q.withSubscriptions != nil,
|
||||
_q.withAssignedSubscriptions != nil,
|
||||
_q.withAnnouncementReads != nil,
|
||||
_q.withAllowedGroups != nil,
|
||||
_q.withUsageLogs != nil,
|
||||
_q.withAttributeValues != nil,
|
||||
@@ -723,6 +760,13 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withAnnouncementReads; query != nil {
|
||||
if err := _q.loadAnnouncementReads(ctx, query, nodes,
|
||||
func(n *User) { n.Edges.AnnouncementReads = []*AnnouncementRead{} },
|
||||
func(n *User, e *AnnouncementRead) { n.Edges.AnnouncementReads = append(n.Edges.AnnouncementReads, e) }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withAllowedGroups; query != nil {
|
||||
if err := _q.loadAllowedGroups(ctx, query, nodes,
|
||||
func(n *User) { n.Edges.AllowedGroups = []*Group{} },
|
||||
@@ -887,6 +931,36 @@ func (_q *UserQuery) loadAssignedSubscriptions(ctx context.Context, query *UserS
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *UserQuery) loadAnnouncementReads(ctx context.Context, query *AnnouncementReadQuery, nodes []*User, init func(*User), assign func(*User, *AnnouncementRead)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*User)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(announcementread.FieldUserID)
|
||||
}
|
||||
query.Where(predicate.AnnouncementRead(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(user.AnnouncementReadsColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.UserID
|
||||
node, ok := nodeids[fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "user_id" returned %v for node %v`, fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *UserQuery) loadAllowedGroups(ctx context.Context, query *GroupQuery, nodes []*User, init func(*User), assign func(*User, *Group)) error {
|
||||
edgeIDs := make([]driver.Value, len(nodes))
|
||||
byID := make(map[int64]*User)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
@@ -187,6 +188,60 @@ func (_u *UserUpdate) SetNillableNotes(v *string) *UserUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (_u *UserUpdate) SetTotpSecretEncrypted(v string) *UserUpdate {
|
||||
_u.mutation.SetTotpSecretEncrypted(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpSecretEncrypted sets the "totp_secret_encrypted" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableTotpSecretEncrypted(v *string) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetTotpSecretEncrypted(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTotpSecretEncrypted clears the value of the "totp_secret_encrypted" field.
|
||||
func (_u *UserUpdate) ClearTotpSecretEncrypted() *UserUpdate {
|
||||
_u.mutation.ClearTotpSecretEncrypted()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (_u *UserUpdate) SetTotpEnabled(v bool) *UserUpdate {
|
||||
_u.mutation.SetTotpEnabled(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabled sets the "totp_enabled" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableTotpEnabled(v *bool) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetTotpEnabled(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (_u *UserUpdate) SetTotpEnabledAt(v time.Time) *UserUpdate {
|
||||
_u.mutation.SetTotpEnabledAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabledAt sets the "totp_enabled_at" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableTotpEnabledAt(v *time.Time) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetTotpEnabledAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTotpEnabledAt clears the value of the "totp_enabled_at" field.
|
||||
func (_u *UserUpdate) ClearTotpEnabledAt() *UserUpdate {
|
||||
_u.mutation.ClearTotpEnabledAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *UserUpdate) AddAPIKeyIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -247,6 +302,21 @@ func (_u *UserUpdate) AddAssignedSubscriptions(v ...*UserSubscription) *UserUpda
|
||||
return _u.AddAssignedSubscriptionIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
|
||||
func (_u *UserUpdate) AddAnnouncementReadIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.AddAnnouncementReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
|
||||
func (_u *UserUpdate) AddAnnouncementReads(v ...*AnnouncementRead) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAnnouncementReadIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
|
||||
func (_u *UserUpdate) AddAllowedGroupIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.AddAllowedGroupIDs(ids...)
|
||||
@@ -396,6 +466,27 @@ func (_u *UserUpdate) RemoveAssignedSubscriptions(v ...*UserSubscription) *UserU
|
||||
return _u.RemoveAssignedSubscriptionIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAnnouncementReads clears all "announcement_reads" edges to the AnnouncementRead entity.
|
||||
func (_u *UserUpdate) ClearAnnouncementReads() *UserUpdate {
|
||||
_u.mutation.ClearAnnouncementReads()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAnnouncementReadIDs removes the "announcement_reads" edge to AnnouncementRead entities by IDs.
|
||||
func (_u *UserUpdate) RemoveAnnouncementReadIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.RemoveAnnouncementReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAnnouncementReads removes "announcement_reads" edges to AnnouncementRead entities.
|
||||
func (_u *UserUpdate) RemoveAnnouncementReads(v ...*AnnouncementRead) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAnnouncementReadIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAllowedGroups clears all "allowed_groups" edges to the Group entity.
|
||||
func (_u *UserUpdate) ClearAllowedGroups() *UserUpdate {
|
||||
_u.mutation.ClearAllowedGroups()
|
||||
@@ -603,6 +694,21 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if value, ok := _u.mutation.Notes(); ok {
|
||||
_spec.SetField(user.FieldNotes, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpSecretEncrypted(); ok {
|
||||
_spec.SetField(user.FieldTotpSecretEncrypted, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.TotpSecretEncryptedCleared() {
|
||||
_spec.ClearField(user.FieldTotpSecretEncrypted, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpEnabled(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpEnabledAt(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabledAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.TotpEnabledAtCleared() {
|
||||
_spec.ClearField(user.FieldTotpEnabledAt, field.TypeTime)
|
||||
}
|
||||
if _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -783,6 +889,51 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AnnouncementReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAnnouncementReadsIDs(); len(nodes) > 0 && !_u.mutation.AnnouncementReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AllowedGroupsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2M,
|
||||
@@ -1147,6 +1298,60 @@ func (_u *UserUpdateOne) SetNillableNotes(v *string) *UserUpdateOne {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpSecretEncrypted sets the "totp_secret_encrypted" field.
|
||||
func (_u *UserUpdateOne) SetTotpSecretEncrypted(v string) *UserUpdateOne {
|
||||
_u.mutation.SetTotpSecretEncrypted(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpSecretEncrypted sets the "totp_secret_encrypted" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableTotpSecretEncrypted(v *string) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetTotpSecretEncrypted(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTotpSecretEncrypted clears the value of the "totp_secret_encrypted" field.
|
||||
func (_u *UserUpdateOne) ClearTotpSecretEncrypted() *UserUpdateOne {
|
||||
_u.mutation.ClearTotpSecretEncrypted()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpEnabled sets the "totp_enabled" field.
|
||||
func (_u *UserUpdateOne) SetTotpEnabled(v bool) *UserUpdateOne {
|
||||
_u.mutation.SetTotpEnabled(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabled sets the "totp_enabled" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableTotpEnabled(v *bool) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetTotpEnabled(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetTotpEnabledAt sets the "totp_enabled_at" field.
|
||||
func (_u *UserUpdateOne) SetTotpEnabledAt(v time.Time) *UserUpdateOne {
|
||||
_u.mutation.SetTotpEnabledAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableTotpEnabledAt sets the "totp_enabled_at" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableTotpEnabledAt(v *time.Time) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetTotpEnabledAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearTotpEnabledAt clears the value of the "totp_enabled_at" field.
|
||||
func (_u *UserUpdateOne) ClearTotpEnabledAt() *UserUpdateOne {
|
||||
_u.mutation.ClearTotpEnabledAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *UserUpdateOne) AddAPIKeyIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -1207,6 +1412,21 @@ func (_u *UserUpdateOne) AddAssignedSubscriptions(v ...*UserSubscription) *UserU
|
||||
return _u.AddAssignedSubscriptionIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
|
||||
func (_u *UserUpdateOne) AddAnnouncementReadIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.AddAnnouncementReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
|
||||
func (_u *UserUpdateOne) AddAnnouncementReads(v ...*AnnouncementRead) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAnnouncementReadIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
|
||||
func (_u *UserUpdateOne) AddAllowedGroupIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.AddAllowedGroupIDs(ids...)
|
||||
@@ -1356,6 +1576,27 @@ func (_u *UserUpdateOne) RemoveAssignedSubscriptions(v ...*UserSubscription) *Us
|
||||
return _u.RemoveAssignedSubscriptionIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAnnouncementReads clears all "announcement_reads" edges to the AnnouncementRead entity.
|
||||
func (_u *UserUpdateOne) ClearAnnouncementReads() *UserUpdateOne {
|
||||
_u.mutation.ClearAnnouncementReads()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAnnouncementReadIDs removes the "announcement_reads" edge to AnnouncementRead entities by IDs.
|
||||
func (_u *UserUpdateOne) RemoveAnnouncementReadIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.RemoveAnnouncementReadIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAnnouncementReads removes "announcement_reads" edges to AnnouncementRead entities.
|
||||
func (_u *UserUpdateOne) RemoveAnnouncementReads(v ...*AnnouncementRead) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAnnouncementReadIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAllowedGroups clears all "allowed_groups" edges to the Group entity.
|
||||
func (_u *UserUpdateOne) ClearAllowedGroups() *UserUpdateOne {
|
||||
_u.mutation.ClearAllowedGroups()
|
||||
@@ -1593,6 +1834,21 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
|
||||
if value, ok := _u.mutation.Notes(); ok {
|
||||
_spec.SetField(user.FieldNotes, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpSecretEncrypted(); ok {
|
||||
_spec.SetField(user.FieldTotpSecretEncrypted, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.TotpSecretEncryptedCleared() {
|
||||
_spec.ClearField(user.FieldTotpSecretEncrypted, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpEnabled(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabled, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.TotpEnabledAt(); ok {
|
||||
_spec.SetField(user.FieldTotpEnabledAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.TotpEnabledAtCleared() {
|
||||
_spec.ClearField(user.FieldTotpEnabledAt, field.TypeTime)
|
||||
}
|
||||
if _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -1773,6 +2029,51 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AnnouncementReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAnnouncementReadsIDs(); len(nodes) > 0 && !_u.mutation.AnnouncementReadsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AnnouncementReadsTable,
|
||||
Columns: []string{user.AnnouncementReadsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AllowedGroupsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2M,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
module github.com/Wei-Shaw/sub2api
|
||||
|
||||
go 1.25.5
|
||||
go 1.25.7
|
||||
|
||||
require (
|
||||
entgo.io/ent v0.14.5
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/dgraph-io/ristretto v0.2.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -11,7 +13,10 @@ require (
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/imroc/req/v3 v3.57.0
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/redis/go-redis/v9 v9.17.2
|
||||
github.com/refraction-networking/utls v1.8.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil/v4 v4.25.6
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
@@ -20,23 +25,24 @@ require (
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
github.com/zeromicro/go-zero v1.9.4
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/net v0.49.0
|
||||
golang.org/x/sync v0.19.0
|
||||
golang.org/x/term v0.38.0
|
||||
golang.org/x/term v0.39.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.44.3
|
||||
)
|
||||
|
||||
require (
|
||||
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/bmatcuk/doublestar v1.3.4 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
@@ -47,7 +53,6 @@ require (
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/docker v28.5.1+incompatible // indirect
|
||||
@@ -70,12 +75,10 @@ require (
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/subcommands v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
|
||||
github.com/icholy/digest v1.1.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
@@ -84,7 +87,6 @@ require (
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mdelapenya/tlscert v0.2.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
@@ -99,19 +101,16 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.57.1 // indirect
|
||||
github.com/refraction-networking/utls v1.8.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
@@ -119,7 +118,6 @@ require (
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/testcontainers/testcontainers-go v0.40.0 // indirect
|
||||
@@ -143,16 +141,13 @@ require (
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/sqlite v1.44.1 // indirect
|
||||
)
|
||||
|
||||
@@ -20,6 +20,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
|
||||
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
||||
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
@@ -44,7 +46,6 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
|
||||
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -53,6 +54,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
|
||||
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
@@ -111,8 +114,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||
@@ -121,6 +124,9 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=
|
||||
@@ -166,7 +172,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
@@ -208,6 +213,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -217,6 +224,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
||||
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
@@ -235,7 +244,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
@@ -339,16 +347,14 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -360,21 +366,16 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU=
|
||||
@@ -395,12 +396,32 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
|
||||
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
|
||||
modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
|
||||
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
|
||||
modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
|
||||
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||
modernc.org/sqlite v1.44.1 h1:qybx/rNpfQipX/t47OxbHmkkJuv2JWifCMH8SVUiDas=
|
||||
modernc.org/sqlite v1.44.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.44.3 h1:+39JvV/HWMcYslAwRxHb8067w+2zowvFOUrOWIy9PjY=
|
||||
modernc.org/sqlite v1.44.3/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
||||
@@ -47,6 +47,7 @@ type Config struct {
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
Ops OpsConfig `mapstructure:"ops"`
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Totp TotpConfig `mapstructure:"totp"`
|
||||
LinuxDo LinuxDoConnectConfig `mapstructure:"linuxdo_connect"`
|
||||
Default DefaultConfig `mapstructure:"default"`
|
||||
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
||||
@@ -143,12 +144,24 @@ type PricingConfig struct {
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Mode string `mapstructure:"mode"` // debug/release
|
||||
ReadHeaderTimeout int `mapstructure:"read_header_timeout"` // 读取请求头超时(秒)
|
||||
IdleTimeout int `mapstructure:"idle_timeout"` // 空闲连接超时(秒)
|
||||
TrustedProxies []string `mapstructure:"trusted_proxies"` // 可信代理列表(CIDR/IP)
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Mode string `mapstructure:"mode"` // debug/release
|
||||
ReadHeaderTimeout int `mapstructure:"read_header_timeout"` // 读取请求头超时(秒)
|
||||
IdleTimeout int `mapstructure:"idle_timeout"` // 空闲连接超时(秒)
|
||||
TrustedProxies []string `mapstructure:"trusted_proxies"` // 可信代理列表(CIDR/IP)
|
||||
MaxRequestBodySize int64 `mapstructure:"max_request_body_size"` // 全局最大请求体限制
|
||||
H2C H2CConfig `mapstructure:"h2c"` // HTTP/2 Cleartext 配置
|
||||
}
|
||||
|
||||
// H2CConfig HTTP/2 Cleartext 配置
|
||||
type H2CConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"` // 是否启用 H2C
|
||||
MaxConcurrentStreams uint32 `mapstructure:"max_concurrent_streams"` // 最大并发流数量
|
||||
IdleTimeout int `mapstructure:"idle_timeout"` // 空闲超时(秒)
|
||||
MaxReadFrameSize int `mapstructure:"max_read_frame_size"` // 最大帧大小(字节)
|
||||
MaxUploadBufferPerConnection int `mapstructure:"max_upload_buffer_per_connection"` // 每个连接的上传缓冲区(字节)
|
||||
MaxUploadBufferPerStream int `mapstructure:"max_upload_buffer_per_stream"` // 每个流的上传缓冲区(字节)
|
||||
}
|
||||
|
||||
type CORSConfig struct {
|
||||
@@ -414,6 +427,8 @@ type RedisConfig struct {
|
||||
PoolSize int `mapstructure:"pool_size"`
|
||||
// MinIdleConns: 最小空闲连接数,保持热连接减少冷启动延迟
|
||||
MinIdleConns int `mapstructure:"min_idle_conns"`
|
||||
// EnableTLS: 是否启用 TLS/SSL 连接
|
||||
EnableTLS bool `mapstructure:"enable_tls"`
|
||||
}
|
||||
|
||||
func (r *RedisConfig) Address() string {
|
||||
@@ -464,6 +479,23 @@ type OpsMetricsCollectorCacheConfig struct {
|
||||
type JWTConfig struct {
|
||||
Secret string `mapstructure:"secret"`
|
||||
ExpireHour int `mapstructure:"expire_hour"`
|
||||
// AccessTokenExpireMinutes: Access Token有效期(分钟),默认15分钟
|
||||
// 短有效期减少被盗用风险,配合Refresh Token实现无感续期
|
||||
AccessTokenExpireMinutes int `mapstructure:"access_token_expire_minutes"`
|
||||
// RefreshTokenExpireDays: Refresh Token有效期(天),默认30天
|
||||
RefreshTokenExpireDays int `mapstructure:"refresh_token_expire_days"`
|
||||
// RefreshWindowMinutes: 刷新窗口(分钟),在Access Token过期前多久开始允许刷新
|
||||
RefreshWindowMinutes int `mapstructure:"refresh_window_minutes"`
|
||||
}
|
||||
|
||||
// TotpConfig TOTP 双因素认证配置
|
||||
type TotpConfig struct {
|
||||
// EncryptionKey 用于加密 TOTP 密钥的 AES-256 密钥(32 字节 hex 编码)
|
||||
// 如果为空,将自动生成一个随机密钥(仅适用于开发环境)
|
||||
EncryptionKey string `mapstructure:"encryption_key"`
|
||||
// EncryptionKeyConfigured 标记加密密钥是否为手动配置(非自动生成)
|
||||
// 只有手动配置了密钥才允许在管理后台启用 TOTP 功能
|
||||
EncryptionKeyConfigured bool `mapstructure:"-"`
|
||||
}
|
||||
|
||||
type TurnstileConfig struct {
|
||||
@@ -626,6 +658,20 @@ func Load() (*Config, error) {
|
||||
log.Println("Warning: JWT secret auto-generated. Consider setting a fixed secret for production.")
|
||||
}
|
||||
|
||||
// Auto-generate TOTP encryption key if not set (32 bytes = 64 hex chars for AES-256)
|
||||
cfg.Totp.EncryptionKey = strings.TrimSpace(cfg.Totp.EncryptionKey)
|
||||
if cfg.Totp.EncryptionKey == "" {
|
||||
key, err := generateJWTSecret(32) // Reuse the same random generation function
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate totp encryption key error: %w", err)
|
||||
}
|
||||
cfg.Totp.EncryptionKey = key
|
||||
cfg.Totp.EncryptionKeyConfigured = false
|
||||
log.Println("Warning: TOTP encryption key auto-generated. Consider setting a fixed key for production.")
|
||||
} else {
|
||||
cfg.Totp.EncryptionKeyConfigured = true
|
||||
}
|
||||
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("validate config error: %w", err)
|
||||
}
|
||||
@@ -660,6 +706,14 @@ func setDefaults() {
|
||||
viper.SetDefault("server.read_header_timeout", 30) // 30秒读取请求头
|
||||
viper.SetDefault("server.idle_timeout", 120) // 120秒空闲超时
|
||||
viper.SetDefault("server.trusted_proxies", []string{})
|
||||
viper.SetDefault("server.max_request_body_size", int64(100*1024*1024))
|
||||
// H2C 默认配置
|
||||
viper.SetDefault("server.h2c.enabled", false)
|
||||
viper.SetDefault("server.h2c.max_concurrent_streams", uint32(50)) // 50 个并发流
|
||||
viper.SetDefault("server.h2c.idle_timeout", 75) // 75 秒
|
||||
viper.SetDefault("server.h2c.max_read_frame_size", 1<<20) // 1MB(够用)
|
||||
viper.SetDefault("server.h2c.max_upload_buffer_per_connection", 2<<20) // 2MB
|
||||
viper.SetDefault("server.h2c.max_upload_buffer_per_stream", 512<<10) // 512KB
|
||||
|
||||
// CORS
|
||||
viper.SetDefault("cors.allowed_origins", []string{})
|
||||
@@ -737,6 +791,7 @@ func setDefaults() {
|
||||
viper.SetDefault("redis.write_timeout_seconds", 3)
|
||||
viper.SetDefault("redis.pool_size", 128)
|
||||
viper.SetDefault("redis.min_idle_conns", 10)
|
||||
viper.SetDefault("redis.enable_tls", false)
|
||||
|
||||
// Ops (vNext)
|
||||
viper.SetDefault("ops.enabled", true)
|
||||
@@ -755,6 +810,12 @@ func setDefaults() {
|
||||
// JWT
|
||||
viper.SetDefault("jwt.secret", "")
|
||||
viper.SetDefault("jwt.expire_hour", 24)
|
||||
viper.SetDefault("jwt.access_token_expire_minutes", 360) // 6小时Access Token有效期
|
||||
viper.SetDefault("jwt.refresh_token_expire_days", 30) // 30天Refresh Token有效期
|
||||
viper.SetDefault("jwt.refresh_window_minutes", 2) // 过期前2分钟开始允许刷新
|
||||
|
||||
// TOTP
|
||||
viper.SetDefault("totp.encryption_key", "")
|
||||
|
||||
// Default
|
||||
// Admin credentials are created via the setup flow (web wizard / CLI / AUTO_SETUP).
|
||||
@@ -881,6 +942,22 @@ func (c *Config) Validate() error {
|
||||
if c.JWT.ExpireHour > 24 {
|
||||
log.Printf("Warning: jwt.expire_hour is %d hours (> 24). Consider shorter expiration for security.", c.JWT.ExpireHour)
|
||||
}
|
||||
// JWT Refresh Token配置验证
|
||||
if c.JWT.AccessTokenExpireMinutes <= 0 {
|
||||
return fmt.Errorf("jwt.access_token_expire_minutes must be positive")
|
||||
}
|
||||
if c.JWT.AccessTokenExpireMinutes > 720 {
|
||||
log.Printf("Warning: jwt.access_token_expire_minutes is %d (> 720). Consider shorter expiration for security.", c.JWT.AccessTokenExpireMinutes)
|
||||
}
|
||||
if c.JWT.RefreshTokenExpireDays <= 0 {
|
||||
return fmt.Errorf("jwt.refresh_token_expire_days must be positive")
|
||||
}
|
||||
if c.JWT.RefreshTokenExpireDays > 90 {
|
||||
log.Printf("Warning: jwt.refresh_token_expire_days is %d (> 90). Consider shorter expiration for security.", c.JWT.RefreshTokenExpireDays)
|
||||
}
|
||||
if c.JWT.RefreshWindowMinutes < 0 {
|
||||
return fmt.Errorf("jwt.refresh_window_minutes must be non-negative")
|
||||
}
|
||||
if c.Security.CSP.Enabled && strings.TrimSpace(c.Security.CSP.Policy) == "" {
|
||||
return fmt.Errorf("security.csp.policy is required when CSP is enabled")
|
||||
}
|
||||
|
||||
226
backend/internal/domain/announcement.go
Normal file
226
backend/internal/domain/announcement.go
Normal file
@@ -0,0 +1,226 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
AnnouncementStatusDraft = "draft"
|
||||
AnnouncementStatusActive = "active"
|
||||
AnnouncementStatusArchived = "archived"
|
||||
)
|
||||
|
||||
const (
|
||||
AnnouncementConditionTypeSubscription = "subscription"
|
||||
AnnouncementConditionTypeBalance = "balance"
|
||||
)
|
||||
|
||||
const (
|
||||
AnnouncementOperatorIn = "in"
|
||||
AnnouncementOperatorGT = "gt"
|
||||
AnnouncementOperatorGTE = "gte"
|
||||
AnnouncementOperatorLT = "lt"
|
||||
AnnouncementOperatorLTE = "lte"
|
||||
AnnouncementOperatorEQ = "eq"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAnnouncementNotFound = infraerrors.NotFound("ANNOUNCEMENT_NOT_FOUND", "announcement not found")
|
||||
ErrAnnouncementInvalidTarget = infraerrors.BadRequest("ANNOUNCEMENT_INVALID_TARGET", "invalid announcement targeting rules")
|
||||
)
|
||||
|
||||
type AnnouncementTargeting struct {
|
||||
// AnyOf 表示 OR:任意一个条件组满足即可展示。
|
||||
AnyOf []AnnouncementConditionGroup `json:"any_of,omitempty"`
|
||||
}
|
||||
|
||||
type AnnouncementConditionGroup struct {
|
||||
// AllOf 表示 AND:组内所有条件都满足才算命中该组。
|
||||
AllOf []AnnouncementCondition `json:"all_of,omitempty"`
|
||||
}
|
||||
|
||||
type AnnouncementCondition struct {
|
||||
// Type: subscription | balance
|
||||
Type string `json:"type"`
|
||||
|
||||
// Operator:
|
||||
// - subscription: in
|
||||
// - balance: gt/gte/lt/lte/eq
|
||||
Operator string `json:"operator"`
|
||||
|
||||
// subscription 条件:匹配的订阅套餐(group_id)
|
||||
GroupIDs []int64 `json:"group_ids,omitempty"`
|
||||
|
||||
// balance 条件:比较阈值
|
||||
Value float64 `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (t AnnouncementTargeting) Matches(balance float64, activeSubscriptionGroupIDs map[int64]struct{}) bool {
|
||||
// 空规则:展示给所有用户
|
||||
if len(t.AnyOf) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, group := range t.AnyOf {
|
||||
if len(group.AllOf) == 0 {
|
||||
// 空条件组不命中(避免 OR 中出现无条件 “全命中”)
|
||||
continue
|
||||
}
|
||||
allMatched := true
|
||||
for _, cond := range group.AllOf {
|
||||
if !cond.Matches(balance, activeSubscriptionGroupIDs) {
|
||||
allMatched = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allMatched {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c AnnouncementCondition) Matches(balance float64, activeSubscriptionGroupIDs map[int64]struct{}) bool {
|
||||
switch c.Type {
|
||||
case AnnouncementConditionTypeSubscription:
|
||||
if c.Operator != AnnouncementOperatorIn {
|
||||
return false
|
||||
}
|
||||
if len(c.GroupIDs) == 0 {
|
||||
return false
|
||||
}
|
||||
if len(activeSubscriptionGroupIDs) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, gid := range c.GroupIDs {
|
||||
if _, ok := activeSubscriptionGroupIDs[gid]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
case AnnouncementConditionTypeBalance:
|
||||
switch c.Operator {
|
||||
case AnnouncementOperatorGT:
|
||||
return balance > c.Value
|
||||
case AnnouncementOperatorGTE:
|
||||
return balance >= c.Value
|
||||
case AnnouncementOperatorLT:
|
||||
return balance < c.Value
|
||||
case AnnouncementOperatorLTE:
|
||||
return balance <= c.Value
|
||||
case AnnouncementOperatorEQ:
|
||||
return balance == c.Value
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (t AnnouncementTargeting) NormalizeAndValidate() (AnnouncementTargeting, error) {
|
||||
normalized := AnnouncementTargeting{AnyOf: make([]AnnouncementConditionGroup, 0, len(t.AnyOf))}
|
||||
|
||||
// 允许空 targeting(展示给所有用户)
|
||||
if len(t.AnyOf) == 0 {
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
if len(t.AnyOf) > 50 {
|
||||
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
|
||||
}
|
||||
|
||||
for _, g := range t.AnyOf {
|
||||
if len(g.AllOf) == 0 {
|
||||
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
|
||||
}
|
||||
if len(g.AllOf) > 50 {
|
||||
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
|
||||
}
|
||||
|
||||
group := AnnouncementConditionGroup{AllOf: make([]AnnouncementCondition, 0, len(g.AllOf))}
|
||||
for _, c := range g.AllOf {
|
||||
cond := AnnouncementCondition{
|
||||
Type: strings.TrimSpace(c.Type),
|
||||
Operator: strings.TrimSpace(c.Operator),
|
||||
Value: c.Value,
|
||||
}
|
||||
for _, gid := range c.GroupIDs {
|
||||
if gid <= 0 {
|
||||
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
|
||||
}
|
||||
cond.GroupIDs = append(cond.GroupIDs, gid)
|
||||
}
|
||||
|
||||
if err := cond.validate(); err != nil {
|
||||
return AnnouncementTargeting{}, err
|
||||
}
|
||||
group.AllOf = append(group.AllOf, cond)
|
||||
}
|
||||
|
||||
normalized.AnyOf = append(normalized.AnyOf, group)
|
||||
}
|
||||
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
func (c AnnouncementCondition) validate() error {
|
||||
switch c.Type {
|
||||
case AnnouncementConditionTypeSubscription:
|
||||
if c.Operator != AnnouncementOperatorIn {
|
||||
return ErrAnnouncementInvalidTarget
|
||||
}
|
||||
if len(c.GroupIDs) == 0 {
|
||||
return ErrAnnouncementInvalidTarget
|
||||
}
|
||||
return nil
|
||||
|
||||
case AnnouncementConditionTypeBalance:
|
||||
switch c.Operator {
|
||||
case AnnouncementOperatorGT, AnnouncementOperatorGTE, AnnouncementOperatorLT, AnnouncementOperatorLTE, AnnouncementOperatorEQ:
|
||||
return nil
|
||||
default:
|
||||
return ErrAnnouncementInvalidTarget
|
||||
}
|
||||
|
||||
default:
|
||||
return ErrAnnouncementInvalidTarget
|
||||
}
|
||||
}
|
||||
|
||||
type Announcement struct {
|
||||
ID int64
|
||||
Title string
|
||||
Content string
|
||||
Status string
|
||||
Targeting AnnouncementTargeting
|
||||
StartsAt *time.Time
|
||||
EndsAt *time.Time
|
||||
CreatedBy *int64
|
||||
UpdatedBy *int64
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (a *Announcement) IsActiveAt(now time.Time) bool {
|
||||
if a == nil {
|
||||
return false
|
||||
}
|
||||
if a.Status != AnnouncementStatusActive {
|
||||
return false
|
||||
}
|
||||
if a.StartsAt != nil && now.Before(*a.StartsAt) {
|
||||
return false
|
||||
}
|
||||
if a.EndsAt != nil && !now.Before(*a.EndsAt) {
|
||||
// ends_at 语义:到点即下线
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
101
backend/internal/domain/constants.go
Normal file
101
backend/internal/domain/constants.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package domain
|
||||
|
||||
// Status constants
|
||||
const (
|
||||
StatusActive = "active"
|
||||
StatusDisabled = "disabled"
|
||||
StatusError = "error"
|
||||
StatusUnused = "unused"
|
||||
StatusUsed = "used"
|
||||
StatusExpired = "expired"
|
||||
)
|
||||
|
||||
// Role constants
|
||||
const (
|
||||
RoleAdmin = "admin"
|
||||
RoleUser = "user"
|
||||
)
|
||||
|
||||
// Platform constants
|
||||
const (
|
||||
PlatformAnthropic = "anthropic"
|
||||
PlatformOpenAI = "openai"
|
||||
PlatformGemini = "gemini"
|
||||
PlatformAntigravity = "antigravity"
|
||||
)
|
||||
|
||||
// Account type constants
|
||||
const (
|
||||
AccountTypeOAuth = "oauth" // OAuth类型账号(full scope: profile + inference)
|
||||
AccountTypeSetupToken = "setup-token" // Setup Token类型账号(inference only scope)
|
||||
AccountTypeAPIKey = "apikey" // API Key类型账号
|
||||
AccountTypeUpstream = "upstream" // 上游透传类型账号(通过 Base URL + API Key 连接上游)
|
||||
)
|
||||
|
||||
// Redeem type constants
|
||||
const (
|
||||
RedeemTypeBalance = "balance"
|
||||
RedeemTypeConcurrency = "concurrency"
|
||||
RedeemTypeSubscription = "subscription"
|
||||
RedeemTypeInvitation = "invitation"
|
||||
)
|
||||
|
||||
// PromoCode status constants
|
||||
const (
|
||||
PromoCodeStatusActive = "active"
|
||||
PromoCodeStatusDisabled = "disabled"
|
||||
)
|
||||
|
||||
// Admin adjustment type constants
|
||||
const (
|
||||
AdjustmentTypeAdminBalance = "admin_balance" // 管理员调整余额
|
||||
AdjustmentTypeAdminConcurrency = "admin_concurrency" // 管理员调整并发数
|
||||
)
|
||||
|
||||
// Group subscription type constants
|
||||
const (
|
||||
SubscriptionTypeStandard = "standard" // 标准计费模式(按余额扣费)
|
||||
SubscriptionTypeSubscription = "subscription" // 订阅模式(按限额控制)
|
||||
)
|
||||
|
||||
// Subscription status constants
|
||||
const (
|
||||
SubscriptionStatusActive = "active"
|
||||
SubscriptionStatusExpired = "expired"
|
||||
SubscriptionStatusSuspended = "suspended"
|
||||
)
|
||||
|
||||
// DefaultAntigravityModelMapping 是 Antigravity 平台的默认模型映射
|
||||
// 当账号未配置 model_mapping 时使用此默认值
|
||||
// 与前端 useModelWhitelist.ts 中的 antigravityDefaultMappings 保持一致
|
||||
var DefaultAntigravityModelMapping = map[string]string{
|
||||
// Claude 白名单
|
||||
"claude-opus-4-6-thinking": "claude-opus-4-6-thinking", // 官方模型
|
||||
"claude-opus-4-6": "claude-opus-4-6-thinking", // 简称映射
|
||||
"claude-opus-4-5-thinking": "claude-opus-4-6-thinking", // 迁移旧模型
|
||||
"claude-sonnet-4-5": "claude-sonnet-4-5",
|
||||
"claude-sonnet-4-5-thinking": "claude-sonnet-4-5-thinking",
|
||||
// Claude 详细版本 ID 映射
|
||||
"claude-opus-4-5-20251101": "claude-opus-4-6-thinking", // 迁移旧模型
|
||||
"claude-sonnet-4-5-20250929": "claude-sonnet-4-5",
|
||||
// Claude Haiku → Sonnet(无 Haiku 支持)
|
||||
"claude-haiku-4-5": "claude-sonnet-4-5",
|
||||
"claude-haiku-4-5-20251001": "claude-sonnet-4-5",
|
||||
// Gemini 2.5 白名单
|
||||
"gemini-2.5-flash": "gemini-2.5-flash",
|
||||
"gemini-2.5-flash-lite": "gemini-2.5-flash-lite",
|
||||
"gemini-2.5-flash-thinking": "gemini-2.5-flash-thinking",
|
||||
"gemini-2.5-pro": "gemini-2.5-pro",
|
||||
// Gemini 3 白名单
|
||||
"gemini-3-flash": "gemini-3-flash",
|
||||
"gemini-3-pro-high": "gemini-3-pro-high",
|
||||
"gemini-3-pro-low": "gemini-3-pro-low",
|
||||
"gemini-3-pro-image": "gemini-3-pro-image",
|
||||
// Gemini 3 preview 映射
|
||||
"gemini-3-flash-preview": "gemini-3-flash",
|
||||
"gemini-3-pro-preview": "gemini-3-pro-high",
|
||||
"gemini-3-pro-image-preview": "gemini-3-pro-image",
|
||||
// 其他官方模型
|
||||
"gpt-oss-120b-medium": "gpt-oss-120b-medium",
|
||||
"tab_flash_lite_preview": "tab_flash_lite_preview",
|
||||
}
|
||||
544
backend/internal/handler/admin/account_data.go
Normal file
544
backend/internal/handler/admin/account_data.go
Normal file
@@ -0,0 +1,544 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
dataType = "sub2api-data"
|
||||
legacyDataType = "sub2api-bundle"
|
||||
dataVersion = 1
|
||||
dataPageCap = 1000
|
||||
)
|
||||
|
||||
type DataPayload struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Version int `json:"version,omitempty"`
|
||||
ExportedAt string `json:"exported_at"`
|
||||
Proxies []DataProxy `json:"proxies"`
|
||||
Accounts []DataAccount `json:"accounts"`
|
||||
}
|
||||
|
||||
type DataProxy struct {
|
||||
ProxyKey string `json:"proxy_key"`
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type DataAccount struct {
|
||||
Name string `json:"name"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Platform string `json:"platform"`
|
||||
Type string `json:"type"`
|
||||
Credentials map[string]any `json:"credentials"`
|
||||
Extra map[string]any `json:"extra,omitempty"`
|
||||
ProxyKey *string `json:"proxy_key,omitempty"`
|
||||
Concurrency int `json:"concurrency"`
|
||||
Priority int `json:"priority"`
|
||||
RateMultiplier *float64 `json:"rate_multiplier,omitempty"`
|
||||
ExpiresAt *int64 `json:"expires_at,omitempty"`
|
||||
AutoPauseOnExpired *bool `json:"auto_pause_on_expired,omitempty"`
|
||||
}
|
||||
|
||||
type DataImportRequest struct {
|
||||
Data DataPayload `json:"data"`
|
||||
SkipDefaultGroupBind *bool `json:"skip_default_group_bind"`
|
||||
}
|
||||
|
||||
type DataImportResult struct {
|
||||
ProxyCreated int `json:"proxy_created"`
|
||||
ProxyReused int `json:"proxy_reused"`
|
||||
ProxyFailed int `json:"proxy_failed"`
|
||||
AccountCreated int `json:"account_created"`
|
||||
AccountFailed int `json:"account_failed"`
|
||||
Errors []DataImportError `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
type DataImportError struct {
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ProxyKey string `json:"proxy_key,omitempty"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func buildProxyKey(protocol, host string, port int, username, password string) string {
|
||||
return fmt.Sprintf("%s|%s|%d|%s|%s", strings.TrimSpace(protocol), strings.TrimSpace(host), port, strings.TrimSpace(username), strings.TrimSpace(password))
|
||||
}
|
||||
|
||||
func (h *AccountHandler) ExportData(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
selectedIDs, err := parseAccountIDs(c)
|
||||
if err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
accounts, err := h.resolveExportAccounts(ctx, selectedIDs, c)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
includeProxies, err := parseIncludeProxies(c)
|
||||
if err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var proxies []service.Proxy
|
||||
if includeProxies {
|
||||
proxies, err = h.resolveExportProxies(ctx, accounts)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
proxies = []service.Proxy{}
|
||||
}
|
||||
|
||||
proxyKeyByID := make(map[int64]string, len(proxies))
|
||||
dataProxies := make([]DataProxy, 0, len(proxies))
|
||||
for i := range proxies {
|
||||
p := proxies[i]
|
||||
key := buildProxyKey(p.Protocol, p.Host, p.Port, p.Username, p.Password)
|
||||
proxyKeyByID[p.ID] = key
|
||||
dataProxies = append(dataProxies, DataProxy{
|
||||
ProxyKey: key,
|
||||
Name: p.Name,
|
||||
Protocol: p.Protocol,
|
||||
Host: p.Host,
|
||||
Port: p.Port,
|
||||
Username: p.Username,
|
||||
Password: p.Password,
|
||||
Status: p.Status,
|
||||
})
|
||||
}
|
||||
|
||||
dataAccounts := make([]DataAccount, 0, len(accounts))
|
||||
for i := range accounts {
|
||||
acc := accounts[i]
|
||||
var proxyKey *string
|
||||
if acc.ProxyID != nil {
|
||||
if key, ok := proxyKeyByID[*acc.ProxyID]; ok {
|
||||
proxyKey = &key
|
||||
}
|
||||
}
|
||||
var expiresAt *int64
|
||||
if acc.ExpiresAt != nil {
|
||||
v := acc.ExpiresAt.Unix()
|
||||
expiresAt = &v
|
||||
}
|
||||
dataAccounts = append(dataAccounts, DataAccount{
|
||||
Name: acc.Name,
|
||||
Notes: acc.Notes,
|
||||
Platform: acc.Platform,
|
||||
Type: acc.Type,
|
||||
Credentials: acc.Credentials,
|
||||
Extra: acc.Extra,
|
||||
ProxyKey: proxyKey,
|
||||
Concurrency: acc.Concurrency,
|
||||
Priority: acc.Priority,
|
||||
RateMultiplier: acc.RateMultiplier,
|
||||
ExpiresAt: expiresAt,
|
||||
AutoPauseOnExpired: &acc.AutoPauseOnExpired,
|
||||
})
|
||||
}
|
||||
|
||||
payload := DataPayload{
|
||||
ExportedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
Proxies: dataProxies,
|
||||
Accounts: dataAccounts,
|
||||
}
|
||||
|
||||
response.Success(c, payload)
|
||||
}
|
||||
|
||||
func (h *AccountHandler) ImportData(c *gin.Context) {
|
||||
var req DataImportRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
dataPayload := req.Data
|
||||
if err := validateDataHeader(dataPayload); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
skipDefaultGroupBind := true
|
||||
if req.SkipDefaultGroupBind != nil {
|
||||
skipDefaultGroupBind = *req.SkipDefaultGroupBind
|
||||
}
|
||||
|
||||
result := DataImportResult{}
|
||||
existingProxies, err := h.listAllProxies(c.Request.Context())
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
proxyKeyToID := make(map[string]int64, len(existingProxies))
|
||||
for i := range existingProxies {
|
||||
p := existingProxies[i]
|
||||
key := buildProxyKey(p.Protocol, p.Host, p.Port, p.Username, p.Password)
|
||||
proxyKeyToID[key] = p.ID
|
||||
}
|
||||
|
||||
for i := range dataPayload.Proxies {
|
||||
item := dataPayload.Proxies[i]
|
||||
key := item.ProxyKey
|
||||
if key == "" {
|
||||
key = buildProxyKey(item.Protocol, item.Host, item.Port, item.Username, item.Password)
|
||||
}
|
||||
if err := validateDataProxy(item); err != nil {
|
||||
result.ProxyFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
normalizedStatus := normalizeProxyStatus(item.Status)
|
||||
if existingID, ok := proxyKeyToID[key]; ok {
|
||||
proxyKeyToID[key] = existingID
|
||||
result.ProxyReused++
|
||||
if normalizedStatus != "" {
|
||||
if proxy, err := h.adminService.GetProxy(c.Request.Context(), existingID); err == nil && proxy != nil && proxy.Status != normalizedStatus {
|
||||
_, _ = h.adminService.UpdateProxy(c.Request.Context(), existingID, &service.UpdateProxyInput{
|
||||
Status: normalizedStatus,
|
||||
})
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
created, err := h.adminService.CreateProxy(c.Request.Context(), &service.CreateProxyInput{
|
||||
Name: defaultProxyName(item.Name),
|
||||
Protocol: item.Protocol,
|
||||
Host: item.Host,
|
||||
Port: item.Port,
|
||||
Username: item.Username,
|
||||
Password: item.Password,
|
||||
})
|
||||
if err != nil {
|
||||
result.ProxyFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
proxyKeyToID[key] = created.ID
|
||||
result.ProxyCreated++
|
||||
|
||||
if normalizedStatus != "" && normalizedStatus != created.Status {
|
||||
_, _ = h.adminService.UpdateProxy(c.Request.Context(), created.ID, &service.UpdateProxyInput{
|
||||
Status: normalizedStatus,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for i := range dataPayload.Accounts {
|
||||
item := dataPayload.Accounts[i]
|
||||
if err := validateDataAccount(item); err != nil {
|
||||
result.AccountFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "account",
|
||||
Name: item.Name,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
var proxyID *int64
|
||||
if item.ProxyKey != nil && *item.ProxyKey != "" {
|
||||
if id, ok := proxyKeyToID[*item.ProxyKey]; ok {
|
||||
proxyID = &id
|
||||
} else {
|
||||
result.AccountFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "account",
|
||||
Name: item.Name,
|
||||
ProxyKey: *item.ProxyKey,
|
||||
Message: "proxy_key not found",
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
accountInput := &service.CreateAccountInput{
|
||||
Name: item.Name,
|
||||
Notes: item.Notes,
|
||||
Platform: item.Platform,
|
||||
Type: item.Type,
|
||||
Credentials: item.Credentials,
|
||||
Extra: item.Extra,
|
||||
ProxyID: proxyID,
|
||||
Concurrency: item.Concurrency,
|
||||
Priority: item.Priority,
|
||||
RateMultiplier: item.RateMultiplier,
|
||||
GroupIDs: nil,
|
||||
ExpiresAt: item.ExpiresAt,
|
||||
AutoPauseOnExpired: item.AutoPauseOnExpired,
|
||||
SkipDefaultGroupBind: skipDefaultGroupBind,
|
||||
}
|
||||
|
||||
if _, err := h.adminService.CreateAccount(c.Request.Context(), accountInput); err != nil {
|
||||
result.AccountFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "account",
|
||||
Name: item.Name,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
result.AccountCreated++
|
||||
}
|
||||
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
func (h *AccountHandler) listAllProxies(ctx context.Context) ([]service.Proxy, error) {
|
||||
page := 1
|
||||
pageSize := dataPageCap
|
||||
var out []service.Proxy
|
||||
for {
|
||||
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, "", "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, items...)
|
||||
if len(out) >= int(total) || len(items) == 0 {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (h *AccountHandler) listAccountsFiltered(ctx context.Context, platform, accountType, status, search string) ([]service.Account, error) {
|
||||
page := 1
|
||||
pageSize := dataPageCap
|
||||
var out []service.Account
|
||||
for {
|
||||
items, total, err := h.adminService.ListAccounts(ctx, page, pageSize, platform, accountType, status, search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, items...)
|
||||
if len(out) >= int(total) || len(items) == 0 {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (h *AccountHandler) resolveExportAccounts(ctx context.Context, ids []int64, c *gin.Context) ([]service.Account, error) {
|
||||
if len(ids) > 0 {
|
||||
accounts, err := h.adminService.GetAccountsByIDs(ctx, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]service.Account, 0, len(accounts))
|
||||
for _, acc := range accounts {
|
||||
if acc == nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, *acc)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
platform := c.Query("platform")
|
||||
accountType := c.Query("type")
|
||||
status := c.Query("status")
|
||||
search := strings.TrimSpace(c.Query("search"))
|
||||
if len(search) > 100 {
|
||||
search = search[:100]
|
||||
}
|
||||
return h.listAccountsFiltered(ctx, platform, accountType, status, search)
|
||||
}
|
||||
|
||||
func (h *AccountHandler) resolveExportProxies(ctx context.Context, accounts []service.Account) ([]service.Proxy, error) {
|
||||
if len(accounts) == 0 {
|
||||
return []service.Proxy{}, nil
|
||||
}
|
||||
|
||||
seen := make(map[int64]struct{})
|
||||
ids := make([]int64, 0)
|
||||
for i := range accounts {
|
||||
if accounts[i].ProxyID == nil {
|
||||
continue
|
||||
}
|
||||
id := *accounts[i].ProxyID
|
||||
if id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return []service.Proxy{}, nil
|
||||
}
|
||||
|
||||
return h.adminService.GetProxiesByIDs(ctx, ids)
|
||||
}
|
||||
|
||||
func parseAccountIDs(c *gin.Context) ([]int64, error) {
|
||||
values := c.QueryArray("ids")
|
||||
if len(values) == 0 {
|
||||
raw := strings.TrimSpace(c.Query("ids"))
|
||||
if raw != "" {
|
||||
values = []string{raw}
|
||||
}
|
||||
}
|
||||
if len(values) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ids := make([]int64, 0, len(values))
|
||||
for _, item := range values {
|
||||
for _, part := range strings.Split(item, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.ParseInt(part, 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
return nil, fmt.Errorf("invalid account id: %s", part)
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func parseIncludeProxies(c *gin.Context) (bool, error) {
|
||||
raw := strings.TrimSpace(strings.ToLower(c.Query("include_proxies")))
|
||||
if raw == "" {
|
||||
return true, nil
|
||||
}
|
||||
switch raw {
|
||||
case "1", "true", "yes", "on":
|
||||
return true, nil
|
||||
case "0", "false", "no", "off":
|
||||
return false, nil
|
||||
default:
|
||||
return true, fmt.Errorf("invalid include_proxies value: %s", raw)
|
||||
}
|
||||
}
|
||||
|
||||
func validateDataHeader(payload DataPayload) error {
|
||||
if payload.Type != "" && payload.Type != dataType && payload.Type != legacyDataType {
|
||||
return fmt.Errorf("unsupported data type: %s", payload.Type)
|
||||
}
|
||||
if payload.Version != 0 && payload.Version != dataVersion {
|
||||
return fmt.Errorf("unsupported data version: %d", payload.Version)
|
||||
}
|
||||
if payload.Proxies == nil {
|
||||
return errors.New("proxies is required")
|
||||
}
|
||||
if payload.Accounts == nil {
|
||||
return errors.New("accounts is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDataProxy(item DataProxy) error {
|
||||
if strings.TrimSpace(item.Protocol) == "" {
|
||||
return errors.New("proxy protocol is required")
|
||||
}
|
||||
if strings.TrimSpace(item.Host) == "" {
|
||||
return errors.New("proxy host is required")
|
||||
}
|
||||
if item.Port <= 0 || item.Port > 65535 {
|
||||
return errors.New("proxy port is invalid")
|
||||
}
|
||||
switch item.Protocol {
|
||||
case "http", "https", "socks5", "socks5h":
|
||||
default:
|
||||
return fmt.Errorf("proxy protocol is invalid: %s", item.Protocol)
|
||||
}
|
||||
if item.Status != "" {
|
||||
normalizedStatus := normalizeProxyStatus(item.Status)
|
||||
if normalizedStatus != service.StatusActive && normalizedStatus != "inactive" {
|
||||
return fmt.Errorf("proxy status is invalid: %s", item.Status)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDataAccount(item DataAccount) error {
|
||||
if strings.TrimSpace(item.Name) == "" {
|
||||
return errors.New("account name is required")
|
||||
}
|
||||
if strings.TrimSpace(item.Platform) == "" {
|
||||
return errors.New("account platform is required")
|
||||
}
|
||||
if strings.TrimSpace(item.Type) == "" {
|
||||
return errors.New("account type is required")
|
||||
}
|
||||
if len(item.Credentials) == 0 {
|
||||
return errors.New("account credentials is required")
|
||||
}
|
||||
switch item.Type {
|
||||
case service.AccountTypeOAuth, service.AccountTypeSetupToken, service.AccountTypeAPIKey, service.AccountTypeUpstream:
|
||||
default:
|
||||
return fmt.Errorf("account type is invalid: %s", item.Type)
|
||||
}
|
||||
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
|
||||
return errors.New("rate_multiplier must be >= 0")
|
||||
}
|
||||
if item.Concurrency < 0 {
|
||||
return errors.New("concurrency must be >= 0")
|
||||
}
|
||||
if item.Priority < 0 {
|
||||
return errors.New("priority must be >= 0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultProxyName(name string) string {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return "imported-proxy"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func normalizeProxyStatus(status string) string {
|
||||
normalized := strings.TrimSpace(strings.ToLower(status))
|
||||
switch normalized {
|
||||
case "":
|
||||
return ""
|
||||
case service.StatusActive:
|
||||
return service.StatusActive
|
||||
case "inactive", service.StatusDisabled:
|
||||
return "inactive"
|
||||
default:
|
||||
return normalized
|
||||
}
|
||||
}
|
||||
231
backend/internal/handler/admin/account_data_handler_test.go
Normal file
231
backend/internal/handler/admin/account_data_handler_test.go
Normal file
@@ -0,0 +1,231 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type dataResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data dataPayload `json:"data"`
|
||||
}
|
||||
|
||||
type dataPayload struct {
|
||||
Type string `json:"type"`
|
||||
Version int `json:"version"`
|
||||
Proxies []dataProxy `json:"proxies"`
|
||||
Accounts []dataAccount `json:"accounts"`
|
||||
}
|
||||
|
||||
type dataProxy struct {
|
||||
ProxyKey string `json:"proxy_key"`
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type dataAccount struct {
|
||||
Name string `json:"name"`
|
||||
Platform string `json:"platform"`
|
||||
Type string `json:"type"`
|
||||
Credentials map[string]any `json:"credentials"`
|
||||
Extra map[string]any `json:"extra"`
|
||||
ProxyKey *string `json:"proxy_key"`
|
||||
Concurrency int `json:"concurrency"`
|
||||
Priority int `json:"priority"`
|
||||
}
|
||||
|
||||
func setupAccountDataRouter() (*gin.Engine, *stubAdminService) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
adminSvc := newStubAdminService()
|
||||
|
||||
h := NewAccountHandler(
|
||||
adminSvc,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
router.GET("/api/v1/admin/accounts/data", h.ExportData)
|
||||
router.POST("/api/v1/admin/accounts/data", h.ImportData)
|
||||
return router, adminSvc
|
||||
}
|
||||
|
||||
func TestExportDataIncludesSecrets(t *testing.T) {
|
||||
router, adminSvc := setupAccountDataRouter()
|
||||
|
||||
proxyID := int64(11)
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: proxyID,
|
||||
Name: "proxy",
|
||||
Protocol: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
{
|
||||
ID: 12,
|
||||
Name: "orphan",
|
||||
Protocol: "https",
|
||||
Host: "10.0.0.1",
|
||||
Port: 443,
|
||||
Username: "o",
|
||||
Password: "p",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
}
|
||||
adminSvc.accounts = []service.Account{
|
||||
{
|
||||
ID: 21,
|
||||
Name: "account",
|
||||
Platform: service.PlatformOpenAI,
|
||||
Type: service.AccountTypeOAuth,
|
||||
Credentials: map[string]any{"token": "secret"},
|
||||
Extra: map[string]any{"note": "x"},
|
||||
ProxyID: &proxyID,
|
||||
Concurrency: 3,
|
||||
Priority: 50,
|
||||
Status: service.StatusDisabled,
|
||||
},
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/accounts/data", nil)
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
var resp dataResponse
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Empty(t, resp.Data.Type)
|
||||
require.Equal(t, 0, resp.Data.Version)
|
||||
require.Len(t, resp.Data.Proxies, 1)
|
||||
require.Equal(t, "pass", resp.Data.Proxies[0].Password)
|
||||
require.Len(t, resp.Data.Accounts, 1)
|
||||
require.Equal(t, "secret", resp.Data.Accounts[0].Credentials["token"])
|
||||
}
|
||||
|
||||
func TestExportDataWithoutProxies(t *testing.T) {
|
||||
router, adminSvc := setupAccountDataRouter()
|
||||
|
||||
proxyID := int64(11)
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: proxyID,
|
||||
Name: "proxy",
|
||||
Protocol: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
}
|
||||
adminSvc.accounts = []service.Account{
|
||||
{
|
||||
ID: 21,
|
||||
Name: "account",
|
||||
Platform: service.PlatformOpenAI,
|
||||
Type: service.AccountTypeOAuth,
|
||||
Credentials: map[string]any{"token": "secret"},
|
||||
ProxyID: &proxyID,
|
||||
Concurrency: 3,
|
||||
Priority: 50,
|
||||
Status: service.StatusDisabled,
|
||||
},
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/accounts/data?include_proxies=false", nil)
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
var resp dataResponse
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Len(t, resp.Data.Proxies, 0)
|
||||
require.Len(t, resp.Data.Accounts, 1)
|
||||
require.Nil(t, resp.Data.Accounts[0].ProxyKey)
|
||||
}
|
||||
|
||||
func TestImportDataReusesProxyAndSkipsDefaultGroup(t *testing.T) {
|
||||
router, adminSvc := setupAccountDataRouter()
|
||||
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "proxy",
|
||||
Protocol: "socks5",
|
||||
Host: "1.2.3.4",
|
||||
Port: 1080,
|
||||
Username: "u",
|
||||
Password: "p",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
}
|
||||
|
||||
dataPayload := map[string]any{
|
||||
"data": map[string]any{
|
||||
"type": dataType,
|
||||
"version": dataVersion,
|
||||
"proxies": []map[string]any{
|
||||
{
|
||||
"proxy_key": "socks5|1.2.3.4|1080|u|p",
|
||||
"name": "proxy",
|
||||
"protocol": "socks5",
|
||||
"host": "1.2.3.4",
|
||||
"port": 1080,
|
||||
"username": "u",
|
||||
"password": "p",
|
||||
"status": "active",
|
||||
},
|
||||
},
|
||||
"accounts": []map[string]any{
|
||||
{
|
||||
"name": "acc",
|
||||
"platform": service.PlatformOpenAI,
|
||||
"type": service.AccountTypeOAuth,
|
||||
"credentials": map[string]any{"token": "x"},
|
||||
"proxy_key": "socks5|1.2.3.4|1080|u|p",
|
||||
"concurrency": 3,
|
||||
"priority": 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
"skip_default_group_bind": true,
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(dataPayload)
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/admin/accounts/data", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
require.Len(t, adminSvc.createdProxies, 0)
|
||||
require.Len(t, adminSvc.createdAccounts, 1)
|
||||
require.True(t, adminSvc.createdAccounts[0].SkipDefaultGroupBind)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/geminicli"
|
||||
@@ -84,7 +85,7 @@ type CreateAccountRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Notes *string `json:"notes"`
|
||||
Platform string `json:"platform" binding:"required"`
|
||||
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey"`
|
||||
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey upstream"`
|
||||
Credentials map[string]any `json:"credentials" binding:"required"`
|
||||
Extra map[string]any `json:"extra"`
|
||||
ProxyID *int64 `json:"proxy_id"`
|
||||
@@ -102,7 +103,7 @@ type CreateAccountRequest struct {
|
||||
type UpdateAccountRequest struct {
|
||||
Name string `json:"name"`
|
||||
Notes *string `json:"notes"`
|
||||
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
|
||||
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey upstream"`
|
||||
Credentials map[string]any `json:"credentials"`
|
||||
Extra map[string]any `json:"extra"`
|
||||
ProxyID *int64 `json:"proxy_id"`
|
||||
@@ -423,10 +424,17 @@ type TestAccountRequest struct {
|
||||
}
|
||||
|
||||
type SyncFromCRSRequest struct {
|
||||
BaseURL string `json:"base_url" binding:"required"`
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
SyncProxies *bool `json:"sync_proxies"`
|
||||
BaseURL string `json:"base_url" binding:"required"`
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
SyncProxies *bool `json:"sync_proxies"`
|
||||
SelectedAccountIDs []string `json:"selected_account_ids"`
|
||||
}
|
||||
|
||||
type PreviewFromCRSRequest struct {
|
||||
BaseURL string `json:"base_url" binding:"required"`
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// Test handles testing account connectivity with SSE streaming
|
||||
@@ -465,10 +473,11 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
|
||||
}
|
||||
|
||||
result, err := h.crsSyncService.SyncFromCRS(c.Request.Context(), service.SyncFromCRSInput{
|
||||
BaseURL: req.BaseURL,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
SyncProxies: syncProxies,
|
||||
BaseURL: req.BaseURL,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
SyncProxies: syncProxies,
|
||||
SelectedAccountIDs: req.SelectedAccountIDs,
|
||||
})
|
||||
if err != nil {
|
||||
// Provide detailed error message for CRS sync failures
|
||||
@@ -479,6 +488,28 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
// PreviewFromCRS handles previewing accounts from CRS before sync
|
||||
// POST /api/v1/admin/accounts/sync/crs/preview
|
||||
func (h *AccountHandler) PreviewFromCRS(c *gin.Context) {
|
||||
var req PreviewFromCRSRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.crsSyncService.PreviewFromCRS(c.Request.Context(), service.SyncFromCRSInput{
|
||||
BaseURL: req.BaseURL,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
})
|
||||
if err != nil {
|
||||
response.InternalError(c, "CRS preview failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
// Refresh handles refreshing account credentials
|
||||
// POST /api/v1/admin/accounts/:id/refresh
|
||||
func (h *AccountHandler) Refresh(c *gin.Context) {
|
||||
@@ -547,9 +578,18 @@ func (h *AccountHandler) Refresh(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 project_id 获取失败,先更新凭证,再标记账户为 error
|
||||
// 特殊处理 project_id:如果新值为空但旧值非空,保留旧值
|
||||
// 这确保了即使 LoadCodeAssist 失败,project_id 也不会丢失
|
||||
if newProjectID, _ := newCredentials["project_id"].(string); newProjectID == "" {
|
||||
if oldProjectID := strings.TrimSpace(account.GetCredential("project_id")); oldProjectID != "" {
|
||||
newCredentials["project_id"] = oldProjectID
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 project_id 获取失败,更新凭证但不标记为 error
|
||||
// LoadCodeAssist 失败可能是临时网络问题,给它机会在下次自动刷新时重试
|
||||
if tokenInfo.ProjectIDMissing {
|
||||
// 先更新凭证
|
||||
// 先更新凭证(token 本身刷新成功了)
|
||||
_, updateErr := h.adminService.UpdateAccount(c.Request.Context(), accountID, &service.UpdateAccountInput{
|
||||
Credentials: newCredentials,
|
||||
})
|
||||
@@ -557,14 +597,10 @@ func (h *AccountHandler) Refresh(c *gin.Context) {
|
||||
response.InternalError(c, "Failed to update credentials: "+updateErr.Error())
|
||||
return
|
||||
}
|
||||
// 标记账户为 error
|
||||
if setErr := h.adminService.SetAccountError(c.Request.Context(), accountID, "missing_project_id: 账户缺少project id,可能无法使用Antigravity"); setErr != nil {
|
||||
response.InternalError(c, "Failed to set account error: "+setErr.Error())
|
||||
return
|
||||
}
|
||||
// 不标记为 error,只返回警告信息
|
||||
response.Success(c, gin.H{
|
||||
"message": "Token refreshed but project_id is missing, account marked as error",
|
||||
"warning": "missing_project_id",
|
||||
"message": "Token refreshed successfully, but project_id could not be retrieved (will retry automatically)",
|
||||
"warning": "missing_project_id_temporary",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -691,11 +727,61 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Return mock data for now
|
||||
ctx := c.Request.Context()
|
||||
success := 0
|
||||
failed := 0
|
||||
results := make([]gin.H, 0, len(req.Accounts))
|
||||
|
||||
for _, item := range req.Accounts {
|
||||
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
|
||||
failed++
|
||||
results = append(results, gin.H{
|
||||
"name": item.Name,
|
||||
"success": false,
|
||||
"error": "rate_multiplier must be >= 0",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
skipCheck := item.ConfirmMixedChannelRisk != nil && *item.ConfirmMixedChannelRisk
|
||||
|
||||
account, err := h.adminService.CreateAccount(ctx, &service.CreateAccountInput{
|
||||
Name: item.Name,
|
||||
Notes: item.Notes,
|
||||
Platform: item.Platform,
|
||||
Type: item.Type,
|
||||
Credentials: item.Credentials,
|
||||
Extra: item.Extra,
|
||||
ProxyID: item.ProxyID,
|
||||
Concurrency: item.Concurrency,
|
||||
Priority: item.Priority,
|
||||
RateMultiplier: item.RateMultiplier,
|
||||
GroupIDs: item.GroupIDs,
|
||||
ExpiresAt: item.ExpiresAt,
|
||||
AutoPauseOnExpired: item.AutoPauseOnExpired,
|
||||
SkipMixedChannelCheck: skipCheck,
|
||||
})
|
||||
if err != nil {
|
||||
failed++
|
||||
results = append(results, gin.H{
|
||||
"name": item.Name,
|
||||
"success": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
success++
|
||||
results = append(results, gin.H{
|
||||
"name": item.Name,
|
||||
"id": account.ID,
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"success": len(req.Accounts),
|
||||
"failed": 0,
|
||||
"results": []gin.H{},
|
||||
"success": success,
|
||||
"failed": failed,
|
||||
"results": results,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1435,3 +1521,9 @@ func (h *AccountHandler) BatchRefreshTier(c *gin.Context) {
|
||||
|
||||
response.Success(c, results)
|
||||
}
|
||||
|
||||
// GetAntigravityDefaultModelMapping 获取 Antigravity 平台的默认模型映射
|
||||
// GET /api/v1/admin/accounts/antigravity/default-model-mapping
|
||||
func (h *AccountHandler) GetAntigravityDefaultModelMapping(c *gin.Context) {
|
||||
response.Success(c, domain.DefaultAntigravityModelMapping)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func setupAdminRouter() (*gin.Engine, *stubAdminService) {
|
||||
router := gin.New()
|
||||
adminSvc := newStubAdminService()
|
||||
|
||||
userHandler := NewUserHandler(adminSvc)
|
||||
userHandler := NewUserHandler(adminSvc, nil)
|
||||
groupHandler := NewGroupHandler(adminSvc)
|
||||
proxyHandler := NewProxyHandler(adminSvc)
|
||||
redeemHandler := NewRedeemHandler(adminSvc)
|
||||
|
||||
@@ -2,19 +2,27 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
)
|
||||
|
||||
type stubAdminService struct {
|
||||
users []service.User
|
||||
apiKeys []service.APIKey
|
||||
groups []service.Group
|
||||
accounts []service.Account
|
||||
proxies []service.Proxy
|
||||
proxyCounts []service.ProxyWithAccountCount
|
||||
redeems []service.RedeemCode
|
||||
users []service.User
|
||||
apiKeys []service.APIKey
|
||||
groups []service.Group
|
||||
accounts []service.Account
|
||||
proxies []service.Proxy
|
||||
proxyCounts []service.ProxyWithAccountCount
|
||||
redeems []service.RedeemCode
|
||||
createdAccounts []*service.CreateAccountInput
|
||||
createdProxies []*service.CreateProxyInput
|
||||
updatedProxyIDs []int64
|
||||
updatedProxies []*service.UpdateProxyInput
|
||||
testedProxyIDs []int64
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func newStubAdminService() *stubAdminService {
|
||||
@@ -177,6 +185,9 @@ func (s *stubAdminService) GetAccountsByIDs(ctx context.Context, ids []int64) ([
|
||||
}
|
||||
|
||||
func (s *stubAdminService) CreateAccount(ctx context.Context, input *service.CreateAccountInput) (*service.Account, error) {
|
||||
s.mu.Lock()
|
||||
s.createdAccounts = append(s.createdAccounts, input)
|
||||
s.mu.Unlock()
|
||||
account := service.Account{ID: 300, Name: input.Name, Status: service.StatusActive}
|
||||
return &account, nil
|
||||
}
|
||||
@@ -214,7 +225,25 @@ func (s *stubAdminService) BulkUpdateAccounts(ctx context.Context, input *servic
|
||||
}
|
||||
|
||||
func (s *stubAdminService) ListProxies(ctx context.Context, page, pageSize int, protocol, status, search string) ([]service.Proxy, int64, error) {
|
||||
return s.proxies, int64(len(s.proxies)), nil
|
||||
search = strings.TrimSpace(strings.ToLower(search))
|
||||
filtered := make([]service.Proxy, 0, len(s.proxies))
|
||||
for _, proxy := range s.proxies {
|
||||
if protocol != "" && proxy.Protocol != protocol {
|
||||
continue
|
||||
}
|
||||
if status != "" && proxy.Status != status {
|
||||
continue
|
||||
}
|
||||
if search != "" {
|
||||
name := strings.ToLower(proxy.Name)
|
||||
host := strings.ToLower(proxy.Host)
|
||||
if !strings.Contains(name, search) && !strings.Contains(host, search) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
filtered = append(filtered, proxy)
|
||||
}
|
||||
return filtered, int64(len(filtered)), nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) ListProxiesWithAccountCount(ctx context.Context, page, pageSize int, protocol, status, search string) ([]service.ProxyWithAccountCount, int64, error) {
|
||||
@@ -230,16 +259,47 @@ func (s *stubAdminService) GetAllProxiesWithAccountCount(ctx context.Context) ([
|
||||
}
|
||||
|
||||
func (s *stubAdminService) GetProxy(ctx context.Context, id int64) (*service.Proxy, error) {
|
||||
for i := range s.proxies {
|
||||
proxy := s.proxies[i]
|
||||
if proxy.ID == id {
|
||||
return &proxy, nil
|
||||
}
|
||||
}
|
||||
proxy := service.Proxy{ID: id, Name: "proxy", Status: service.StatusActive}
|
||||
return &proxy, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) GetProxiesByIDs(ctx context.Context, ids []int64) ([]service.Proxy, error) {
|
||||
if len(ids) == 0 {
|
||||
return []service.Proxy{}, nil
|
||||
}
|
||||
out := make([]service.Proxy, 0, len(ids))
|
||||
seen := make(map[int64]struct{}, len(ids))
|
||||
for _, id := range ids {
|
||||
seen[id] = struct{}{}
|
||||
}
|
||||
for i := range s.proxies {
|
||||
proxy := s.proxies[i]
|
||||
if _, ok := seen[proxy.ID]; ok {
|
||||
out = append(out, proxy)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) CreateProxy(ctx context.Context, input *service.CreateProxyInput) (*service.Proxy, error) {
|
||||
s.mu.Lock()
|
||||
s.createdProxies = append(s.createdProxies, input)
|
||||
s.mu.Unlock()
|
||||
proxy := service.Proxy{ID: 400, Name: input.Name, Status: service.StatusActive}
|
||||
return &proxy, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) UpdateProxy(ctx context.Context, id int64, input *service.UpdateProxyInput) (*service.Proxy, error) {
|
||||
s.mu.Lock()
|
||||
s.updatedProxyIDs = append(s.updatedProxyIDs, id)
|
||||
s.updatedProxies = append(s.updatedProxies, input)
|
||||
s.mu.Unlock()
|
||||
proxy := service.Proxy{ID: id, Name: input.Name, Status: service.StatusActive}
|
||||
return &proxy, nil
|
||||
}
|
||||
@@ -261,6 +321,9 @@ func (s *stubAdminService) CheckProxyExists(ctx context.Context, host string, po
|
||||
}
|
||||
|
||||
func (s *stubAdminService) TestProxy(ctx context.Context, id int64) (*service.ProxyTestResult, error) {
|
||||
s.mu.Lock()
|
||||
s.testedProxyIDs = append(s.testedProxyIDs, id)
|
||||
s.mu.Unlock()
|
||||
return &service.ProxyTestResult{Success: true, Message: "ok"}, nil
|
||||
}
|
||||
|
||||
@@ -290,5 +353,13 @@ func (s *stubAdminService) ExpireRedeemCode(ctx context.Context, id int64) (*ser
|
||||
return &code, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) GetUserBalanceHistory(ctx context.Context, userID int64, page, pageSize int, codeType string) ([]service.RedeemCode, int64, float64, error) {
|
||||
return s.redeems, int64(len(s.redeems)), 100.0, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) UpdateGroupSortOrders(ctx context.Context, updates []service.GroupSortOrderUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure stub implements interface.
|
||||
var _ service.AdminService = (*stubAdminService)(nil)
|
||||
|
||||
246
backend/internal/handler/admin/announcement_handler.go
Normal file
246
backend/internal/handler/admin/announcement_handler.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AnnouncementHandler handles admin announcement management
|
||||
type AnnouncementHandler struct {
|
||||
announcementService *service.AnnouncementService
|
||||
}
|
||||
|
||||
// NewAnnouncementHandler creates a new admin announcement handler
|
||||
func NewAnnouncementHandler(announcementService *service.AnnouncementService) *AnnouncementHandler {
|
||||
return &AnnouncementHandler{
|
||||
announcementService: announcementService,
|
||||
}
|
||||
}
|
||||
|
||||
type CreateAnnouncementRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
Status string `json:"status" binding:"omitempty,oneof=draft active archived"`
|
||||
Targeting service.AnnouncementTargeting `json:"targeting"`
|
||||
StartsAt *int64 `json:"starts_at"` // Unix seconds, 0/empty = immediate
|
||||
EndsAt *int64 `json:"ends_at"` // Unix seconds, 0/empty = never
|
||||
}
|
||||
|
||||
type UpdateAnnouncementRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
Status *string `json:"status" binding:"omitempty,oneof=draft active archived"`
|
||||
Targeting *service.AnnouncementTargeting `json:"targeting"`
|
||||
StartsAt *int64 `json:"starts_at"` // Unix seconds, 0 = clear
|
||||
EndsAt *int64 `json:"ends_at"` // Unix seconds, 0 = clear
|
||||
}
|
||||
|
||||
// List handles listing announcements with filters
|
||||
// GET /api/v1/admin/announcements
|
||||
func (h *AnnouncementHandler) List(c *gin.Context) {
|
||||
page, pageSize := response.ParsePagination(c)
|
||||
status := strings.TrimSpace(c.Query("status"))
|
||||
search := strings.TrimSpace(c.Query("search"))
|
||||
if len(search) > 200 {
|
||||
search = search[:200]
|
||||
}
|
||||
|
||||
params := pagination.PaginationParams{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
items, paginationResult, err := h.announcementService.List(
|
||||
c.Request.Context(),
|
||||
params,
|
||||
service.AnnouncementListFilters{Status: status, Search: search},
|
||||
)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
out := make([]dto.Announcement, 0, len(items))
|
||||
for i := range items {
|
||||
out = append(out, *dto.AnnouncementFromService(&items[i]))
|
||||
}
|
||||
response.Paginated(c, out, paginationResult.Total, page, pageSize)
|
||||
}
|
||||
|
||||
// GetByID handles getting an announcement by ID
|
||||
// GET /api/v1/admin/announcements/:id
|
||||
func (h *AnnouncementHandler) GetByID(c *gin.Context) {
|
||||
announcementID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil || announcementID <= 0 {
|
||||
response.BadRequest(c, "Invalid announcement ID")
|
||||
return
|
||||
}
|
||||
|
||||
item, err := h.announcementService.GetByID(c.Request.Context(), announcementID)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, dto.AnnouncementFromService(item))
|
||||
}
|
||||
|
||||
// Create handles creating a new announcement
|
||||
// POST /api/v1/admin/announcements
|
||||
func (h *AnnouncementHandler) Create(c *gin.Context) {
|
||||
var req CreateAnnouncementRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not found in context")
|
||||
return
|
||||
}
|
||||
|
||||
input := &service.CreateAnnouncementInput{
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
Status: req.Status,
|
||||
Targeting: req.Targeting,
|
||||
ActorID: &subject.UserID,
|
||||
}
|
||||
|
||||
if req.StartsAt != nil && *req.StartsAt > 0 {
|
||||
t := time.Unix(*req.StartsAt, 0)
|
||||
input.StartsAt = &t
|
||||
}
|
||||
if req.EndsAt != nil && *req.EndsAt > 0 {
|
||||
t := time.Unix(*req.EndsAt, 0)
|
||||
input.EndsAt = &t
|
||||
}
|
||||
|
||||
created, err := h.announcementService.Create(c.Request.Context(), input)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, dto.AnnouncementFromService(created))
|
||||
}
|
||||
|
||||
// Update handles updating an announcement
|
||||
// PUT /api/v1/admin/announcements/:id
|
||||
func (h *AnnouncementHandler) Update(c *gin.Context) {
|
||||
announcementID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil || announcementID <= 0 {
|
||||
response.BadRequest(c, "Invalid announcement ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateAnnouncementRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not found in context")
|
||||
return
|
||||
}
|
||||
|
||||
input := &service.UpdateAnnouncementInput{
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
Status: req.Status,
|
||||
Targeting: req.Targeting,
|
||||
ActorID: &subject.UserID,
|
||||
}
|
||||
|
||||
if req.StartsAt != nil {
|
||||
if *req.StartsAt == 0 {
|
||||
var cleared *time.Time = nil
|
||||
input.StartsAt = &cleared
|
||||
} else {
|
||||
t := time.Unix(*req.StartsAt, 0)
|
||||
ptr := &t
|
||||
input.StartsAt = &ptr
|
||||
}
|
||||
}
|
||||
|
||||
if req.EndsAt != nil {
|
||||
if *req.EndsAt == 0 {
|
||||
var cleared *time.Time = nil
|
||||
input.EndsAt = &cleared
|
||||
} else {
|
||||
t := time.Unix(*req.EndsAt, 0)
|
||||
ptr := &t
|
||||
input.EndsAt = &ptr
|
||||
}
|
||||
}
|
||||
|
||||
updated, err := h.announcementService.Update(c.Request.Context(), announcementID, input)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, dto.AnnouncementFromService(updated))
|
||||
}
|
||||
|
||||
// Delete handles deleting an announcement
|
||||
// DELETE /api/v1/admin/announcements/:id
|
||||
func (h *AnnouncementHandler) Delete(c *gin.Context) {
|
||||
announcementID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil || announcementID <= 0 {
|
||||
response.BadRequest(c, "Invalid announcement ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.announcementService.Delete(c.Request.Context(), announcementID); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "Announcement deleted successfully"})
|
||||
}
|
||||
|
||||
// ListReadStatus handles listing users read status for an announcement
|
||||
// GET /api/v1/admin/announcements/:id/read-status
|
||||
func (h *AnnouncementHandler) ListReadStatus(c *gin.Context) {
|
||||
announcementID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil || announcementID <= 0 {
|
||||
response.BadRequest(c, "Invalid announcement ID")
|
||||
return
|
||||
}
|
||||
|
||||
page, pageSize := response.ParsePagination(c)
|
||||
params := pagination.PaginationParams{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
search := strings.TrimSpace(c.Query("search"))
|
||||
if len(search) > 200 {
|
||||
search = search[:200]
|
||||
}
|
||||
|
||||
items, paginationResult, err := h.announcementService.ListUserReadStatus(
|
||||
c.Request.Context(),
|
||||
announcementID,
|
||||
params,
|
||||
search,
|
||||
)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Paginated(c, items, paginationResult.Total, page, pageSize)
|
||||
}
|
||||
273
backend/internal/handler/admin/error_passthrough_handler.go
Normal file
273
backend/internal/handler/admin/error_passthrough_handler.go
Normal file
@@ -0,0 +1,273 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/model"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ErrorPassthroughHandler 处理错误透传规则的 HTTP 请求
|
||||
type ErrorPassthroughHandler struct {
|
||||
service *service.ErrorPassthroughService
|
||||
}
|
||||
|
||||
// NewErrorPassthroughHandler 创建错误透传规则处理器
|
||||
func NewErrorPassthroughHandler(service *service.ErrorPassthroughService) *ErrorPassthroughHandler {
|
||||
return &ErrorPassthroughHandler{service: service}
|
||||
}
|
||||
|
||||
// CreateErrorPassthroughRuleRequest 创建规则请求
|
||||
type CreateErrorPassthroughRuleRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Priority int `json:"priority"`
|
||||
ErrorCodes []int `json:"error_codes"`
|
||||
Keywords []string `json:"keywords"`
|
||||
MatchMode string `json:"match_mode"`
|
||||
Platforms []string `json:"platforms"`
|
||||
PassthroughCode *bool `json:"passthrough_code"`
|
||||
ResponseCode *int `json:"response_code"`
|
||||
PassthroughBody *bool `json:"passthrough_body"`
|
||||
CustomMessage *string `json:"custom_message"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
// UpdateErrorPassthroughRuleRequest 更新规则请求(部分更新,所有字段可选)
|
||||
type UpdateErrorPassthroughRuleRequest struct {
|
||||
Name *string `json:"name"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Priority *int `json:"priority"`
|
||||
ErrorCodes []int `json:"error_codes"`
|
||||
Keywords []string `json:"keywords"`
|
||||
MatchMode *string `json:"match_mode"`
|
||||
Platforms []string `json:"platforms"`
|
||||
PassthroughCode *bool `json:"passthrough_code"`
|
||||
ResponseCode *int `json:"response_code"`
|
||||
PassthroughBody *bool `json:"passthrough_body"`
|
||||
CustomMessage *string `json:"custom_message"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
// List 获取所有规则
|
||||
// GET /api/v1/admin/error-passthrough-rules
|
||||
func (h *ErrorPassthroughHandler) List(c *gin.Context) {
|
||||
rules, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
response.Success(c, rules)
|
||||
}
|
||||
|
||||
// GetByID 根据 ID 获取规则
|
||||
// GET /api/v1/admin/error-passthrough-rules/:id
|
||||
func (h *ErrorPassthroughHandler) GetByID(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := h.service.GetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if rule == nil {
|
||||
response.NotFound(c, "Rule not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, rule)
|
||||
}
|
||||
|
||||
// Create 创建规则
|
||||
// POST /api/v1/admin/error-passthrough-rules
|
||||
func (h *ErrorPassthroughHandler) Create(c *gin.Context) {
|
||||
var req CreateErrorPassthroughRuleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
rule := &model.ErrorPassthroughRule{
|
||||
Name: req.Name,
|
||||
Priority: req.Priority,
|
||||
ErrorCodes: req.ErrorCodes,
|
||||
Keywords: req.Keywords,
|
||||
Platforms: req.Platforms,
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if req.Enabled != nil {
|
||||
rule.Enabled = *req.Enabled
|
||||
} else {
|
||||
rule.Enabled = true
|
||||
}
|
||||
if req.MatchMode != "" {
|
||||
rule.MatchMode = req.MatchMode
|
||||
} else {
|
||||
rule.MatchMode = model.MatchModeAny
|
||||
}
|
||||
if req.PassthroughCode != nil {
|
||||
rule.PassthroughCode = *req.PassthroughCode
|
||||
} else {
|
||||
rule.PassthroughCode = true
|
||||
}
|
||||
if req.PassthroughBody != nil {
|
||||
rule.PassthroughBody = *req.PassthroughBody
|
||||
} else {
|
||||
rule.PassthroughBody = true
|
||||
}
|
||||
rule.ResponseCode = req.ResponseCode
|
||||
rule.CustomMessage = req.CustomMessage
|
||||
rule.Description = req.Description
|
||||
|
||||
// 确保切片不为 nil
|
||||
if rule.ErrorCodes == nil {
|
||||
rule.ErrorCodes = []int{}
|
||||
}
|
||||
if rule.Keywords == nil {
|
||||
rule.Keywords = []string{}
|
||||
}
|
||||
if rule.Platforms == nil {
|
||||
rule.Platforms = []string{}
|
||||
}
|
||||
|
||||
created, err := h.service.Create(c.Request.Context(), rule)
|
||||
if err != nil {
|
||||
if _, ok := err.(*model.ValidationError); ok {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, created)
|
||||
}
|
||||
|
||||
// Update 更新规则(支持部分更新)
|
||||
// PUT /api/v1/admin/error-passthrough-rules/:id
|
||||
func (h *ErrorPassthroughHandler) Update(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateErrorPassthroughRuleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 先获取现有规则
|
||||
existing, err := h.service.GetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if existing == nil {
|
||||
response.NotFound(c, "Rule not found")
|
||||
return
|
||||
}
|
||||
|
||||
// 部分更新:只更新请求中提供的字段
|
||||
rule := &model.ErrorPassthroughRule{
|
||||
ID: id,
|
||||
Name: existing.Name,
|
||||
Enabled: existing.Enabled,
|
||||
Priority: existing.Priority,
|
||||
ErrorCodes: existing.ErrorCodes,
|
||||
Keywords: existing.Keywords,
|
||||
MatchMode: existing.MatchMode,
|
||||
Platforms: existing.Platforms,
|
||||
PassthroughCode: existing.PassthroughCode,
|
||||
ResponseCode: existing.ResponseCode,
|
||||
PassthroughBody: existing.PassthroughBody,
|
||||
CustomMessage: existing.CustomMessage,
|
||||
Description: existing.Description,
|
||||
}
|
||||
|
||||
// 应用请求中提供的更新
|
||||
if req.Name != nil {
|
||||
rule.Name = *req.Name
|
||||
}
|
||||
if req.Enabled != nil {
|
||||
rule.Enabled = *req.Enabled
|
||||
}
|
||||
if req.Priority != nil {
|
||||
rule.Priority = *req.Priority
|
||||
}
|
||||
if req.ErrorCodes != nil {
|
||||
rule.ErrorCodes = req.ErrorCodes
|
||||
}
|
||||
if req.Keywords != nil {
|
||||
rule.Keywords = req.Keywords
|
||||
}
|
||||
if req.MatchMode != nil {
|
||||
rule.MatchMode = *req.MatchMode
|
||||
}
|
||||
if req.Platforms != nil {
|
||||
rule.Platforms = req.Platforms
|
||||
}
|
||||
if req.PassthroughCode != nil {
|
||||
rule.PassthroughCode = *req.PassthroughCode
|
||||
}
|
||||
if req.ResponseCode != nil {
|
||||
rule.ResponseCode = req.ResponseCode
|
||||
}
|
||||
if req.PassthroughBody != nil {
|
||||
rule.PassthroughBody = *req.PassthroughBody
|
||||
}
|
||||
if req.CustomMessage != nil {
|
||||
rule.CustomMessage = req.CustomMessage
|
||||
}
|
||||
if req.Description != nil {
|
||||
rule.Description = req.Description
|
||||
}
|
||||
|
||||
// 确保切片不为 nil
|
||||
if rule.ErrorCodes == nil {
|
||||
rule.ErrorCodes = []int{}
|
||||
}
|
||||
if rule.Keywords == nil {
|
||||
rule.Keywords = []string{}
|
||||
}
|
||||
if rule.Platforms == nil {
|
||||
rule.Platforms = []string{}
|
||||
}
|
||||
|
||||
updated, err := h.service.Update(c.Request.Context(), rule)
|
||||
if err != nil {
|
||||
if _, ok := err.(*model.ValidationError); ok {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, updated)
|
||||
}
|
||||
|
||||
// Delete 删除规则
|
||||
// DELETE /api/v1/admin/error-passthrough-rules/:id
|
||||
func (h *ErrorPassthroughHandler) Delete(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "Rule deleted successfully"})
|
||||
}
|
||||
@@ -35,14 +35,20 @@ type CreateGroupRequest struct {
|
||||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
||||
MonthlyLimitUSD *float64 `json:"monthly_limit_usd"`
|
||||
// 图片生成计费配置(antigravity 和 gemini 平台使用,负数表示清除配置)
|
||||
ImagePrice1K *float64 `json:"image_price_1k"`
|
||||
ImagePrice2K *float64 `json:"image_price_2k"`
|
||||
ImagePrice4K *float64 `json:"image_price_4k"`
|
||||
ClaudeCodeOnly bool `json:"claude_code_only"`
|
||||
FallbackGroupID *int64 `json:"fallback_group_id"`
|
||||
ImagePrice1K *float64 `json:"image_price_1k"`
|
||||
ImagePrice2K *float64 `json:"image_price_2k"`
|
||||
ImagePrice4K *float64 `json:"image_price_4k"`
|
||||
ClaudeCodeOnly bool `json:"claude_code_only"`
|
||||
FallbackGroupID *int64 `json:"fallback_group_id"`
|
||||
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request"`
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||
// 支持的模型系列(仅 antigravity 平台使用)
|
||||
SupportedModelScopes []string `json:"supported_model_scopes"`
|
||||
// 从指定分组复制账号(创建后自动绑定)
|
||||
CopyAccountsFromGroupIDs []int64 `json:"copy_accounts_from_group_ids"`
|
||||
}
|
||||
|
||||
// UpdateGroupRequest represents update group request
|
||||
@@ -58,14 +64,20 @@ type UpdateGroupRequest struct {
|
||||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
||||
MonthlyLimitUSD *float64 `json:"monthly_limit_usd"`
|
||||
// 图片生成计费配置(antigravity 和 gemini 平台使用,负数表示清除配置)
|
||||
ImagePrice1K *float64 `json:"image_price_1k"`
|
||||
ImagePrice2K *float64 `json:"image_price_2k"`
|
||||
ImagePrice4K *float64 `json:"image_price_4k"`
|
||||
ClaudeCodeOnly *bool `json:"claude_code_only"`
|
||||
FallbackGroupID *int64 `json:"fallback_group_id"`
|
||||
ImagePrice1K *float64 `json:"image_price_1k"`
|
||||
ImagePrice2K *float64 `json:"image_price_2k"`
|
||||
ImagePrice4K *float64 `json:"image_price_4k"`
|
||||
ClaudeCodeOnly *bool `json:"claude_code_only"`
|
||||
FallbackGroupID *int64 `json:"fallback_group_id"`
|
||||
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request"`
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled *bool `json:"model_routing_enabled"`
|
||||
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||
// 支持的模型系列(仅 antigravity 平台使用)
|
||||
SupportedModelScopes *[]string `json:"supported_model_scopes"`
|
||||
// 从指定分组复制账号(同步操作:先清空当前分组的账号绑定,再绑定源分组的账号)
|
||||
CopyAccountsFromGroupIDs []int64 `json:"copy_accounts_from_group_ids"`
|
||||
}
|
||||
|
||||
// List handles listing all groups with pagination
|
||||
@@ -155,22 +167,26 @@ func (h *GroupHandler) Create(c *gin.Context) {
|
||||
}
|
||||
|
||||
group, err := h.adminService.CreateGroup(c.Request.Context(), &service.CreateGroupInput{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Platform: req.Platform,
|
||||
RateMultiplier: req.RateMultiplier,
|
||||
IsExclusive: req.IsExclusive,
|
||||
SubscriptionType: req.SubscriptionType,
|
||||
DailyLimitUSD: req.DailyLimitUSD,
|
||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||
ImagePrice1K: req.ImagePrice1K,
|
||||
ImagePrice2K: req.ImagePrice2K,
|
||||
ImagePrice4K: req.ImagePrice4K,
|
||||
ClaudeCodeOnly: req.ClaudeCodeOnly,
|
||||
FallbackGroupID: req.FallbackGroupID,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Platform: req.Platform,
|
||||
RateMultiplier: req.RateMultiplier,
|
||||
IsExclusive: req.IsExclusive,
|
||||
SubscriptionType: req.SubscriptionType,
|
||||
DailyLimitUSD: req.DailyLimitUSD,
|
||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||
ImagePrice1K: req.ImagePrice1K,
|
||||
ImagePrice2K: req.ImagePrice2K,
|
||||
ImagePrice4K: req.ImagePrice4K,
|
||||
ClaudeCodeOnly: req.ClaudeCodeOnly,
|
||||
FallbackGroupID: req.FallbackGroupID,
|
||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
MCPXMLInject: req.MCPXMLInject,
|
||||
SupportedModelScopes: req.SupportedModelScopes,
|
||||
CopyAccountsFromGroupIDs: req.CopyAccountsFromGroupIDs,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
@@ -196,23 +212,27 @@ func (h *GroupHandler) Update(c *gin.Context) {
|
||||
}
|
||||
|
||||
group, err := h.adminService.UpdateGroup(c.Request.Context(), groupID, &service.UpdateGroupInput{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Platform: req.Platform,
|
||||
RateMultiplier: req.RateMultiplier,
|
||||
IsExclusive: req.IsExclusive,
|
||||
Status: req.Status,
|
||||
SubscriptionType: req.SubscriptionType,
|
||||
DailyLimitUSD: req.DailyLimitUSD,
|
||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||
ImagePrice1K: req.ImagePrice1K,
|
||||
ImagePrice2K: req.ImagePrice2K,
|
||||
ImagePrice4K: req.ImagePrice4K,
|
||||
ClaudeCodeOnly: req.ClaudeCodeOnly,
|
||||
FallbackGroupID: req.FallbackGroupID,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Platform: req.Platform,
|
||||
RateMultiplier: req.RateMultiplier,
|
||||
IsExclusive: req.IsExclusive,
|
||||
Status: req.Status,
|
||||
SubscriptionType: req.SubscriptionType,
|
||||
DailyLimitUSD: req.DailyLimitUSD,
|
||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||
ImagePrice1K: req.ImagePrice1K,
|
||||
ImagePrice2K: req.ImagePrice2K,
|
||||
ImagePrice4K: req.ImagePrice4K,
|
||||
ClaudeCodeOnly: req.ClaudeCodeOnly,
|
||||
FallbackGroupID: req.FallbackGroupID,
|
||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
MCPXMLInject: req.MCPXMLInject,
|
||||
SupportedModelScopes: req.SupportedModelScopes,
|
||||
CopyAccountsFromGroupIDs: req.CopyAccountsFromGroupIDs,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
@@ -282,3 +302,36 @@ func (h *GroupHandler) GetGroupAPIKeys(c *gin.Context) {
|
||||
}
|
||||
response.Paginated(c, outKeys, total, page, pageSize)
|
||||
}
|
||||
|
||||
// UpdateSortOrderRequest represents the request to update group sort orders
|
||||
type UpdateSortOrderRequest struct {
|
||||
Updates []struct {
|
||||
ID int64 `json:"id" binding:"required"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
} `json:"updates" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// UpdateSortOrder handles updating group sort orders
|
||||
// PUT /api/v1/admin/groups/sort-order
|
||||
func (h *GroupHandler) UpdateSortOrder(c *gin.Context) {
|
||||
var req UpdateSortOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
updates := make([]service.GroupSortOrderUpdate, 0, len(req.Updates))
|
||||
for _, u := range req.Updates {
|
||||
updates = append(updates, service.GroupSortOrderUpdate{
|
||||
ID: u.ID,
|
||||
SortOrder: u.SortOrder,
|
||||
})
|
||||
}
|
||||
|
||||
if err := h.adminService.UpdateGroupSortOrders(c.Request.Context(), updates); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "Sort order updated successfully"})
|
||||
}
|
||||
|
||||
@@ -63,6 +63,43 @@ func (h *OpsHandler) GetConcurrencyStats(c *gin.Context) {
|
||||
response.Success(c, payload)
|
||||
}
|
||||
|
||||
// GetUserConcurrencyStats returns real-time concurrency usage for all active users.
|
||||
// GET /api/v1/admin/ops/user-concurrency
|
||||
func (h *OpsHandler) GetUserConcurrencyStats(c *gin.Context) {
|
||||
if h.opsService == nil {
|
||||
response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
|
||||
return
|
||||
}
|
||||
if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !h.opsService.IsRealtimeMonitoringEnabled(c.Request.Context()) {
|
||||
response.Success(c, gin.H{
|
||||
"enabled": false,
|
||||
"user": map[int64]*service.UserConcurrencyInfo{},
|
||||
"timestamp": time.Now().UTC(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
users, collectedAt, err := h.opsService.GetUserConcurrencyStats(c.Request.Context())
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
payload := gin.H{
|
||||
"enabled": true,
|
||||
"user": users,
|
||||
}
|
||||
if collectedAt != nil {
|
||||
payload["timestamp"] = collectedAt.UTC()
|
||||
}
|
||||
response.Success(c, payload)
|
||||
}
|
||||
|
||||
// GetAccountAvailability returns account availability statistics.
|
||||
// GET /api/v1/admin/ops/account-availability
|
||||
//
|
||||
|
||||
239
backend/internal/handler/admin/proxy_data.go
Normal file
239
backend/internal/handler/admin/proxy_data.go
Normal file
@@ -0,0 +1,239 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ExportData exports proxy-only data for migration.
|
||||
func (h *ProxyHandler) ExportData(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
selectedIDs, err := parseProxyIDs(c)
|
||||
if err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var proxies []service.Proxy
|
||||
if len(selectedIDs) > 0 {
|
||||
proxies, err = h.getProxiesByIDs(ctx, selectedIDs)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
protocol := c.Query("protocol")
|
||||
status := c.Query("status")
|
||||
search := strings.TrimSpace(c.Query("search"))
|
||||
if len(search) > 100 {
|
||||
search = search[:100]
|
||||
}
|
||||
|
||||
proxies, err = h.listProxiesFiltered(ctx, protocol, status, search)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
dataProxies := make([]DataProxy, 0, len(proxies))
|
||||
for i := range proxies {
|
||||
p := proxies[i]
|
||||
key := buildProxyKey(p.Protocol, p.Host, p.Port, p.Username, p.Password)
|
||||
dataProxies = append(dataProxies, DataProxy{
|
||||
ProxyKey: key,
|
||||
Name: p.Name,
|
||||
Protocol: p.Protocol,
|
||||
Host: p.Host,
|
||||
Port: p.Port,
|
||||
Username: p.Username,
|
||||
Password: p.Password,
|
||||
Status: p.Status,
|
||||
})
|
||||
}
|
||||
|
||||
payload := DataPayload{
|
||||
ExportedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
Proxies: dataProxies,
|
||||
Accounts: []DataAccount{},
|
||||
}
|
||||
|
||||
response.Success(c, payload)
|
||||
}
|
||||
|
||||
// ImportData imports proxy-only data for migration.
|
||||
func (h *ProxyHandler) ImportData(c *gin.Context) {
|
||||
type ProxyImportRequest struct {
|
||||
Data DataPayload `json:"data"`
|
||||
}
|
||||
|
||||
var req ProxyImportRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := validateDataHeader(req.Data); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
result := DataImportResult{}
|
||||
|
||||
existingProxies, err := h.listProxiesFiltered(ctx, "", "", "")
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
proxyByKey := make(map[string]service.Proxy, len(existingProxies))
|
||||
for i := range existingProxies {
|
||||
p := existingProxies[i]
|
||||
key := buildProxyKey(p.Protocol, p.Host, p.Port, p.Username, p.Password)
|
||||
proxyByKey[key] = p
|
||||
}
|
||||
|
||||
latencyProbeIDs := make([]int64, 0, len(req.Data.Proxies))
|
||||
for i := range req.Data.Proxies {
|
||||
item := req.Data.Proxies[i]
|
||||
key := item.ProxyKey
|
||||
if key == "" {
|
||||
key = buildProxyKey(item.Protocol, item.Host, item.Port, item.Username, item.Password)
|
||||
}
|
||||
|
||||
if err := validateDataProxy(item); err != nil {
|
||||
result.ProxyFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
normalizedStatus := normalizeProxyStatus(item.Status)
|
||||
if existing, ok := proxyByKey[key]; ok {
|
||||
result.ProxyReused++
|
||||
if normalizedStatus != "" && normalizedStatus != existing.Status {
|
||||
if _, err := h.adminService.UpdateProxy(ctx, existing.ID, &service.UpdateProxyInput{Status: normalizedStatus}); err != nil {
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: "update status failed: " + err.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
latencyProbeIDs = append(latencyProbeIDs, existing.ID)
|
||||
continue
|
||||
}
|
||||
|
||||
created, err := h.adminService.CreateProxy(ctx, &service.CreateProxyInput{
|
||||
Name: defaultProxyName(item.Name),
|
||||
Protocol: item.Protocol,
|
||||
Host: item.Host,
|
||||
Port: item.Port,
|
||||
Username: item.Username,
|
||||
Password: item.Password,
|
||||
})
|
||||
if err != nil {
|
||||
result.ProxyFailed++
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
result.ProxyCreated++
|
||||
proxyByKey[key] = *created
|
||||
|
||||
if normalizedStatus != "" && normalizedStatus != created.Status {
|
||||
if _, err := h.adminService.UpdateProxy(ctx, created.ID, &service.UpdateProxyInput{Status: normalizedStatus}); err != nil {
|
||||
result.Errors = append(result.Errors, DataImportError{
|
||||
Kind: "proxy",
|
||||
Name: item.Name,
|
||||
ProxyKey: key,
|
||||
Message: "update status failed: " + err.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
// CreateProxy already triggers a latency probe, avoid double probing here.
|
||||
}
|
||||
|
||||
if len(latencyProbeIDs) > 0 {
|
||||
ids := append([]int64(nil), latencyProbeIDs...)
|
||||
go func() {
|
||||
for _, id := range ids {
|
||||
_, _ = h.adminService.TestProxy(context.Background(), id)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
func (h *ProxyHandler) getProxiesByIDs(ctx context.Context, ids []int64) ([]service.Proxy, error) {
|
||||
if len(ids) == 0 {
|
||||
return []service.Proxy{}, nil
|
||||
}
|
||||
return h.adminService.GetProxiesByIDs(ctx, ids)
|
||||
}
|
||||
|
||||
func parseProxyIDs(c *gin.Context) ([]int64, error) {
|
||||
values := c.QueryArray("ids")
|
||||
if len(values) == 0 {
|
||||
raw := strings.TrimSpace(c.Query("ids"))
|
||||
if raw != "" {
|
||||
values = []string{raw}
|
||||
}
|
||||
}
|
||||
if len(values) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ids := make([]int64, 0, len(values))
|
||||
for _, item := range values {
|
||||
for _, part := range strings.Split(item, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.ParseInt(part, 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
return nil, fmt.Errorf("invalid proxy id: %s", part)
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (h *ProxyHandler) listProxiesFiltered(ctx context.Context, protocol, status, search string) ([]service.Proxy, error) {
|
||||
page := 1
|
||||
pageSize := dataPageCap
|
||||
var out []service.Proxy
|
||||
for {
|
||||
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, protocol, status, search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, items...)
|
||||
if len(out) >= int(total) || len(items) == 0 {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
188
backend/internal/handler/admin/proxy_data_handler_test.go
Normal file
188
backend/internal/handler/admin/proxy_data_handler_test.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type proxyDataResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data DataPayload `json:"data"`
|
||||
}
|
||||
|
||||
type proxyImportResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data DataImportResult `json:"data"`
|
||||
}
|
||||
|
||||
func setupProxyDataRouter() (*gin.Engine, *stubAdminService) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
adminSvc := newStubAdminService()
|
||||
|
||||
h := NewProxyHandler(adminSvc)
|
||||
router.GET("/api/v1/admin/proxies/data", h.ExportData)
|
||||
router.POST("/api/v1/admin/proxies/data", h.ImportData)
|
||||
|
||||
return router, adminSvc
|
||||
}
|
||||
|
||||
func TestProxyExportDataRespectsFilters(t *testing.T) {
|
||||
router, adminSvc := setupProxyDataRouter()
|
||||
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "proxy-a",
|
||||
Protocol: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Name: "proxy-b",
|
||||
Protocol: "https",
|
||||
Host: "10.0.0.2",
|
||||
Port: 443,
|
||||
Username: "u",
|
||||
Password: "p",
|
||||
Status: service.StatusDisabled,
|
||||
},
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/proxies/data?protocol=https", nil)
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
var resp proxyDataResponse
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Empty(t, resp.Data.Type)
|
||||
require.Equal(t, 0, resp.Data.Version)
|
||||
require.Len(t, resp.Data.Proxies, 1)
|
||||
require.Len(t, resp.Data.Accounts, 0)
|
||||
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
|
||||
}
|
||||
|
||||
func TestProxyExportDataWithSelectedIDs(t *testing.T) {
|
||||
router, adminSvc := setupProxyDataRouter()
|
||||
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "proxy-a",
|
||||
Protocol: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Name: "proxy-b",
|
||||
Protocol: "https",
|
||||
Host: "10.0.0.2",
|
||||
Port: 443,
|
||||
Username: "u",
|
||||
Password: "p",
|
||||
Status: service.StatusDisabled,
|
||||
},
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/proxies/data?ids=2", nil)
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
var resp proxyDataResponse
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Len(t, resp.Data.Proxies, 1)
|
||||
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
|
||||
require.Equal(t, "10.0.0.2", resp.Data.Proxies[0].Host)
|
||||
}
|
||||
|
||||
func TestProxyImportDataReusesAndTriggersLatencyProbe(t *testing.T) {
|
||||
router, adminSvc := setupProxyDataRouter()
|
||||
|
||||
adminSvc.proxies = []service.Proxy{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "proxy-a",
|
||||
Protocol: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Status: service.StatusActive,
|
||||
},
|
||||
}
|
||||
|
||||
payload := map[string]any{
|
||||
"data": map[string]any{
|
||||
"type": dataType,
|
||||
"version": dataVersion,
|
||||
"proxies": []map[string]any{
|
||||
{
|
||||
"proxy_key": "http|127.0.0.1|8080|user|pass",
|
||||
"name": "proxy-a",
|
||||
"protocol": "http",
|
||||
"host": "127.0.0.1",
|
||||
"port": 8080,
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
"status": "inactive",
|
||||
},
|
||||
{
|
||||
"proxy_key": "https|10.0.0.2|443|u|p",
|
||||
"name": "proxy-b",
|
||||
"protocol": "https",
|
||||
"host": "10.0.0.2",
|
||||
"port": 443,
|
||||
"username": "u",
|
||||
"password": "p",
|
||||
"status": "active",
|
||||
},
|
||||
},
|
||||
"accounts": []map[string]any{},
|
||||
},
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/admin/proxies/data", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
var resp proxyImportResponse
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Equal(t, 1, resp.Data.ProxyCreated)
|
||||
require.Equal(t, 1, resp.Data.ProxyReused)
|
||||
require.Equal(t, 0, resp.Data.ProxyFailed)
|
||||
|
||||
adminSvc.mu.Lock()
|
||||
updatedIDs := append([]int64(nil), adminSvc.updatedProxyIDs...)
|
||||
adminSvc.mu.Unlock()
|
||||
require.Contains(t, updatedIDs, int64(1))
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
adminSvc.mu.Lock()
|
||||
defer adminSvc.mu.Unlock()
|
||||
return len(adminSvc.testedProxyIDs) == 1
|
||||
}, time.Second, 10*time.Millisecond)
|
||||
}
|
||||
@@ -29,7 +29,7 @@ func NewRedeemHandler(adminService service.AdminService) *RedeemHandler {
|
||||
// GenerateRedeemCodesRequest represents generate redeem codes request
|
||||
type GenerateRedeemCodesRequest struct {
|
||||
Count int `json:"count" binding:"required,min=1,max=100"`
|
||||
Type string `json:"type" binding:"required,oneof=balance concurrency subscription"`
|
||||
Type string `json:"type" binding:"required,oneof=balance concurrency subscription invitation"`
|
||||
Value float64 `json:"value" binding:"min=0"`
|
||||
GroupID *int64 `json:"group_id"` // 订阅类型必填
|
||||
ValidityDays int `json:"validity_days" binding:"omitempty,max=36500"` // 订阅类型使用,默认30天,最大100年
|
||||
|
||||
@@ -48,6 +48,10 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
||||
RegistrationEnabled: settings.RegistrationEnabled,
|
||||
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
||||
PromoCodeEnabled: settings.PromoCodeEnabled,
|
||||
PasswordResetEnabled: settings.PasswordResetEnabled,
|
||||
InvitationCodeEnabled: settings.InvitationCodeEnabled,
|
||||
TotpEnabled: settings.TotpEnabled,
|
||||
TotpEncryptionKeyConfigured: h.settingService.IsTotpEncryptionKeyConfigured(),
|
||||
SMTPHost: settings.SMTPHost,
|
||||
SMTPPort: settings.SMTPPort,
|
||||
SMTPUsername: settings.SMTPUsername,
|
||||
@@ -70,6 +74,8 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
||||
DocURL: settings.DocURL,
|
||||
HomeContent: settings.HomeContent,
|
||||
HideCcsImportButton: settings.HideCcsImportButton,
|
||||
PurchaseSubscriptionEnabled: settings.PurchaseSubscriptionEnabled,
|
||||
PurchaseSubscriptionURL: settings.PurchaseSubscriptionURL,
|
||||
DefaultConcurrency: settings.DefaultConcurrency,
|
||||
DefaultBalance: settings.DefaultBalance,
|
||||
EnableModelFallback: settings.EnableModelFallback,
|
||||
@@ -89,9 +95,12 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
||||
// UpdateSettingsRequest 更新设置请求
|
||||
type UpdateSettingsRequest struct {
|
||||
// 注册设置
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
InvitationCodeEnabled bool `json:"invitation_code_enabled"`
|
||||
TotpEnabled bool `json:"totp_enabled"` // TOTP 双因素认证
|
||||
|
||||
// 邮件服务设置
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
@@ -114,14 +123,16 @@ type UpdateSettingsRequest struct {
|
||||
LinuxDoConnectRedirectURL string `json:"linuxdo_connect_redirect_url"`
|
||||
|
||||
// OEM设置
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
PurchaseSubscriptionEnabled *bool `json:"purchase_subscription_enabled"`
|
||||
PurchaseSubscriptionURL *string `json:"purchase_subscription_url"`
|
||||
|
||||
// 默认配置
|
||||
DefaultConcurrency int `json:"default_concurrency"`
|
||||
@@ -198,6 +209,16 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// TOTP 双因素认证参数验证
|
||||
// 只有手动配置了加密密钥才允许启用 TOTP 功能
|
||||
if req.TotpEnabled && !previousSettings.TotpEnabled {
|
||||
// 尝试启用 TOTP,检查加密密钥是否已手动配置
|
||||
if !h.settingService.IsTotpEncryptionKeyConfigured() {
|
||||
response.BadRequest(c, "Cannot enable TOTP: TOTP_ENCRYPTION_KEY environment variable must be configured first. Generate a key with 'openssl rand -hex 32' and set it in your environment.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// LinuxDo Connect 参数验证
|
||||
if req.LinuxDoConnectEnabled {
|
||||
req.LinuxDoConnectClientID = strings.TrimSpace(req.LinuxDoConnectClientID)
|
||||
@@ -227,6 +248,34 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// “购买订阅”页面配置验证
|
||||
purchaseEnabled := previousSettings.PurchaseSubscriptionEnabled
|
||||
if req.PurchaseSubscriptionEnabled != nil {
|
||||
purchaseEnabled = *req.PurchaseSubscriptionEnabled
|
||||
}
|
||||
purchaseURL := previousSettings.PurchaseSubscriptionURL
|
||||
if req.PurchaseSubscriptionURL != nil {
|
||||
purchaseURL = strings.TrimSpace(*req.PurchaseSubscriptionURL)
|
||||
}
|
||||
|
||||
// - 启用时要求 URL 合法且非空
|
||||
// - 禁用时允许为空;若提供了 URL 也做基本校验,避免误配置
|
||||
if purchaseEnabled {
|
||||
if purchaseURL == "" {
|
||||
response.BadRequest(c, "Purchase Subscription URL is required when enabled")
|
||||
return
|
||||
}
|
||||
if err := config.ValidateAbsoluteHTTPURL(purchaseURL); err != nil {
|
||||
response.BadRequest(c, "Purchase Subscription URL must be an absolute http(s) URL")
|
||||
return
|
||||
}
|
||||
} else if purchaseURL != "" {
|
||||
if err := config.ValidateAbsoluteHTTPURL(purchaseURL); err != nil {
|
||||
response.BadRequest(c, "Purchase Subscription URL must be an absolute http(s) URL")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Ops metrics collector interval validation (seconds).
|
||||
if req.OpsMetricsIntervalSeconds != nil {
|
||||
v := *req.OpsMetricsIntervalSeconds
|
||||
@@ -240,40 +289,45 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}
|
||||
|
||||
settings := &service.SystemSettings{
|
||||
RegistrationEnabled: req.RegistrationEnabled,
|
||||
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
||||
PromoCodeEnabled: req.PromoCodeEnabled,
|
||||
SMTPHost: req.SMTPHost,
|
||||
SMTPPort: req.SMTPPort,
|
||||
SMTPUsername: req.SMTPUsername,
|
||||
SMTPPassword: req.SMTPPassword,
|
||||
SMTPFrom: req.SMTPFrom,
|
||||
SMTPFromName: req.SMTPFromName,
|
||||
SMTPUseTLS: req.SMTPUseTLS,
|
||||
TurnstileEnabled: req.TurnstileEnabled,
|
||||
TurnstileSiteKey: req.TurnstileSiteKey,
|
||||
TurnstileSecretKey: req.TurnstileSecretKey,
|
||||
LinuxDoConnectEnabled: req.LinuxDoConnectEnabled,
|
||||
LinuxDoConnectClientID: req.LinuxDoConnectClientID,
|
||||
LinuxDoConnectClientSecret: req.LinuxDoConnectClientSecret,
|
||||
LinuxDoConnectRedirectURL: req.LinuxDoConnectRedirectURL,
|
||||
SiteName: req.SiteName,
|
||||
SiteLogo: req.SiteLogo,
|
||||
SiteSubtitle: req.SiteSubtitle,
|
||||
APIBaseURL: req.APIBaseURL,
|
||||
ContactInfo: req.ContactInfo,
|
||||
DocURL: req.DocURL,
|
||||
HomeContent: req.HomeContent,
|
||||
HideCcsImportButton: req.HideCcsImportButton,
|
||||
DefaultConcurrency: req.DefaultConcurrency,
|
||||
DefaultBalance: req.DefaultBalance,
|
||||
EnableModelFallback: req.EnableModelFallback,
|
||||
FallbackModelAnthropic: req.FallbackModelAnthropic,
|
||||
FallbackModelOpenAI: req.FallbackModelOpenAI,
|
||||
FallbackModelGemini: req.FallbackModelGemini,
|
||||
FallbackModelAntigravity: req.FallbackModelAntigravity,
|
||||
EnableIdentityPatch: req.EnableIdentityPatch,
|
||||
IdentityPatchPrompt: req.IdentityPatchPrompt,
|
||||
RegistrationEnabled: req.RegistrationEnabled,
|
||||
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
||||
PromoCodeEnabled: req.PromoCodeEnabled,
|
||||
PasswordResetEnabled: req.PasswordResetEnabled,
|
||||
InvitationCodeEnabled: req.InvitationCodeEnabled,
|
||||
TotpEnabled: req.TotpEnabled,
|
||||
SMTPHost: req.SMTPHost,
|
||||
SMTPPort: req.SMTPPort,
|
||||
SMTPUsername: req.SMTPUsername,
|
||||
SMTPPassword: req.SMTPPassword,
|
||||
SMTPFrom: req.SMTPFrom,
|
||||
SMTPFromName: req.SMTPFromName,
|
||||
SMTPUseTLS: req.SMTPUseTLS,
|
||||
TurnstileEnabled: req.TurnstileEnabled,
|
||||
TurnstileSiteKey: req.TurnstileSiteKey,
|
||||
TurnstileSecretKey: req.TurnstileSecretKey,
|
||||
LinuxDoConnectEnabled: req.LinuxDoConnectEnabled,
|
||||
LinuxDoConnectClientID: req.LinuxDoConnectClientID,
|
||||
LinuxDoConnectClientSecret: req.LinuxDoConnectClientSecret,
|
||||
LinuxDoConnectRedirectURL: req.LinuxDoConnectRedirectURL,
|
||||
SiteName: req.SiteName,
|
||||
SiteLogo: req.SiteLogo,
|
||||
SiteSubtitle: req.SiteSubtitle,
|
||||
APIBaseURL: req.APIBaseURL,
|
||||
ContactInfo: req.ContactInfo,
|
||||
DocURL: req.DocURL,
|
||||
HomeContent: req.HomeContent,
|
||||
HideCcsImportButton: req.HideCcsImportButton,
|
||||
PurchaseSubscriptionEnabled: purchaseEnabled,
|
||||
PurchaseSubscriptionURL: purchaseURL,
|
||||
DefaultConcurrency: req.DefaultConcurrency,
|
||||
DefaultBalance: req.DefaultBalance,
|
||||
EnableModelFallback: req.EnableModelFallback,
|
||||
FallbackModelAnthropic: req.FallbackModelAnthropic,
|
||||
FallbackModelOpenAI: req.FallbackModelOpenAI,
|
||||
FallbackModelGemini: req.FallbackModelGemini,
|
||||
FallbackModelAntigravity: req.FallbackModelAntigravity,
|
||||
EnableIdentityPatch: req.EnableIdentityPatch,
|
||||
IdentityPatchPrompt: req.IdentityPatchPrompt,
|
||||
OpsMonitoringEnabled: func() bool {
|
||||
if req.OpsMonitoringEnabled != nil {
|
||||
return *req.OpsMonitoringEnabled
|
||||
@@ -318,6 +372,10 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
RegistrationEnabled: updatedSettings.RegistrationEnabled,
|
||||
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
|
||||
PromoCodeEnabled: updatedSettings.PromoCodeEnabled,
|
||||
PasswordResetEnabled: updatedSettings.PasswordResetEnabled,
|
||||
InvitationCodeEnabled: updatedSettings.InvitationCodeEnabled,
|
||||
TotpEnabled: updatedSettings.TotpEnabled,
|
||||
TotpEncryptionKeyConfigured: h.settingService.IsTotpEncryptionKeyConfigured(),
|
||||
SMTPHost: updatedSettings.SMTPHost,
|
||||
SMTPPort: updatedSettings.SMTPPort,
|
||||
SMTPUsername: updatedSettings.SMTPUsername,
|
||||
@@ -340,6 +398,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
DocURL: updatedSettings.DocURL,
|
||||
HomeContent: updatedSettings.HomeContent,
|
||||
HideCcsImportButton: updatedSettings.HideCcsImportButton,
|
||||
PurchaseSubscriptionEnabled: updatedSettings.PurchaseSubscriptionEnabled,
|
||||
PurchaseSubscriptionURL: updatedSettings.PurchaseSubscriptionURL,
|
||||
DefaultConcurrency: updatedSettings.DefaultConcurrency,
|
||||
DefaultBalance: updatedSettings.DefaultBalance,
|
||||
EnableModelFallback: updatedSettings.EnableModelFallback,
|
||||
@@ -384,6 +444,12 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
|
||||
if before.EmailVerifyEnabled != after.EmailVerifyEnabled {
|
||||
changed = append(changed, "email_verify_enabled")
|
||||
}
|
||||
if before.PasswordResetEnabled != after.PasswordResetEnabled {
|
||||
changed = append(changed, "password_reset_enabled")
|
||||
}
|
||||
if before.TotpEnabled != after.TotpEnabled {
|
||||
changed = append(changed, "totp_enabled")
|
||||
}
|
||||
if before.SMTPHost != after.SMTPHost {
|
||||
changed = append(changed, "smtp_host")
|
||||
}
|
||||
|
||||
@@ -77,7 +77,11 @@ func (h *SubscriptionHandler) List(c *gin.Context) {
|
||||
}
|
||||
status := c.Query("status")
|
||||
|
||||
subscriptions, pagination, err := h.subscriptionService.List(c.Request.Context(), page, pageSize, userID, groupID, status)
|
||||
// Parse sorting parameters
|
||||
sortBy := c.DefaultQuery("sort_by", "created_at")
|
||||
sortOrder := c.DefaultQuery("sort_order", "desc")
|
||||
|
||||
subscriptions, pagination, err := h.subscriptionService.List(c.Request.Context(), page, pageSize, userID, groupID, status, sortBy, sortOrder)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
|
||||
@@ -11,15 +11,23 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserWithConcurrency wraps AdminUser with current concurrency info
|
||||
type UserWithConcurrency struct {
|
||||
dto.AdminUser
|
||||
CurrentConcurrency int `json:"current_concurrency"`
|
||||
}
|
||||
|
||||
// UserHandler handles admin user management
|
||||
type UserHandler struct {
|
||||
adminService service.AdminService
|
||||
adminService service.AdminService
|
||||
concurrencyService *service.ConcurrencyService
|
||||
}
|
||||
|
||||
// NewUserHandler creates a new admin user handler
|
||||
func NewUserHandler(adminService service.AdminService) *UserHandler {
|
||||
func NewUserHandler(adminService service.AdminService, concurrencyService *service.ConcurrencyService) *UserHandler {
|
||||
return &UserHandler{
|
||||
adminService: adminService,
|
||||
adminService: adminService,
|
||||
concurrencyService: concurrencyService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +53,9 @@ type UpdateUserRequest struct {
|
||||
Concurrency *int `json:"concurrency"`
|
||||
Status string `json:"status" binding:"omitempty,oneof=active disabled"`
|
||||
AllowedGroups *[]int64 `json:"allowed_groups"`
|
||||
// GroupRates 用户专属分组倍率配置
|
||||
// map[groupID]*rate,nil 表示删除该分组的专属倍率
|
||||
GroupRates map[int64]*float64 `json:"group_rates"`
|
||||
}
|
||||
|
||||
// UpdateBalanceRequest represents balance update request
|
||||
@@ -84,10 +95,30 @@ func (h *UserHandler) List(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
out := make([]dto.AdminUser, 0, len(users))
|
||||
for i := range users {
|
||||
out = append(out, *dto.UserFromServiceAdmin(&users[i]))
|
||||
// Batch get current concurrency (nil map if unavailable)
|
||||
var loadInfo map[int64]*service.UserLoadInfo
|
||||
if len(users) > 0 && h.concurrencyService != nil {
|
||||
usersConcurrency := make([]service.UserWithConcurrency, len(users))
|
||||
for i := range users {
|
||||
usersConcurrency[i] = service.UserWithConcurrency{
|
||||
ID: users[i].ID,
|
||||
MaxConcurrency: users[i].Concurrency,
|
||||
}
|
||||
}
|
||||
loadInfo, _ = h.concurrencyService.GetUsersLoadBatch(c.Request.Context(), usersConcurrency)
|
||||
}
|
||||
|
||||
// Build response with concurrency info
|
||||
out := make([]UserWithConcurrency, len(users))
|
||||
for i := range users {
|
||||
out[i] = UserWithConcurrency{
|
||||
AdminUser: *dto.UserFromServiceAdmin(&users[i]),
|
||||
}
|
||||
if info := loadInfo[users[i].ID]; info != nil {
|
||||
out[i].CurrentConcurrency = info.CurrentConcurrency
|
||||
}
|
||||
}
|
||||
|
||||
response.Paginated(c, out, total, page, pageSize)
|
||||
}
|
||||
|
||||
@@ -183,6 +214,7 @@ func (h *UserHandler) Update(c *gin.Context) {
|
||||
Concurrency: req.Concurrency,
|
||||
Status: req.Status,
|
||||
AllowedGroups: req.AllowedGroups,
|
||||
GroupRates: req.GroupRates,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
@@ -277,3 +309,44 @@ func (h *UserHandler) GetUserUsage(c *gin.Context) {
|
||||
|
||||
response.Success(c, stats)
|
||||
}
|
||||
|
||||
// GetBalanceHistory handles getting user's balance/concurrency change history
|
||||
// GET /api/v1/admin/users/:id/balance-history
|
||||
// Query params:
|
||||
// - type: filter by record type (balance, admin_balance, concurrency, admin_concurrency, subscription)
|
||||
func (h *UserHandler) GetBalanceHistory(c *gin.Context) {
|
||||
userID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid user ID")
|
||||
return
|
||||
}
|
||||
|
||||
page, pageSize := response.ParsePagination(c)
|
||||
codeType := c.Query("type")
|
||||
|
||||
codes, total, totalRecharged, err := h.adminService.GetUserBalanceHistory(c.Request.Context(), userID, page, pageSize, codeType)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to admin DTO (includes notes field for admin visibility)
|
||||
out := make([]dto.AdminRedeemCode, 0, len(codes))
|
||||
for i := range codes {
|
||||
out = append(out, *dto.RedeemCodeFromServiceAdmin(&codes[i]))
|
||||
}
|
||||
|
||||
// Custom response with total_recharged alongside pagination
|
||||
pages := int((total + int64(pageSize) - 1) / int64(pageSize))
|
||||
if pages < 1 {
|
||||
pages = 1
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"items": out,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"pages": pages,
|
||||
"total_recharged": totalRecharged,
|
||||
})
|
||||
}
|
||||
|
||||
81
backend/internal/handler/announcement_handler.go
Normal file
81
backend/internal/handler/announcement_handler.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AnnouncementHandler handles user announcement operations
|
||||
type AnnouncementHandler struct {
|
||||
announcementService *service.AnnouncementService
|
||||
}
|
||||
|
||||
// NewAnnouncementHandler creates a new user announcement handler
|
||||
func NewAnnouncementHandler(announcementService *service.AnnouncementService) *AnnouncementHandler {
|
||||
return &AnnouncementHandler{
|
||||
announcementService: announcementService,
|
||||
}
|
||||
}
|
||||
|
||||
// List handles listing announcements visible to current user
|
||||
// GET /api/v1/announcements
|
||||
func (h *AnnouncementHandler) List(c *gin.Context) {
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not found in context")
|
||||
return
|
||||
}
|
||||
|
||||
unreadOnly := parseBoolQuery(c.Query("unread_only"))
|
||||
|
||||
items, err := h.announcementService.ListForUser(c.Request.Context(), subject.UserID, unreadOnly)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
out := make([]dto.UserAnnouncement, 0, len(items))
|
||||
for i := range items {
|
||||
out = append(out, *dto.UserAnnouncementFromService(&items[i]))
|
||||
}
|
||||
response.Success(c, out)
|
||||
}
|
||||
|
||||
// MarkRead marks an announcement as read for current user
|
||||
// POST /api/v1/announcements/:id/read
|
||||
func (h *AnnouncementHandler) MarkRead(c *gin.Context) {
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not found in context")
|
||||
return
|
||||
}
|
||||
|
||||
announcementID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil || announcementID <= 0 {
|
||||
response.BadRequest(c, "Invalid announcement ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.announcementService.MarkRead(c.Request.Context(), subject.UserID, announcementID); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "ok"})
|
||||
}
|
||||
|
||||
func parseBoolQuery(v string) bool {
|
||||
switch strings.TrimSpace(strings.ToLower(v)) {
|
||||
case "1", "true", "yes", "y", "on":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
|
||||
@@ -27,11 +28,13 @@ func NewAPIKeyHandler(apiKeyService *service.APIKeyService) *APIKeyHandler {
|
||||
|
||||
// CreateAPIKeyRequest represents the create API key request payload
|
||||
type CreateAPIKeyRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
GroupID *int64 `json:"group_id"` // nullable
|
||||
CustomKey *string `json:"custom_key"` // 可选的自定义key
|
||||
IPWhitelist []string `json:"ip_whitelist"` // IP 白名单
|
||||
IPBlacklist []string `json:"ip_blacklist"` // IP 黑名单
|
||||
Name string `json:"name" binding:"required"`
|
||||
GroupID *int64 `json:"group_id"` // nullable
|
||||
CustomKey *string `json:"custom_key"` // 可选的自定义key
|
||||
IPWhitelist []string `json:"ip_whitelist"` // IP 白名单
|
||||
IPBlacklist []string `json:"ip_blacklist"` // IP 黑名单
|
||||
Quota *float64 `json:"quota"` // 配额限制 (USD)
|
||||
ExpiresInDays *int `json:"expires_in_days"` // 过期天数
|
||||
}
|
||||
|
||||
// UpdateAPIKeyRequest represents the update API key request payload
|
||||
@@ -41,6 +44,9 @@ type UpdateAPIKeyRequest struct {
|
||||
Status string `json:"status" binding:"omitempty,oneof=active inactive"`
|
||||
IPWhitelist []string `json:"ip_whitelist"` // IP 白名单
|
||||
IPBlacklist []string `json:"ip_blacklist"` // IP 黑名单
|
||||
Quota *float64 `json:"quota"` // 配额限制 (USD), 0=无限制
|
||||
ExpiresAt *string `json:"expires_at"` // 过期时间 (ISO 8601)
|
||||
ResetQuota *bool `json:"reset_quota"` // 重置已用配额
|
||||
}
|
||||
|
||||
// List handles listing user's API keys with pagination
|
||||
@@ -114,11 +120,15 @@ func (h *APIKeyHandler) Create(c *gin.Context) {
|
||||
}
|
||||
|
||||
svcReq := service.CreateAPIKeyRequest{
|
||||
Name: req.Name,
|
||||
GroupID: req.GroupID,
|
||||
CustomKey: req.CustomKey,
|
||||
IPWhitelist: req.IPWhitelist,
|
||||
IPBlacklist: req.IPBlacklist,
|
||||
Name: req.Name,
|
||||
GroupID: req.GroupID,
|
||||
CustomKey: req.CustomKey,
|
||||
IPWhitelist: req.IPWhitelist,
|
||||
IPBlacklist: req.IPBlacklist,
|
||||
ExpiresInDays: req.ExpiresInDays,
|
||||
}
|
||||
if req.Quota != nil {
|
||||
svcReq.Quota = *req.Quota
|
||||
}
|
||||
key, err := h.apiKeyService.Create(c.Request.Context(), subject.UserID, svcReq)
|
||||
if err != nil {
|
||||
@@ -153,6 +163,8 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
|
||||
svcReq := service.UpdateAPIKeyRequest{
|
||||
IPWhitelist: req.IPWhitelist,
|
||||
IPBlacklist: req.IPBlacklist,
|
||||
Quota: req.Quota,
|
||||
ResetQuota: req.ResetQuota,
|
||||
}
|
||||
if req.Name != "" {
|
||||
svcReq.Name = &req.Name
|
||||
@@ -161,6 +173,21 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
|
||||
if req.Status != "" {
|
||||
svcReq.Status = &req.Status
|
||||
}
|
||||
// Parse expires_at if provided
|
||||
if req.ExpiresAt != nil {
|
||||
if *req.ExpiresAt == "" {
|
||||
// Empty string means clear expiration
|
||||
svcReq.ExpiresAt = nil
|
||||
svcReq.ClearExpiration = true
|
||||
} else {
|
||||
t, err := time.Parse(time.RFC3339, *req.ExpiresAt)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid expires_at format: "+err.Error())
|
||||
return
|
||||
}
|
||||
svcReq.ExpiresAt = &t
|
||||
}
|
||||
}
|
||||
|
||||
key, err := h.apiKeyService.Update(c.Request.Context(), keyID, subject.UserID, svcReq)
|
||||
if err != nil {
|
||||
@@ -216,3 +243,21 @@ func (h *APIKeyHandler) GetAvailableGroups(c *gin.Context) {
|
||||
}
|
||||
response.Success(c, out)
|
||||
}
|
||||
|
||||
// GetUserGroupRates 获取当前用户的专属分组倍率配置
|
||||
// GET /api/v1/groups/rates
|
||||
func (h *APIKeyHandler) GetUserGroupRates(c *gin.Context) {
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
rates, err := h.apiKeyService.GetUserGroupRates(c.Request.Context(), subject.UserID)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, rates)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/ip"
|
||||
@@ -13,21 +15,25 @@ import (
|
||||
|
||||
// AuthHandler handles authentication-related requests
|
||||
type AuthHandler struct {
|
||||
cfg *config.Config
|
||||
authService *service.AuthService
|
||||
userService *service.UserService
|
||||
settingSvc *service.SettingService
|
||||
promoService *service.PromoService
|
||||
cfg *config.Config
|
||||
authService *service.AuthService
|
||||
userService *service.UserService
|
||||
settingSvc *service.SettingService
|
||||
promoService *service.PromoService
|
||||
redeemService *service.RedeemService
|
||||
totpService *service.TotpService
|
||||
}
|
||||
|
||||
// NewAuthHandler creates a new AuthHandler
|
||||
func NewAuthHandler(cfg *config.Config, authService *service.AuthService, userService *service.UserService, settingService *service.SettingService, promoService *service.PromoService) *AuthHandler {
|
||||
func NewAuthHandler(cfg *config.Config, authService *service.AuthService, userService *service.UserService, settingService *service.SettingService, promoService *service.PromoService, redeemService *service.RedeemService, totpService *service.TotpService) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
cfg: cfg,
|
||||
authService: authService,
|
||||
userService: userService,
|
||||
settingSvc: settingService,
|
||||
promoService: promoService,
|
||||
cfg: cfg,
|
||||
authService: authService,
|
||||
userService: userService,
|
||||
settingSvc: settingService,
|
||||
promoService: promoService,
|
||||
redeemService: redeemService,
|
||||
totpService: totpService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +43,8 @@ type RegisterRequest struct {
|
||||
Password string `json:"password" binding:"required,min=6"`
|
||||
VerifyCode string `json:"verify_code"`
|
||||
TurnstileToken string `json:"turnstile_token"`
|
||||
PromoCode string `json:"promo_code"` // 注册优惠码
|
||||
PromoCode string `json:"promo_code"` // 注册优惠码
|
||||
InvitationCode string `json:"invitation_code"` // 邀请码
|
||||
}
|
||||
|
||||
// SendVerifyCodeRequest 发送验证码请求
|
||||
@@ -61,9 +68,39 @@ type LoginRequest struct {
|
||||
|
||||
// AuthResponse 认证响应格式(匹配前端期望)
|
||||
type AuthResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
User *dto.User `json:"user"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"` // 新增:Refresh Token
|
||||
ExpiresIn int `json:"expires_in,omitempty"` // 新增:Access Token有效期(秒)
|
||||
TokenType string `json:"token_type"`
|
||||
User *dto.User `json:"user"`
|
||||
}
|
||||
|
||||
// respondWithTokenPair 生成 Token 对并返回认证响应
|
||||
// 如果 Token 对生成失败,回退到只返回 Access Token(向后兼容)
|
||||
func (h *AuthHandler) respondWithTokenPair(c *gin.Context, user *service.User) {
|
||||
tokenPair, err := h.authService.GenerateTokenPair(c.Request.Context(), user, "")
|
||||
if err != nil {
|
||||
slog.Error("failed to generate token pair", "error", err, "user_id", user.ID)
|
||||
// 回退到只返回Access Token
|
||||
token, tokenErr := h.authService.GenerateToken(user)
|
||||
if tokenErr != nil {
|
||||
response.InternalError(c, "Failed to generate token")
|
||||
return
|
||||
}
|
||||
response.Success(c, AuthResponse{
|
||||
AccessToken: token,
|
||||
TokenType: "Bearer",
|
||||
User: dto.UserFromService(user),
|
||||
})
|
||||
return
|
||||
}
|
||||
response.Success(c, AuthResponse{
|
||||
AccessToken: tokenPair.AccessToken,
|
||||
RefreshToken: tokenPair.RefreshToken,
|
||||
ExpiresIn: tokenPair.ExpiresIn,
|
||||
TokenType: "Bearer",
|
||||
User: dto.UserFromService(user),
|
||||
})
|
||||
}
|
||||
|
||||
// Register handles user registration
|
||||
@@ -83,17 +120,13 @@ func (h *AuthHandler) Register(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
token, user, err := h.authService.RegisterWithVerification(c.Request.Context(), req.Email, req.Password, req.VerifyCode, req.PromoCode)
|
||||
_, user, err := h.authService.RegisterWithVerification(c.Request.Context(), req.Email, req.Password, req.VerifyCode, req.PromoCode, req.InvitationCode)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, AuthResponse{
|
||||
AccessToken: token,
|
||||
TokenType: "Bearer",
|
||||
User: dto.UserFromService(user),
|
||||
})
|
||||
h.respondWithTokenPair(c, user)
|
||||
}
|
||||
|
||||
// SendVerifyCode 发送邮箱验证码
|
||||
@@ -143,12 +176,92 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
_ = token // token 由 authService.Login 返回但此处由 respondWithTokenPair 重新生成
|
||||
|
||||
response.Success(c, AuthResponse{
|
||||
AccessToken: token,
|
||||
TokenType: "Bearer",
|
||||
User: dto.UserFromService(user),
|
||||
})
|
||||
// Check if TOTP 2FA is enabled for this user
|
||||
if h.totpService != nil && h.settingSvc.IsTotpEnabled(c.Request.Context()) && user.TotpEnabled {
|
||||
// Create a temporary login session for 2FA
|
||||
tempToken, err := h.totpService.CreateLoginSession(c.Request.Context(), user.ID, user.Email)
|
||||
if err != nil {
|
||||
response.InternalError(c, "Failed to create 2FA session")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, TotpLoginResponse{
|
||||
Requires2FA: true,
|
||||
TempToken: tempToken,
|
||||
UserEmailMasked: service.MaskEmail(user.Email),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
h.respondWithTokenPair(c, user)
|
||||
}
|
||||
|
||||
// TotpLoginResponse represents the response when 2FA is required
|
||||
type TotpLoginResponse struct {
|
||||
Requires2FA bool `json:"requires_2fa"`
|
||||
TempToken string `json:"temp_token,omitempty"`
|
||||
UserEmailMasked string `json:"user_email_masked,omitempty"`
|
||||
}
|
||||
|
||||
// Login2FARequest represents the 2FA login request
|
||||
type Login2FARequest struct {
|
||||
TempToken string `json:"temp_token" binding:"required"`
|
||||
TotpCode string `json:"totp_code" binding:"required,len=6"`
|
||||
}
|
||||
|
||||
// Login2FA completes the login with 2FA verification
|
||||
// POST /api/v1/auth/login/2fa
|
||||
func (h *AuthHandler) Login2FA(c *gin.Context) {
|
||||
var req Login2FARequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("login_2fa_request",
|
||||
"temp_token_len", len(req.TempToken),
|
||||
"totp_code_len", len(req.TotpCode))
|
||||
|
||||
// Get the login session
|
||||
session, err := h.totpService.GetLoginSession(c.Request.Context(), req.TempToken)
|
||||
if err != nil || session == nil {
|
||||
tokenPrefix := ""
|
||||
if len(req.TempToken) >= 8 {
|
||||
tokenPrefix = req.TempToken[:8]
|
||||
}
|
||||
slog.Debug("login_2fa_session_invalid",
|
||||
"temp_token_prefix", tokenPrefix,
|
||||
"error", err)
|
||||
response.BadRequest(c, "Invalid or expired 2FA session")
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("login_2fa_session_found",
|
||||
"user_id", session.UserID,
|
||||
"email", session.Email)
|
||||
|
||||
// Verify the TOTP code
|
||||
if err := h.totpService.VerifyCode(c.Request.Context(), session.UserID, req.TotpCode); err != nil {
|
||||
slog.Debug("login_2fa_verify_failed",
|
||||
"user_id", session.UserID,
|
||||
"error", err)
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete the login session
|
||||
_ = h.totpService.DeleteLoginSession(c.Request.Context(), req.TempToken)
|
||||
|
||||
// Get the user
|
||||
user, err := h.userService.GetByID(c.Request.Context(), session.UserID)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
h.respondWithTokenPair(c, user)
|
||||
}
|
||||
|
||||
// GetCurrentUser handles getting current authenticated user
|
||||
@@ -247,3 +360,239 @@ func (h *AuthHandler) ValidatePromoCode(c *gin.Context) {
|
||||
BonusAmount: promoCode.BonusAmount,
|
||||
})
|
||||
}
|
||||
|
||||
// ValidateInvitationCodeRequest 验证邀请码请求
|
||||
type ValidateInvitationCodeRequest struct {
|
||||
Code string `json:"code" binding:"required"`
|
||||
}
|
||||
|
||||
// ValidateInvitationCodeResponse 验证邀请码响应
|
||||
type ValidateInvitationCodeResponse struct {
|
||||
Valid bool `json:"valid"`
|
||||
ErrorCode string `json:"error_code,omitempty"`
|
||||
}
|
||||
|
||||
// ValidateInvitationCode 验证邀请码(公开接口,注册前调用)
|
||||
// POST /api/v1/auth/validate-invitation-code
|
||||
func (h *AuthHandler) ValidateInvitationCode(c *gin.Context) {
|
||||
// 检查邀请码功能是否启用
|
||||
if h.settingSvc == nil || !h.settingSvc.IsInvitationCodeEnabled(c.Request.Context()) {
|
||||
response.Success(c, ValidateInvitationCodeResponse{
|
||||
Valid: false,
|
||||
ErrorCode: "INVITATION_CODE_DISABLED",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var req ValidateInvitationCodeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 验证邀请码
|
||||
redeemCode, err := h.redeemService.GetByCode(c.Request.Context(), req.Code)
|
||||
if err != nil {
|
||||
response.Success(c, ValidateInvitationCodeResponse{
|
||||
Valid: false,
|
||||
ErrorCode: "INVITATION_CODE_NOT_FOUND",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查类型和状态
|
||||
if redeemCode.Type != service.RedeemTypeInvitation {
|
||||
response.Success(c, ValidateInvitationCodeResponse{
|
||||
Valid: false,
|
||||
ErrorCode: "INVITATION_CODE_INVALID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if redeemCode.Status != service.StatusUnused {
|
||||
response.Success(c, ValidateInvitationCodeResponse{
|
||||
Valid: false,
|
||||
ErrorCode: "INVITATION_CODE_USED",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, ValidateInvitationCodeResponse{
|
||||
Valid: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ForgotPasswordRequest 忘记密码请求
|
||||
type ForgotPasswordRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
TurnstileToken string `json:"turnstile_token"`
|
||||
}
|
||||
|
||||
// ForgotPasswordResponse 忘记密码响应
|
||||
type ForgotPasswordResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// ForgotPassword 请求密码重置
|
||||
// POST /api/v1/auth/forgot-password
|
||||
func (h *AuthHandler) ForgotPassword(c *gin.Context) {
|
||||
var req ForgotPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Turnstile 验证
|
||||
if err := h.authService.VerifyTurnstile(c.Request.Context(), req.TurnstileToken, ip.GetClientIP(c)); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Build frontend base URL from request
|
||||
scheme := "https"
|
||||
if c.Request.TLS == nil {
|
||||
// Check X-Forwarded-Proto header (common in reverse proxy setups)
|
||||
if proto := c.GetHeader("X-Forwarded-Proto"); proto != "" {
|
||||
scheme = proto
|
||||
} else {
|
||||
scheme = "http"
|
||||
}
|
||||
}
|
||||
frontendBaseURL := scheme + "://" + c.Request.Host
|
||||
|
||||
// Request password reset (async)
|
||||
// Note: This returns success even if email doesn't exist (to prevent enumeration)
|
||||
if err := h.authService.RequestPasswordResetAsync(c.Request.Context(), req.Email, frontendBaseURL); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, ForgotPasswordResponse{
|
||||
Message: "If your email is registered, you will receive a password reset link shortly.",
|
||||
})
|
||||
}
|
||||
|
||||
// ResetPasswordRequest 重置密码请求
|
||||
type ResetPasswordRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Token string `json:"token" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
// ResetPasswordResponse 重置密码响应
|
||||
type ResetPasswordResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// ResetPassword 重置密码
|
||||
// POST /api/v1/auth/reset-password
|
||||
func (h *AuthHandler) ResetPassword(c *gin.Context) {
|
||||
var req ResetPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Reset password
|
||||
if err := h.authService.ResetPassword(c.Request.Context(), req.Email, req.Token, req.NewPassword); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, ResetPasswordResponse{
|
||||
Message: "Your password has been reset successfully. You can now log in with your new password.",
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== Token Refresh Endpoints ====================
|
||||
|
||||
// RefreshTokenRequest 刷新Token请求
|
||||
type RefreshTokenRequest struct {
|
||||
RefreshToken string `json:"refresh_token" binding:"required"`
|
||||
}
|
||||
|
||||
// RefreshTokenResponse 刷新Token响应
|
||||
type RefreshTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int `json:"expires_in"` // Access Token有效期(秒)
|
||||
TokenType string `json:"token_type"`
|
||||
}
|
||||
|
||||
// RefreshToken 刷新Token
|
||||
// POST /api/v1/auth/refresh
|
||||
func (h *AuthHandler) RefreshToken(c *gin.Context) {
|
||||
var req RefreshTokenRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
tokenPair, err := h.authService.RefreshTokenPair(c.Request.Context(), req.RefreshToken)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, RefreshTokenResponse{
|
||||
AccessToken: tokenPair.AccessToken,
|
||||
RefreshToken: tokenPair.RefreshToken,
|
||||
ExpiresIn: tokenPair.ExpiresIn,
|
||||
TokenType: "Bearer",
|
||||
})
|
||||
}
|
||||
|
||||
// LogoutRequest 登出请求
|
||||
type LogoutRequest struct {
|
||||
RefreshToken string `json:"refresh_token,omitempty"` // 可选:撤销指定的Refresh Token
|
||||
}
|
||||
|
||||
// LogoutResponse 登出响应
|
||||
type LogoutResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Logout 用户登出
|
||||
// POST /api/v1/auth/logout
|
||||
func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
var req LogoutRequest
|
||||
// 允许空请求体(向后兼容)
|
||||
_ = c.ShouldBindJSON(&req)
|
||||
|
||||
// 如果提供了Refresh Token,撤销它
|
||||
if req.RefreshToken != "" {
|
||||
if err := h.authService.RevokeRefreshToken(c.Request.Context(), req.RefreshToken); err != nil {
|
||||
slog.Debug("failed to revoke refresh token", "error", err)
|
||||
// 不影响登出流程
|
||||
}
|
||||
}
|
||||
|
||||
response.Success(c, LogoutResponse{
|
||||
Message: "Logged out successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// RevokeAllSessionsResponse 撤销所有会话响应
|
||||
type RevokeAllSessionsResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// RevokeAllSessions 撤销当前用户的所有会话
|
||||
// POST /api/v1/auth/revoke-all-sessions
|
||||
func (h *AuthHandler) RevokeAllSessions(c *gin.Context) {
|
||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.authService.RevokeAllUserSessions(c.Request.Context(), subject.UserID); err != nil {
|
||||
slog.Error("failed to revoke all sessions", "user_id", subject.UserID, "error", err)
|
||||
response.InternalError(c, "Failed to revoke sessions")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, RevokeAllSessionsResponse{
|
||||
Message: "All sessions have been revoked. Please log in again.",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
|
||||
email = linuxDoSyntheticEmail(subject)
|
||||
}
|
||||
|
||||
jwtToken, _, err := h.authService.LoginOrRegisterOAuth(c.Request.Context(), email, username)
|
||||
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username)
|
||||
if err != nil {
|
||||
// 避免把内部细节泄露给客户端;给前端保留结构化原因与提示信息即可。
|
||||
redirectOAuthError(c, frontendCallback, "login_failed", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
@@ -219,7 +219,9 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
|
||||
}
|
||||
|
||||
fragment := url.Values{}
|
||||
fragment.Set("access_token", jwtToken)
|
||||
fragment.Set("access_token", tokenPair.AccessToken)
|
||||
fragment.Set("refresh_token", tokenPair.RefreshToken)
|
||||
fragment.Set("expires_in", fmt.Sprintf("%d", tokenPair.ExpiresIn))
|
||||
fragment.Set("token_type", "Bearer")
|
||||
fragment.Set("redirect", redirectTo)
|
||||
redirectWithFragment(c, frontendCallback, fragment)
|
||||
|
||||
74
backend/internal/handler/dto/announcement.go
Normal file
74
backend/internal/handler/dto/announcement.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
)
|
||||
|
||||
type Announcement struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Status string `json:"status"`
|
||||
|
||||
Targeting service.AnnouncementTargeting `json:"targeting"`
|
||||
|
||||
StartsAt *time.Time `json:"starts_at,omitempty"`
|
||||
EndsAt *time.Time `json:"ends_at,omitempty"`
|
||||
|
||||
CreatedBy *int64 `json:"created_by,omitempty"`
|
||||
UpdatedBy *int64 `json:"updated_by,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type UserAnnouncement struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
|
||||
StartsAt *time.Time `json:"starts_at,omitempty"`
|
||||
EndsAt *time.Time `json:"ends_at,omitempty"`
|
||||
|
||||
ReadAt *time.Time `json:"read_at,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func AnnouncementFromService(a *service.Announcement) *Announcement {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return &Announcement{
|
||||
ID: a.ID,
|
||||
Title: a.Title,
|
||||
Content: a.Content,
|
||||
Status: a.Status,
|
||||
Targeting: a.Targeting,
|
||||
StartsAt: a.StartsAt,
|
||||
EndsAt: a.EndsAt,
|
||||
CreatedBy: a.CreatedBy,
|
||||
UpdatedBy: a.UpdatedBy,
|
||||
CreatedAt: a.CreatedAt,
|
||||
UpdatedAt: a.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func UserAnnouncementFromService(a *service.UserAnnouncement) *UserAnnouncement {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return &UserAnnouncement{
|
||||
ID: a.Announcement.ID,
|
||||
Title: a.Announcement.Title,
|
||||
Content: a.Announcement.Content,
|
||||
StartsAt: a.Announcement.StartsAt,
|
||||
EndsAt: a.Announcement.EndsAt,
|
||||
ReadAt: a.ReadAt,
|
||||
CreatedAt: a.Announcement.CreatedAt,
|
||||
UpdatedAt: a.Announcement.UpdatedAt,
|
||||
}
|
||||
}
|
||||
@@ -58,8 +58,9 @@ func UserFromServiceAdmin(u *service.User) *AdminUser {
|
||||
return nil
|
||||
}
|
||||
return &AdminUser{
|
||||
User: *base,
|
||||
Notes: u.Notes,
|
||||
User: *base,
|
||||
Notes: u.Notes,
|
||||
GroupRates: u.GroupRates,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +77,9 @@ func APIKeyFromService(k *service.APIKey) *APIKey {
|
||||
Status: k.Status,
|
||||
IPWhitelist: k.IPWhitelist,
|
||||
IPBlacklist: k.IPBlacklist,
|
||||
Quota: k.Quota,
|
||||
QuotaUsed: k.QuotaUsed,
|
||||
ExpiresAt: k.ExpiresAt,
|
||||
CreatedAt: k.CreatedAt,
|
||||
UpdatedAt: k.UpdatedAt,
|
||||
User: UserFromServiceShallow(k.User),
|
||||
@@ -105,10 +109,13 @@ func GroupFromServiceAdmin(g *service.Group) *AdminGroup {
|
||||
return nil
|
||||
}
|
||||
out := &AdminGroup{
|
||||
Group: groupFromServiceBase(g),
|
||||
ModelRouting: g.ModelRouting,
|
||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||
AccountCount: g.AccountCount,
|
||||
Group: groupFromServiceBase(g),
|
||||
ModelRouting: g.ModelRouting,
|
||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||
MCPXMLInject: g.MCPXMLInject,
|
||||
SupportedModelScopes: g.SupportedModelScopes,
|
||||
AccountCount: g.AccountCount,
|
||||
SortOrder: g.SortOrder,
|
||||
}
|
||||
if len(g.AccountGroups) > 0 {
|
||||
out.AccountGroups = make([]AccountGroup, 0, len(g.AccountGroups))
|
||||
@@ -138,8 +145,10 @@ func groupFromServiceBase(g *service.Group) Group {
|
||||
ImagePrice4K: g.ImagePrice4K,
|
||||
ClaudeCodeOnly: g.ClaudeCodeOnly,
|
||||
FallbackGroupID: g.FallbackGroupID,
|
||||
CreatedAt: g.CreatedAt,
|
||||
UpdatedAt: g.UpdatedAt,
|
||||
// 无效请求兜底分组
|
||||
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
||||
CreatedAt: g.CreatedAt,
|
||||
UpdatedAt: g.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +330,7 @@ func RedeemCodeFromServiceAdmin(rc *service.RedeemCode) *AdminRedeemCode {
|
||||
}
|
||||
|
||||
func redeemCodeFromServiceBase(rc *service.RedeemCode) RedeemCode {
|
||||
return RedeemCode{
|
||||
out := RedeemCode{
|
||||
ID: rc.ID,
|
||||
Code: rc.Code,
|
||||
Type: rc.Type,
|
||||
@@ -335,6 +344,14 @@ func redeemCodeFromServiceBase(rc *service.RedeemCode) RedeemCode {
|
||||
User: UserFromServiceShallow(rc.User),
|
||||
Group: GroupFromServiceShallow(rc.Group),
|
||||
}
|
||||
|
||||
// For admin_balance/admin_concurrency types, include notes so users can see
|
||||
// why they were charged or credited by admin
|
||||
if (rc.Type == "admin_balance" || rc.Type == "admin_concurrency") && rc.Notes != "" {
|
||||
out.Notes = &rc.Notes
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// AccountSummaryFromService returns a minimal AccountSummary for usage log display.
|
||||
@@ -358,6 +375,7 @@ func usageLogFromServiceUser(l *service.UsageLog) UsageLog {
|
||||
AccountID: l.AccountID,
|
||||
RequestID: l.RequestID,
|
||||
Model: l.Model,
|
||||
ReasoningEffort: l.ReasoningEffort,
|
||||
GroupID: l.GroupID,
|
||||
SubscriptionID: l.SubscriptionID,
|
||||
InputTokens: l.InputTokens,
|
||||
|
||||
@@ -2,9 +2,13 @@ package dto
|
||||
|
||||
// SystemSettings represents the admin settings API response payload.
|
||||
type SystemSettings struct {
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
InvitationCodeEnabled bool `json:"invitation_code_enabled"`
|
||||
TotpEnabled bool `json:"totp_enabled"` // TOTP 双因素认证
|
||||
TotpEncryptionKeyConfigured bool `json:"totp_encryption_key_configured"` // TOTP 加密密钥是否已配置
|
||||
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
SMTPPort int `json:"smtp_port"`
|
||||
@@ -23,14 +27,16 @@ type SystemSettings struct {
|
||||
LinuxDoConnectClientSecretConfigured bool `json:"linuxdo_connect_client_secret_configured"`
|
||||
LinuxDoConnectRedirectURL string `json:"linuxdo_connect_redirect_url"`
|
||||
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
PurchaseSubscriptionEnabled bool `json:"purchase_subscription_enabled"`
|
||||
PurchaseSubscriptionURL string `json:"purchase_subscription_url"`
|
||||
|
||||
DefaultConcurrency int `json:"default_concurrency"`
|
||||
DefaultBalance float64 `json:"default_balance"`
|
||||
@@ -54,21 +60,26 @@ type SystemSettings struct {
|
||||
}
|
||||
|
||||
type PublicSettings struct {
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
LinuxDoOAuthEnabled bool `json:"linuxdo_oauth_enabled"`
|
||||
Version string `json:"version"`
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
InvitationCodeEnabled bool `json:"invitation_code_enabled"`
|
||||
TotpEnabled bool `json:"totp_enabled"` // TOTP 双因素认证
|
||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||
SiteName string `json:"site_name"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocURL string `json:"doc_url"`
|
||||
HomeContent string `json:"home_content"`
|
||||
HideCcsImportButton bool `json:"hide_ccs_import_button"`
|
||||
PurchaseSubscriptionEnabled bool `json:"purchase_subscription_enabled"`
|
||||
PurchaseSubscriptionURL string `json:"purchase_subscription_url"`
|
||||
LinuxDoOAuthEnabled bool `json:"linuxdo_oauth_enabled"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// StreamTimeoutSettings 流超时处理配置 DTO
|
||||
|
||||
@@ -24,19 +24,25 @@ type AdminUser struct {
|
||||
User
|
||||
|
||||
Notes string `json:"notes"`
|
||||
// GroupRates 用户专属分组倍率配置
|
||||
// map[groupID]rateMultiplier
|
||||
GroupRates map[int64]float64 `json:"group_rates,omitempty"`
|
||||
}
|
||||
|
||||
type APIKey struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
GroupID *int64 `json:"group_id"`
|
||||
Status string `json:"status"`
|
||||
IPWhitelist []string `json:"ip_whitelist"`
|
||||
IPBlacklist []string `json:"ip_blacklist"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
GroupID *int64 `json:"group_id"`
|
||||
Status string `json:"status"`
|
||||
IPWhitelist []string `json:"ip_whitelist"`
|
||||
IPBlacklist []string `json:"ip_blacklist"`
|
||||
Quota float64 `json:"quota"` // Quota limit in USD (0 = unlimited)
|
||||
QuotaUsed float64 `json:"quota_used"` // Used quota amount in USD
|
||||
ExpiresAt *time.Time `json:"expires_at"` // Expiration time (nil = never expires)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
User *User `json:"user,omitempty"`
|
||||
Group *Group `json:"group,omitempty"`
|
||||
@@ -64,6 +70,8 @@ type Group struct {
|
||||
// Claude Code 客户端限制
|
||||
ClaudeCodeOnly bool `json:"claude_code_only"`
|
||||
FallbackGroupID *int64 `json:"fallback_group_id"`
|
||||
// 无效请求兜底分组
|
||||
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
@@ -78,8 +86,16 @@ type AdminGroup struct {
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||
|
||||
AccountGroups []AccountGroup `json:"account_groups,omitempty"`
|
||||
AccountCount int64 `json:"account_count,omitempty"`
|
||||
// MCP XML 协议注入(仅 antigravity 平台使用)
|
||||
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||||
|
||||
// 支持的模型系列(仅 antigravity 平台使用)
|
||||
SupportedModelScopes []string `json:"supported_model_scopes"`
|
||||
AccountGroups []AccountGroup `json:"account_groups,omitempty"`
|
||||
AccountCount int64 `json:"account_count,omitempty"`
|
||||
|
||||
// 分组排序
|
||||
SortOrder int `json:"sort_order"`
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
@@ -198,6 +214,10 @@ type RedeemCode struct {
|
||||
GroupID *int64 `json:"group_id"`
|
||||
ValidityDays int `json:"validity_days"`
|
||||
|
||||
// Notes is only populated for admin_balance/admin_concurrency types
|
||||
// so users can see why they were charged or credited
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
|
||||
User *User `json:"user,omitempty"`
|
||||
Group *Group `json:"group,omitempty"`
|
||||
}
|
||||
@@ -218,6 +238,9 @@ type UsageLog struct {
|
||||
AccountID int64 `json:"account_id"`
|
||||
RequestID string `json:"request_id"`
|
||||
Model string `json:"model"`
|
||||
// ReasoningEffort is the request's reasoning effort level (OpenAI Responses API).
|
||||
// nil means not provided / not applicable.
|
||||
ReasoningEffort *string `json:"reasoning_effort,omitempty"`
|
||||
|
||||
GroupID *int64 `json:"group_id"`
|
||||
SubscriptionID *int64 `json:"subscription_id"`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user