mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-08 17:14:45 +08:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fb43b91bf | ||
|
|
6e8188ed64 | ||
|
|
db6f53e2c9 | ||
|
|
acabdc2f99 | ||
|
|
169aa4716e | ||
|
|
c0753320a0 | ||
|
|
38d875b06f | ||
|
|
1ada6cf768 | ||
|
|
2b528c5f81 | ||
|
|
f6dd4752e7 | ||
|
|
b19c7875a4 | ||
|
|
d99a3ef14b | ||
|
|
fc8fa83fcc | ||
|
|
6dcd99468b | ||
|
|
d5ba7b80d3 | ||
|
|
a3b81ef7bc | ||
|
|
015974a27e | ||
|
|
4cf756ebe6 | ||
|
|
823497a2af | ||
|
|
66fe484f0d | ||
|
|
216321aa9e | ||
|
|
5a52cb608c | ||
|
|
1181b332f7 | ||
|
|
58b1777198 | ||
|
|
0c7a58fcc7 | ||
|
|
17ae51c0a0 | ||
|
|
4790aced15 | ||
|
|
3f0017d1f1 | ||
|
|
cb72262ad8 | ||
|
|
195e227c04 | ||
|
|
f5603b0780 | ||
|
|
752882a022 | ||
|
|
9731b961d0 | ||
|
|
2920409404 | ||
|
|
7dbbfc22b6 | ||
|
|
aaaa68ea7f | ||
|
|
af753de481 | ||
|
|
3956819c78 | ||
|
|
168aa57810 | ||
|
|
706af2920f | ||
|
|
4d078a8854 | ||
|
|
b6a4182904 | ||
|
|
4251a5a451 | ||
|
|
34aa77e4e1 | ||
|
|
c27d511736 | ||
|
|
d6f8ac0226 | ||
|
|
ef11abcbfd | ||
|
|
6fa704d6fc | ||
|
|
0400fcdca4 | ||
|
|
d936eb6518 | ||
|
|
3b7d0c42f1 | ||
|
|
5b1907fe61 | ||
|
|
e800af54f9 | ||
|
|
d4c2b723a5 | ||
|
|
6451b3cd83 | ||
|
|
c4628d4604 | ||
|
|
ee6d01fd1c | ||
|
|
5668736389 | ||
|
|
1aef4ce20d | ||
|
|
7c419dfc50 | ||
|
|
ce7893ee44 | ||
|
|
4c1293a74c | ||
|
|
d43599243c | ||
|
|
be60d1e7e3 | ||
|
|
fb313356f7 | ||
|
|
d20697beb3 | ||
|
|
048ed061c2 | ||
|
|
91f9d4c7a9 | ||
|
|
a60dbb5533 | ||
|
|
471b1c3eeb | ||
|
|
94750fb61f | ||
|
|
5b57313c8a | ||
|
|
794a9f969b | ||
|
|
c52c47e122 | ||
|
|
e67dbbdb8a | ||
|
|
204190f807 | ||
|
|
411ebe4d17 | ||
|
|
ee29b9428b | ||
|
|
85f53ef2dd | ||
|
|
960c09cdce | ||
|
|
b05e90e4e4 | ||
|
|
7cc7e15174 | ||
|
|
0f79c3cc0e | ||
|
|
ae3d6fd776 | ||
|
|
118ca5cf6d | ||
|
|
a11a0f289c | ||
|
|
090c9e665b | ||
|
|
c8e5455df0 | ||
|
|
fd29fe11b4 | ||
|
|
07d80f76d0 | ||
|
|
eef12cb900 | ||
|
|
06216aad53 | ||
|
|
64b52c4383 | ||
|
|
ad2ff90851 | ||
|
|
8664cff859 | ||
|
|
aa6f253374 | ||
|
|
f60f943d0c | ||
|
|
46dda58355 | ||
|
|
bfcc562c35 | ||
|
|
87426e5dda | ||
|
|
99308ab4fb | ||
|
|
d4d21d5ef3 | ||
|
|
f8e7255c32 | ||
|
|
e99063e12b | ||
|
|
5dd8b8802b | ||
|
|
27ed042c56 | ||
|
|
6708f40005 | ||
|
|
7122b3b3b6 | ||
|
|
d36392b74f | ||
|
|
7dddd06583 | ||
|
|
c86d445cb7 | ||
|
|
6c036d7b59 | ||
|
|
e78c864650 | ||
|
|
25a0d49af9 | ||
|
|
7489da49cb | ||
|
|
4df712624e | ||
|
|
73ffb58518 | ||
|
|
a4953785d9 | ||
|
|
d92e71a1f0 | ||
|
|
a8c3dfb0c1 | ||
|
|
2c06255f0e | ||
|
|
a527559526 | ||
|
|
7e6a197ddb | ||
|
|
603b361fb9 | ||
|
|
2632a7102d | ||
|
|
63453fbfa0 | ||
|
|
50f9272850 | ||
|
|
3932bf0353 | ||
|
|
ce2422324c | ||
|
|
0aa216915b | ||
|
|
60afc7f3ed | ||
|
|
1dd3521190 | ||
|
|
44785a9a8c | ||
|
|
e91fba82a8 | ||
|
|
84d6480b4e | ||
|
|
c0e296f4a9 | ||
|
|
0dc4b113d8 | ||
|
|
c8e55ab2ac | ||
|
|
fb9930004c | ||
|
|
a185ad1144 | ||
|
|
cc4cc806ea | ||
|
|
7fe09c8342 | ||
|
|
43d9ef7f62 | ||
|
|
482bc289bf | ||
|
|
552118eb7f | ||
|
|
537af60e33 | ||
|
|
aad4163d22 | ||
|
|
cc86f94474 | ||
|
|
d505c5b2f2 | ||
|
|
71bf5b9e77 | ||
|
|
7eda43c99e | ||
|
|
81b865b89d | ||
|
|
b0d41823bd | ||
|
|
519b0b245a | ||
|
|
75e7c3dd06 | ||
|
|
691e2767a4 | ||
|
|
1f2ced896a | ||
|
|
112a2d0866 | ||
|
|
b1702de522 | ||
|
|
ff3f514f6b | ||
|
|
09da6904f5 | ||
|
|
acb718d355 | ||
|
|
26106eb0ac | ||
|
|
26438f7232 | ||
|
|
df1ef3deb6 | ||
|
|
6c86cf7605 | ||
|
|
e51a32881b | ||
|
|
25e1632628 | ||
|
|
45bd9ac705 | ||
|
|
7fdc2b2d29 | ||
|
|
bd4bf00856 | ||
|
|
68671749d8 |
16
.github/audit-exceptions.yml
vendored
Normal file
16
.github/audit-exceptions.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
version: 1
|
||||||
|
exceptions:
|
||||||
|
- package: xlsx
|
||||||
|
advisory: "GHSA-4r6h-8v6p-xvw6"
|
||||||
|
severity: high
|
||||||
|
reason: "Admin export only; switched to dynamic import to reduce exposure (CVE-2023-30533)"
|
||||||
|
mitigation: "Load only on export; restrict export permissions and data scope"
|
||||||
|
expires_on: "2026-04-05"
|
||||||
|
owner: "security@your-domain"
|
||||||
|
- package: xlsx
|
||||||
|
advisory: "GHSA-5pgg-2g8v-p4x9"
|
||||||
|
severity: high
|
||||||
|
reason: "Admin export only; switched to dynamic import to reduce exposure (CVE-2024-22363)"
|
||||||
|
mitigation: "Load only on export; restrict export permissions and data scope"
|
||||||
|
expires_on: "2026-04-05"
|
||||||
|
owner: "security@your-domain"
|
||||||
10
.github/workflows/backend-ci.yml
vendored
10
.github/workflows/backend-ci.yml
vendored
@@ -15,8 +15,11 @@ jobs:
|
|||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: backend/go.mod
|
go-version-file: backend/go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
|
- name: Verify Go version
|
||||||
|
run: |
|
||||||
|
go version | grep -q 'go1.25.5'
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
working-directory: backend
|
working-directory: backend
|
||||||
run: make test-unit
|
run: make test-unit
|
||||||
@@ -31,8 +34,11 @@ jobs:
|
|||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: backend/go.mod
|
go-version-file: backend/go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
|
- name: Verify Go version
|
||||||
|
run: |
|
||||||
|
go version | grep -q 'go1.25.5'
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v9
|
uses: golangci/golangci-lint-action@v9
|
||||||
with:
|
with:
|
||||||
|
|||||||
83
.github/workflows/release.yml
vendored
83
.github/workflows/release.yml
vendored
@@ -4,6 +4,22 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Tag to release (e.g., v1.0.0)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
simple_release:
|
||||||
|
description: 'Simple release: only x86_64 GHCR image, skip other artifacts'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
# 环境变量:合并 workflow_dispatch 输入和 repository variable
|
||||||
|
# tag push 触发时读取 vars.SIMPLE_RELEASE,workflow_dispatch 时使用输入参数
|
||||||
|
env:
|
||||||
|
SIMPLE_RELEASE: ${{ github.event.inputs.simple_release == 'true' || vars.SIMPLE_RELEASE == 'true' }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -19,7 +35,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Update VERSION file
|
- name: Update VERSION file
|
||||||
run: |
|
run: |
|
||||||
VERSION=${GITHUB_REF#refs/tags/v}
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
VERSION=${{ github.event.inputs.tag }}
|
||||||
|
VERSION=${VERSION#v}
|
||||||
|
else
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/v}
|
||||||
|
fi
|
||||||
echo "$VERSION" > backend/cmd/server/VERSION
|
echo "$VERSION" > backend/cmd/server/VERSION
|
||||||
echo "Updated VERSION file to: $VERSION"
|
echo "Updated VERSION file to: $VERSION"
|
||||||
|
|
||||||
@@ -36,19 +57,24 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: frontend/package-lock.json
|
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
|
||||||
- name: Build frontend
|
- name: Build frontend
|
||||||
run: npm run build
|
run: pnpm run build
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
|
||||||
- name: Upload frontend artifact
|
- name: Upload frontend artifact
|
||||||
@@ -66,6 +92,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
ref: ${{ github.event.inputs.tag || github.ref }}
|
||||||
|
|
||||||
- name: Download VERSION artifact
|
- name: Download VERSION artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
@@ -82,9 +109,14 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version-file: backend/go.mod
|
||||||
|
check-latest: false
|
||||||
cache-dependency-path: backend/go.sum
|
cache-dependency-path: backend/go.sum
|
||||||
|
|
||||||
|
- name: Verify Go version
|
||||||
|
run: |
|
||||||
|
go version | grep -q 'go1.25.5'
|
||||||
|
|
||||||
# Docker setup for GoReleaser
|
# Docker setup for GoReleaser
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
@@ -93,7 +125,10 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
|
if: ${{ env.DOCKERHUB_USERNAME != '' }}
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
env:
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
@@ -113,7 +148,11 @@ jobs:
|
|||||||
- name: Get tag message
|
- name: Get tag message
|
||||||
id: tag_message
|
id: tag_message
|
||||||
run: |
|
run: |
|
||||||
TAG_NAME=${GITHUB_REF#refs/tags/}
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
TAG_NAME=${{ github.event.inputs.tag }}
|
||||||
|
else
|
||||||
|
TAG_NAME=${GITHUB_REF#refs/tags/}
|
||||||
|
fi
|
||||||
echo "Processing tag: $TAG_NAME"
|
echo "Processing tag: $TAG_NAME"
|
||||||
|
|
||||||
# 获取完整的 tag message(跳过第一行标题)
|
# 获取完整的 tag message(跳过第一行标题)
|
||||||
@@ -137,18 +176,21 @@ jobs:
|
|||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v6
|
||||||
with:
|
with:
|
||||||
version: '~> v2'
|
version: '~> v2'
|
||||||
args: release --clean --skip=validate
|
args: release --clean --skip=validate ${{ env.SIMPLE_RELEASE == 'true' && '--config=.goreleaser.simple.yaml' || '' }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAG_MESSAGE: ${{ steps.tag_message.outputs.message }}
|
TAG_MESSAGE: ${{ steps.tag_message.outputs.message }}
|
||||||
GITHUB_REPO_OWNER: ${{ github.repository_owner }}
|
GITHUB_REPO_OWNER: ${{ github.repository_owner }}
|
||||||
GITHUB_REPO_OWNER_LOWER: ${{ steps.lowercase.outputs.owner }}
|
GITHUB_REPO_OWNER_LOWER: ${{ steps.lowercase.outputs.owner }}
|
||||||
GITHUB_REPO_NAME: ${{ github.event.repository.name }}
|
GITHUB_REPO_NAME: ${{ github.event.repository.name }}
|
||||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME || 'skip' }}
|
||||||
|
|
||||||
# Update DockerHub description
|
# Update DockerHub description
|
||||||
- name: Update DockerHub description
|
- name: Update DockerHub description
|
||||||
|
if: ${{ env.SIMPLE_RELEASE != 'true' && env.DOCKERHUB_USERNAME != '' }}
|
||||||
uses: peter-evans/dockerhub-description@v4
|
uses: peter-evans/dockerhub-description@v4
|
||||||
|
env:
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
@@ -158,9 +200,11 @@ jobs:
|
|||||||
|
|
||||||
# Send Telegram notification
|
# Send Telegram notification
|
||||||
- name: Send Telegram Notification
|
- name: Send Telegram Notification
|
||||||
|
if: ${{ env.SIMPLE_RELEASE != 'true' }}
|
||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
# 检查必要的环境变量
|
# 检查必要的环境变量
|
||||||
@@ -169,10 +213,13 @@ jobs:
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TAG_NAME=${GITHUB_REF#refs/tags/}
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
TAG_NAME=${{ github.event.inputs.tag }}
|
||||||
|
else
|
||||||
|
TAG_NAME=${GITHUB_REF#refs/tags/}
|
||||||
|
fi
|
||||||
VERSION=${TAG_NAME#v}
|
VERSION=${TAG_NAME#v}
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
DOCKER_IMAGE="${{ secrets.DOCKERHUB_USERNAME }}/sub2api"
|
|
||||||
GHCR_IMAGE="ghcr.io/${REPO,,}" # ${,,} converts to lowercase
|
GHCR_IMAGE="ghcr.io/${REPO,,}" # ${,,} converts to lowercase
|
||||||
|
|
||||||
# 获取 tag message 内容
|
# 获取 tag message 内容
|
||||||
@@ -194,14 +241,20 @@ jobs:
|
|||||||
|
|
||||||
MESSAGE+="🐳 *Docker 部署:*"$'\n'
|
MESSAGE+="🐳 *Docker 部署:*"$'\n'
|
||||||
MESSAGE+="\`\`\`bash"$'\n'
|
MESSAGE+="\`\`\`bash"$'\n'
|
||||||
MESSAGE+="# Docker Hub"$'\n'
|
# 根据是否配置 DockerHub 动态生成
|
||||||
MESSAGE+="docker pull ${DOCKER_IMAGE}:${TAG_NAME}"$'\n'
|
if [ -n "$DOCKERHUB_USERNAME" ]; then
|
||||||
MESSAGE+="# GitHub Container Registry"$'\n'
|
DOCKER_IMAGE="${DOCKERHUB_USERNAME}/sub2api"
|
||||||
|
MESSAGE+="# Docker Hub"$'\n'
|
||||||
|
MESSAGE+="docker pull ${DOCKER_IMAGE}:${TAG_NAME}"$'\n'
|
||||||
|
MESSAGE+="# GitHub Container Registry"$'\n'
|
||||||
|
fi
|
||||||
MESSAGE+="docker pull ${GHCR_IMAGE}:${TAG_NAME}"$'\n'
|
MESSAGE+="docker pull ${GHCR_IMAGE}:${TAG_NAME}"$'\n'
|
||||||
MESSAGE+="\`\`\`"$'\n'$'\n'
|
MESSAGE+="\`\`\`"$'\n'$'\n'
|
||||||
MESSAGE+="🔗 *相关链接:*"$'\n'
|
MESSAGE+="🔗 *相关链接:*"$'\n'
|
||||||
MESSAGE+="• [GitHub Release](https://github.com/${REPO}/releases/tag/${TAG_NAME})"$'\n'
|
MESSAGE+="• [GitHub Release](https://github.com/${REPO}/releases/tag/${TAG_NAME})"$'\n'
|
||||||
MESSAGE+="• [Docker Hub](https://hub.docker.com/r/${DOCKER_IMAGE})"$'\n'
|
if [ -n "$DOCKERHUB_USERNAME" ]; then
|
||||||
|
MESSAGE+="• [Docker Hub](https://hub.docker.com/r/${DOCKER_IMAGE})"$'\n'
|
||||||
|
fi
|
||||||
MESSAGE+="• [GitHub Packages](https://github.com/${REPO}/pkgs/container/sub2api)"$'\n'$'\n'
|
MESSAGE+="• [GitHub Packages](https://github.com/${REPO}/pkgs/container/sub2api)"$'\n'$'\n'
|
||||||
MESSAGE+="#Sub2API #Release #${TAG_NAME//./_}"
|
MESSAGE+="#Sub2API #Release #${TAG_NAME//./_}"
|
||||||
|
|
||||||
|
|||||||
62
.github/workflows/security-scan.yml
vendored
Normal file
62
.github/workflows/security-scan.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
name: Security Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 3 * * 1'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
backend-security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: backend/go.mod
|
||||||
|
check-latest: false
|
||||||
|
cache-dependency-path: backend/go.sum
|
||||||
|
- name: Verify Go version
|
||||||
|
run: |
|
||||||
|
go version | grep -q 'go1.25.5'
|
||||||
|
- name: Run govulncheck
|
||||||
|
working-directory: backend
|
||||||
|
run: |
|
||||||
|
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
govulncheck ./...
|
||||||
|
- name: Run gosec
|
||||||
|
working-directory: backend
|
||||||
|
run: |
|
||||||
|
go install github.com/securego/gosec/v2/cmd/gosec@latest
|
||||||
|
gosec -severity high -confidence high ./...
|
||||||
|
|
||||||
|
frontend-security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: frontend
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Run pnpm audit
|
||||||
|
working-directory: frontend
|
||||||
|
run: |
|
||||||
|
pnpm audit --prod --audit-level=high --json > audit.json || true
|
||||||
|
- name: Check audit exceptions
|
||||||
|
run: |
|
||||||
|
python tools/check_pnpm_audit_exceptions.py \
|
||||||
|
--audit frontend/audit.json \
|
||||||
|
--exceptions .github/audit-exceptions.yml
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -33,6 +33,7 @@ frontend/dist/
|
|||||||
*.local
|
*.local
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
vite.config.d.ts
|
vite.config.d.ts
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
|
||||||
# 日志
|
# 日志
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
@@ -48,6 +49,7 @@ pnpm-debug.log*
|
|||||||
.env.*.local
|
.env.*.local
|
||||||
*.env
|
*.env
|
||||||
!.env.example
|
!.env.example
|
||||||
|
docker-compose.override.yml
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# IDE / 编辑器
|
# IDE / 编辑器
|
||||||
@@ -118,3 +120,9 @@ docs/
|
|||||||
code-reviews/
|
code-reviews/
|
||||||
AGENTS.md
|
AGENTS.md
|
||||||
backend/cmd/server/server
|
backend/cmd/server/server
|
||||||
|
deploy/docker-compose.override.yml
|
||||||
|
.gocache/
|
||||||
|
vite.config.js
|
||||||
|
!docs/
|
||||||
|
docs/*
|
||||||
|
!docs/dependency-security.md
|
||||||
|
|||||||
86
.goreleaser.simple.yaml
Normal file
86
.goreleaser.simple.yaml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# 简化版 GoReleaser 配置 - 仅发布 x86_64 GHCR 镜像
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
project_name: sub2api
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy -C backend
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- id: sub2api
|
||||||
|
dir: backend
|
||||||
|
main: ./cmd/server
|
||||||
|
binary: sub2api
|
||||||
|
flags:
|
||||||
|
- -tags=embed
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
- -X main.Commit={{.Commit}}
|
||||||
|
- -X main.Date={{.Date}}
|
||||||
|
- -X main.BuildType=release
|
||||||
|
|
||||||
|
# 跳过 archives
|
||||||
|
archives: []
|
||||||
|
|
||||||
|
# 跳过 checksum
|
||||||
|
checksum:
|
||||||
|
disable: true
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
disable: true
|
||||||
|
|
||||||
|
# 仅 GHCR x86_64 镜像
|
||||||
|
dockers:
|
||||||
|
- id: ghcr-amd64
|
||||||
|
goos: linux
|
||||||
|
goarch: amd64
|
||||||
|
image_templates:
|
||||||
|
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
|
||||||
|
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}"
|
||||||
|
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:latest"
|
||||||
|
dockerfile: Dockerfile.goreleaser
|
||||||
|
use: buildx
|
||||||
|
build_flag_templates:
|
||||||
|
- "--platform=linux/amd64"
|
||||||
|
- "--label=org.opencontainers.image.version={{ .Version }}"
|
||||||
|
- "--label=org.opencontainers.image.revision={{ .Commit }}"
|
||||||
|
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}"
|
||||||
|
|
||||||
|
# 跳过 manifests(单架构不需要)
|
||||||
|
docker_manifests: []
|
||||||
|
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: "{{ .Env.GITHUB_REPO_OWNER }}"
|
||||||
|
name: "{{ .Env.GITHUB_REPO_NAME }}"
|
||||||
|
draft: false
|
||||||
|
prerelease: auto
|
||||||
|
name_template: "Sub2API {{.Version}} (Simple)"
|
||||||
|
# 跳过上传二进制包
|
||||||
|
skip_upload: true
|
||||||
|
header: |
|
||||||
|
> AI API Gateway Platform - 将 AI 订阅配额分发和管理
|
||||||
|
> ⚡ Simple Release: 仅包含 x86_64 GHCR 镜像
|
||||||
|
|
||||||
|
{{ .Env.TAG_MESSAGE }}
|
||||||
|
|
||||||
|
footer: |
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📥 Installation
|
||||||
|
|
||||||
|
**Docker (x86_64 only):**
|
||||||
|
```bash
|
||||||
|
docker pull ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- [GitHub Repository](https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }})
|
||||||
@@ -54,9 +54,11 @@ changelog:
|
|||||||
|
|
||||||
# Docker images
|
# Docker images
|
||||||
dockers:
|
dockers:
|
||||||
|
# DockerHub images (skipped if DOCKERHUB_USERNAME is 'skip')
|
||||||
- id: amd64
|
- id: amd64
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
||||||
dockerfile: Dockerfile.goreleaser
|
dockerfile: Dockerfile.goreleaser
|
||||||
@@ -69,6 +71,7 @@ dockers:
|
|||||||
- id: arm64
|
- id: arm64
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
||||||
dockerfile: Dockerfile.goreleaser
|
dockerfile: Dockerfile.goreleaser
|
||||||
@@ -107,22 +110,27 @@ dockers:
|
|||||||
|
|
||||||
# Docker manifests for multi-arch support
|
# Docker manifests for multi-arch support
|
||||||
docker_manifests:
|
docker_manifests:
|
||||||
|
# DockerHub manifests (skipped if DOCKERHUB_USERNAME is 'skip')
|
||||||
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}"
|
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}"
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
||||||
|
|
||||||
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:latest"
|
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:latest"
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
||||||
|
|
||||||
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Major }}.{{ .Minor }}"
|
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Major }}.{{ .Minor }}"
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
||||||
|
|
||||||
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Major }}"
|
- name_template: "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Major }}"
|
||||||
|
skip_push: '{{ if eq .Env.DOCKERHUB_USERNAME "skip" }}true{{ else }}false{{ end }}'
|
||||||
image_templates:
|
image_templates:
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
|
||||||
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
|
||||||
@@ -169,9 +177,11 @@ release:
|
|||||||
|
|
||||||
**Docker:**
|
**Docker:**
|
||||||
```bash
|
```bash
|
||||||
|
{{ if ne .Env.DOCKERHUB_USERNAME "skip" -}}
|
||||||
# Docker Hub
|
# Docker Hub
|
||||||
docker pull {{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}
|
docker pull {{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}
|
||||||
|
|
||||||
|
{{ end -}}
|
||||||
# GitHub Container Registry
|
# GitHub Container Registry
|
||||||
docker pull ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}
|
docker pull ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}
|
||||||
```
|
```
|
||||||
|
|||||||
13
Dockerfile
13
Dockerfile
@@ -7,8 +7,8 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
ARG NODE_IMAGE=node:24-alpine
|
ARG NODE_IMAGE=node:24-alpine
|
||||||
ARG GOLANG_IMAGE=golang:1.25-alpine
|
ARG GOLANG_IMAGE=golang:1.25.5-alpine
|
||||||
ARG ALPINE_IMAGE=alpine:3.19
|
ARG ALPINE_IMAGE=alpine:3.20
|
||||||
ARG GOPROXY=https://goproxy.cn,direct
|
ARG GOPROXY=https://goproxy.cn,direct
|
||||||
ARG GOSUMDB=sum.golang.google.cn
|
ARG GOSUMDB=sum.golang.google.cn
|
||||||
|
|
||||||
@@ -19,13 +19,16 @@ FROM ${NODE_IMAGE} AS frontend-builder
|
|||||||
|
|
||||||
WORKDIR /app/frontend
|
WORKDIR /app/frontend
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
# Install dependencies first (better caching)
|
# Install dependencies first (better caching)
|
||||||
COPY frontend/package*.json ./
|
COPY frontend/package.json frontend/pnpm-lock.yaml ./
|
||||||
RUN npm ci
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Copy frontend source and build
|
# Copy frontend source and build
|
||||||
COPY frontend/ ./
|
COPY frontend/ ./
|
||||||
RUN npm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Stage 2: Backend Builder
|
# Stage 2: Backend Builder
|
||||||
|
|||||||
14
Makefile
14
Makefile
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: build build-backend build-frontend
|
.PHONY: build build-backend build-frontend test test-backend test-frontend
|
||||||
|
|
||||||
# 一键编译前后端
|
# 一键编译前后端
|
||||||
build: build-backend build-frontend
|
build: build-backend build-frontend
|
||||||
@@ -9,4 +9,14 @@ build-backend:
|
|||||||
|
|
||||||
# 编译前端(需要已安装依赖)
|
# 编译前端(需要已安装依赖)
|
||||||
build-frontend:
|
build-frontend:
|
||||||
@npm --prefix frontend run build
|
@pnpm --dir frontend run build
|
||||||
|
|
||||||
|
# 运行测试(后端 + 前端)
|
||||||
|
test: test-backend test-frontend
|
||||||
|
|
||||||
|
test-backend:
|
||||||
|
@$(MAKE) -C backend test
|
||||||
|
|
||||||
|
test-frontend:
|
||||||
|
@pnpm --dir frontend run lint:check
|
||||||
|
@pnpm --dir frontend run typecheck
|
||||||
|
|||||||
96
README.md
96
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[](https://golang.org/)
|
[](https://golang.org/)
|
||||||
[](https://vuejs.org/)
|
[](https://vuejs.org/)
|
||||||
[](https://www.postgresql.org/)
|
[](https://www.postgresql.org/)
|
||||||
[](https://redis.io/)
|
[](https://redis.io/)
|
||||||
@@ -44,13 +44,19 @@ Sub2API is an AI API gateway platform designed to distribute and manage API quot
|
|||||||
|
|
||||||
| Component | Technology |
|
| Component | Technology |
|
||||||
|-----------|------------|
|
|-----------|------------|
|
||||||
| Backend | Go 1.21+, Gin, GORM |
|
| Backend | Go 1.25.5, Gin, Ent |
|
||||||
| Frontend | Vue 3.4+, Vite 5+, TailwindCSS |
|
| Frontend | Vue 3.4+, Vite 5+, TailwindCSS |
|
||||||
| Database | PostgreSQL 15+ |
|
| Database | PostgreSQL 15+ |
|
||||||
| Cache/Queue | Redis 7+ |
|
| Cache/Queue | Redis 7+ |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- Dependency Security: `docs/dependency-security.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
### Method 1: Script Installation (Recommended)
|
### Method 1: Script Installation (Recommended)
|
||||||
@@ -160,6 +166,22 @@ ADMIN_PASSWORD=your_admin_password
|
|||||||
|
|
||||||
# Optional: Custom port
|
# Optional: Custom port
|
||||||
SERVER_PORT=8080
|
SERVER_PORT=8080
|
||||||
|
|
||||||
|
# Optional: Security configuration
|
||||||
|
# Enable URL allowlist validation (false to skip allowlist checks, only basic format validation)
|
||||||
|
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Allow private IP addresses for upstream/pricing/CRS (for internal deployments)
|
||||||
|
SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=false
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -218,20 +240,23 @@ Build and run from source code for development or customization.
|
|||||||
git clone https://github.com/Wei-Shaw/sub2api.git
|
git clone https://github.com/Wei-Shaw/sub2api.git
|
||||||
cd sub2api
|
cd sub2api
|
||||||
|
|
||||||
# 2. Build frontend
|
# 2. Install pnpm (if not already installed)
|
||||||
|
npm install -g pnpm
|
||||||
|
|
||||||
|
# 3. Build frontend
|
||||||
cd frontend
|
cd frontend
|
||||||
npm install
|
pnpm install
|
||||||
npm run build
|
pnpm run build
|
||||||
# Output will be in ../backend/internal/web/dist/
|
# Output will be in ../backend/internal/web/dist/
|
||||||
|
|
||||||
# 3. Build backend with embedded frontend
|
# 4. Build backend with embedded frontend
|
||||||
cd ../backend
|
cd ../backend
|
||||||
go build -tags embed -o sub2api ./cmd/server
|
go build -tags embed -o sub2api ./cmd/server
|
||||||
|
|
||||||
# 4. Create configuration file
|
# 5. Create configuration file
|
||||||
cp ../deploy/config.example.yaml ./config.yaml
|
cp ../deploy/config.example.yaml ./config.yaml
|
||||||
|
|
||||||
# 5. Edit configuration
|
# 6. Edit configuration
|
||||||
nano config.yaml
|
nano config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -268,6 +293,59 @@ default:
|
|||||||
rate_multiplier: 1.0
|
rate_multiplier: 1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additional security-related options are available in `config.yaml`:
|
||||||
|
|
||||||
|
- `cors.allowed_origins` for CORS allowlist
|
||||||
|
- `security.url_allowlist` for upstream/pricing/CRS host allowlists
|
||||||
|
- `security.url_allowlist.enabled` to disable URL validation (use with caution)
|
||||||
|
- `security.url_allowlist.allow_insecure_http` to allow HTTP URLs when validation is disabled
|
||||||
|
- `security.url_allowlist.allow_private_hosts` to allow private/local IP addresses
|
||||||
|
- `security.response_headers.enabled` to enable configurable response header filtering (disabled uses default allowlist)
|
||||||
|
- `security.csp` to control Content-Security-Policy headers
|
||||||
|
- `billing.circuit_breaker` to fail closed on billing errors
|
||||||
|
- `server.trusted_proxies` to enable X-Forwarded-For parsing
|
||||||
|
- `turnstile.required` to require Turnstile in release mode
|
||||||
|
|
||||||
|
**⚠️ Security Warning: HTTP URL Configuration**
|
||||||
|
|
||||||
|
When `security.url_allowlist.enabled=false`, the system performs minimal URL validation by default, **rejecting HTTP URLs** and only allowing HTTPS. To allow HTTP URLs (e.g., for development or internal testing), you must explicitly set:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
security:
|
||||||
|
url_allowlist:
|
||||||
|
enabled: false # Disable allowlist checks
|
||||||
|
allow_insecure_http: true # Allow HTTP URLs (⚠️ INSECURE)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Or via environment variable:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||||
|
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Risks of allowing HTTP:**
|
||||||
|
- API keys and data transmitted in **plaintext** (vulnerable to interception)
|
||||||
|
- Susceptible to **man-in-the-middle (MITM) attacks**
|
||||||
|
- **NOT suitable for production** environments
|
||||||
|
|
||||||
|
**When to use HTTP:**
|
||||||
|
- ✅ Development/testing with local servers (http://localhost)
|
||||||
|
- ✅ Internal networks with trusted endpoints
|
||||||
|
- ✅ Testing account connectivity before obtaining HTTPS
|
||||||
|
- ❌ Production environments (use HTTPS only)
|
||||||
|
|
||||||
|
**Example error without this setting:**
|
||||||
|
```
|
||||||
|
Invalid base URL: invalid url scheme: http
|
||||||
|
```
|
||||||
|
|
||||||
|
If you disable URL validation or response header filtering, harden your network layer:
|
||||||
|
- Enforce an egress allowlist for upstream domains/IPs
|
||||||
|
- Block private/loopback/link-local ranges
|
||||||
|
- Enforce TLS-only outbound traffic
|
||||||
|
- Strip sensitive upstream response headers at the proxy
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 6. Run the application
|
# 6. Run the application
|
||||||
./sub2api
|
./sub2api
|
||||||
@@ -282,7 +360,7 @@ go run ./cmd/server
|
|||||||
|
|
||||||
# Frontend (with hot reload)
|
# Frontend (with hot reload)
|
||||||
cd frontend
|
cd frontend
|
||||||
npm run dev
|
pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Code Generation
|
#### Code Generation
|
||||||
|
|||||||
96
README_CN.md
96
README_CN.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[](https://golang.org/)
|
[](https://golang.org/)
|
||||||
[](https://vuejs.org/)
|
[](https://vuejs.org/)
|
||||||
[](https://www.postgresql.org/)
|
[](https://www.postgresql.org/)
|
||||||
[](https://redis.io/)
|
[](https://redis.io/)
|
||||||
@@ -44,13 +44,19 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅(
|
|||||||
|
|
||||||
| 组件 | 技术 |
|
| 组件 | 技术 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 后端 | Go 1.21+, Gin, GORM |
|
| 后端 | Go 1.25.5, Gin, Ent |
|
||||||
| 前端 | Vue 3.4+, Vite 5+, TailwindCSS |
|
| 前端 | Vue 3.4+, Vite 5+, TailwindCSS |
|
||||||
| 数据库 | PostgreSQL 15+ |
|
| 数据库 | PostgreSQL 15+ |
|
||||||
| 缓存/队列 | Redis 7+ |
|
| 缓存/队列 | Redis 7+ |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
- 依赖安全:`docs/dependency-security.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 部署方式
|
## 部署方式
|
||||||
|
|
||||||
### 方式一:脚本安装(推荐)
|
### 方式一:脚本安装(推荐)
|
||||||
@@ -160,6 +166,22 @@ ADMIN_PASSWORD=your_admin_password
|
|||||||
|
|
||||||
# 可选:自定义端口
|
# 可选:自定义端口
|
||||||
SERVER_PORT=8080
|
SERVER_PORT=8080
|
||||||
|
|
||||||
|
# 可选:安全配置
|
||||||
|
# 启用 URL 白名单验证(false 则跳过白名单检查,仅做基本格式校验)
|
||||||
|
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||||
|
|
||||||
|
# 关闭白名单时,是否允许 http:// URL(默认 false,只允许 https://)
|
||||||
|
# ⚠️ 警告:允许 HTTP 会暴露 API 密钥(明文传输)
|
||||||
|
# 仅建议在以下场景使用:
|
||||||
|
# - 开发/测试环境
|
||||||
|
# - 内部可信网络
|
||||||
|
# - 本地测试服务器(http://localhost)
|
||||||
|
# 生产环境:保持 false 或仅使用 HTTPS URL
|
||||||
|
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=false
|
||||||
|
|
||||||
|
# 是否允许私有 IP 地址用于上游/定价/CRS(内网部署时使用)
|
||||||
|
SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=false
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -218,20 +240,23 @@ docker-compose logs -f
|
|||||||
git clone https://github.com/Wei-Shaw/sub2api.git
|
git clone https://github.com/Wei-Shaw/sub2api.git
|
||||||
cd sub2api
|
cd sub2api
|
||||||
|
|
||||||
# 2. 编译前端
|
# 2. 安装 pnpm(如果还没有安装)
|
||||||
|
npm install -g pnpm
|
||||||
|
|
||||||
|
# 3. 编译前端
|
||||||
cd frontend
|
cd frontend
|
||||||
npm install
|
pnpm install
|
||||||
npm run build
|
pnpm run build
|
||||||
# 构建产物输出到 ../backend/internal/web/dist/
|
# 构建产物输出到 ../backend/internal/web/dist/
|
||||||
|
|
||||||
# 3. 编译后端(嵌入前端)
|
# 4. 编译后端(嵌入前端)
|
||||||
cd ../backend
|
cd ../backend
|
||||||
go build -tags embed -o sub2api ./cmd/server
|
go build -tags embed -o sub2api ./cmd/server
|
||||||
|
|
||||||
# 4. 创建配置文件
|
# 5. 创建配置文件
|
||||||
cp ../deploy/config.example.yaml ./config.yaml
|
cp ../deploy/config.example.yaml ./config.yaml
|
||||||
|
|
||||||
# 5. 编辑配置
|
# 6. 编辑配置
|
||||||
nano config.yaml
|
nano config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -268,6 +293,59 @@ default:
|
|||||||
rate_multiplier: 1.0
|
rate_multiplier: 1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`config.yaml` 还支持以下安全相关配置:
|
||||||
|
|
||||||
|
- `cors.allowed_origins` 配置 CORS 白名单
|
||||||
|
- `security.url_allowlist` 配置上游/价格数据/CRS 主机白名单
|
||||||
|
- `security.url_allowlist.enabled` 可关闭 URL 校验(慎用)
|
||||||
|
- `security.url_allowlist.allow_insecure_http` 关闭校验时允许 HTTP URL
|
||||||
|
- `security.url_allowlist.allow_private_hosts` 允许私有/本地 IP 地址
|
||||||
|
- `security.response_headers.enabled` 可启用可配置响应头过滤(关闭时使用默认白名单)
|
||||||
|
- `security.csp` 配置 Content-Security-Policy
|
||||||
|
- `billing.circuit_breaker` 计费异常时 fail-closed
|
||||||
|
- `server.trusted_proxies` 启用可信代理解析 X-Forwarded-For
|
||||||
|
- `turnstile.required` 在 release 模式强制启用 Turnstile
|
||||||
|
|
||||||
|
**⚠️ 安全警告:HTTP URL 配置**
|
||||||
|
|
||||||
|
当 `security.url_allowlist.enabled=false` 时,系统默认执行最小 URL 校验,**拒绝 HTTP URL**,仅允许 HTTPS。要允许 HTTP URL(例如用于开发或内网测试),必须显式设置:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
security:
|
||||||
|
url_allowlist:
|
||||||
|
enabled: false # 禁用白名单检查
|
||||||
|
allow_insecure_http: true # 允许 HTTP URL(⚠️ 不安全)
|
||||||
|
```
|
||||||
|
|
||||||
|
**或通过环境变量:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||||||
|
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**允许 HTTP 的风险:**
|
||||||
|
- API 密钥和数据以**明文传输**(可被截获)
|
||||||
|
- 易受**中间人攻击 (MITM)**
|
||||||
|
- **不适合生产环境**
|
||||||
|
|
||||||
|
**适用场景:**
|
||||||
|
- ✅ 开发/测试环境的本地服务器(http://localhost)
|
||||||
|
- ✅ 内网可信端点
|
||||||
|
- ✅ 获取 HTTPS 前测试账号连通性
|
||||||
|
- ❌ 生产环境(仅使用 HTTPS)
|
||||||
|
|
||||||
|
**未设置此项时的错误示例:**
|
||||||
|
```
|
||||||
|
Invalid base URL: invalid url scheme: http
|
||||||
|
```
|
||||||
|
|
||||||
|
如关闭 URL 校验或响应头过滤,请加强网络层防护:
|
||||||
|
- 出站访问白名单限制上游域名/IP
|
||||||
|
- 阻断私网/回环/链路本地地址
|
||||||
|
- 强制仅允许 TLS 出站
|
||||||
|
- 在反向代理层移除敏感响应头
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 6. 运行应用
|
# 6. 运行应用
|
||||||
./sub2api
|
./sub2api
|
||||||
@@ -282,7 +360,7 @@ go run ./cmd/server
|
|||||||
|
|
||||||
# 前端(支持热重载)
|
# 前端(支持热重载)
|
||||||
cd frontend
|
cd frontend
|
||||||
npm run dev
|
pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 代码生成
|
#### 代码生成
|
||||||
|
|||||||
@@ -83,7 +83,14 @@ linters:
|
|||||||
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"]
|
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"]
|
||||||
# Run `GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck` to see all available checks and enabled by config checks.
|
# Run `GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck` to see all available checks and enabled by config checks.
|
||||||
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
|
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
|
||||||
|
# Temporarily disable style checks to allow CI to pass
|
||||||
checks:
|
checks:
|
||||||
|
- all
|
||||||
|
- -ST1000 # Package comment format
|
||||||
|
- -ST1003 # Poorly chosen identifier (ApiKey vs APIKey)
|
||||||
|
- -ST1020 # Comment on exported method format
|
||||||
|
- -ST1021 # Comment on exported type format
|
||||||
|
- -ST1022 # Comment on exported variable format
|
||||||
# Invalid regular expression.
|
# Invalid regular expression.
|
||||||
# https://staticcheck.dev/docs/checks/#SA1000
|
# https://staticcheck.dev/docs/checks/#SA1000
|
||||||
- SA1000
|
- SA1000
|
||||||
@@ -369,15 +376,7 @@ linters:
|
|||||||
# Ineffectual Go compiler directive.
|
# Ineffectual Go compiler directive.
|
||||||
# https://staticcheck.dev/docs/checks/#SA9009
|
# https://staticcheck.dev/docs/checks/#SA9009
|
||||||
- SA9009
|
- SA9009
|
||||||
# Incorrect or missing package comment.
|
# NOTE: ST1000, ST1001, ST1003, ST1020, ST1021, ST1022 are disabled above
|
||||||
# https://staticcheck.dev/docs/checks/#ST1000
|
|
||||||
- ST1000
|
|
||||||
# Dot imports are discouraged.
|
|
||||||
# https://staticcheck.dev/docs/checks/#ST1001
|
|
||||||
- ST1001
|
|
||||||
# Poorly chosen identifier.
|
|
||||||
# https://staticcheck.dev/docs/checks/#ST1003
|
|
||||||
- ST1003
|
|
||||||
# Incorrectly formatted error string.
|
# Incorrectly formatted error string.
|
||||||
# https://staticcheck.dev/docs/checks/#ST1005
|
# https://staticcheck.dev/docs/checks/#ST1005
|
||||||
- ST1005
|
- ST1005
|
||||||
@@ -411,15 +410,7 @@ linters:
|
|||||||
# Importing the same package multiple times.
|
# Importing the same package multiple times.
|
||||||
# https://staticcheck.dev/docs/checks/#ST1019
|
# https://staticcheck.dev/docs/checks/#ST1019
|
||||||
- ST1019
|
- ST1019
|
||||||
# The documentation of an exported function should start with the function's name.
|
# NOTE: ST1020, ST1021, ST1022 removed (disabled above)
|
||||||
# https://staticcheck.dev/docs/checks/#ST1020
|
|
||||||
- ST1020
|
|
||||||
# The documentation of an exported type should start with type's name.
|
|
||||||
# https://staticcheck.dev/docs/checks/#ST1021
|
|
||||||
- ST1021
|
|
||||||
# The documentation of an exported variable or constant should start with variable's name.
|
|
||||||
# https://staticcheck.dev/docs/checks/#ST1022
|
|
||||||
- ST1022
|
|
||||||
# Redundant type in variable declaration.
|
# Redundant type in variable declaration.
|
||||||
# https://staticcheck.dev/docs/checks/#ST1023
|
# https://staticcheck.dev/docs/checks/#ST1023
|
||||||
- ST1023
|
- ST1023
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.21-alpine
|
FROM golang:1.25.5-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
.PHONY: build test-unit test-integration test-e2e
|
.PHONY: build test test-unit test-integration test-e2e
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -o bin/server ./cmd/server
|
go build -o bin/server ./cmd/server
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test ./...
|
||||||
|
golangci-lint run ./...
|
||||||
|
|
||||||
test-unit:
|
test-unit:
|
||||||
go test -tags=unit ./...
|
go test -tags=unit ./...
|
||||||
|
|
||||||
|
|||||||
57
backend/cmd/jwtgen/main.go
Normal file
57
backend/cmd/jwtgen/main.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/Wei-Shaw/sub2api/ent/runtime"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/repository"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
email := flag.String("email", "", "Admin email to issue a JWT for (defaults to first active admin)")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
cfg, err := config.Load()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to load config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, sqlDB, err := repository.InitEnt(cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to init db: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := client.Close(); err != nil {
|
||||||
|
log.Printf("failed to close db: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
userRepo := repository.NewUserRepository(client, sqlDB)
|
||||||
|
authService := service.NewAuthService(userRepo, cfg, nil, nil, nil, nil)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var user *service.User
|
||||||
|
if *email != "" {
|
||||||
|
user, err = userRepo.GetByEmail(ctx, *email)
|
||||||
|
} else {
|
||||||
|
user, err = userRepo.GetFirstAdmin(ctx)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to resolve admin user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := authService.GenerateToken(user)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to generate token: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("ADMIN_EMAIL=%s\nADMIN_USER_ID=%d\nJWT=%s\n", user.Email, user.ID, token)
|
||||||
|
}
|
||||||
@@ -86,7 +86,8 @@ func main() {
|
|||||||
func runSetupServer() {
|
func runSetupServer() {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
r.Use(middleware.Recovery())
|
r.Use(middleware.Recovery())
|
||||||
r.Use(middleware.CORS())
|
r.Use(middleware.CORS(config.CORSConfig{}))
|
||||||
|
r.Use(middleware.SecurityHeaders(config.CSPConfig{Enabled: true, Policy: config.DefaultCSPPolicy}))
|
||||||
|
|
||||||
// Register setup routes
|
// Register setup routes
|
||||||
setup.RegisterRoutes(r)
|
setup.RegisterRoutes(r)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func provideCleanup(
|
|||||||
entClient *ent.Client,
|
entClient *ent.Client,
|
||||||
rdb *redis.Client,
|
rdb *redis.Client,
|
||||||
tokenRefresh *service.TokenRefreshService,
|
tokenRefresh *service.TokenRefreshService,
|
||||||
|
accountExpiry *service.AccountExpiryService,
|
||||||
pricing *service.PricingService,
|
pricing *service.PricingService,
|
||||||
emailQueue *service.EmailQueueService,
|
emailQueue *service.EmailQueueService,
|
||||||
billingCache *service.BillingCacheService,
|
billingCache *service.BillingCacheService,
|
||||||
@@ -84,6 +85,10 @@ func provideCleanup(
|
|||||||
tokenRefresh.Stop()
|
tokenRefresh.Stop()
|
||||||
return nil
|
return nil
|
||||||
}},
|
}},
|
||||||
|
{"AccountExpiryService", func() error {
|
||||||
|
accountExpiry.Stop()
|
||||||
|
return nil
|
||||||
|
}},
|
||||||
{"PricingService", func() error {
|
{"PricingService", func() error {
|
||||||
pricing.Stop()
|
pricing.Stop()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -55,14 +55,14 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
userService := service.NewUserService(userRepository)
|
userService := service.NewUserService(userRepository)
|
||||||
authHandler := handler.NewAuthHandler(configConfig, authService, userService)
|
authHandler := handler.NewAuthHandler(configConfig, authService, userService)
|
||||||
userHandler := handler.NewUserHandler(userService)
|
userHandler := handler.NewUserHandler(userService)
|
||||||
apiKeyRepository := repository.NewApiKeyRepository(client)
|
apiKeyRepository := repository.NewAPIKeyRepository(client)
|
||||||
groupRepository := repository.NewGroupRepository(client, db)
|
groupRepository := repository.NewGroupRepository(client, db)
|
||||||
userSubscriptionRepository := repository.NewUserSubscriptionRepository(client)
|
userSubscriptionRepository := repository.NewUserSubscriptionRepository(client)
|
||||||
apiKeyCache := repository.NewApiKeyCache(redisClient)
|
apiKeyCache := repository.NewAPIKeyCache(redisClient)
|
||||||
apiKeyService := service.NewApiKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
|
apiKeyService := service.NewAPIKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
|
||||||
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
|
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
|
||||||
usageLogRepository := repository.NewUsageLogRepository(client, db)
|
usageLogRepository := repository.NewUsageLogRepository(client, db)
|
||||||
usageService := service.NewUsageService(usageLogRepository, userRepository)
|
usageService := service.NewUsageService(usageLogRepository, userRepository, client)
|
||||||
usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
|
usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
|
||||||
redeemCodeRepository := repository.NewRedeemCodeRepository(client)
|
redeemCodeRepository := repository.NewRedeemCodeRepository(client)
|
||||||
billingCache := repository.NewBillingCache(redisClient)
|
billingCache := repository.NewBillingCache(redisClient)
|
||||||
@@ -76,7 +76,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
dashboardHandler := admin.NewDashboardHandler(dashboardService)
|
dashboardHandler := admin.NewDashboardHandler(dashboardService)
|
||||||
accountRepository := repository.NewAccountRepository(client, db)
|
accountRepository := repository.NewAccountRepository(client, db)
|
||||||
proxyRepository := repository.NewProxyRepository(client, db)
|
proxyRepository := repository.NewProxyRepository(client, db)
|
||||||
proxyExitInfoProber := repository.NewProxyExitInfoProber()
|
proxyExitInfoProber := repository.NewProxyExitInfoProber(configConfig)
|
||||||
adminService := service.NewAdminService(userRepository, groupRepository, accountRepository, proxyRepository, apiKeyRepository, redeemCodeRepository, billingCacheService, proxyExitInfoProber)
|
adminService := service.NewAdminService(userRepository, groupRepository, accountRepository, proxyRepository, apiKeyRepository, redeemCodeRepository, billingCacheService, proxyExitInfoProber)
|
||||||
adminUserHandler := admin.NewUserHandler(adminService)
|
adminUserHandler := admin.NewUserHandler(adminService)
|
||||||
groupHandler := admin.NewGroupHandler(adminService)
|
groupHandler := admin.NewGroupHandler(adminService)
|
||||||
@@ -87,8 +87,10 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
geminiOAuthClient := repository.NewGeminiOAuthClient(configConfig)
|
geminiOAuthClient := repository.NewGeminiOAuthClient(configConfig)
|
||||||
geminiCliCodeAssistClient := repository.NewGeminiCliCodeAssistClient()
|
geminiCliCodeAssistClient := repository.NewGeminiCliCodeAssistClient()
|
||||||
geminiOAuthService := service.NewGeminiOAuthService(proxyRepository, geminiOAuthClient, geminiCliCodeAssistClient, configConfig)
|
geminiOAuthService := service.NewGeminiOAuthService(proxyRepository, geminiOAuthClient, geminiCliCodeAssistClient, configConfig)
|
||||||
|
antigravityOAuthService := service.NewAntigravityOAuthService(proxyRepository)
|
||||||
geminiQuotaService := service.NewGeminiQuotaService(configConfig, settingRepository)
|
geminiQuotaService := service.NewGeminiQuotaService(configConfig, settingRepository)
|
||||||
rateLimitService := service.NewRateLimitService(accountRepository, usageLogRepository, configConfig, geminiQuotaService)
|
tempUnschedCache := repository.NewTempUnschedCache(redisClient)
|
||||||
|
rateLimitService := service.NewRateLimitService(accountRepository, usageLogRepository, configConfig, geminiQuotaService, tempUnschedCache)
|
||||||
claudeUsageFetcher := repository.NewClaudeUsageFetcher()
|
claudeUsageFetcher := repository.NewClaudeUsageFetcher()
|
||||||
antigravityQuotaFetcher := service.NewAntigravityQuotaFetcher(proxyRepository)
|
antigravityQuotaFetcher := service.NewAntigravityQuotaFetcher(proxyRepository)
|
||||||
usageCache := service.NewUsageCache()
|
usageCache := service.NewUsageCache()
|
||||||
@@ -96,15 +98,14 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
geminiTokenCache := repository.NewGeminiTokenCache(redisClient)
|
geminiTokenCache := repository.NewGeminiTokenCache(redisClient)
|
||||||
geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
|
geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
|
||||||
gatewayCache := repository.NewGatewayCache(redisClient)
|
gatewayCache := repository.NewGatewayCache(redisClient)
|
||||||
antigravityOAuthService := service.NewAntigravityOAuthService(proxyRepository)
|
|
||||||
antigravityTokenProvider := service.NewAntigravityTokenProvider(accountRepository, geminiTokenCache, antigravityOAuthService)
|
antigravityTokenProvider := service.NewAntigravityTokenProvider(accountRepository, geminiTokenCache, antigravityOAuthService)
|
||||||
httpUpstream := repository.NewHTTPUpstream(configConfig)
|
httpUpstream := repository.NewHTTPUpstream(configConfig)
|
||||||
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, antigravityTokenProvider, rateLimitService, httpUpstream)
|
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, antigravityTokenProvider, rateLimitService, httpUpstream, settingService)
|
||||||
accountTestService := service.NewAccountTestService(accountRepository, oAuthService, openAIOAuthService, geminiTokenProvider, antigravityGatewayService, httpUpstream)
|
accountTestService := service.NewAccountTestService(accountRepository, geminiTokenProvider, antigravityGatewayService, httpUpstream, configConfig)
|
||||||
concurrencyCache := repository.ProvideConcurrencyCache(redisClient, configConfig)
|
concurrencyCache := repository.ProvideConcurrencyCache(redisClient, configConfig)
|
||||||
concurrencyService := service.ProvideConcurrencyService(concurrencyCache, accountRepository, configConfig)
|
concurrencyService := service.ProvideConcurrencyService(concurrencyCache, accountRepository, configConfig)
|
||||||
crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService)
|
crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService, configConfig)
|
||||||
accountHandler := admin.NewAccountHandler(adminService, oAuthService, openAIOAuthService, geminiOAuthService, rateLimitService, accountUsageService, accountTestService, concurrencyService, crsSyncService)
|
accountHandler := admin.NewAccountHandler(adminService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, rateLimitService, accountUsageService, accountTestService, concurrencyService, crsSyncService)
|
||||||
oAuthHandler := admin.NewOAuthHandler(oAuthService)
|
oAuthHandler := admin.NewOAuthHandler(oAuthService)
|
||||||
openAIOAuthHandler := admin.NewOpenAIOAuthHandler(openAIOAuthService, adminService)
|
openAIOAuthHandler := admin.NewOpenAIOAuthHandler(openAIOAuthService, adminService)
|
||||||
geminiOAuthHandler := admin.NewGeminiOAuthHandler(geminiOAuthService)
|
geminiOAuthHandler := admin.NewGeminiOAuthHandler(geminiOAuthService)
|
||||||
@@ -113,7 +114,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
adminRedeemHandler := admin.NewRedeemHandler(adminService)
|
adminRedeemHandler := admin.NewRedeemHandler(adminService)
|
||||||
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService)
|
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService)
|
||||||
updateCache := repository.NewUpdateCache(redisClient)
|
updateCache := repository.NewUpdateCache(redisClient)
|
||||||
gitHubReleaseClient := repository.NewGitHubReleaseClient()
|
gitHubReleaseClient := repository.ProvideGitHubReleaseClient(configConfig)
|
||||||
serviceBuildInfo := provideServiceBuildInfo(buildInfo)
|
serviceBuildInfo := provideServiceBuildInfo(buildInfo)
|
||||||
updateService := service.ProvideUpdateService(updateCache, gitHubReleaseClient, serviceBuildInfo)
|
updateService := service.ProvideUpdateService(updateCache, gitHubReleaseClient, serviceBuildInfo)
|
||||||
systemHandler := handler.ProvideSystemHandler(updateService)
|
systemHandler := handler.ProvideSystemHandler(updateService)
|
||||||
@@ -124,7 +125,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
userAttributeService := service.NewUserAttributeService(userAttributeDefinitionRepository, userAttributeValueRepository)
|
userAttributeService := service.NewUserAttributeService(userAttributeDefinitionRepository, userAttributeValueRepository)
|
||||||
userAttributeHandler := admin.NewUserAttributeHandler(userAttributeService)
|
userAttributeHandler := admin.NewUserAttributeHandler(userAttributeService)
|
||||||
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, settingHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler)
|
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, settingHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler)
|
||||||
pricingRemoteClient := repository.NewPricingRemoteClient()
|
pricingRemoteClient := repository.ProvidePricingRemoteClient(configConfig)
|
||||||
pricingService, err := service.ProvidePricingService(configConfig, pricingRemoteClient)
|
pricingService, err := service.ProvidePricingService(configConfig, pricingRemoteClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -135,19 +136,20 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
timingWheelService := service.ProvideTimingWheelService()
|
timingWheelService := service.ProvideTimingWheelService()
|
||||||
deferredService := service.ProvideDeferredService(accountRepository, timingWheelService)
|
deferredService := service.ProvideDeferredService(accountRepository, timingWheelService)
|
||||||
gatewayService := service.NewGatewayService(accountRepository, groupRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, concurrencyService, billingService, rateLimitService, billingCacheService, identityService, httpUpstream, deferredService)
|
gatewayService := service.NewGatewayService(accountRepository, groupRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, concurrencyService, billingService, rateLimitService, billingCacheService, identityService, httpUpstream, deferredService)
|
||||||
geminiMessagesCompatService := service.NewGeminiMessagesCompatService(accountRepository, groupRepository, gatewayCache, geminiTokenProvider, rateLimitService, httpUpstream, antigravityGatewayService)
|
geminiMessagesCompatService := service.NewGeminiMessagesCompatService(accountRepository, groupRepository, gatewayCache, geminiTokenProvider, rateLimitService, httpUpstream, antigravityGatewayService, configConfig)
|
||||||
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService)
|
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, configConfig)
|
||||||
openAIGatewayService := service.NewOpenAIGatewayService(accountRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, concurrencyService, billingService, rateLimitService, billingCacheService, httpUpstream, deferredService)
|
openAIGatewayService := service.NewOpenAIGatewayService(accountRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, concurrencyService, billingService, rateLimitService, billingCacheService, httpUpstream, deferredService)
|
||||||
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService)
|
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, configConfig)
|
||||||
handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
|
handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
|
||||||
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler)
|
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler)
|
||||||
jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService)
|
jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService)
|
||||||
adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService)
|
adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService)
|
||||||
apiKeyAuthMiddleware := middleware.NewApiKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
|
apiKeyAuthMiddleware := middleware.NewAPIKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
|
||||||
engine := server.ProvideRouter(configConfig, handlers, jwtAuthMiddleware, adminAuthMiddleware, apiKeyAuthMiddleware, apiKeyService, subscriptionService)
|
engine := server.ProvideRouter(configConfig, handlers, jwtAuthMiddleware, adminAuthMiddleware, apiKeyAuthMiddleware, apiKeyService, subscriptionService)
|
||||||
httpServer := server.ProvideHTTPServer(configConfig, engine)
|
httpServer := server.ProvideHTTPServer(configConfig, engine)
|
||||||
tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, configConfig)
|
tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, configConfig)
|
||||||
v := provideCleanup(client, redisClient, tokenRefreshService, pricingService, emailQueueService, billingCacheService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService)
|
accountExpiryService := service.ProvideAccountExpiryService(accountRepository)
|
||||||
|
v := provideCleanup(client, redisClient, tokenRefreshService, accountExpiryService, pricingService, emailQueueService, billingCacheService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService)
|
||||||
application := &Application{
|
application := &Application{
|
||||||
Server: httpServer,
|
Server: httpServer,
|
||||||
Cleanup: v,
|
Cleanup: v,
|
||||||
@@ -173,6 +175,7 @@ func provideCleanup(
|
|||||||
entClient *ent.Client,
|
entClient *ent.Client,
|
||||||
rdb *redis.Client,
|
rdb *redis.Client,
|
||||||
tokenRefresh *service.TokenRefreshService,
|
tokenRefresh *service.TokenRefreshService,
|
||||||
|
accountExpiry *service.AccountExpiryService,
|
||||||
pricing *service.PricingService,
|
pricing *service.PricingService,
|
||||||
emailQueue *service.EmailQueueService,
|
emailQueue *service.EmailQueueService,
|
||||||
billingCache *service.BillingCacheService,
|
billingCache *service.BillingCacheService,
|
||||||
@@ -193,6 +196,10 @@ func provideCleanup(
|
|||||||
tokenRefresh.Stop()
|
tokenRefresh.Stop()
|
||||||
return nil
|
return nil
|
||||||
}},
|
}},
|
||||||
|
{"AccountExpiryService", func() error {
|
||||||
|
accountExpiry.Stop()
|
||||||
|
return nil
|
||||||
|
}},
|
||||||
{"PricingService", func() error {
|
{"PricingService", func() error {
|
||||||
pricing.Stop()
|
pricing.Stop()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ type Account struct {
|
|||||||
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
||||||
// Name holds the value of the "name" field.
|
// Name holds the value of the "name" field.
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
// Notes holds the value of the "notes" field.
|
||||||
|
Notes *string `json:"notes,omitempty"`
|
||||||
// Platform holds the value of the "platform" field.
|
// Platform holds the value of the "platform" field.
|
||||||
Platform string `json:"platform,omitempty"`
|
Platform string `json:"platform,omitempty"`
|
||||||
// Type holds the value of the "type" field.
|
// Type holds the value of the "type" field.
|
||||||
@@ -47,6 +49,10 @@ type Account struct {
|
|||||||
ErrorMessage *string `json:"error_message,omitempty"`
|
ErrorMessage *string `json:"error_message,omitempty"`
|
||||||
// LastUsedAt holds the value of the "last_used_at" field.
|
// LastUsedAt holds the value of the "last_used_at" field.
|
||||||
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
|
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
|
||||||
|
// Account expiration time (NULL means no expiration).
|
||||||
|
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||||
|
// Auto pause scheduling when account expires.
|
||||||
|
AutoPauseOnExpired bool `json:"auto_pause_on_expired,omitempty"`
|
||||||
// Schedulable holds the value of the "schedulable" field.
|
// Schedulable holds the value of the "schedulable" field.
|
||||||
Schedulable bool `json:"schedulable,omitempty"`
|
Schedulable bool `json:"schedulable,omitempty"`
|
||||||
// RateLimitedAt holds the value of the "rate_limited_at" field.
|
// RateLimitedAt holds the value of the "rate_limited_at" field.
|
||||||
@@ -127,13 +133,13 @@ func (*Account) scanValues(columns []string) ([]any, error) {
|
|||||||
switch columns[i] {
|
switch columns[i] {
|
||||||
case account.FieldCredentials, account.FieldExtra:
|
case account.FieldCredentials, account.FieldExtra:
|
||||||
values[i] = new([]byte)
|
values[i] = new([]byte)
|
||||||
case account.FieldSchedulable:
|
case account.FieldAutoPauseOnExpired, account.FieldSchedulable:
|
||||||
values[i] = new(sql.NullBool)
|
values[i] = new(sql.NullBool)
|
||||||
case account.FieldID, account.FieldProxyID, account.FieldConcurrency, account.FieldPriority:
|
case account.FieldID, account.FieldProxyID, account.FieldConcurrency, account.FieldPriority:
|
||||||
values[i] = new(sql.NullInt64)
|
values[i] = new(sql.NullInt64)
|
||||||
case account.FieldName, account.FieldPlatform, account.FieldType, account.FieldStatus, account.FieldErrorMessage, account.FieldSessionWindowStatus:
|
case account.FieldName, account.FieldNotes, account.FieldPlatform, account.FieldType, account.FieldStatus, account.FieldErrorMessage, account.FieldSessionWindowStatus:
|
||||||
values[i] = new(sql.NullString)
|
values[i] = new(sql.NullString)
|
||||||
case account.FieldCreatedAt, account.FieldUpdatedAt, account.FieldDeletedAt, account.FieldLastUsedAt, account.FieldRateLimitedAt, account.FieldRateLimitResetAt, account.FieldOverloadUntil, account.FieldSessionWindowStart, account.FieldSessionWindowEnd:
|
case account.FieldCreatedAt, account.FieldUpdatedAt, account.FieldDeletedAt, account.FieldLastUsedAt, account.FieldExpiresAt, account.FieldRateLimitedAt, account.FieldRateLimitResetAt, account.FieldOverloadUntil, account.FieldSessionWindowStart, account.FieldSessionWindowEnd:
|
||||||
values[i] = new(sql.NullTime)
|
values[i] = new(sql.NullTime)
|
||||||
default:
|
default:
|
||||||
values[i] = new(sql.UnknownType)
|
values[i] = new(sql.UnknownType)
|
||||||
@@ -181,6 +187,13 @@ func (_m *Account) assignValues(columns []string, values []any) error {
|
|||||||
} else if value.Valid {
|
} else if value.Valid {
|
||||||
_m.Name = value.String
|
_m.Name = value.String
|
||||||
}
|
}
|
||||||
|
case account.FieldNotes:
|
||||||
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field notes", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.Notes = new(string)
|
||||||
|
*_m.Notes = value.String
|
||||||
|
}
|
||||||
case account.FieldPlatform:
|
case account.FieldPlatform:
|
||||||
if value, ok := values[i].(*sql.NullString); !ok {
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
return fmt.Errorf("unexpected type %T for field platform", values[i])
|
return fmt.Errorf("unexpected type %T for field platform", values[i])
|
||||||
@@ -248,6 +261,19 @@ func (_m *Account) assignValues(columns []string, values []any) error {
|
|||||||
_m.LastUsedAt = new(time.Time)
|
_m.LastUsedAt = new(time.Time)
|
||||||
*_m.LastUsedAt = value.Time
|
*_m.LastUsedAt = value.Time
|
||||||
}
|
}
|
||||||
|
case account.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
|
||||||
|
}
|
||||||
|
case account.FieldAutoPauseOnExpired:
|
||||||
|
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field auto_pause_on_expired", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.AutoPauseOnExpired = value.Bool
|
||||||
|
}
|
||||||
case account.FieldSchedulable:
|
case account.FieldSchedulable:
|
||||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||||
return fmt.Errorf("unexpected type %T for field schedulable", values[i])
|
return fmt.Errorf("unexpected type %T for field schedulable", values[i])
|
||||||
@@ -366,6 +392,11 @@ func (_m *Account) String() string {
|
|||||||
builder.WriteString("name=")
|
builder.WriteString("name=")
|
||||||
builder.WriteString(_m.Name)
|
builder.WriteString(_m.Name)
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
if v := _m.Notes; v != nil {
|
||||||
|
builder.WriteString("notes=")
|
||||||
|
builder.WriteString(*v)
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
builder.WriteString("platform=")
|
builder.WriteString("platform=")
|
||||||
builder.WriteString(_m.Platform)
|
builder.WriteString(_m.Platform)
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
@@ -402,6 +433,14 @@ func (_m *Account) String() string {
|
|||||||
builder.WriteString(v.Format(time.ANSIC))
|
builder.WriteString(v.Format(time.ANSIC))
|
||||||
}
|
}
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
if v := _m.ExpiresAt; v != nil {
|
||||||
|
builder.WriteString("expires_at=")
|
||||||
|
builder.WriteString(v.Format(time.ANSIC))
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
|
builder.WriteString("auto_pause_on_expired=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", _m.AutoPauseOnExpired))
|
||||||
|
builder.WriteString(", ")
|
||||||
builder.WriteString("schedulable=")
|
builder.WriteString("schedulable=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", _m.Schedulable))
|
builder.WriteString(fmt.Sprintf("%v", _m.Schedulable))
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ const (
|
|||||||
FieldDeletedAt = "deleted_at"
|
FieldDeletedAt = "deleted_at"
|
||||||
// FieldName holds the string denoting the name field in the database.
|
// FieldName holds the string denoting the name field in the database.
|
||||||
FieldName = "name"
|
FieldName = "name"
|
||||||
|
// FieldNotes holds the string denoting the notes field in the database.
|
||||||
|
FieldNotes = "notes"
|
||||||
// FieldPlatform holds the string denoting the platform field in the database.
|
// FieldPlatform holds the string denoting the platform field in the database.
|
||||||
FieldPlatform = "platform"
|
FieldPlatform = "platform"
|
||||||
// FieldType holds the string denoting the type field in the database.
|
// FieldType holds the string denoting the type field in the database.
|
||||||
@@ -43,6 +45,10 @@ const (
|
|||||||
FieldErrorMessage = "error_message"
|
FieldErrorMessage = "error_message"
|
||||||
// FieldLastUsedAt holds the string denoting the last_used_at field in the database.
|
// FieldLastUsedAt holds the string denoting the last_used_at field in the database.
|
||||||
FieldLastUsedAt = "last_used_at"
|
FieldLastUsedAt = "last_used_at"
|
||||||
|
// FieldExpiresAt holds the string denoting the expires_at field in the database.
|
||||||
|
FieldExpiresAt = "expires_at"
|
||||||
|
// FieldAutoPauseOnExpired holds the string denoting the auto_pause_on_expired field in the database.
|
||||||
|
FieldAutoPauseOnExpired = "auto_pause_on_expired"
|
||||||
// FieldSchedulable holds the string denoting the schedulable field in the database.
|
// FieldSchedulable holds the string denoting the schedulable field in the database.
|
||||||
FieldSchedulable = "schedulable"
|
FieldSchedulable = "schedulable"
|
||||||
// FieldRateLimitedAt holds the string denoting the rate_limited_at field in the database.
|
// FieldRateLimitedAt holds the string denoting the rate_limited_at field in the database.
|
||||||
@@ -102,6 +108,7 @@ var Columns = []string{
|
|||||||
FieldUpdatedAt,
|
FieldUpdatedAt,
|
||||||
FieldDeletedAt,
|
FieldDeletedAt,
|
||||||
FieldName,
|
FieldName,
|
||||||
|
FieldNotes,
|
||||||
FieldPlatform,
|
FieldPlatform,
|
||||||
FieldType,
|
FieldType,
|
||||||
FieldCredentials,
|
FieldCredentials,
|
||||||
@@ -112,6 +119,8 @@ var Columns = []string{
|
|||||||
FieldStatus,
|
FieldStatus,
|
||||||
FieldErrorMessage,
|
FieldErrorMessage,
|
||||||
FieldLastUsedAt,
|
FieldLastUsedAt,
|
||||||
|
FieldExpiresAt,
|
||||||
|
FieldAutoPauseOnExpired,
|
||||||
FieldSchedulable,
|
FieldSchedulable,
|
||||||
FieldRateLimitedAt,
|
FieldRateLimitedAt,
|
||||||
FieldRateLimitResetAt,
|
FieldRateLimitResetAt,
|
||||||
@@ -169,6 +178,8 @@ var (
|
|||||||
DefaultStatus string
|
DefaultStatus string
|
||||||
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||||
StatusValidator func(string) error
|
StatusValidator func(string) error
|
||||||
|
// DefaultAutoPauseOnExpired holds the default value on creation for the "auto_pause_on_expired" field.
|
||||||
|
DefaultAutoPauseOnExpired bool
|
||||||
// DefaultSchedulable holds the default value on creation for the "schedulable" field.
|
// DefaultSchedulable holds the default value on creation for the "schedulable" field.
|
||||||
DefaultSchedulable bool
|
DefaultSchedulable bool
|
||||||
// SessionWindowStatusValidator is a validator for the "session_window_status" field. It is called by the builders before save.
|
// SessionWindowStatusValidator is a validator for the "session_window_status" field. It is called by the builders before save.
|
||||||
@@ -203,6 +214,11 @@ func ByName(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldName, opts...).ToFunc()
|
return sql.OrderByField(FieldName, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByNotes orders the results by the notes field.
|
||||||
|
func ByNotes(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldNotes, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// ByPlatform orders the results by the platform field.
|
// ByPlatform orders the results by the platform field.
|
||||||
func ByPlatform(opts ...sql.OrderTermOption) OrderOption {
|
func ByPlatform(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return sql.OrderByField(FieldPlatform, opts...).ToFunc()
|
return sql.OrderByField(FieldPlatform, opts...).ToFunc()
|
||||||
@@ -243,6 +259,16 @@ func ByLastUsedAt(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldLastUsedAt, opts...).ToFunc()
|
return sql.OrderByField(FieldLastUsedAt, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByExpiresAt orders the results by the expires_at field.
|
||||||
|
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldExpiresAt, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByAutoPauseOnExpired orders the results by the auto_pause_on_expired field.
|
||||||
|
func ByAutoPauseOnExpired(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldAutoPauseOnExpired, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// BySchedulable orders the results by the schedulable field.
|
// BySchedulable orders the results by the schedulable field.
|
||||||
func BySchedulable(opts ...sql.OrderTermOption) OrderOption {
|
func BySchedulable(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return sql.OrderByField(FieldSchedulable, opts...).ToFunc()
|
return sql.OrderByField(FieldSchedulable, opts...).ToFunc()
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ func Name(v string) predicate.Account {
|
|||||||
return predicate.Account(sql.FieldEQ(FieldName, v))
|
return predicate.Account(sql.FieldEQ(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notes applies equality check predicate on the "notes" field. It's identical to NotesEQ.
|
||||||
|
func Notes(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
// Platform applies equality check predicate on the "platform" field. It's identical to PlatformEQ.
|
// Platform applies equality check predicate on the "platform" field. It's identical to PlatformEQ.
|
||||||
func Platform(v string) predicate.Account {
|
func Platform(v string) predicate.Account {
|
||||||
return predicate.Account(sql.FieldEQ(FieldPlatform, v))
|
return predicate.Account(sql.FieldEQ(FieldPlatform, v))
|
||||||
@@ -115,6 +120,16 @@ func LastUsedAt(v time.Time) predicate.Account {
|
|||||||
return predicate.Account(sql.FieldEQ(FieldLastUsedAt, v))
|
return predicate.Account(sql.FieldEQ(FieldLastUsedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExpiresAt applies equality check predicate on the "expires_at" field. It's identical to ExpiresAtEQ.
|
||||||
|
func ExpiresAt(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoPauseOnExpired applies equality check predicate on the "auto_pause_on_expired" field. It's identical to AutoPauseOnExpiredEQ.
|
||||||
|
func AutoPauseOnExpired(v bool) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldAutoPauseOnExpired, v))
|
||||||
|
}
|
||||||
|
|
||||||
// Schedulable applies equality check predicate on the "schedulable" field. It's identical to SchedulableEQ.
|
// Schedulable applies equality check predicate on the "schedulable" field. It's identical to SchedulableEQ.
|
||||||
func Schedulable(v bool) predicate.Account {
|
func Schedulable(v bool) predicate.Account {
|
||||||
return predicate.Account(sql.FieldEQ(FieldSchedulable, v))
|
return predicate.Account(sql.FieldEQ(FieldSchedulable, v))
|
||||||
@@ -345,6 +360,81 @@ func NameContainsFold(v string) predicate.Account {
|
|||||||
return predicate.Account(sql.FieldContainsFold(FieldName, v))
|
return predicate.Account(sql.FieldContainsFold(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotesEQ applies the EQ predicate on the "notes" field.
|
||||||
|
func NotesEQ(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesNEQ applies the NEQ predicate on the "notes" field.
|
||||||
|
func NotesNEQ(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNEQ(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesIn applies the In predicate on the "notes" field.
|
||||||
|
func NotesIn(vs ...string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldIn(FieldNotes, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesNotIn applies the NotIn predicate on the "notes" field.
|
||||||
|
func NotesNotIn(vs ...string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNotIn(FieldNotes, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesGT applies the GT predicate on the "notes" field.
|
||||||
|
func NotesGT(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldGT(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesGTE applies the GTE predicate on the "notes" field.
|
||||||
|
func NotesGTE(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldGTE(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesLT applies the LT predicate on the "notes" field.
|
||||||
|
func NotesLT(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldLT(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesLTE applies the LTE predicate on the "notes" field.
|
||||||
|
func NotesLTE(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldLTE(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesContains applies the Contains predicate on the "notes" field.
|
||||||
|
func NotesContains(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldContains(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesHasPrefix applies the HasPrefix predicate on the "notes" field.
|
||||||
|
func NotesHasPrefix(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldHasPrefix(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesHasSuffix applies the HasSuffix predicate on the "notes" field.
|
||||||
|
func NotesHasSuffix(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldHasSuffix(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesIsNil applies the IsNil predicate on the "notes" field.
|
||||||
|
func NotesIsNil() predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldIsNull(FieldNotes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesNotNil applies the NotNil predicate on the "notes" field.
|
||||||
|
func NotesNotNil() predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNotNull(FieldNotes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesEqualFold applies the EqualFold predicate on the "notes" field.
|
||||||
|
func NotesEqualFold(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEqualFold(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotesContainsFold applies the ContainsFold predicate on the "notes" field.
|
||||||
|
func NotesContainsFold(v string) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldContainsFold(FieldNotes, v))
|
||||||
|
}
|
||||||
|
|
||||||
// PlatformEQ applies the EQ predicate on the "platform" field.
|
// PlatformEQ applies the EQ predicate on the "platform" field.
|
||||||
func PlatformEQ(v string) predicate.Account {
|
func PlatformEQ(v string) predicate.Account {
|
||||||
return predicate.Account(sql.FieldEQ(FieldPlatform, v))
|
return predicate.Account(sql.FieldEQ(FieldPlatform, v))
|
||||||
@@ -775,6 +865,66 @@ func LastUsedAtNotNil() predicate.Account {
|
|||||||
return predicate.Account(sql.FieldNotNull(FieldLastUsedAt))
|
return predicate.Account(sql.FieldNotNull(FieldLastUsedAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExpiresAtEQ applies the EQ predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtEQ(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtNEQ applies the NEQ predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtNEQ(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNEQ(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtIn applies the In predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtIn(vs ...time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldIn(FieldExpiresAt, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtNotIn applies the NotIn predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtNotIn(vs ...time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNotIn(FieldExpiresAt, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtGT applies the GT predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtGT(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldGT(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtGTE applies the GTE predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtGTE(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldGTE(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtLT applies the LT predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtLT(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldLT(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtLTE applies the LTE predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtLTE(v time.Time) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldLTE(FieldExpiresAt, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtIsNil applies the IsNil predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtIsNil() predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldIsNull(FieldExpiresAt))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpiresAtNotNil applies the NotNil predicate on the "expires_at" field.
|
||||||
|
func ExpiresAtNotNil() predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNotNull(FieldExpiresAt))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoPauseOnExpiredEQ applies the EQ predicate on the "auto_pause_on_expired" field.
|
||||||
|
func AutoPauseOnExpiredEQ(v bool) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldEQ(FieldAutoPauseOnExpired, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoPauseOnExpiredNEQ applies the NEQ predicate on the "auto_pause_on_expired" field.
|
||||||
|
func AutoPauseOnExpiredNEQ(v bool) predicate.Account {
|
||||||
|
return predicate.Account(sql.FieldNEQ(FieldAutoPauseOnExpired, v))
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulableEQ applies the EQ predicate on the "schedulable" field.
|
// SchedulableEQ applies the EQ predicate on the "schedulable" field.
|
||||||
func SchedulableEQ(v bool) predicate.Account {
|
func SchedulableEQ(v bool) predicate.Account {
|
||||||
return predicate.Account(sql.FieldEQ(FieldSchedulable, v))
|
return predicate.Account(sql.FieldEQ(FieldSchedulable, v))
|
||||||
|
|||||||
@@ -73,6 +73,20 @@ func (_c *AccountCreate) SetName(v string) *AccountCreate {
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (_c *AccountCreate) SetNotes(v string) *AccountCreate {
|
||||||
|
_c.mutation.SetNotes(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableNotes sets the "notes" field if the given value is not nil.
|
||||||
|
func (_c *AccountCreate) SetNillableNotes(v *string) *AccountCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetNotes(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (_c *AccountCreate) SetPlatform(v string) *AccountCreate {
|
func (_c *AccountCreate) SetPlatform(v string) *AccountCreate {
|
||||||
_c.mutation.SetPlatform(v)
|
_c.mutation.SetPlatform(v)
|
||||||
@@ -181,6 +195,34 @@ func (_c *AccountCreate) SetNillableLastUsedAt(v *time.Time) *AccountCreate {
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (_c *AccountCreate) SetExpiresAt(v time.Time) *AccountCreate {
|
||||||
|
_c.mutation.SetExpiresAt(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||||
|
func (_c *AccountCreate) SetNillableExpiresAt(v *time.Time) *AccountCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetExpiresAt(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (_c *AccountCreate) SetAutoPauseOnExpired(v bool) *AccountCreate {
|
||||||
|
_c.mutation.SetAutoPauseOnExpired(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableAutoPauseOnExpired sets the "auto_pause_on_expired" field if the given value is not nil.
|
||||||
|
func (_c *AccountCreate) SetNillableAutoPauseOnExpired(v *bool) *AccountCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetAutoPauseOnExpired(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (_c *AccountCreate) SetSchedulable(v bool) *AccountCreate {
|
func (_c *AccountCreate) SetSchedulable(v bool) *AccountCreate {
|
||||||
_c.mutation.SetSchedulable(v)
|
_c.mutation.SetSchedulable(v)
|
||||||
@@ -391,6 +433,10 @@ func (_c *AccountCreate) defaults() error {
|
|||||||
v := account.DefaultStatus
|
v := account.DefaultStatus
|
||||||
_c.mutation.SetStatus(v)
|
_c.mutation.SetStatus(v)
|
||||||
}
|
}
|
||||||
|
if _, ok := _c.mutation.AutoPauseOnExpired(); !ok {
|
||||||
|
v := account.DefaultAutoPauseOnExpired
|
||||||
|
_c.mutation.SetAutoPauseOnExpired(v)
|
||||||
|
}
|
||||||
if _, ok := _c.mutation.Schedulable(); !ok {
|
if _, ok := _c.mutation.Schedulable(); !ok {
|
||||||
v := account.DefaultSchedulable
|
v := account.DefaultSchedulable
|
||||||
_c.mutation.SetSchedulable(v)
|
_c.mutation.SetSchedulable(v)
|
||||||
@@ -450,6 +496,9 @@ func (_c *AccountCreate) check() error {
|
|||||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Account.status": %w`, err)}
|
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Account.status": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if _, ok := _c.mutation.AutoPauseOnExpired(); !ok {
|
||||||
|
return &ValidationError{Name: "auto_pause_on_expired", err: errors.New(`ent: missing required field "Account.auto_pause_on_expired"`)}
|
||||||
|
}
|
||||||
if _, ok := _c.mutation.Schedulable(); !ok {
|
if _, ok := _c.mutation.Schedulable(); !ok {
|
||||||
return &ValidationError{Name: "schedulable", err: errors.New(`ent: missing required field "Account.schedulable"`)}
|
return &ValidationError{Name: "schedulable", err: errors.New(`ent: missing required field "Account.schedulable"`)}
|
||||||
}
|
}
|
||||||
@@ -501,6 +550,10 @@ func (_c *AccountCreate) createSpec() (*Account, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(account.FieldName, field.TypeString, value)
|
_spec.SetField(account.FieldName, field.TypeString, value)
|
||||||
_node.Name = value
|
_node.Name = value
|
||||||
}
|
}
|
||||||
|
if value, ok := _c.mutation.Notes(); ok {
|
||||||
|
_spec.SetField(account.FieldNotes, field.TypeString, value)
|
||||||
|
_node.Notes = &value
|
||||||
|
}
|
||||||
if value, ok := _c.mutation.Platform(); ok {
|
if value, ok := _c.mutation.Platform(); ok {
|
||||||
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
||||||
_node.Platform = value
|
_node.Platform = value
|
||||||
@@ -537,6 +590,14 @@ func (_c *AccountCreate) createSpec() (*Account, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(account.FieldLastUsedAt, field.TypeTime, value)
|
_spec.SetField(account.FieldLastUsedAt, field.TypeTime, value)
|
||||||
_node.LastUsedAt = &value
|
_node.LastUsedAt = &value
|
||||||
}
|
}
|
||||||
|
if value, ok := _c.mutation.ExpiresAt(); ok {
|
||||||
|
_spec.SetField(account.FieldExpiresAt, field.TypeTime, value)
|
||||||
|
_node.ExpiresAt = &value
|
||||||
|
}
|
||||||
|
if value, ok := _c.mutation.AutoPauseOnExpired(); ok {
|
||||||
|
_spec.SetField(account.FieldAutoPauseOnExpired, field.TypeBool, value)
|
||||||
|
_node.AutoPauseOnExpired = value
|
||||||
|
}
|
||||||
if value, ok := _c.mutation.Schedulable(); ok {
|
if value, ok := _c.mutation.Schedulable(); ok {
|
||||||
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
||||||
_node.Schedulable = value
|
_node.Schedulable = value
|
||||||
@@ -712,6 +773,24 @@ func (u *AccountUpsert) UpdateName() *AccountUpsert {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (u *AccountUpsert) SetNotes(v string) *AccountUpsert {
|
||||||
|
u.Set(account.FieldNotes, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNotes sets the "notes" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsert) UpdateNotes() *AccountUpsert {
|
||||||
|
u.SetExcluded(account.FieldNotes)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearNotes clears the value of the "notes" field.
|
||||||
|
func (u *AccountUpsert) ClearNotes() *AccountUpsert {
|
||||||
|
u.SetNull(account.FieldNotes)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (u *AccountUpsert) SetPlatform(v string) *AccountUpsert {
|
func (u *AccountUpsert) SetPlatform(v string) *AccountUpsert {
|
||||||
u.Set(account.FieldPlatform, v)
|
u.Set(account.FieldPlatform, v)
|
||||||
@@ -862,6 +941,36 @@ func (u *AccountUpsert) ClearLastUsedAt() *AccountUpsert {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (u *AccountUpsert) SetExpiresAt(v time.Time) *AccountUpsert {
|
||||||
|
u.Set(account.FieldExpiresAt, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsert) UpdateExpiresAt() *AccountUpsert {
|
||||||
|
u.SetExcluded(account.FieldExpiresAt)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||||
|
func (u *AccountUpsert) ClearExpiresAt() *AccountUpsert {
|
||||||
|
u.SetNull(account.FieldExpiresAt)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (u *AccountUpsert) SetAutoPauseOnExpired(v bool) *AccountUpsert {
|
||||||
|
u.Set(account.FieldAutoPauseOnExpired, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateAutoPauseOnExpired sets the "auto_pause_on_expired" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsert) UpdateAutoPauseOnExpired() *AccountUpsert {
|
||||||
|
u.SetExcluded(account.FieldAutoPauseOnExpired)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (u *AccountUpsert) SetSchedulable(v bool) *AccountUpsert {
|
func (u *AccountUpsert) SetSchedulable(v bool) *AccountUpsert {
|
||||||
u.Set(account.FieldSchedulable, v)
|
u.Set(account.FieldSchedulable, v)
|
||||||
@@ -1076,6 +1185,27 @@ func (u *AccountUpsertOne) UpdateName() *AccountUpsertOne {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (u *AccountUpsertOne) SetNotes(v string) *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetNotes(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNotes sets the "notes" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertOne) UpdateNotes() *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateNotes()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearNotes clears the value of the "notes" field.
|
||||||
|
func (u *AccountUpsertOne) ClearNotes() *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.ClearNotes()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (u *AccountUpsertOne) SetPlatform(v string) *AccountUpsertOne {
|
func (u *AccountUpsertOne) SetPlatform(v string) *AccountUpsertOne {
|
||||||
return u.Update(func(s *AccountUpsert) {
|
return u.Update(func(s *AccountUpsert) {
|
||||||
@@ -1251,6 +1381,41 @@ func (u *AccountUpsertOne) ClearLastUsedAt() *AccountUpsertOne {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (u *AccountUpsertOne) SetExpiresAt(v time.Time) *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetExpiresAt(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertOne) UpdateExpiresAt() *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateExpiresAt()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||||
|
func (u *AccountUpsertOne) ClearExpiresAt() *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.ClearExpiresAt()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (u *AccountUpsertOne) SetAutoPauseOnExpired(v bool) *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetAutoPauseOnExpired(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateAutoPauseOnExpired sets the "auto_pause_on_expired" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertOne) UpdateAutoPauseOnExpired() *AccountUpsertOne {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateAutoPauseOnExpired()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (u *AccountUpsertOne) SetSchedulable(v bool) *AccountUpsertOne {
|
func (u *AccountUpsertOne) SetSchedulable(v bool) *AccountUpsertOne {
|
||||||
return u.Update(func(s *AccountUpsert) {
|
return u.Update(func(s *AccountUpsert) {
|
||||||
@@ -1651,6 +1816,27 @@ func (u *AccountUpsertBulk) UpdateName() *AccountUpsertBulk {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (u *AccountUpsertBulk) SetNotes(v string) *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetNotes(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNotes sets the "notes" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertBulk) UpdateNotes() *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateNotes()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearNotes clears the value of the "notes" field.
|
||||||
|
func (u *AccountUpsertBulk) ClearNotes() *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.ClearNotes()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (u *AccountUpsertBulk) SetPlatform(v string) *AccountUpsertBulk {
|
func (u *AccountUpsertBulk) SetPlatform(v string) *AccountUpsertBulk {
|
||||||
return u.Update(func(s *AccountUpsert) {
|
return u.Update(func(s *AccountUpsert) {
|
||||||
@@ -1826,6 +2012,41 @@ func (u *AccountUpsertBulk) ClearLastUsedAt() *AccountUpsertBulk {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (u *AccountUpsertBulk) SetExpiresAt(v time.Time) *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetExpiresAt(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertBulk) UpdateExpiresAt() *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateExpiresAt()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||||
|
func (u *AccountUpsertBulk) ClearExpiresAt() *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.ClearExpiresAt()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (u *AccountUpsertBulk) SetAutoPauseOnExpired(v bool) *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.SetAutoPauseOnExpired(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateAutoPauseOnExpired sets the "auto_pause_on_expired" field to the value that was provided on create.
|
||||||
|
func (u *AccountUpsertBulk) UpdateAutoPauseOnExpired() *AccountUpsertBulk {
|
||||||
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
s.UpdateAutoPauseOnExpired()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (u *AccountUpsertBulk) SetSchedulable(v bool) *AccountUpsertBulk {
|
func (u *AccountUpsertBulk) SetSchedulable(v bool) *AccountUpsertBulk {
|
||||||
return u.Update(func(s *AccountUpsert) {
|
return u.Update(func(s *AccountUpsert) {
|
||||||
|
|||||||
@@ -71,6 +71,26 @@ func (_u *AccountUpdate) SetNillableName(v *string) *AccountUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (_u *AccountUpdate) SetNotes(v string) *AccountUpdate {
|
||||||
|
_u.mutation.SetNotes(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableNotes sets the "notes" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdate) SetNillableNotes(v *string) *AccountUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetNotes(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearNotes clears the value of the "notes" field.
|
||||||
|
func (_u *AccountUpdate) ClearNotes() *AccountUpdate {
|
||||||
|
_u.mutation.ClearNotes()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (_u *AccountUpdate) SetPlatform(v string) *AccountUpdate {
|
func (_u *AccountUpdate) SetPlatform(v string) *AccountUpdate {
|
||||||
_u.mutation.SetPlatform(v)
|
_u.mutation.SetPlatform(v)
|
||||||
@@ -227,6 +247,40 @@ func (_u *AccountUpdate) ClearLastUsedAt() *AccountUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (_u *AccountUpdate) SetExpiresAt(v time.Time) *AccountUpdate {
|
||||||
|
_u.mutation.SetExpiresAt(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdate) SetNillableExpiresAt(v *time.Time) *AccountUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetExpiresAt(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||||
|
func (_u *AccountUpdate) ClearExpiresAt() *AccountUpdate {
|
||||||
|
_u.mutation.ClearExpiresAt()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (_u *AccountUpdate) SetAutoPauseOnExpired(v bool) *AccountUpdate {
|
||||||
|
_u.mutation.SetAutoPauseOnExpired(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableAutoPauseOnExpired sets the "auto_pause_on_expired" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdate) SetNillableAutoPauseOnExpired(v *bool) *AccountUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetAutoPauseOnExpired(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (_u *AccountUpdate) SetSchedulable(v bool) *AccountUpdate {
|
func (_u *AccountUpdate) SetSchedulable(v bool) *AccountUpdate {
|
||||||
_u.mutation.SetSchedulable(v)
|
_u.mutation.SetSchedulable(v)
|
||||||
@@ -545,6 +599,12 @@ func (_u *AccountUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
|||||||
if value, ok := _u.mutation.Name(); ok {
|
if value, ok := _u.mutation.Name(); ok {
|
||||||
_spec.SetField(account.FieldName, field.TypeString, value)
|
_spec.SetField(account.FieldName, field.TypeString, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.Notes(); ok {
|
||||||
|
_spec.SetField(account.FieldNotes, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.NotesCleared() {
|
||||||
|
_spec.ClearField(account.FieldNotes, field.TypeString)
|
||||||
|
}
|
||||||
if value, ok := _u.mutation.Platform(); ok {
|
if value, ok := _u.mutation.Platform(); ok {
|
||||||
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
||||||
}
|
}
|
||||||
@@ -584,6 +644,15 @@ func (_u *AccountUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
|||||||
if _u.mutation.LastUsedAtCleared() {
|
if _u.mutation.LastUsedAtCleared() {
|
||||||
_spec.ClearField(account.FieldLastUsedAt, field.TypeTime)
|
_spec.ClearField(account.FieldLastUsedAt, field.TypeTime)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.ExpiresAt(); ok {
|
||||||
|
_spec.SetField(account.FieldExpiresAt, field.TypeTime, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ExpiresAtCleared() {
|
||||||
|
_spec.ClearField(account.FieldExpiresAt, field.TypeTime)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AutoPauseOnExpired(); ok {
|
||||||
|
_spec.SetField(account.FieldAutoPauseOnExpired, field.TypeBool, value)
|
||||||
|
}
|
||||||
if value, ok := _u.mutation.Schedulable(); ok {
|
if value, ok := _u.mutation.Schedulable(); ok {
|
||||||
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
||||||
}
|
}
|
||||||
@@ -814,6 +883,26 @@ func (_u *AccountUpdateOne) SetNillableName(v *string) *AccountUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotes sets the "notes" field.
|
||||||
|
func (_u *AccountUpdateOne) SetNotes(v string) *AccountUpdateOne {
|
||||||
|
_u.mutation.SetNotes(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableNotes sets the "notes" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdateOne) SetNillableNotes(v *string) *AccountUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetNotes(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearNotes clears the value of the "notes" field.
|
||||||
|
func (_u *AccountUpdateOne) ClearNotes() *AccountUpdateOne {
|
||||||
|
_u.mutation.ClearNotes()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetPlatform sets the "platform" field.
|
// SetPlatform sets the "platform" field.
|
||||||
func (_u *AccountUpdateOne) SetPlatform(v string) *AccountUpdateOne {
|
func (_u *AccountUpdateOne) SetPlatform(v string) *AccountUpdateOne {
|
||||||
_u.mutation.SetPlatform(v)
|
_u.mutation.SetPlatform(v)
|
||||||
@@ -970,6 +1059,40 @@ func (_u *AccountUpdateOne) ClearLastUsedAt() *AccountUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExpiresAt sets the "expires_at" field.
|
||||||
|
func (_u *AccountUpdateOne) SetExpiresAt(v time.Time) *AccountUpdateOne {
|
||||||
|
_u.mutation.SetExpiresAt(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdateOne) SetNillableExpiresAt(v *time.Time) *AccountUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetExpiresAt(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExpiresAt clears the value of the "expires_at" field.
|
||||||
|
func (_u *AccountUpdateOne) ClearExpiresAt() *AccountUpdateOne {
|
||||||
|
_u.mutation.ClearExpiresAt()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAutoPauseOnExpired sets the "auto_pause_on_expired" field.
|
||||||
|
func (_u *AccountUpdateOne) SetAutoPauseOnExpired(v bool) *AccountUpdateOne {
|
||||||
|
_u.mutation.SetAutoPauseOnExpired(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableAutoPauseOnExpired sets the "auto_pause_on_expired" field if the given value is not nil.
|
||||||
|
func (_u *AccountUpdateOne) SetNillableAutoPauseOnExpired(v *bool) *AccountUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetAutoPauseOnExpired(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetSchedulable sets the "schedulable" field.
|
// SetSchedulable sets the "schedulable" field.
|
||||||
func (_u *AccountUpdateOne) SetSchedulable(v bool) *AccountUpdateOne {
|
func (_u *AccountUpdateOne) SetSchedulable(v bool) *AccountUpdateOne {
|
||||||
_u.mutation.SetSchedulable(v)
|
_u.mutation.SetSchedulable(v)
|
||||||
@@ -1318,6 +1441,12 @@ func (_u *AccountUpdateOne) sqlSave(ctx context.Context) (_node *Account, err er
|
|||||||
if value, ok := _u.mutation.Name(); ok {
|
if value, ok := _u.mutation.Name(); ok {
|
||||||
_spec.SetField(account.FieldName, field.TypeString, value)
|
_spec.SetField(account.FieldName, field.TypeString, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.Notes(); ok {
|
||||||
|
_spec.SetField(account.FieldNotes, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.NotesCleared() {
|
||||||
|
_spec.ClearField(account.FieldNotes, field.TypeString)
|
||||||
|
}
|
||||||
if value, ok := _u.mutation.Platform(); ok {
|
if value, ok := _u.mutation.Platform(); ok {
|
||||||
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
_spec.SetField(account.FieldPlatform, field.TypeString, value)
|
||||||
}
|
}
|
||||||
@@ -1357,6 +1486,15 @@ func (_u *AccountUpdateOne) sqlSave(ctx context.Context) (_node *Account, err er
|
|||||||
if _u.mutation.LastUsedAtCleared() {
|
if _u.mutation.LastUsedAtCleared() {
|
||||||
_spec.ClearField(account.FieldLastUsedAt, field.TypeTime)
|
_spec.ClearField(account.FieldLastUsedAt, field.TypeTime)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.ExpiresAt(); ok {
|
||||||
|
_spec.SetField(account.FieldExpiresAt, field.TypeTime, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ExpiresAtCleared() {
|
||||||
|
_spec.ClearField(account.FieldExpiresAt, field.TypeTime)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AutoPauseOnExpired(); ok {
|
||||||
|
_spec.SetField(account.FieldAutoPauseOnExpired, field.TypeBool, value)
|
||||||
|
}
|
||||||
if value, ok := _u.mutation.Schedulable(); ok {
|
if value, ok := _u.mutation.Schedulable(); ok {
|
||||||
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
_spec.SetField(account.FieldSchedulable, field.TypeBool, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKey is the model entity for the ApiKey schema.
|
// APIKey is the model entity for the APIKey schema.
|
||||||
type ApiKey struct {
|
type APIKey struct {
|
||||||
config `json:"-"`
|
config `json:"-"`
|
||||||
// ID of the ent.
|
// ID of the ent.
|
||||||
ID int64 `json:"id,omitempty"`
|
ID int64 `json:"id,omitempty"`
|
||||||
@@ -36,13 +36,13 @@ type ApiKey struct {
|
|||||||
// Status holds the value of the "status" field.
|
// Status holds the value of the "status" field.
|
||||||
Status string `json:"status,omitempty"`
|
Status string `json:"status,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
// The values are being populated by the ApiKeyQuery when eager-loading is set.
|
// The values are being populated by the APIKeyQuery when eager-loading is set.
|
||||||
Edges ApiKeyEdges `json:"edges"`
|
Edges APIKeyEdges `json:"edges"`
|
||||||
selectValues sql.SelectValues
|
selectValues sql.SelectValues
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyEdges holds the relations/edges for other nodes in the graph.
|
// APIKeyEdges holds the relations/edges for other nodes in the graph.
|
||||||
type ApiKeyEdges struct {
|
type APIKeyEdges struct {
|
||||||
// User holds the value of the user edge.
|
// User holds the value of the user edge.
|
||||||
User *User `json:"user,omitempty"`
|
User *User `json:"user,omitempty"`
|
||||||
// Group holds the value of the group edge.
|
// Group holds the value of the group edge.
|
||||||
@@ -56,7 +56,7 @@ type ApiKeyEdges struct {
|
|||||||
|
|
||||||
// UserOrErr returns the User value or an error if the edge
|
// UserOrErr returns the User value or an error if the edge
|
||||||
// was not loaded in eager-loading, or loaded but was not found.
|
// was not loaded in eager-loading, or loaded but was not found.
|
||||||
func (e ApiKeyEdges) UserOrErr() (*User, error) {
|
func (e APIKeyEdges) UserOrErr() (*User, error) {
|
||||||
if e.User != nil {
|
if e.User != nil {
|
||||||
return e.User, nil
|
return e.User, nil
|
||||||
} else if e.loadedTypes[0] {
|
} else if e.loadedTypes[0] {
|
||||||
@@ -67,7 +67,7 @@ func (e ApiKeyEdges) UserOrErr() (*User, error) {
|
|||||||
|
|
||||||
// GroupOrErr returns the Group value or an error if the edge
|
// GroupOrErr returns the Group value or an error if the edge
|
||||||
// was not loaded in eager-loading, or loaded but was not found.
|
// was not loaded in eager-loading, or loaded but was not found.
|
||||||
func (e ApiKeyEdges) GroupOrErr() (*Group, error) {
|
func (e APIKeyEdges) GroupOrErr() (*Group, error) {
|
||||||
if e.Group != nil {
|
if e.Group != nil {
|
||||||
return e.Group, nil
|
return e.Group, nil
|
||||||
} else if e.loadedTypes[1] {
|
} else if e.loadedTypes[1] {
|
||||||
@@ -78,7 +78,7 @@ func (e ApiKeyEdges) GroupOrErr() (*Group, error) {
|
|||||||
|
|
||||||
// UsageLogsOrErr returns the UsageLogs value or an error if the edge
|
// UsageLogsOrErr returns the UsageLogs value or an error if the edge
|
||||||
// was not loaded in eager-loading.
|
// was not loaded in eager-loading.
|
||||||
func (e ApiKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
|
func (e APIKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
|
||||||
if e.loadedTypes[2] {
|
if e.loadedTypes[2] {
|
||||||
return e.UsageLogs, nil
|
return e.UsageLogs, nil
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ func (e ApiKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scanValues returns the types for scanning values from sql.Rows.
|
// scanValues returns the types for scanning values from sql.Rows.
|
||||||
func (*ApiKey) scanValues(columns []string) ([]any, error) {
|
func (*APIKey) scanValues(columns []string) ([]any, error) {
|
||||||
values := make([]any, len(columns))
|
values := make([]any, len(columns))
|
||||||
for i := range columns {
|
for i := range columns {
|
||||||
switch columns[i] {
|
switch columns[i] {
|
||||||
@@ -104,8 +104,8 @@ func (*ApiKey) scanValues(columns []string) ([]any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||||
// to the ApiKey fields.
|
// to the APIKey fields.
|
||||||
func (_m *ApiKey) assignValues(columns []string, values []any) error {
|
func (_m *APIKey) assignValues(columns []string, values []any) error {
|
||||||
if m, n := len(values), len(columns); m < n {
|
if m, n := len(values), len(columns); m < n {
|
||||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||||
}
|
}
|
||||||
@@ -174,49 +174,49 @@ func (_m *ApiKey) assignValues(columns []string, values []any) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns the ent.Value that was dynamically selected and assigned to the ApiKey.
|
// Value returns the ent.Value that was dynamically selected and assigned to the APIKey.
|
||||||
// This includes values selected through modifiers, order, etc.
|
// This includes values selected through modifiers, order, etc.
|
||||||
func (_m *ApiKey) Value(name string) (ent.Value, error) {
|
func (_m *APIKey) Value(name string) (ent.Value, error) {
|
||||||
return _m.selectValues.Get(name)
|
return _m.selectValues.Get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryUser queries the "user" edge of the ApiKey entity.
|
// QueryUser queries the "user" edge of the APIKey entity.
|
||||||
func (_m *ApiKey) QueryUser() *UserQuery {
|
func (_m *APIKey) QueryUser() *UserQuery {
|
||||||
return NewApiKeyClient(_m.config).QueryUser(_m)
|
return NewAPIKeyClient(_m.config).QueryUser(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryGroup queries the "group" edge of the ApiKey entity.
|
// QueryGroup queries the "group" edge of the APIKey entity.
|
||||||
func (_m *ApiKey) QueryGroup() *GroupQuery {
|
func (_m *APIKey) QueryGroup() *GroupQuery {
|
||||||
return NewApiKeyClient(_m.config).QueryGroup(_m)
|
return NewAPIKeyClient(_m.config).QueryGroup(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryUsageLogs queries the "usage_logs" edge of the ApiKey entity.
|
// QueryUsageLogs queries the "usage_logs" edge of the APIKey entity.
|
||||||
func (_m *ApiKey) QueryUsageLogs() *UsageLogQuery {
|
func (_m *APIKey) QueryUsageLogs() *UsageLogQuery {
|
||||||
return NewApiKeyClient(_m.config).QueryUsageLogs(_m)
|
return NewAPIKeyClient(_m.config).QueryUsageLogs(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update returns a builder for updating this ApiKey.
|
// Update returns a builder for updating this APIKey.
|
||||||
// Note that you need to call ApiKey.Unwrap() before calling this method if this ApiKey
|
// Note that you need to call APIKey.Unwrap() before calling this method if this APIKey
|
||||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||||
func (_m *ApiKey) Update() *ApiKeyUpdateOne {
|
func (_m *APIKey) Update() *APIKeyUpdateOne {
|
||||||
return NewApiKeyClient(_m.config).UpdateOne(_m)
|
return NewAPIKeyClient(_m.config).UpdateOne(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap unwraps the ApiKey entity that was returned from a transaction after it was closed,
|
// Unwrap unwraps the APIKey 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.
|
// so that all future queries will be executed through the driver which created the transaction.
|
||||||
func (_m *ApiKey) Unwrap() *ApiKey {
|
func (_m *APIKey) Unwrap() *APIKey {
|
||||||
_tx, ok := _m.config.driver.(*txDriver)
|
_tx, ok := _m.config.driver.(*txDriver)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("ent: ApiKey is not a transactional entity")
|
panic("ent: APIKey is not a transactional entity")
|
||||||
}
|
}
|
||||||
_m.config.driver = _tx.drv
|
_m.config.driver = _tx.drv
|
||||||
return _m
|
return _m
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements the fmt.Stringer.
|
// String implements the fmt.Stringer.
|
||||||
func (_m *ApiKey) String() string {
|
func (_m *APIKey) String() string {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
builder.WriteString("ApiKey(")
|
builder.WriteString("APIKey(")
|
||||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||||
builder.WriteString("created_at=")
|
builder.WriteString("created_at=")
|
||||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||||
@@ -249,5 +249,5 @@ func (_m *ApiKey) String() string {
|
|||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeys is a parsable slice of ApiKey.
|
// APIKeys is a parsable slice of APIKey.
|
||||||
type ApiKeys []*ApiKey
|
type APIKeys []*APIKey
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ var (
|
|||||||
StatusValidator func(string) error
|
StatusValidator func(string) error
|
||||||
)
|
)
|
||||||
|
|
||||||
// OrderOption defines the ordering options for the ApiKey queries.
|
// OrderOption defines the ordering options for the APIKey queries.
|
||||||
type OrderOption func(*sql.Selector)
|
type OrderOption func(*sql.Selector)
|
||||||
|
|
||||||
// ByID orders the results by the id field.
|
// ByID orders the results by the id field.
|
||||||
|
|||||||
@@ -11,468 +11,468 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ID filters vertices based on their ID field.
|
// ID filters vertices based on their ID field.
|
||||||
func ID(id int64) predicate.ApiKey {
|
func ID(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldID, id))
|
return predicate.APIKey(sql.FieldEQ(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDEQ applies the EQ predicate on the ID field.
|
// IDEQ applies the EQ predicate on the ID field.
|
||||||
func IDEQ(id int64) predicate.ApiKey {
|
func IDEQ(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldID, id))
|
return predicate.APIKey(sql.FieldEQ(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDNEQ applies the NEQ predicate on the ID field.
|
// IDNEQ applies the NEQ predicate on the ID field.
|
||||||
func IDNEQ(id int64) predicate.ApiKey {
|
func IDNEQ(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldID, id))
|
return predicate.APIKey(sql.FieldNEQ(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDIn applies the In predicate on the ID field.
|
// IDIn applies the In predicate on the ID field.
|
||||||
func IDIn(ids ...int64) predicate.ApiKey {
|
func IDIn(ids ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldID, ids...))
|
return predicate.APIKey(sql.FieldIn(FieldID, ids...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDNotIn applies the NotIn predicate on the ID field.
|
// IDNotIn applies the NotIn predicate on the ID field.
|
||||||
func IDNotIn(ids ...int64) predicate.ApiKey {
|
func IDNotIn(ids ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldID, ids...))
|
return predicate.APIKey(sql.FieldNotIn(FieldID, ids...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDGT applies the GT predicate on the ID field.
|
// IDGT applies the GT predicate on the ID field.
|
||||||
func IDGT(id int64) predicate.ApiKey {
|
func IDGT(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldID, id))
|
return predicate.APIKey(sql.FieldGT(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDGTE applies the GTE predicate on the ID field.
|
// IDGTE applies the GTE predicate on the ID field.
|
||||||
func IDGTE(id int64) predicate.ApiKey {
|
func IDGTE(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldID, id))
|
return predicate.APIKey(sql.FieldGTE(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDLT applies the LT predicate on the ID field.
|
// IDLT applies the LT predicate on the ID field.
|
||||||
func IDLT(id int64) predicate.ApiKey {
|
func IDLT(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldID, id))
|
return predicate.APIKey(sql.FieldLT(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDLTE applies the LTE predicate on the ID field.
|
// IDLTE applies the LTE predicate on the ID field.
|
||||||
func IDLTE(id int64) predicate.ApiKey {
|
func IDLTE(id int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldID, id))
|
return predicate.APIKey(sql.FieldLTE(FieldID, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||||
func CreatedAt(v time.Time) predicate.ApiKey {
|
func CreatedAt(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||||
func UpdatedAt(v time.Time) predicate.ApiKey {
|
func UpdatedAt(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
|
// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
|
||||||
func DeletedAt(v time.Time) predicate.ApiKey {
|
func DeletedAt(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
|
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
|
||||||
func UserID(v int64) predicate.ApiKey {
|
func UserID(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldUserID, v))
|
return predicate.APIKey(sql.FieldEQ(FieldUserID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key applies equality check predicate on the "key" field. It's identical to KeyEQ.
|
// Key applies equality check predicate on the "key" field. It's identical to KeyEQ.
|
||||||
func Key(v string) predicate.ApiKey {
|
func Key(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldKey, v))
|
return predicate.APIKey(sql.FieldEQ(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
|
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
|
||||||
func Name(v string) predicate.ApiKey {
|
func Name(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldName, v))
|
return predicate.APIKey(sql.FieldEQ(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
|
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
|
||||||
func GroupID(v int64) predicate.ApiKey {
|
func GroupID(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldGroupID, v))
|
return predicate.APIKey(sql.FieldEQ(FieldGroupID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
|
// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
|
||||||
func Status(v string) predicate.ApiKey {
|
func Status(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldStatus, v))
|
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||||
func CreatedAtEQ(v time.Time) predicate.ApiKey {
|
func CreatedAtEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||||
func CreatedAtNEQ(v time.Time) predicate.ApiKey {
|
func CreatedAtNEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||||
func CreatedAtIn(vs ...time.Time) predicate.ApiKey {
|
func CreatedAtIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldCreatedAt, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldCreatedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||||
func CreatedAtNotIn(vs ...time.Time) predicate.ApiKey {
|
func CreatedAtNotIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldCreatedAt, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||||
func CreatedAtGT(v time.Time) predicate.ApiKey {
|
func CreatedAtGT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldGT(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||||
func CreatedAtGTE(v time.Time) predicate.ApiKey {
|
func CreatedAtGTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldGTE(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||||
func CreatedAtLT(v time.Time) predicate.ApiKey {
|
func CreatedAtLT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldLT(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||||
func CreatedAtLTE(v time.Time) predicate.ApiKey {
|
func CreatedAtLTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldCreatedAt, v))
|
return predicate.APIKey(sql.FieldLTE(FieldCreatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||||
func UpdatedAtEQ(v time.Time) predicate.ApiKey {
|
func UpdatedAtEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||||
func UpdatedAtNEQ(v time.Time) predicate.ApiKey {
|
func UpdatedAtNEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||||
func UpdatedAtIn(vs ...time.Time) predicate.ApiKey {
|
func UpdatedAtIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldUpdatedAt, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||||
func UpdatedAtNotIn(vs ...time.Time) predicate.ApiKey {
|
func UpdatedAtNotIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||||
func UpdatedAtGT(v time.Time) predicate.ApiKey {
|
func UpdatedAtGT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldGT(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||||
func UpdatedAtGTE(v time.Time) predicate.ApiKey {
|
func UpdatedAtGTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldGTE(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||||
func UpdatedAtLT(v time.Time) predicate.ApiKey {
|
func UpdatedAtLT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldLT(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||||
func UpdatedAtLTE(v time.Time) predicate.ApiKey {
|
func UpdatedAtLTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldUpdatedAt, v))
|
return predicate.APIKey(sql.FieldLTE(FieldUpdatedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
|
// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
|
||||||
func DeletedAtEQ(v time.Time) predicate.ApiKey {
|
func DeletedAtEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldEQ(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
|
// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
|
||||||
func DeletedAtNEQ(v time.Time) predicate.ApiKey {
|
func DeletedAtNEQ(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtIn applies the In predicate on the "deleted_at" field.
|
// DeletedAtIn applies the In predicate on the "deleted_at" field.
|
||||||
func DeletedAtIn(vs ...time.Time) predicate.ApiKey {
|
func DeletedAtIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldDeletedAt, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldDeletedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
|
// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
|
||||||
func DeletedAtNotIn(vs ...time.Time) predicate.ApiKey {
|
func DeletedAtNotIn(vs ...time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldDeletedAt, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldDeletedAt, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtGT applies the GT predicate on the "deleted_at" field.
|
// DeletedAtGT applies the GT predicate on the "deleted_at" field.
|
||||||
func DeletedAtGT(v time.Time) predicate.ApiKey {
|
func DeletedAtGT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldGT(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
|
// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
|
||||||
func DeletedAtGTE(v time.Time) predicate.ApiKey {
|
func DeletedAtGTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldGTE(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtLT applies the LT predicate on the "deleted_at" field.
|
// DeletedAtLT applies the LT predicate on the "deleted_at" field.
|
||||||
func DeletedAtLT(v time.Time) predicate.ApiKey {
|
func DeletedAtLT(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldLT(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
|
// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
|
||||||
func DeletedAtLTE(v time.Time) predicate.ApiKey {
|
func DeletedAtLTE(v time.Time) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldDeletedAt, v))
|
return predicate.APIKey(sql.FieldLTE(FieldDeletedAt, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
|
// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
|
||||||
func DeletedAtIsNil() predicate.ApiKey {
|
func DeletedAtIsNil() predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIsNull(FieldDeletedAt))
|
return predicate.APIKey(sql.FieldIsNull(FieldDeletedAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
|
// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
|
||||||
func DeletedAtNotNil() predicate.ApiKey {
|
func DeletedAtNotNil() predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotNull(FieldDeletedAt))
|
return predicate.APIKey(sql.FieldNotNull(FieldDeletedAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserIDEQ applies the EQ predicate on the "user_id" field.
|
// UserIDEQ applies the EQ predicate on the "user_id" field.
|
||||||
func UserIDEQ(v int64) predicate.ApiKey {
|
func UserIDEQ(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldUserID, v))
|
return predicate.APIKey(sql.FieldEQ(FieldUserID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
|
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
|
||||||
func UserIDNEQ(v int64) predicate.ApiKey {
|
func UserIDNEQ(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldUserID, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldUserID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserIDIn applies the In predicate on the "user_id" field.
|
// UserIDIn applies the In predicate on the "user_id" field.
|
||||||
func UserIDIn(vs ...int64) predicate.ApiKey {
|
func UserIDIn(vs ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldUserID, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldUserID, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
|
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
|
||||||
func UserIDNotIn(vs ...int64) predicate.ApiKey {
|
func UserIDNotIn(vs ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldUserID, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldUserID, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyEQ applies the EQ predicate on the "key" field.
|
// KeyEQ applies the EQ predicate on the "key" field.
|
||||||
func KeyEQ(v string) predicate.ApiKey {
|
func KeyEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldKey, v))
|
return predicate.APIKey(sql.FieldEQ(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyNEQ applies the NEQ predicate on the "key" field.
|
// KeyNEQ applies the NEQ predicate on the "key" field.
|
||||||
func KeyNEQ(v string) predicate.ApiKey {
|
func KeyNEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldKey, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyIn applies the In predicate on the "key" field.
|
// KeyIn applies the In predicate on the "key" field.
|
||||||
func KeyIn(vs ...string) predicate.ApiKey {
|
func KeyIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldKey, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldKey, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyNotIn applies the NotIn predicate on the "key" field.
|
// KeyNotIn applies the NotIn predicate on the "key" field.
|
||||||
func KeyNotIn(vs ...string) predicate.ApiKey {
|
func KeyNotIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldKey, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldKey, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyGT applies the GT predicate on the "key" field.
|
// KeyGT applies the GT predicate on the "key" field.
|
||||||
func KeyGT(v string) predicate.ApiKey {
|
func KeyGT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldKey, v))
|
return predicate.APIKey(sql.FieldGT(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyGTE applies the GTE predicate on the "key" field.
|
// KeyGTE applies the GTE predicate on the "key" field.
|
||||||
func KeyGTE(v string) predicate.ApiKey {
|
func KeyGTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldKey, v))
|
return predicate.APIKey(sql.FieldGTE(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyLT applies the LT predicate on the "key" field.
|
// KeyLT applies the LT predicate on the "key" field.
|
||||||
func KeyLT(v string) predicate.ApiKey {
|
func KeyLT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldKey, v))
|
return predicate.APIKey(sql.FieldLT(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyLTE applies the LTE predicate on the "key" field.
|
// KeyLTE applies the LTE predicate on the "key" field.
|
||||||
func KeyLTE(v string) predicate.ApiKey {
|
func KeyLTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldKey, v))
|
return predicate.APIKey(sql.FieldLTE(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyContains applies the Contains predicate on the "key" field.
|
// KeyContains applies the Contains predicate on the "key" field.
|
||||||
func KeyContains(v string) predicate.ApiKey {
|
func KeyContains(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContains(FieldKey, v))
|
return predicate.APIKey(sql.FieldContains(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyHasPrefix applies the HasPrefix predicate on the "key" field.
|
// KeyHasPrefix applies the HasPrefix predicate on the "key" field.
|
||||||
func KeyHasPrefix(v string) predicate.ApiKey {
|
func KeyHasPrefix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasPrefix(FieldKey, v))
|
return predicate.APIKey(sql.FieldHasPrefix(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyHasSuffix applies the HasSuffix predicate on the "key" field.
|
// KeyHasSuffix applies the HasSuffix predicate on the "key" field.
|
||||||
func KeyHasSuffix(v string) predicate.ApiKey {
|
func KeyHasSuffix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasSuffix(FieldKey, v))
|
return predicate.APIKey(sql.FieldHasSuffix(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyEqualFold applies the EqualFold predicate on the "key" field.
|
// KeyEqualFold applies the EqualFold predicate on the "key" field.
|
||||||
func KeyEqualFold(v string) predicate.ApiKey {
|
func KeyEqualFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEqualFold(FieldKey, v))
|
return predicate.APIKey(sql.FieldEqualFold(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyContainsFold applies the ContainsFold predicate on the "key" field.
|
// KeyContainsFold applies the ContainsFold predicate on the "key" field.
|
||||||
func KeyContainsFold(v string) predicate.ApiKey {
|
func KeyContainsFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContainsFold(FieldKey, v))
|
return predicate.APIKey(sql.FieldContainsFold(FieldKey, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameEQ applies the EQ predicate on the "name" field.
|
// NameEQ applies the EQ predicate on the "name" field.
|
||||||
func NameEQ(v string) predicate.ApiKey {
|
func NameEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldName, v))
|
return predicate.APIKey(sql.FieldEQ(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameNEQ applies the NEQ predicate on the "name" field.
|
// NameNEQ applies the NEQ predicate on the "name" field.
|
||||||
func NameNEQ(v string) predicate.ApiKey {
|
func NameNEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldName, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameIn applies the In predicate on the "name" field.
|
// NameIn applies the In predicate on the "name" field.
|
||||||
func NameIn(vs ...string) predicate.ApiKey {
|
func NameIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldName, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldName, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameNotIn applies the NotIn predicate on the "name" field.
|
// NameNotIn applies the NotIn predicate on the "name" field.
|
||||||
func NameNotIn(vs ...string) predicate.ApiKey {
|
func NameNotIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldName, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldName, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameGT applies the GT predicate on the "name" field.
|
// NameGT applies the GT predicate on the "name" field.
|
||||||
func NameGT(v string) predicate.ApiKey {
|
func NameGT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldName, v))
|
return predicate.APIKey(sql.FieldGT(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameGTE applies the GTE predicate on the "name" field.
|
// NameGTE applies the GTE predicate on the "name" field.
|
||||||
func NameGTE(v string) predicate.ApiKey {
|
func NameGTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldName, v))
|
return predicate.APIKey(sql.FieldGTE(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameLT applies the LT predicate on the "name" field.
|
// NameLT applies the LT predicate on the "name" field.
|
||||||
func NameLT(v string) predicate.ApiKey {
|
func NameLT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldName, v))
|
return predicate.APIKey(sql.FieldLT(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameLTE applies the LTE predicate on the "name" field.
|
// NameLTE applies the LTE predicate on the "name" field.
|
||||||
func NameLTE(v string) predicate.ApiKey {
|
func NameLTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldName, v))
|
return predicate.APIKey(sql.FieldLTE(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameContains applies the Contains predicate on the "name" field.
|
// NameContains applies the Contains predicate on the "name" field.
|
||||||
func NameContains(v string) predicate.ApiKey {
|
func NameContains(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContains(FieldName, v))
|
return predicate.APIKey(sql.FieldContains(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
|
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
|
||||||
func NameHasPrefix(v string) predicate.ApiKey {
|
func NameHasPrefix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasPrefix(FieldName, v))
|
return predicate.APIKey(sql.FieldHasPrefix(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
|
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
|
||||||
func NameHasSuffix(v string) predicate.ApiKey {
|
func NameHasSuffix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasSuffix(FieldName, v))
|
return predicate.APIKey(sql.FieldHasSuffix(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameEqualFold applies the EqualFold predicate on the "name" field.
|
// NameEqualFold applies the EqualFold predicate on the "name" field.
|
||||||
func NameEqualFold(v string) predicate.ApiKey {
|
func NameEqualFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEqualFold(FieldName, v))
|
return predicate.APIKey(sql.FieldEqualFold(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameContainsFold applies the ContainsFold predicate on the "name" field.
|
// NameContainsFold applies the ContainsFold predicate on the "name" field.
|
||||||
func NameContainsFold(v string) predicate.ApiKey {
|
func NameContainsFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContainsFold(FieldName, v))
|
return predicate.APIKey(sql.FieldContainsFold(FieldName, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDEQ applies the EQ predicate on the "group_id" field.
|
// GroupIDEQ applies the EQ predicate on the "group_id" field.
|
||||||
func GroupIDEQ(v int64) predicate.ApiKey {
|
func GroupIDEQ(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldGroupID, v))
|
return predicate.APIKey(sql.FieldEQ(FieldGroupID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
|
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
|
||||||
func GroupIDNEQ(v int64) predicate.ApiKey {
|
func GroupIDNEQ(v int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldGroupID, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldGroupID, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDIn applies the In predicate on the "group_id" field.
|
// GroupIDIn applies the In predicate on the "group_id" field.
|
||||||
func GroupIDIn(vs ...int64) predicate.ApiKey {
|
func GroupIDIn(vs ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldGroupID, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldGroupID, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
|
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
|
||||||
func GroupIDNotIn(vs ...int64) predicate.ApiKey {
|
func GroupIDNotIn(vs ...int64) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldGroupID, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldGroupID, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDIsNil applies the IsNil predicate on the "group_id" field.
|
// GroupIDIsNil applies the IsNil predicate on the "group_id" field.
|
||||||
func GroupIDIsNil() predicate.ApiKey {
|
func GroupIDIsNil() predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIsNull(FieldGroupID))
|
return predicate.APIKey(sql.FieldIsNull(FieldGroupID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupIDNotNil applies the NotNil predicate on the "group_id" field.
|
// GroupIDNotNil applies the NotNil predicate on the "group_id" field.
|
||||||
func GroupIDNotNil() predicate.ApiKey {
|
func GroupIDNotNil() predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotNull(FieldGroupID))
|
return predicate.APIKey(sql.FieldNotNull(FieldGroupID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusEQ applies the EQ predicate on the "status" field.
|
// StatusEQ applies the EQ predicate on the "status" field.
|
||||||
func StatusEQ(v string) predicate.ApiKey {
|
func StatusEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEQ(FieldStatus, v))
|
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusNEQ applies the NEQ predicate on the "status" field.
|
// StatusNEQ applies the NEQ predicate on the "status" field.
|
||||||
func StatusNEQ(v string) predicate.ApiKey {
|
func StatusNEQ(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNEQ(FieldStatus, v))
|
return predicate.APIKey(sql.FieldNEQ(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusIn applies the In predicate on the "status" field.
|
// StatusIn applies the In predicate on the "status" field.
|
||||||
func StatusIn(vs ...string) predicate.ApiKey {
|
func StatusIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldIn(FieldStatus, vs...))
|
return predicate.APIKey(sql.FieldIn(FieldStatus, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusNotIn applies the NotIn predicate on the "status" field.
|
// StatusNotIn applies the NotIn predicate on the "status" field.
|
||||||
func StatusNotIn(vs ...string) predicate.ApiKey {
|
func StatusNotIn(vs ...string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldNotIn(FieldStatus, vs...))
|
return predicate.APIKey(sql.FieldNotIn(FieldStatus, vs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusGT applies the GT predicate on the "status" field.
|
// StatusGT applies the GT predicate on the "status" field.
|
||||||
func StatusGT(v string) predicate.ApiKey {
|
func StatusGT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGT(FieldStatus, v))
|
return predicate.APIKey(sql.FieldGT(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusGTE applies the GTE predicate on the "status" field.
|
// StatusGTE applies the GTE predicate on the "status" field.
|
||||||
func StatusGTE(v string) predicate.ApiKey {
|
func StatusGTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldGTE(FieldStatus, v))
|
return predicate.APIKey(sql.FieldGTE(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusLT applies the LT predicate on the "status" field.
|
// StatusLT applies the LT predicate on the "status" field.
|
||||||
func StatusLT(v string) predicate.ApiKey {
|
func StatusLT(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLT(FieldStatus, v))
|
return predicate.APIKey(sql.FieldLT(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusLTE applies the LTE predicate on the "status" field.
|
// StatusLTE applies the LTE predicate on the "status" field.
|
||||||
func StatusLTE(v string) predicate.ApiKey {
|
func StatusLTE(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldLTE(FieldStatus, v))
|
return predicate.APIKey(sql.FieldLTE(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusContains applies the Contains predicate on the "status" field.
|
// StatusContains applies the Contains predicate on the "status" field.
|
||||||
func StatusContains(v string) predicate.ApiKey {
|
func StatusContains(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContains(FieldStatus, v))
|
return predicate.APIKey(sql.FieldContains(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusHasPrefix applies the HasPrefix predicate on the "status" field.
|
// StatusHasPrefix applies the HasPrefix predicate on the "status" field.
|
||||||
func StatusHasPrefix(v string) predicate.ApiKey {
|
func StatusHasPrefix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasPrefix(FieldStatus, v))
|
return predicate.APIKey(sql.FieldHasPrefix(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusHasSuffix applies the HasSuffix predicate on the "status" field.
|
// StatusHasSuffix applies the HasSuffix predicate on the "status" field.
|
||||||
func StatusHasSuffix(v string) predicate.ApiKey {
|
func StatusHasSuffix(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldHasSuffix(FieldStatus, v))
|
return predicate.APIKey(sql.FieldHasSuffix(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusEqualFold applies the EqualFold predicate on the "status" field.
|
// StatusEqualFold applies the EqualFold predicate on the "status" field.
|
||||||
func StatusEqualFold(v string) predicate.ApiKey {
|
func StatusEqualFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldEqualFold(FieldStatus, v))
|
return predicate.APIKey(sql.FieldEqualFold(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusContainsFold applies the ContainsFold predicate on the "status" field.
|
// StatusContainsFold applies the ContainsFold predicate on the "status" field.
|
||||||
func StatusContainsFold(v string) predicate.ApiKey {
|
func StatusContainsFold(v string) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.FieldContainsFold(FieldStatus, v))
|
return predicate.APIKey(sql.FieldContainsFold(FieldStatus, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasUser applies the HasEdge predicate on the "user" edge.
|
// HasUser applies the HasEdge predicate on the "user" edge.
|
||||||
func HasUser() predicate.ApiKey {
|
func HasUser() predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
sqlgraph.From(Table, FieldID),
|
sqlgraph.From(Table, FieldID),
|
||||||
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
||||||
@@ -482,8 +482,8 @@ func HasUser() predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
|
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
|
||||||
func HasUserWith(preds ...predicate.User) predicate.ApiKey {
|
func HasUserWith(preds ...predicate.User) predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := newUserStep()
|
step := newUserStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
for _, p := range preds {
|
for _, p := range preds {
|
||||||
@@ -494,8 +494,8 @@ func HasUserWith(preds ...predicate.User) predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasGroup applies the HasEdge predicate on the "group" edge.
|
// HasGroup applies the HasEdge predicate on the "group" edge.
|
||||||
func HasGroup() predicate.ApiKey {
|
func HasGroup() predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
sqlgraph.From(Table, FieldID),
|
sqlgraph.From(Table, FieldID),
|
||||||
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
|
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
|
||||||
@@ -505,8 +505,8 @@ func HasGroup() predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
|
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
|
||||||
func HasGroupWith(preds ...predicate.Group) predicate.ApiKey {
|
func HasGroupWith(preds ...predicate.Group) predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := newGroupStep()
|
step := newGroupStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
for _, p := range preds {
|
for _, p := range preds {
|
||||||
@@ -517,8 +517,8 @@ func HasGroupWith(preds ...predicate.Group) predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasUsageLogs applies the HasEdge predicate on the "usage_logs" edge.
|
// HasUsageLogs applies the HasEdge predicate on the "usage_logs" edge.
|
||||||
func HasUsageLogs() predicate.ApiKey {
|
func HasUsageLogs() predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
sqlgraph.From(Table, FieldID),
|
sqlgraph.From(Table, FieldID),
|
||||||
sqlgraph.Edge(sqlgraph.O2M, false, UsageLogsTable, UsageLogsColumn),
|
sqlgraph.Edge(sqlgraph.O2M, false, UsageLogsTable, UsageLogsColumn),
|
||||||
@@ -528,8 +528,8 @@ func HasUsageLogs() predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasUsageLogsWith applies the HasEdge predicate on the "usage_logs" edge with a given conditions (other predicates).
|
// HasUsageLogsWith applies the HasEdge predicate on the "usage_logs" edge with a given conditions (other predicates).
|
||||||
func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.ApiKey {
|
func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.APIKey {
|
||||||
return predicate.ApiKey(func(s *sql.Selector) {
|
return predicate.APIKey(func(s *sql.Selector) {
|
||||||
step := newUsageLogsStep()
|
step := newUsageLogsStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
for _, p := range preds {
|
for _, p := range preds {
|
||||||
@@ -540,16 +540,16 @@ func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// And groups predicates with the AND operator between them.
|
// And groups predicates with the AND operator between them.
|
||||||
func And(predicates ...predicate.ApiKey) predicate.ApiKey {
|
func And(predicates ...predicate.APIKey) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.AndPredicates(predicates...))
|
return predicate.APIKey(sql.AndPredicates(predicates...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or groups predicates with the OR operator between them.
|
// Or groups predicates with the OR operator between them.
|
||||||
func Or(predicates ...predicate.ApiKey) predicate.ApiKey {
|
func Or(predicates ...predicate.APIKey) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.OrPredicates(predicates...))
|
return predicate.APIKey(sql.OrPredicates(predicates...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not applies the not operator on the given predicate.
|
// Not applies the not operator on the given predicate.
|
||||||
func Not(p predicate.ApiKey) predicate.ApiKey {
|
func Not(p predicate.APIKey) predicate.APIKey {
|
||||||
return predicate.ApiKey(sql.NotPredicates(p))
|
return predicate.APIKey(sql.NotPredicates(p))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,22 +17,22 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKeyCreate is the builder for creating a ApiKey entity.
|
// APIKeyCreate is the builder for creating a APIKey entity.
|
||||||
type ApiKeyCreate struct {
|
type APIKeyCreate struct {
|
||||||
config
|
config
|
||||||
mutation *ApiKeyMutation
|
mutation *APIKeyMutation
|
||||||
hooks []Hook
|
hooks []Hook
|
||||||
conflict []sql.ConflictOption
|
conflict []sql.ConflictOption
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCreatedAt sets the "created_at" field.
|
// SetCreatedAt sets the "created_at" field.
|
||||||
func (_c *ApiKeyCreate) SetCreatedAt(v time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetCreatedAt(v time.Time) *APIKeyCreate {
|
||||||
_c.mutation.SetCreatedAt(v)
|
_c.mutation.SetCreatedAt(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||||
func (_c *ApiKeyCreate) SetNillableCreatedAt(v *time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetNillableCreatedAt(v *time.Time) *APIKeyCreate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_c.SetCreatedAt(*v)
|
_c.SetCreatedAt(*v)
|
||||||
}
|
}
|
||||||
@@ -40,13 +40,13 @@ func (_c *ApiKeyCreate) SetNillableCreatedAt(v *time.Time) *ApiKeyCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (_c *ApiKeyCreate) SetUpdatedAt(v time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetUpdatedAt(v time.Time) *APIKeyCreate {
|
||||||
_c.mutation.SetUpdatedAt(v)
|
_c.mutation.SetUpdatedAt(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||||
func (_c *ApiKeyCreate) SetNillableUpdatedAt(v *time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetNillableUpdatedAt(v *time.Time) *APIKeyCreate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_c.SetUpdatedAt(*v)
|
_c.SetUpdatedAt(*v)
|
||||||
}
|
}
|
||||||
@@ -54,13 +54,13 @@ func (_c *ApiKeyCreate) SetNillableUpdatedAt(v *time.Time) *ApiKeyCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (_c *ApiKeyCreate) SetDeletedAt(v time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetDeletedAt(v time.Time) *APIKeyCreate {
|
||||||
_c.mutation.SetDeletedAt(v)
|
_c.mutation.SetDeletedAt(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||||
func (_c *ApiKeyCreate) SetNillableDeletedAt(v *time.Time) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetNillableDeletedAt(v *time.Time) *APIKeyCreate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_c.SetDeletedAt(*v)
|
_c.SetDeletedAt(*v)
|
||||||
}
|
}
|
||||||
@@ -68,31 +68,31 @@ func (_c *ApiKeyCreate) SetNillableDeletedAt(v *time.Time) *ApiKeyCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (_c *ApiKeyCreate) SetUserID(v int64) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetUserID(v int64) *APIKeyCreate {
|
||||||
_c.mutation.SetUserID(v)
|
_c.mutation.SetUserID(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (_c *ApiKeyCreate) SetKey(v string) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetKey(v string) *APIKeyCreate {
|
||||||
_c.mutation.SetKey(v)
|
_c.mutation.SetKey(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (_c *ApiKeyCreate) SetName(v string) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetName(v string) *APIKeyCreate {
|
||||||
_c.mutation.SetName(v)
|
_c.mutation.SetName(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (_c *ApiKeyCreate) SetGroupID(v int64) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetGroupID(v int64) *APIKeyCreate {
|
||||||
_c.mutation.SetGroupID(v)
|
_c.mutation.SetGroupID(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
||||||
func (_c *ApiKeyCreate) SetNillableGroupID(v *int64) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetNillableGroupID(v *int64) *APIKeyCreate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_c.SetGroupID(*v)
|
_c.SetGroupID(*v)
|
||||||
}
|
}
|
||||||
@@ -100,13 +100,13 @@ func (_c *ApiKeyCreate) SetNillableGroupID(v *int64) *ApiKeyCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (_c *ApiKeyCreate) SetStatus(v string) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetStatus(v string) *APIKeyCreate {
|
||||||
_c.mutation.SetStatus(v)
|
_c.mutation.SetStatus(v)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableStatus sets the "status" field if the given value is not nil.
|
// SetNillableStatus sets the "status" field if the given value is not nil.
|
||||||
func (_c *ApiKeyCreate) SetNillableStatus(v *string) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetNillableStatus(v *string) *APIKeyCreate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_c.SetStatus(*v)
|
_c.SetStatus(*v)
|
||||||
}
|
}
|
||||||
@@ -114,23 +114,23 @@ func (_c *ApiKeyCreate) SetNillableStatus(v *string) *ApiKeyCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUser sets the "user" edge to the User entity.
|
// SetUser sets the "user" edge to the User entity.
|
||||||
func (_c *ApiKeyCreate) SetUser(v *User) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetUser(v *User) *APIKeyCreate {
|
||||||
return _c.SetUserID(v.ID)
|
return _c.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroup sets the "group" edge to the Group entity.
|
// SetGroup sets the "group" edge to the Group entity.
|
||||||
func (_c *ApiKeyCreate) SetGroup(v *Group) *ApiKeyCreate {
|
func (_c *APIKeyCreate) SetGroup(v *Group) *APIKeyCreate {
|
||||||
return _c.SetGroupID(v.ID)
|
return _c.SetGroupID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
||||||
func (_c *ApiKeyCreate) AddUsageLogIDs(ids ...int64) *ApiKeyCreate {
|
func (_c *APIKeyCreate) AddUsageLogIDs(ids ...int64) *APIKeyCreate {
|
||||||
_c.mutation.AddUsageLogIDs(ids...)
|
_c.mutation.AddUsageLogIDs(ids...)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
||||||
func (_c *ApiKeyCreate) AddUsageLogs(v ...*UsageLog) *ApiKeyCreate {
|
func (_c *APIKeyCreate) AddUsageLogs(v ...*UsageLog) *APIKeyCreate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -138,13 +138,13 @@ func (_c *ApiKeyCreate) AddUsageLogs(v ...*UsageLog) *ApiKeyCreate {
|
|||||||
return _c.AddUsageLogIDs(ids...)
|
return _c.AddUsageLogIDs(ids...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutation returns the ApiKeyMutation object of the builder.
|
// Mutation returns the APIKeyMutation object of the builder.
|
||||||
func (_c *ApiKeyCreate) Mutation() *ApiKeyMutation {
|
func (_c *APIKeyCreate) Mutation() *APIKeyMutation {
|
||||||
return _c.mutation
|
return _c.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save creates the ApiKey in the database.
|
// Save creates the APIKey in the database.
|
||||||
func (_c *ApiKeyCreate) Save(ctx context.Context) (*ApiKey, error) {
|
func (_c *APIKeyCreate) Save(ctx context.Context) (*APIKey, error) {
|
||||||
if err := _c.defaults(); err != nil {
|
if err := _c.defaults(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ func (_c *ApiKeyCreate) Save(ctx context.Context) (*ApiKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveX calls Save and panics if Save returns an error.
|
// SaveX calls Save and panics if Save returns an error.
|
||||||
func (_c *ApiKeyCreate) SaveX(ctx context.Context) *ApiKey {
|
func (_c *APIKeyCreate) SaveX(ctx context.Context) *APIKey {
|
||||||
v, err := _c.Save(ctx)
|
v, err := _c.Save(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -161,20 +161,20 @@ func (_c *ApiKeyCreate) SaveX(ctx context.Context) *ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (_c *ApiKeyCreate) Exec(ctx context.Context) error {
|
func (_c *APIKeyCreate) Exec(ctx context.Context) error {
|
||||||
_, err := _c.Save(ctx)
|
_, err := _c.Save(ctx)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_c *ApiKeyCreate) ExecX(ctx context.Context) {
|
func (_c *APIKeyCreate) ExecX(ctx context.Context) {
|
||||||
if err := _c.Exec(ctx); err != nil {
|
if err := _c.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults sets the default values of the builder before save.
|
// defaults sets the default values of the builder before save.
|
||||||
func (_c *ApiKeyCreate) defaults() error {
|
func (_c *APIKeyCreate) defaults() error {
|
||||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||||
if apikey.DefaultCreatedAt == nil {
|
if apikey.DefaultCreatedAt == nil {
|
||||||
return fmt.Errorf("ent: uninitialized apikey.DefaultCreatedAt (forgotten import ent/runtime?)")
|
return fmt.Errorf("ent: uninitialized apikey.DefaultCreatedAt (forgotten import ent/runtime?)")
|
||||||
@@ -197,47 +197,47 @@ func (_c *ApiKeyCreate) defaults() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check runs all checks and user-defined validators on the builder.
|
// check runs all checks and user-defined validators on the builder.
|
||||||
func (_c *ApiKeyCreate) check() error {
|
func (_c *APIKeyCreate) check() error {
|
||||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ApiKey.created_at"`)}
|
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "APIKey.created_at"`)}
|
||||||
}
|
}
|
||||||
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
||||||
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ApiKey.updated_at"`)}
|
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "APIKey.updated_at"`)}
|
||||||
}
|
}
|
||||||
if _, ok := _c.mutation.UserID(); !ok {
|
if _, ok := _c.mutation.UserID(); !ok {
|
||||||
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "ApiKey.user_id"`)}
|
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "APIKey.user_id"`)}
|
||||||
}
|
}
|
||||||
if _, ok := _c.mutation.Key(); !ok {
|
if _, ok := _c.mutation.Key(); !ok {
|
||||||
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "ApiKey.key"`)}
|
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "APIKey.key"`)}
|
||||||
}
|
}
|
||||||
if v, ok := _c.mutation.Key(); ok {
|
if v, ok := _c.mutation.Key(); ok {
|
||||||
if err := apikey.KeyValidator(v); err != nil {
|
if err := apikey.KeyValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
|
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := _c.mutation.Name(); !ok {
|
if _, ok := _c.mutation.Name(); !ok {
|
||||||
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ApiKey.name"`)}
|
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "APIKey.name"`)}
|
||||||
}
|
}
|
||||||
if v, ok := _c.mutation.Name(); ok {
|
if v, ok := _c.mutation.Name(); ok {
|
||||||
if err := apikey.NameValidator(v); err != nil {
|
if err := apikey.NameValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
|
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := _c.mutation.Status(); !ok {
|
if _, ok := _c.mutation.Status(); !ok {
|
||||||
return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "ApiKey.status"`)}
|
return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "APIKey.status"`)}
|
||||||
}
|
}
|
||||||
if v, ok := _c.mutation.Status(); ok {
|
if v, ok := _c.mutation.Status(); ok {
|
||||||
if err := apikey.StatusValidator(v); err != nil {
|
if err := apikey.StatusValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
|
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(_c.mutation.UserIDs()) == 0 {
|
if len(_c.mutation.UserIDs()) == 0 {
|
||||||
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "ApiKey.user"`)}
|
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "APIKey.user"`)}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *ApiKeyCreate) sqlSave(ctx context.Context) (*ApiKey, error) {
|
func (_c *APIKeyCreate) sqlSave(ctx context.Context) (*APIKey, error) {
|
||||||
if err := _c.check(); err != nil {
|
if err := _c.check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -255,9 +255,9 @@ func (_c *ApiKeyCreate) sqlSave(ctx context.Context) (*ApiKey, error) {
|
|||||||
return _node, nil
|
return _node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
|
func (_c *APIKeyCreate) createSpec() (*APIKey, *sqlgraph.CreateSpec) {
|
||||||
var (
|
var (
|
||||||
_node = &ApiKey{config: _c.config}
|
_node = &APIKey{config: _c.config}
|
||||||
_spec = sqlgraph.NewCreateSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
_spec = sqlgraph.NewCreateSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
||||||
)
|
)
|
||||||
_spec.OnConflict = _c.conflict
|
_spec.OnConflict = _c.conflict
|
||||||
@@ -341,7 +341,7 @@ func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
|
|||||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||||
// of the `INSERT` statement. For example:
|
// of the `INSERT` statement. For example:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// SetCreatedAt(v).
|
// SetCreatedAt(v).
|
||||||
// OnConflict(
|
// OnConflict(
|
||||||
// // Update the row with the new values
|
// // Update the row with the new values
|
||||||
@@ -350,13 +350,13 @@ func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
|
|||||||
// ).
|
// ).
|
||||||
// // Override some of the fields with custom
|
// // Override some of the fields with custom
|
||||||
// // update values.
|
// // update values.
|
||||||
// Update(func(u *ent.ApiKeyUpsert) {
|
// Update(func(u *ent.APIKeyUpsert) {
|
||||||
// SetCreatedAt(v+v).
|
// SetCreatedAt(v+v).
|
||||||
// }).
|
// }).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (_c *ApiKeyCreate) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertOne {
|
func (_c *APIKeyCreate) OnConflict(opts ...sql.ConflictOption) *APIKeyUpsertOne {
|
||||||
_c.conflict = opts
|
_c.conflict = opts
|
||||||
return &ApiKeyUpsertOne{
|
return &APIKeyUpsertOne{
|
||||||
create: _c,
|
create: _c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,121 +364,121 @@ func (_c *ApiKeyCreate) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertOne
|
|||||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||||
// as conflict target. Using this option is equivalent to using:
|
// as conflict target. Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(sql.ConflictColumns(columns...)).
|
// OnConflict(sql.ConflictColumns(columns...)).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (_c *ApiKeyCreate) OnConflictColumns(columns ...string) *ApiKeyUpsertOne {
|
func (_c *APIKeyCreate) OnConflictColumns(columns ...string) *APIKeyUpsertOne {
|
||||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||||
return &ApiKeyUpsertOne{
|
return &APIKeyUpsertOne{
|
||||||
create: _c,
|
create: _c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// ApiKeyUpsertOne is the builder for "upsert"-ing
|
// APIKeyUpsertOne is the builder for "upsert"-ing
|
||||||
// one ApiKey node.
|
// one APIKey node.
|
||||||
ApiKeyUpsertOne struct {
|
APIKeyUpsertOne struct {
|
||||||
create *ApiKeyCreate
|
create *APIKeyCreate
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyUpsert is the "OnConflict" setter.
|
// APIKeyUpsert is the "OnConflict" setter.
|
||||||
ApiKeyUpsert struct {
|
APIKeyUpsert struct {
|
||||||
*sql.UpdateSet
|
*sql.UpdateSet
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (u *ApiKeyUpsert) SetUpdatedAt(v time.Time) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetUpdatedAt(v time.Time) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldUpdatedAt, v)
|
u.Set(apikey.FieldUpdatedAt, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateUpdatedAt() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateUpdatedAt() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldUpdatedAt)
|
u.SetExcluded(apikey.FieldUpdatedAt)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsert) SetDeletedAt(v time.Time) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetDeletedAt(v time.Time) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldDeletedAt, v)
|
u.Set(apikey.FieldDeletedAt, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateDeletedAt() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateDeletedAt() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldDeletedAt)
|
u.SetExcluded(apikey.FieldDeletedAt)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsert) ClearDeletedAt() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) ClearDeletedAt() *APIKeyUpsert {
|
||||||
u.SetNull(apikey.FieldDeletedAt)
|
u.SetNull(apikey.FieldDeletedAt)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (u *ApiKeyUpsert) SetUserID(v int64) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetUserID(v int64) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldUserID, v)
|
u.Set(apikey.FieldUserID, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateUserID() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateUserID() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldUserID)
|
u.SetExcluded(apikey.FieldUserID)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (u *ApiKeyUpsert) SetKey(v string) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetKey(v string) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldKey, v)
|
u.Set(apikey.FieldKey, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKey sets the "key" field to the value that was provided on create.
|
// UpdateKey sets the "key" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateKey() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateKey() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldKey)
|
u.SetExcluded(apikey.FieldKey)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (u *ApiKeyUpsert) SetName(v string) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetName(v string) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldName, v)
|
u.Set(apikey.FieldName, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateName sets the "name" field to the value that was provided on create.
|
// UpdateName sets the "name" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateName() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateName() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldName)
|
u.SetExcluded(apikey.FieldName)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (u *ApiKeyUpsert) SetGroupID(v int64) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetGroupID(v int64) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldGroupID, v)
|
u.Set(apikey.FieldGroupID, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateGroupID() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateGroupID() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldGroupID)
|
u.SetExcluded(apikey.FieldGroupID)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroupID clears the value of the "group_id" field.
|
// ClearGroupID clears the value of the "group_id" field.
|
||||||
func (u *ApiKeyUpsert) ClearGroupID() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) ClearGroupID() *APIKeyUpsert {
|
||||||
u.SetNull(apikey.FieldGroupID)
|
u.SetNull(apikey.FieldGroupID)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (u *ApiKeyUpsert) SetStatus(v string) *ApiKeyUpsert {
|
func (u *APIKeyUpsert) SetStatus(v string) *APIKeyUpsert {
|
||||||
u.Set(apikey.FieldStatus, v)
|
u.Set(apikey.FieldStatus, v)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus sets the "status" field to the value that was provided on create.
|
// UpdateStatus sets the "status" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsert) UpdateStatus() *ApiKeyUpsert {
|
func (u *APIKeyUpsert) UpdateStatus() *APIKeyUpsert {
|
||||||
u.SetExcluded(apikey.FieldStatus)
|
u.SetExcluded(apikey.FieldStatus)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
@@ -486,12 +486,12 @@ func (u *ApiKeyUpsert) UpdateStatus() *ApiKeyUpsert {
|
|||||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||||
// Using this option is equivalent to using:
|
// Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(
|
// OnConflict(
|
||||||
// sql.ResolveWithNewValues(),
|
// sql.ResolveWithNewValues(),
|
||||||
// ).
|
// ).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (u *ApiKeyUpsertOne) UpdateNewValues() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateNewValues() *APIKeyUpsertOne {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||||
@@ -504,159 +504,159 @@ func (u *ApiKeyUpsertOne) UpdateNewValues() *ApiKeyUpsertOne {
|
|||||||
// Ignore sets each column to itself in case of conflict.
|
// Ignore sets each column to itself in case of conflict.
|
||||||
// Using this option is equivalent to using:
|
// Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(sql.ResolveWithIgnore()).
|
// OnConflict(sql.ResolveWithIgnore()).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (u *ApiKeyUpsertOne) Ignore() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) Ignore() *APIKeyUpsertOne {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||||
// Supported only by SQLite and PostgreSQL.
|
// Supported only by SQLite and PostgreSQL.
|
||||||
func (u *ApiKeyUpsertOne) DoNothing() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) DoNothing() *APIKeyUpsertOne {
|
||||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update allows overriding fields `UPDATE` values. See the ApiKeyCreate.OnConflict
|
// Update allows overriding fields `UPDATE` values. See the APIKeyCreate.OnConflict
|
||||||
// documentation for more info.
|
// documentation for more info.
|
||||||
func (u *ApiKeyUpsertOne) Update(set func(*ApiKeyUpsert)) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) Update(set func(*APIKeyUpsert)) *APIKeyUpsertOne {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||||
set(&ApiKeyUpsert{UpdateSet: update})
|
set(&APIKeyUpsert{UpdateSet: update})
|
||||||
}))
|
}))
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (u *ApiKeyUpsertOne) SetUpdatedAt(v time.Time) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetUpdatedAt(v time.Time) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetUpdatedAt(v)
|
s.SetUpdatedAt(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateUpdatedAt() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateUpdatedAt() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateUpdatedAt()
|
s.UpdateUpdatedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsertOne) SetDeletedAt(v time.Time) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetDeletedAt(v time.Time) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetDeletedAt(v)
|
s.SetDeletedAt(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateDeletedAt() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateDeletedAt() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateDeletedAt()
|
s.UpdateDeletedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsertOne) ClearDeletedAt() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) ClearDeletedAt() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.ClearDeletedAt()
|
s.ClearDeletedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (u *ApiKeyUpsertOne) SetUserID(v int64) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetUserID(v int64) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetUserID(v)
|
s.SetUserID(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateUserID() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateUserID() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateUserID()
|
s.UpdateUserID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (u *ApiKeyUpsertOne) SetKey(v string) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetKey(v string) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetKey(v)
|
s.SetKey(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKey sets the "key" field to the value that was provided on create.
|
// UpdateKey sets the "key" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateKey() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateKey() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateKey()
|
s.UpdateKey()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (u *ApiKeyUpsertOne) SetName(v string) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetName(v string) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetName(v)
|
s.SetName(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateName sets the "name" field to the value that was provided on create.
|
// UpdateName sets the "name" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateName() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateName() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateName()
|
s.UpdateName()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (u *ApiKeyUpsertOne) SetGroupID(v int64) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetGroupID(v int64) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetGroupID(v)
|
s.SetGroupID(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateGroupID() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateGroupID() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateGroupID()
|
s.UpdateGroupID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroupID clears the value of the "group_id" field.
|
// ClearGroupID clears the value of the "group_id" field.
|
||||||
func (u *ApiKeyUpsertOne) ClearGroupID() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) ClearGroupID() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.ClearGroupID()
|
s.ClearGroupID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (u *ApiKeyUpsertOne) SetStatus(v string) *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) SetStatus(v string) *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetStatus(v)
|
s.SetStatus(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus sets the "status" field to the value that was provided on create.
|
// UpdateStatus sets the "status" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertOne) UpdateStatus() *ApiKeyUpsertOne {
|
func (u *APIKeyUpsertOne) UpdateStatus() *APIKeyUpsertOne {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateStatus()
|
s.UpdateStatus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *ApiKeyUpsertOne) Exec(ctx context.Context) error {
|
func (u *APIKeyUpsertOne) Exec(ctx context.Context) error {
|
||||||
if len(u.create.conflict) == 0 {
|
if len(u.create.conflict) == 0 {
|
||||||
return errors.New("ent: missing options for ApiKeyCreate.OnConflict")
|
return errors.New("ent: missing options for APIKeyCreate.OnConflict")
|
||||||
}
|
}
|
||||||
return u.create.Exec(ctx)
|
return u.create.Exec(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (u *ApiKeyUpsertOne) ExecX(ctx context.Context) {
|
func (u *APIKeyUpsertOne) ExecX(ctx context.Context) {
|
||||||
if err := u.create.Exec(ctx); err != nil {
|
if err := u.create.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
||||||
func (u *ApiKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
func (u *APIKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
||||||
node, err := u.create.Save(ctx)
|
node, err := u.create.Save(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return id, err
|
||||||
@@ -665,7 +665,7 @@ func (u *ApiKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IDX is like ID, but panics if an error occurs.
|
// IDX is like ID, but panics if an error occurs.
|
||||||
func (u *ApiKeyUpsertOne) IDX(ctx context.Context) int64 {
|
func (u *APIKeyUpsertOne) IDX(ctx context.Context) int64 {
|
||||||
id, err := u.ID(ctx)
|
id, err := u.ID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -673,28 +673,28 @@ func (u *ApiKeyUpsertOne) IDX(ctx context.Context) int64 {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyCreateBulk is the builder for creating many ApiKey entities in bulk.
|
// APIKeyCreateBulk is the builder for creating many APIKey entities in bulk.
|
||||||
type ApiKeyCreateBulk struct {
|
type APIKeyCreateBulk struct {
|
||||||
config
|
config
|
||||||
err error
|
err error
|
||||||
builders []*ApiKeyCreate
|
builders []*APIKeyCreate
|
||||||
conflict []sql.ConflictOption
|
conflict []sql.ConflictOption
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save creates the ApiKey entities in the database.
|
// Save creates the APIKey entities in the database.
|
||||||
func (_c *ApiKeyCreateBulk) Save(ctx context.Context) ([]*ApiKey, error) {
|
func (_c *APIKeyCreateBulk) Save(ctx context.Context) ([]*APIKey, error) {
|
||||||
if _c.err != nil {
|
if _c.err != nil {
|
||||||
return nil, _c.err
|
return nil, _c.err
|
||||||
}
|
}
|
||||||
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
|
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
|
||||||
nodes := make([]*ApiKey, len(_c.builders))
|
nodes := make([]*APIKey, len(_c.builders))
|
||||||
mutators := make([]Mutator, len(_c.builders))
|
mutators := make([]Mutator, len(_c.builders))
|
||||||
for i := range _c.builders {
|
for i := range _c.builders {
|
||||||
func(i int, root context.Context) {
|
func(i int, root context.Context) {
|
||||||
builder := _c.builders[i]
|
builder := _c.builders[i]
|
||||||
builder.defaults()
|
builder.defaults()
|
||||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||||
mutation, ok := m.(*ApiKeyMutation)
|
mutation, ok := m.(*APIKeyMutation)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||||
}
|
}
|
||||||
@@ -742,7 +742,7 @@ func (_c *ApiKeyCreateBulk) Save(ctx context.Context) ([]*ApiKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveX is like Save, but panics if an error occurs.
|
// SaveX is like Save, but panics if an error occurs.
|
||||||
func (_c *ApiKeyCreateBulk) SaveX(ctx context.Context) []*ApiKey {
|
func (_c *APIKeyCreateBulk) SaveX(ctx context.Context) []*APIKey {
|
||||||
v, err := _c.Save(ctx)
|
v, err := _c.Save(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -751,13 +751,13 @@ func (_c *ApiKeyCreateBulk) SaveX(ctx context.Context) []*ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (_c *ApiKeyCreateBulk) Exec(ctx context.Context) error {
|
func (_c *APIKeyCreateBulk) Exec(ctx context.Context) error {
|
||||||
_, err := _c.Save(ctx)
|
_, err := _c.Save(ctx)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
|
func (_c *APIKeyCreateBulk) ExecX(ctx context.Context) {
|
||||||
if err := _c.Exec(ctx); err != nil {
|
if err := _c.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -766,7 +766,7 @@ func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
|
|||||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||||
// of the `INSERT` statement. For example:
|
// of the `INSERT` statement. For example:
|
||||||
//
|
//
|
||||||
// client.ApiKey.CreateBulk(builders...).
|
// client.APIKey.CreateBulk(builders...).
|
||||||
// OnConflict(
|
// OnConflict(
|
||||||
// // Update the row with the new values
|
// // Update the row with the new values
|
||||||
// // the was proposed for insertion.
|
// // the was proposed for insertion.
|
||||||
@@ -774,13 +774,13 @@ func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
|
|||||||
// ).
|
// ).
|
||||||
// // Override some of the fields with custom
|
// // Override some of the fields with custom
|
||||||
// // update values.
|
// // update values.
|
||||||
// Update(func(u *ent.ApiKeyUpsert) {
|
// Update(func(u *ent.APIKeyUpsert) {
|
||||||
// SetCreatedAt(v+v).
|
// SetCreatedAt(v+v).
|
||||||
// }).
|
// }).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (_c *ApiKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertBulk {
|
func (_c *APIKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *APIKeyUpsertBulk {
|
||||||
_c.conflict = opts
|
_c.conflict = opts
|
||||||
return &ApiKeyUpsertBulk{
|
return &APIKeyUpsertBulk{
|
||||||
create: _c,
|
create: _c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,31 +788,31 @@ func (_c *ApiKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsert
|
|||||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||||
// as conflict target. Using this option is equivalent to using:
|
// as conflict target. Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(sql.ConflictColumns(columns...)).
|
// OnConflict(sql.ConflictColumns(columns...)).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (_c *ApiKeyCreateBulk) OnConflictColumns(columns ...string) *ApiKeyUpsertBulk {
|
func (_c *APIKeyCreateBulk) OnConflictColumns(columns ...string) *APIKeyUpsertBulk {
|
||||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||||
return &ApiKeyUpsertBulk{
|
return &APIKeyUpsertBulk{
|
||||||
create: _c,
|
create: _c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyUpsertBulk is the builder for "upsert"-ing
|
// APIKeyUpsertBulk is the builder for "upsert"-ing
|
||||||
// a bulk of ApiKey nodes.
|
// a bulk of APIKey nodes.
|
||||||
type ApiKeyUpsertBulk struct {
|
type APIKeyUpsertBulk struct {
|
||||||
create *ApiKeyCreateBulk
|
create *APIKeyCreateBulk
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateNewValues updates the mutable fields using the new values that
|
// UpdateNewValues updates the mutable fields using the new values that
|
||||||
// were set on create. Using this option is equivalent to using:
|
// were set on create. Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(
|
// OnConflict(
|
||||||
// sql.ResolveWithNewValues(),
|
// sql.ResolveWithNewValues(),
|
||||||
// ).
|
// ).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (u *ApiKeyUpsertBulk) UpdateNewValues() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateNewValues() *APIKeyUpsertBulk {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||||
for _, b := range u.create.builders {
|
for _, b := range u.create.builders {
|
||||||
@@ -827,160 +827,160 @@ func (u *ApiKeyUpsertBulk) UpdateNewValues() *ApiKeyUpsertBulk {
|
|||||||
// Ignore sets each column to itself in case of conflict.
|
// Ignore sets each column to itself in case of conflict.
|
||||||
// Using this option is equivalent to using:
|
// Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
// client.ApiKey.Create().
|
// client.APIKey.Create().
|
||||||
// OnConflict(sql.ResolveWithIgnore()).
|
// OnConflict(sql.ResolveWithIgnore()).
|
||||||
// Exec(ctx)
|
// Exec(ctx)
|
||||||
func (u *ApiKeyUpsertBulk) Ignore() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) Ignore() *APIKeyUpsertBulk {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||||
// Supported only by SQLite and PostgreSQL.
|
// Supported only by SQLite and PostgreSQL.
|
||||||
func (u *ApiKeyUpsertBulk) DoNothing() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) DoNothing() *APIKeyUpsertBulk {
|
||||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update allows overriding fields `UPDATE` values. See the ApiKeyCreateBulk.OnConflict
|
// Update allows overriding fields `UPDATE` values. See the APIKeyCreateBulk.OnConflict
|
||||||
// documentation for more info.
|
// documentation for more info.
|
||||||
func (u *ApiKeyUpsertBulk) Update(set func(*ApiKeyUpsert)) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) Update(set func(*APIKeyUpsert)) *APIKeyUpsertBulk {
|
||||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||||
set(&ApiKeyUpsert{UpdateSet: update})
|
set(&APIKeyUpsert{UpdateSet: update})
|
||||||
}))
|
}))
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetUpdatedAt(v time.Time) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetUpdatedAt(v time.Time) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetUpdatedAt(v)
|
s.SetUpdatedAt(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateUpdatedAt() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateUpdatedAt() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateUpdatedAt()
|
s.UpdateUpdatedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetDeletedAt(v time.Time) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetDeletedAt(v time.Time) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetDeletedAt(v)
|
s.SetDeletedAt(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateDeletedAt() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateDeletedAt() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateDeletedAt()
|
s.UpdateDeletedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||||
func (u *ApiKeyUpsertBulk) ClearDeletedAt() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) ClearDeletedAt() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.ClearDeletedAt()
|
s.ClearDeletedAt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetUserID(v int64) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetUserID(v int64) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetUserID(v)
|
s.SetUserID(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
// UpdateUserID sets the "user_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateUserID() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateUserID() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateUserID()
|
s.UpdateUserID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetKey(v string) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetKey(v string) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetKey(v)
|
s.SetKey(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKey sets the "key" field to the value that was provided on create.
|
// UpdateKey sets the "key" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateKey() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateKey() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateKey()
|
s.UpdateKey()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetName(v string) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetName(v string) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetName(v)
|
s.SetName(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateName sets the "name" field to the value that was provided on create.
|
// UpdateName sets the "name" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateName() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateName() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateName()
|
s.UpdateName()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetGroupID(v int64) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetGroupID(v int64) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetGroupID(v)
|
s.SetGroupID(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateGroupID() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateGroupID() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateGroupID()
|
s.UpdateGroupID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroupID clears the value of the "group_id" field.
|
// ClearGroupID clears the value of the "group_id" field.
|
||||||
func (u *ApiKeyUpsertBulk) ClearGroupID() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) ClearGroupID() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.ClearGroupID()
|
s.ClearGroupID()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (u *ApiKeyUpsertBulk) SetStatus(v string) *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) SetStatus(v string) *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.SetStatus(v)
|
s.SetStatus(v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus sets the "status" field to the value that was provided on create.
|
// UpdateStatus sets the "status" field to the value that was provided on create.
|
||||||
func (u *ApiKeyUpsertBulk) UpdateStatus() *ApiKeyUpsertBulk {
|
func (u *APIKeyUpsertBulk) UpdateStatus() *APIKeyUpsertBulk {
|
||||||
return u.Update(func(s *ApiKeyUpsert) {
|
return u.Update(func(s *APIKeyUpsert) {
|
||||||
s.UpdateStatus()
|
s.UpdateStatus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *ApiKeyUpsertBulk) Exec(ctx context.Context) error {
|
func (u *APIKeyUpsertBulk) Exec(ctx context.Context) error {
|
||||||
if u.create.err != nil {
|
if u.create.err != nil {
|
||||||
return u.create.err
|
return u.create.err
|
||||||
}
|
}
|
||||||
for i, b := range u.create.builders {
|
for i, b := range u.create.builders {
|
||||||
if len(b.conflict) != 0 {
|
if len(b.conflict) != 0 {
|
||||||
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ApiKeyCreateBulk instead", i)
|
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the APIKeyCreateBulk instead", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(u.create.conflict) == 0 {
|
if len(u.create.conflict) == 0 {
|
||||||
return errors.New("ent: missing options for ApiKeyCreateBulk.OnConflict")
|
return errors.New("ent: missing options for APIKeyCreateBulk.OnConflict")
|
||||||
}
|
}
|
||||||
return u.create.Exec(ctx)
|
return u.create.Exec(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (u *ApiKeyUpsertBulk) ExecX(ctx context.Context) {
|
func (u *APIKeyUpsertBulk) ExecX(ctx context.Context) {
|
||||||
if err := u.create.Exec(ctx); err != nil {
|
if err := u.create.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,26 +12,26 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKeyDelete is the builder for deleting a ApiKey entity.
|
// APIKeyDelete is the builder for deleting a APIKey entity.
|
||||||
type ApiKeyDelete struct {
|
type APIKeyDelete struct {
|
||||||
config
|
config
|
||||||
hooks []Hook
|
hooks []Hook
|
||||||
mutation *ApiKeyMutation
|
mutation *APIKeyMutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where appends a list predicates to the ApiKeyDelete builder.
|
// Where appends a list predicates to the APIKeyDelete builder.
|
||||||
func (_d *ApiKeyDelete) Where(ps ...predicate.ApiKey) *ApiKeyDelete {
|
func (_d *APIKeyDelete) Where(ps ...predicate.APIKey) *APIKeyDelete {
|
||||||
_d.mutation.Where(ps...)
|
_d.mutation.Where(ps...)
|
||||||
return _d
|
return _d
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||||
func (_d *ApiKeyDelete) Exec(ctx context.Context) (int, error) {
|
func (_d *APIKeyDelete) Exec(ctx context.Context) (int, error) {
|
||||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_d *ApiKeyDelete) ExecX(ctx context.Context) int {
|
func (_d *APIKeyDelete) ExecX(ctx context.Context) int {
|
||||||
n, err := _d.Exec(ctx)
|
n, err := _d.Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -39,7 +39,7 @@ func (_d *ApiKeyDelete) ExecX(ctx context.Context) int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_d *ApiKeyDelete) sqlExec(ctx context.Context) (int, error) {
|
func (_d *APIKeyDelete) sqlExec(ctx context.Context) (int, error) {
|
||||||
_spec := sqlgraph.NewDeleteSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
_spec := sqlgraph.NewDeleteSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
||||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||||
_spec.Predicate = func(selector *sql.Selector) {
|
_spec.Predicate = func(selector *sql.Selector) {
|
||||||
@@ -56,19 +56,19 @@ func (_d *ApiKeyDelete) sqlExec(ctx context.Context) (int, error) {
|
|||||||
return affected, err
|
return affected, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyDeleteOne is the builder for deleting a single ApiKey entity.
|
// APIKeyDeleteOne is the builder for deleting a single APIKey entity.
|
||||||
type ApiKeyDeleteOne struct {
|
type APIKeyDeleteOne struct {
|
||||||
_d *ApiKeyDelete
|
_d *APIKeyDelete
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where appends a list predicates to the ApiKeyDelete builder.
|
// Where appends a list predicates to the APIKeyDelete builder.
|
||||||
func (_d *ApiKeyDeleteOne) Where(ps ...predicate.ApiKey) *ApiKeyDeleteOne {
|
func (_d *APIKeyDeleteOne) Where(ps ...predicate.APIKey) *APIKeyDeleteOne {
|
||||||
_d._d.mutation.Where(ps...)
|
_d._d.mutation.Where(ps...)
|
||||||
return _d
|
return _d
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the deletion query.
|
// Exec executes the deletion query.
|
||||||
func (_d *ApiKeyDeleteOne) Exec(ctx context.Context) error {
|
func (_d *APIKeyDeleteOne) Exec(ctx context.Context) error {
|
||||||
n, err := _d._d.Exec(ctx)
|
n, err := _d._d.Exec(ctx)
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
@@ -81,7 +81,7 @@ func (_d *ApiKeyDeleteOne) Exec(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_d *ApiKeyDeleteOne) ExecX(ctx context.Context) {
|
func (_d *APIKeyDeleteOne) ExecX(ctx context.Context) {
|
||||||
if err := _d.Exec(ctx); err != nil {
|
if err := _d.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKeyQuery is the builder for querying ApiKey entities.
|
// APIKeyQuery is the builder for querying APIKey entities.
|
||||||
type ApiKeyQuery struct {
|
type APIKeyQuery struct {
|
||||||
config
|
config
|
||||||
ctx *QueryContext
|
ctx *QueryContext
|
||||||
order []apikey.OrderOption
|
order []apikey.OrderOption
|
||||||
inters []Interceptor
|
inters []Interceptor
|
||||||
predicates []predicate.ApiKey
|
predicates []predicate.APIKey
|
||||||
withUser *UserQuery
|
withUser *UserQuery
|
||||||
withGroup *GroupQuery
|
withGroup *GroupQuery
|
||||||
withUsageLogs *UsageLogQuery
|
withUsageLogs *UsageLogQuery
|
||||||
@@ -34,39 +34,39 @@ type ApiKeyQuery struct {
|
|||||||
path func(context.Context) (*sql.Selector, error)
|
path func(context.Context) (*sql.Selector, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where adds a new predicate for the ApiKeyQuery builder.
|
// Where adds a new predicate for the APIKeyQuery builder.
|
||||||
func (_q *ApiKeyQuery) Where(ps ...predicate.ApiKey) *ApiKeyQuery {
|
func (_q *APIKeyQuery) Where(ps ...predicate.APIKey) *APIKeyQuery {
|
||||||
_q.predicates = append(_q.predicates, ps...)
|
_q.predicates = append(_q.predicates, ps...)
|
||||||
return _q
|
return _q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit the number of records to be returned by this query.
|
// Limit the number of records to be returned by this query.
|
||||||
func (_q *ApiKeyQuery) Limit(limit int) *ApiKeyQuery {
|
func (_q *APIKeyQuery) Limit(limit int) *APIKeyQuery {
|
||||||
_q.ctx.Limit = &limit
|
_q.ctx.Limit = &limit
|
||||||
return _q
|
return _q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset to start from.
|
// Offset to start from.
|
||||||
func (_q *ApiKeyQuery) Offset(offset int) *ApiKeyQuery {
|
func (_q *APIKeyQuery) Offset(offset int) *APIKeyQuery {
|
||||||
_q.ctx.Offset = &offset
|
_q.ctx.Offset = &offset
|
||||||
return _q
|
return _q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unique configures the query builder to filter duplicate records on query.
|
// 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.
|
// By default, unique is set to true, and can be disabled using this method.
|
||||||
func (_q *ApiKeyQuery) Unique(unique bool) *ApiKeyQuery {
|
func (_q *APIKeyQuery) Unique(unique bool) *APIKeyQuery {
|
||||||
_q.ctx.Unique = &unique
|
_q.ctx.Unique = &unique
|
||||||
return _q
|
return _q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order specifies how the records should be ordered.
|
// Order specifies how the records should be ordered.
|
||||||
func (_q *ApiKeyQuery) Order(o ...apikey.OrderOption) *ApiKeyQuery {
|
func (_q *APIKeyQuery) Order(o ...apikey.OrderOption) *APIKeyQuery {
|
||||||
_q.order = append(_q.order, o...)
|
_q.order = append(_q.order, o...)
|
||||||
return _q
|
return _q
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryUser chains the current query on the "user" edge.
|
// QueryUser chains the current query on the "user" edge.
|
||||||
func (_q *ApiKeyQuery) QueryUser() *UserQuery {
|
func (_q *APIKeyQuery) QueryUser() *UserQuery {
|
||||||
query := (&UserClient{config: _q.config}).Query()
|
query := (&UserClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
@@ -88,7 +88,7 @@ func (_q *ApiKeyQuery) QueryUser() *UserQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryGroup chains the current query on the "group" edge.
|
// QueryGroup chains the current query on the "group" edge.
|
||||||
func (_q *ApiKeyQuery) QueryGroup() *GroupQuery {
|
func (_q *APIKeyQuery) QueryGroup() *GroupQuery {
|
||||||
query := (&GroupClient{config: _q.config}).Query()
|
query := (&GroupClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
@@ -110,7 +110,7 @@ func (_q *ApiKeyQuery) QueryGroup() *GroupQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryUsageLogs chains the current query on the "usage_logs" edge.
|
// QueryUsageLogs chains the current query on the "usage_logs" edge.
|
||||||
func (_q *ApiKeyQuery) QueryUsageLogs() *UsageLogQuery {
|
func (_q *APIKeyQuery) QueryUsageLogs() *UsageLogQuery {
|
||||||
query := (&UsageLogClient{config: _q.config}).Query()
|
query := (&UsageLogClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
@@ -131,9 +131,9 @@ func (_q *ApiKeyQuery) QueryUsageLogs() *UsageLogQuery {
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
// First returns the first ApiKey entity from the query.
|
// First returns the first APIKey entity from the query.
|
||||||
// Returns a *NotFoundError when no ApiKey was found.
|
// Returns a *NotFoundError when no APIKey was found.
|
||||||
func (_q *ApiKeyQuery) First(ctx context.Context) (*ApiKey, error) {
|
func (_q *APIKeyQuery) First(ctx context.Context) (*APIKey, error) {
|
||||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -145,7 +145,7 @@ func (_q *ApiKeyQuery) First(ctx context.Context) (*ApiKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FirstX is like First, but panics if an error occurs.
|
// FirstX is like First, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) FirstX(ctx context.Context) *ApiKey {
|
func (_q *APIKeyQuery) FirstX(ctx context.Context) *APIKey {
|
||||||
node, err := _q.First(ctx)
|
node, err := _q.First(ctx)
|
||||||
if err != nil && !IsNotFound(err) {
|
if err != nil && !IsNotFound(err) {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -153,9 +153,9 @@ func (_q *ApiKeyQuery) FirstX(ctx context.Context) *ApiKey {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstID returns the first ApiKey ID from the query.
|
// FirstID returns the first APIKey ID from the query.
|
||||||
// Returns a *NotFoundError when no ApiKey ID was found.
|
// Returns a *NotFoundError when no APIKey ID was found.
|
||||||
func (_q *ApiKeyQuery) FirstID(ctx context.Context) (id int64, err error) {
|
func (_q *APIKeyQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||||
var ids []int64
|
var ids []int64
|
||||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||||
return
|
return
|
||||||
@@ -168,7 +168,7 @@ func (_q *ApiKeyQuery) FirstID(ctx context.Context) (id int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) FirstIDX(ctx context.Context) int64 {
|
func (_q *APIKeyQuery) FirstIDX(ctx context.Context) int64 {
|
||||||
id, err := _q.FirstID(ctx)
|
id, err := _q.FirstID(ctx)
|
||||||
if err != nil && !IsNotFound(err) {
|
if err != nil && !IsNotFound(err) {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -176,10 +176,10 @@ func (_q *ApiKeyQuery) FirstIDX(ctx context.Context) int64 {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only returns a single ApiKey entity found by the query, ensuring it only returns one.
|
// Only returns a single APIKey entity found by the query, ensuring it only returns one.
|
||||||
// Returns a *NotSingularError when more than one ApiKey entity is found.
|
// Returns a *NotSingularError when more than one APIKey entity is found.
|
||||||
// Returns a *NotFoundError when no ApiKey entities are found.
|
// Returns a *NotFoundError when no APIKey entities are found.
|
||||||
func (_q *ApiKeyQuery) Only(ctx context.Context) (*ApiKey, error) {
|
func (_q *APIKeyQuery) Only(ctx context.Context) (*APIKey, error) {
|
||||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -195,7 +195,7 @@ func (_q *ApiKeyQuery) Only(ctx context.Context) (*ApiKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OnlyX is like Only, but panics if an error occurs.
|
// OnlyX is like Only, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) OnlyX(ctx context.Context) *ApiKey {
|
func (_q *APIKeyQuery) OnlyX(ctx context.Context) *APIKey {
|
||||||
node, err := _q.Only(ctx)
|
node, err := _q.Only(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -203,10 +203,10 @@ func (_q *ApiKeyQuery) OnlyX(ctx context.Context) *ApiKey {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnlyID is like Only, but returns the only ApiKey ID in the query.
|
// OnlyID is like Only, but returns the only APIKey ID in the query.
|
||||||
// Returns a *NotSingularError when more than one ApiKey ID is found.
|
// Returns a *NotSingularError when more than one APIKey ID is found.
|
||||||
// Returns a *NotFoundError when no entities are found.
|
// Returns a *NotFoundError when no entities are found.
|
||||||
func (_q *ApiKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
func (_q *APIKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||||
var ids []int64
|
var ids []int64
|
||||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||||
return
|
return
|
||||||
@@ -223,7 +223,7 @@ func (_q *ApiKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) OnlyIDX(ctx context.Context) int64 {
|
func (_q *APIKeyQuery) OnlyIDX(ctx context.Context) int64 {
|
||||||
id, err := _q.OnlyID(ctx)
|
id, err := _q.OnlyID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -231,18 +231,18 @@ func (_q *ApiKeyQuery) OnlyIDX(ctx context.Context) int64 {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// All executes the query and returns a list of ApiKeys.
|
// All executes the query and returns a list of APIKeys.
|
||||||
func (_q *ApiKeyQuery) All(ctx context.Context) ([]*ApiKey, error) {
|
func (_q *APIKeyQuery) All(ctx context.Context) ([]*APIKey, error) {
|
||||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qr := querierAll[[]*ApiKey, *ApiKeyQuery]()
|
qr := querierAll[[]*APIKey, *APIKeyQuery]()
|
||||||
return withInterceptors[[]*ApiKey](ctx, _q, qr, _q.inters)
|
return withInterceptors[[]*APIKey](ctx, _q, qr, _q.inters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllX is like All, but panics if an error occurs.
|
// AllX is like All, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) AllX(ctx context.Context) []*ApiKey {
|
func (_q *APIKeyQuery) AllX(ctx context.Context) []*APIKey {
|
||||||
nodes, err := _q.All(ctx)
|
nodes, err := _q.All(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -250,8 +250,8 @@ func (_q *ApiKeyQuery) AllX(ctx context.Context) []*ApiKey {
|
|||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDs executes the query and returns a list of ApiKey IDs.
|
// IDs executes the query and returns a list of APIKey IDs.
|
||||||
func (_q *ApiKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
func (_q *APIKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||||
if _q.ctx.Unique == nil && _q.path != nil {
|
if _q.ctx.Unique == nil && _q.path != nil {
|
||||||
_q.Unique(true)
|
_q.Unique(true)
|
||||||
}
|
}
|
||||||
@@ -263,7 +263,7 @@ func (_q *ApiKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IDsX is like IDs, but panics if an error occurs.
|
// IDsX is like IDs, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) IDsX(ctx context.Context) []int64 {
|
func (_q *APIKeyQuery) IDsX(ctx context.Context) []int64 {
|
||||||
ids, err := _q.IDs(ctx)
|
ids, err := _q.IDs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -272,16 +272,16 @@ func (_q *ApiKeyQuery) IDsX(ctx context.Context) []int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the count of the given query.
|
// Count returns the count of the given query.
|
||||||
func (_q *ApiKeyQuery) Count(ctx context.Context) (int, error) {
|
func (_q *APIKeyQuery) Count(ctx context.Context) (int, error) {
|
||||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return withInterceptors[int](ctx, _q, querierCount[*ApiKeyQuery](), _q.inters)
|
return withInterceptors[int](ctx, _q, querierCount[*APIKeyQuery](), _q.inters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountX is like Count, but panics if an error occurs.
|
// CountX is like Count, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) CountX(ctx context.Context) int {
|
func (_q *APIKeyQuery) CountX(ctx context.Context) int {
|
||||||
count, err := _q.Count(ctx)
|
count, err := _q.Count(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -290,7 +290,7 @@ func (_q *ApiKeyQuery) CountX(ctx context.Context) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns true if the query has elements in the graph.
|
// Exist returns true if the query has elements in the graph.
|
||||||
func (_q *ApiKeyQuery) Exist(ctx context.Context) (bool, error) {
|
func (_q *APIKeyQuery) Exist(ctx context.Context) (bool, error) {
|
||||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||||
switch _, err := _q.FirstID(ctx); {
|
switch _, err := _q.FirstID(ctx); {
|
||||||
case IsNotFound(err):
|
case IsNotFound(err):
|
||||||
@@ -303,7 +303,7 @@ func (_q *ApiKeyQuery) Exist(ctx context.Context) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExistX is like Exist, but panics if an error occurs.
|
// ExistX is like Exist, but panics if an error occurs.
|
||||||
func (_q *ApiKeyQuery) ExistX(ctx context.Context) bool {
|
func (_q *APIKeyQuery) ExistX(ctx context.Context) bool {
|
||||||
exist, err := _q.Exist(ctx)
|
exist, err := _q.Exist(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -311,18 +311,18 @@ func (_q *ApiKeyQuery) ExistX(ctx context.Context) bool {
|
|||||||
return exist
|
return exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone returns a duplicate of the ApiKeyQuery builder, including all associated steps. It can be
|
// Clone returns a duplicate of the APIKeyQuery builder, including all associated steps. It can be
|
||||||
// used to prepare common query builders and use them differently after the clone is made.
|
// used to prepare common query builders and use them differently after the clone is made.
|
||||||
func (_q *ApiKeyQuery) Clone() *ApiKeyQuery {
|
func (_q *APIKeyQuery) Clone() *APIKeyQuery {
|
||||||
if _q == nil {
|
if _q == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &ApiKeyQuery{
|
return &APIKeyQuery{
|
||||||
config: _q.config,
|
config: _q.config,
|
||||||
ctx: _q.ctx.Clone(),
|
ctx: _q.ctx.Clone(),
|
||||||
order: append([]apikey.OrderOption{}, _q.order...),
|
order: append([]apikey.OrderOption{}, _q.order...),
|
||||||
inters: append([]Interceptor{}, _q.inters...),
|
inters: append([]Interceptor{}, _q.inters...),
|
||||||
predicates: append([]predicate.ApiKey{}, _q.predicates...),
|
predicates: append([]predicate.APIKey{}, _q.predicates...),
|
||||||
withUser: _q.withUser.Clone(),
|
withUser: _q.withUser.Clone(),
|
||||||
withGroup: _q.withGroup.Clone(),
|
withGroup: _q.withGroup.Clone(),
|
||||||
withUsageLogs: _q.withUsageLogs.Clone(),
|
withUsageLogs: _q.withUsageLogs.Clone(),
|
||||||
@@ -334,7 +334,7 @@ func (_q *ApiKeyQuery) Clone() *ApiKeyQuery {
|
|||||||
|
|
||||||
// WithUser tells the query-builder to eager-load the nodes that are connected to
|
// 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.
|
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *ApiKeyQuery) WithUser(opts ...func(*UserQuery)) *ApiKeyQuery {
|
func (_q *APIKeyQuery) WithUser(opts ...func(*UserQuery)) *APIKeyQuery {
|
||||||
query := (&UserClient{config: _q.config}).Query()
|
query := (&UserClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
@@ -345,7 +345,7 @@ func (_q *ApiKeyQuery) WithUser(opts ...func(*UserQuery)) *ApiKeyQuery {
|
|||||||
|
|
||||||
// WithGroup tells the query-builder to eager-load the nodes that are connected to
|
// WithGroup tells the query-builder to eager-load the nodes that are connected to
|
||||||
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
|
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *ApiKeyQuery) WithGroup(opts ...func(*GroupQuery)) *ApiKeyQuery {
|
func (_q *APIKeyQuery) WithGroup(opts ...func(*GroupQuery)) *APIKeyQuery {
|
||||||
query := (&GroupClient{config: _q.config}).Query()
|
query := (&GroupClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
@@ -356,7 +356,7 @@ func (_q *ApiKeyQuery) WithGroup(opts ...func(*GroupQuery)) *ApiKeyQuery {
|
|||||||
|
|
||||||
// WithUsageLogs tells the query-builder to eager-load the nodes that are connected to
|
// WithUsageLogs tells the query-builder to eager-load the nodes that are connected to
|
||||||
// the "usage_logs" edge. The optional arguments are used to configure the query builder of the edge.
|
// the "usage_logs" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *ApiKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *ApiKeyQuery {
|
func (_q *APIKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *APIKeyQuery {
|
||||||
query := (&UsageLogClient{config: _q.config}).Query()
|
query := (&UsageLogClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
@@ -375,13 +375,13 @@ func (_q *ApiKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *ApiKeyQuery
|
|||||||
// Count int `json:"count,omitempty"`
|
// Count int `json:"count,omitempty"`
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// client.ApiKey.Query().
|
// client.APIKey.Query().
|
||||||
// GroupBy(apikey.FieldCreatedAt).
|
// GroupBy(apikey.FieldCreatedAt).
|
||||||
// Aggregate(ent.Count()).
|
// Aggregate(ent.Count()).
|
||||||
// Scan(ctx, &v)
|
// Scan(ctx, &v)
|
||||||
func (_q *ApiKeyQuery) GroupBy(field string, fields ...string) *ApiKeyGroupBy {
|
func (_q *APIKeyQuery) GroupBy(field string, fields ...string) *APIKeyGroupBy {
|
||||||
_q.ctx.Fields = append([]string{field}, fields...)
|
_q.ctx.Fields = append([]string{field}, fields...)
|
||||||
grbuild := &ApiKeyGroupBy{build: _q}
|
grbuild := &APIKeyGroupBy{build: _q}
|
||||||
grbuild.flds = &_q.ctx.Fields
|
grbuild.flds = &_q.ctx.Fields
|
||||||
grbuild.label = apikey.Label
|
grbuild.label = apikey.Label
|
||||||
grbuild.scan = grbuild.Scan
|
grbuild.scan = grbuild.Scan
|
||||||
@@ -397,23 +397,23 @@ func (_q *ApiKeyQuery) GroupBy(field string, fields ...string) *ApiKeyGroupBy {
|
|||||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// client.ApiKey.Query().
|
// client.APIKey.Query().
|
||||||
// Select(apikey.FieldCreatedAt).
|
// Select(apikey.FieldCreatedAt).
|
||||||
// Scan(ctx, &v)
|
// Scan(ctx, &v)
|
||||||
func (_q *ApiKeyQuery) Select(fields ...string) *ApiKeySelect {
|
func (_q *APIKeyQuery) Select(fields ...string) *APIKeySelect {
|
||||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||||
sbuild := &ApiKeySelect{ApiKeyQuery: _q}
|
sbuild := &APIKeySelect{APIKeyQuery: _q}
|
||||||
sbuild.label = apikey.Label
|
sbuild.label = apikey.Label
|
||||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||||
return sbuild
|
return sbuild
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregate returns a ApiKeySelect configured with the given aggregations.
|
// Aggregate returns a APIKeySelect configured with the given aggregations.
|
||||||
func (_q *ApiKeyQuery) Aggregate(fns ...AggregateFunc) *ApiKeySelect {
|
func (_q *APIKeyQuery) Aggregate(fns ...AggregateFunc) *APIKeySelect {
|
||||||
return _q.Select().Aggregate(fns...)
|
return _q.Select().Aggregate(fns...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) prepareQuery(ctx context.Context) error {
|
func (_q *APIKeyQuery) prepareQuery(ctx context.Context) error {
|
||||||
for _, inter := range _q.inters {
|
for _, inter := range _q.inters {
|
||||||
if inter == nil {
|
if inter == nil {
|
||||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||||
@@ -439,9 +439,9 @@ func (_q *ApiKeyQuery) prepareQuery(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKey, error) {
|
func (_q *APIKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*APIKey, error) {
|
||||||
var (
|
var (
|
||||||
nodes = []*ApiKey{}
|
nodes = []*APIKey{}
|
||||||
_spec = _q.querySpec()
|
_spec = _q.querySpec()
|
||||||
loadedTypes = [3]bool{
|
loadedTypes = [3]bool{
|
||||||
_q.withUser != nil,
|
_q.withUser != nil,
|
||||||
@@ -450,10 +450,10 @@ func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKe
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||||
return (*ApiKey).scanValues(nil, columns)
|
return (*APIKey).scanValues(nil, columns)
|
||||||
}
|
}
|
||||||
_spec.Assign = func(columns []string, values []any) error {
|
_spec.Assign = func(columns []string, values []any) error {
|
||||||
node := &ApiKey{config: _q.config}
|
node := &APIKey{config: _q.config}
|
||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
node.Edges.loadedTypes = loadedTypes
|
node.Edges.loadedTypes = loadedTypes
|
||||||
return node.assignValues(columns, values)
|
return node.assignValues(columns, values)
|
||||||
@@ -469,29 +469,29 @@ func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKe
|
|||||||
}
|
}
|
||||||
if query := _q.withUser; query != nil {
|
if query := _q.withUser; query != nil {
|
||||||
if err := _q.loadUser(ctx, query, nodes, nil,
|
if err := _q.loadUser(ctx, query, nodes, nil,
|
||||||
func(n *ApiKey, e *User) { n.Edges.User = e }); err != nil {
|
func(n *APIKey, e *User) { n.Edges.User = e }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if query := _q.withGroup; query != nil {
|
if query := _q.withGroup; query != nil {
|
||||||
if err := _q.loadGroup(ctx, query, nodes, nil,
|
if err := _q.loadGroup(ctx, query, nodes, nil,
|
||||||
func(n *ApiKey, e *Group) { n.Edges.Group = e }); err != nil {
|
func(n *APIKey, e *Group) { n.Edges.Group = e }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if query := _q.withUsageLogs; query != nil {
|
if query := _q.withUsageLogs; query != nil {
|
||||||
if err := _q.loadUsageLogs(ctx, query, nodes,
|
if err := _q.loadUsageLogs(ctx, query, nodes,
|
||||||
func(n *ApiKey) { n.Edges.UsageLogs = []*UsageLog{} },
|
func(n *APIKey) { n.Edges.UsageLogs = []*UsageLog{} },
|
||||||
func(n *ApiKey, e *UsageLog) { n.Edges.UsageLogs = append(n.Edges.UsageLogs, e) }); err != nil {
|
func(n *APIKey, e *UsageLog) { n.Edges.UsageLogs = append(n.Edges.UsageLogs, e) }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *User)) error {
|
func (_q *APIKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *User)) error {
|
||||||
ids := make([]int64, 0, len(nodes))
|
ids := make([]int64, 0, len(nodes))
|
||||||
nodeids := make(map[int64][]*ApiKey)
|
nodeids := make(map[int64][]*APIKey)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
fk := nodes[i].UserID
|
fk := nodes[i].UserID
|
||||||
if _, ok := nodeids[fk]; !ok {
|
if _, ok := nodeids[fk]; !ok {
|
||||||
@@ -518,9 +518,9 @@ func (_q *ApiKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (_q *ApiKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *Group)) error {
|
func (_q *APIKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *Group)) error {
|
||||||
ids := make([]int64, 0, len(nodes))
|
ids := make([]int64, 0, len(nodes))
|
||||||
nodeids := make(map[int64][]*ApiKey)
|
nodeids := make(map[int64][]*APIKey)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
if nodes[i].GroupID == nil {
|
if nodes[i].GroupID == nil {
|
||||||
continue
|
continue
|
||||||
@@ -550,9 +550,9 @@ func (_q *ApiKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes [
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (_q *ApiKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *UsageLog)) error {
|
func (_q *APIKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *UsageLog)) error {
|
||||||
fks := make([]driver.Value, 0, len(nodes))
|
fks := make([]driver.Value, 0, len(nodes))
|
||||||
nodeids := make(map[int64]*ApiKey)
|
nodeids := make(map[int64]*APIKey)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
fks = append(fks, nodes[i].ID)
|
fks = append(fks, nodes[i].ID)
|
||||||
nodeids[nodes[i].ID] = nodes[i]
|
nodeids[nodes[i].ID] = nodes[i]
|
||||||
@@ -581,7 +581,7 @@ func (_q *ApiKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) sqlCount(ctx context.Context) (int, error) {
|
func (_q *APIKeyQuery) sqlCount(ctx context.Context) (int, error) {
|
||||||
_spec := _q.querySpec()
|
_spec := _q.querySpec()
|
||||||
_spec.Node.Columns = _q.ctx.Fields
|
_spec.Node.Columns = _q.ctx.Fields
|
||||||
if len(_q.ctx.Fields) > 0 {
|
if len(_q.ctx.Fields) > 0 {
|
||||||
@@ -590,7 +590,7 @@ func (_q *ApiKeyQuery) sqlCount(ctx context.Context) (int, error) {
|
|||||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) querySpec() *sqlgraph.QuerySpec {
|
func (_q *APIKeyQuery) querySpec() *sqlgraph.QuerySpec {
|
||||||
_spec := sqlgraph.NewQuerySpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
_spec := sqlgraph.NewQuerySpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
||||||
_spec.From = _q.sql
|
_spec.From = _q.sql
|
||||||
if unique := _q.ctx.Unique; unique != nil {
|
if unique := _q.ctx.Unique; unique != nil {
|
||||||
@@ -636,7 +636,7 @@ func (_q *ApiKeyQuery) querySpec() *sqlgraph.QuerySpec {
|
|||||||
return _spec
|
return _spec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *ApiKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
func (_q *APIKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||||
builder := sql.Dialect(_q.driver.Dialect())
|
builder := sql.Dialect(_q.driver.Dialect())
|
||||||
t1 := builder.Table(apikey.Table)
|
t1 := builder.Table(apikey.Table)
|
||||||
columns := _q.ctx.Fields
|
columns := _q.ctx.Fields
|
||||||
@@ -668,28 +668,28 @@ func (_q *ApiKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
|||||||
return selector
|
return selector
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyGroupBy is the group-by builder for ApiKey entities.
|
// APIKeyGroupBy is the group-by builder for APIKey entities.
|
||||||
type ApiKeyGroupBy struct {
|
type APIKeyGroupBy struct {
|
||||||
selector
|
selector
|
||||||
build *ApiKeyQuery
|
build *APIKeyQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregate adds the given aggregation functions to the group-by query.
|
// Aggregate adds the given aggregation functions to the group-by query.
|
||||||
func (_g *ApiKeyGroupBy) Aggregate(fns ...AggregateFunc) *ApiKeyGroupBy {
|
func (_g *APIKeyGroupBy) Aggregate(fns ...AggregateFunc) *APIKeyGroupBy {
|
||||||
_g.fns = append(_g.fns, fns...)
|
_g.fns = append(_g.fns, fns...)
|
||||||
return _g
|
return _g
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan applies the selector query and scans the result into the given value.
|
// Scan applies the selector query and scans the result into the given value.
|
||||||
func (_g *ApiKeyGroupBy) Scan(ctx context.Context, v any) error {
|
func (_g *APIKeyGroupBy) Scan(ctx context.Context, v any) error {
|
||||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return scanWithInterceptors[*ApiKeyQuery, *ApiKeyGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
return scanWithInterceptors[*APIKeyQuery, *APIKeyGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_g *ApiKeyGroupBy) sqlScan(ctx context.Context, root *ApiKeyQuery, v any) error {
|
func (_g *APIKeyGroupBy) sqlScan(ctx context.Context, root *APIKeyQuery, v any) error {
|
||||||
selector := root.sqlQuery(ctx).Select()
|
selector := root.sqlQuery(ctx).Select()
|
||||||
aggregation := make([]string, 0, len(_g.fns))
|
aggregation := make([]string, 0, len(_g.fns))
|
||||||
for _, fn := range _g.fns {
|
for _, fn := range _g.fns {
|
||||||
@@ -716,28 +716,28 @@ func (_g *ApiKeyGroupBy) sqlScan(ctx context.Context, root *ApiKeyQuery, v any)
|
|||||||
return sql.ScanSlice(rows, v)
|
return sql.ScanSlice(rows, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeySelect is the builder for selecting fields of ApiKey entities.
|
// APIKeySelect is the builder for selecting fields of APIKey entities.
|
||||||
type ApiKeySelect struct {
|
type APIKeySelect struct {
|
||||||
*ApiKeyQuery
|
*APIKeyQuery
|
||||||
selector
|
selector
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregate adds the given aggregation functions to the selector query.
|
// Aggregate adds the given aggregation functions to the selector query.
|
||||||
func (_s *ApiKeySelect) Aggregate(fns ...AggregateFunc) *ApiKeySelect {
|
func (_s *APIKeySelect) Aggregate(fns ...AggregateFunc) *APIKeySelect {
|
||||||
_s.fns = append(_s.fns, fns...)
|
_s.fns = append(_s.fns, fns...)
|
||||||
return _s
|
return _s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan applies the selector query and scans the result into the given value.
|
// Scan applies the selector query and scans the result into the given value.
|
||||||
func (_s *ApiKeySelect) Scan(ctx context.Context, v any) error {
|
func (_s *APIKeySelect) Scan(ctx context.Context, v any) error {
|
||||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||||
if err := _s.prepareQuery(ctx); err != nil {
|
if err := _s.prepareQuery(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return scanWithInterceptors[*ApiKeyQuery, *ApiKeySelect](ctx, _s.ApiKeyQuery, _s, _s.inters, v)
|
return scanWithInterceptors[*APIKeyQuery, *APIKeySelect](ctx, _s.APIKeyQuery, _s, _s.inters, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_s *ApiKeySelect) sqlScan(ctx context.Context, root *ApiKeyQuery, v any) error {
|
func (_s *APIKeySelect) sqlScan(ctx context.Context, root *APIKeyQuery, v any) error {
|
||||||
selector := root.sqlQuery(ctx)
|
selector := root.sqlQuery(ctx)
|
||||||
aggregation := make([]string, 0, len(_s.fns))
|
aggregation := make([]string, 0, len(_s.fns))
|
||||||
for _, fn := range _s.fns {
|
for _, fn := range _s.fns {
|
||||||
|
|||||||
@@ -18,33 +18,33 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKeyUpdate is the builder for updating ApiKey entities.
|
// APIKeyUpdate is the builder for updating APIKey entities.
|
||||||
type ApiKeyUpdate struct {
|
type APIKeyUpdate struct {
|
||||||
config
|
config
|
||||||
hooks []Hook
|
hooks []Hook
|
||||||
mutation *ApiKeyMutation
|
mutation *APIKeyMutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where appends a list predicates to the ApiKeyUpdate builder.
|
// Where appends a list predicates to the APIKeyUpdate builder.
|
||||||
func (_u *ApiKeyUpdate) Where(ps ...predicate.ApiKey) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) Where(ps ...predicate.APIKey) *APIKeyUpdate {
|
||||||
_u.mutation.Where(ps...)
|
_u.mutation.Where(ps...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (_u *ApiKeyUpdate) SetUpdatedAt(v time.Time) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetUpdatedAt(v time.Time) *APIKeyUpdate {
|
||||||
_u.mutation.SetUpdatedAt(v)
|
_u.mutation.SetUpdatedAt(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (_u *ApiKeyUpdate) SetDeletedAt(v time.Time) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetDeletedAt(v time.Time) *APIKeyUpdate {
|
||||||
_u.mutation.SetDeletedAt(v)
|
_u.mutation.SetDeletedAt(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableDeletedAt(v *time.Time) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetDeletedAt(*v)
|
_u.SetDeletedAt(*v)
|
||||||
}
|
}
|
||||||
@@ -52,19 +52,19 @@ func (_u *ApiKeyUpdate) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||||
func (_u *ApiKeyUpdate) ClearDeletedAt() *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) ClearDeletedAt() *APIKeyUpdate {
|
||||||
_u.mutation.ClearDeletedAt()
|
_u.mutation.ClearDeletedAt()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (_u *ApiKeyUpdate) SetUserID(v int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetUserID(v int64) *APIKeyUpdate {
|
||||||
_u.mutation.SetUserID(v)
|
_u.mutation.SetUserID(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableUserID(v *int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableUserID(v *int64) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetUserID(*v)
|
_u.SetUserID(*v)
|
||||||
}
|
}
|
||||||
@@ -72,13 +72,13 @@ func (_u *ApiKeyUpdate) SetNillableUserID(v *int64) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (_u *ApiKeyUpdate) SetKey(v string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetKey(v string) *APIKeyUpdate {
|
||||||
_u.mutation.SetKey(v)
|
_u.mutation.SetKey(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableKey sets the "key" field if the given value is not nil.
|
// SetNillableKey sets the "key" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableKey(v *string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableKey(v *string) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetKey(*v)
|
_u.SetKey(*v)
|
||||||
}
|
}
|
||||||
@@ -86,13 +86,13 @@ func (_u *ApiKeyUpdate) SetNillableKey(v *string) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (_u *ApiKeyUpdate) SetName(v string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetName(v string) *APIKeyUpdate {
|
||||||
_u.mutation.SetName(v)
|
_u.mutation.SetName(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableName sets the "name" field if the given value is not nil.
|
// SetNillableName sets the "name" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableName(v *string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableName(v *string) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetName(*v)
|
_u.SetName(*v)
|
||||||
}
|
}
|
||||||
@@ -100,13 +100,13 @@ func (_u *ApiKeyUpdate) SetNillableName(v *string) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (_u *ApiKeyUpdate) SetGroupID(v int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetGroupID(v int64) *APIKeyUpdate {
|
||||||
_u.mutation.SetGroupID(v)
|
_u.mutation.SetGroupID(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableGroupID(v *int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableGroupID(v *int64) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetGroupID(*v)
|
_u.SetGroupID(*v)
|
||||||
}
|
}
|
||||||
@@ -114,19 +114,19 @@ func (_u *ApiKeyUpdate) SetNillableGroupID(v *int64) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroupID clears the value of the "group_id" field.
|
// ClearGroupID clears the value of the "group_id" field.
|
||||||
func (_u *ApiKeyUpdate) ClearGroupID() *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) ClearGroupID() *APIKeyUpdate {
|
||||||
_u.mutation.ClearGroupID()
|
_u.mutation.ClearGroupID()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (_u *ApiKeyUpdate) SetStatus(v string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetStatus(v string) *APIKeyUpdate {
|
||||||
_u.mutation.SetStatus(v)
|
_u.mutation.SetStatus(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableStatus sets the "status" field if the given value is not nil.
|
// SetNillableStatus sets the "status" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdate) SetNillableStatus(v *string) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetNillableStatus(v *string) *APIKeyUpdate {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetStatus(*v)
|
_u.SetStatus(*v)
|
||||||
}
|
}
|
||||||
@@ -134,23 +134,23 @@ func (_u *ApiKeyUpdate) SetNillableStatus(v *string) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUser sets the "user" edge to the User entity.
|
// SetUser sets the "user" edge to the User entity.
|
||||||
func (_u *ApiKeyUpdate) SetUser(v *User) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetUser(v *User) *APIKeyUpdate {
|
||||||
return _u.SetUserID(v.ID)
|
return _u.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroup sets the "group" edge to the Group entity.
|
// SetGroup sets the "group" edge to the Group entity.
|
||||||
func (_u *ApiKeyUpdate) SetGroup(v *Group) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) SetGroup(v *Group) *APIKeyUpdate {
|
||||||
return _u.SetGroupID(v.ID)
|
return _u.SetGroupID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
||||||
func (_u *ApiKeyUpdate) AddUsageLogIDs(ids ...int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) AddUsageLogIDs(ids ...int64) *APIKeyUpdate {
|
||||||
_u.mutation.AddUsageLogIDs(ids...)
|
_u.mutation.AddUsageLogIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
||||||
func (_u *ApiKeyUpdate) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) AddUsageLogs(v ...*UsageLog) *APIKeyUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -158,37 +158,37 @@ func (_u *ApiKeyUpdate) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
|
|||||||
return _u.AddUsageLogIDs(ids...)
|
return _u.AddUsageLogIDs(ids...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutation returns the ApiKeyMutation object of the builder.
|
// Mutation returns the APIKeyMutation object of the builder.
|
||||||
func (_u *ApiKeyUpdate) Mutation() *ApiKeyMutation {
|
func (_u *APIKeyUpdate) Mutation() *APIKeyMutation {
|
||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearUser clears the "user" edge to the User entity.
|
// ClearUser clears the "user" edge to the User entity.
|
||||||
func (_u *ApiKeyUpdate) ClearUser() *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) ClearUser() *APIKeyUpdate {
|
||||||
_u.mutation.ClearUser()
|
_u.mutation.ClearUser()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroup clears the "group" edge to the Group entity.
|
// ClearGroup clears the "group" edge to the Group entity.
|
||||||
func (_u *ApiKeyUpdate) ClearGroup() *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) ClearGroup() *APIKeyUpdate {
|
||||||
_u.mutation.ClearGroup()
|
_u.mutation.ClearGroup()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
|
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
|
||||||
func (_u *ApiKeyUpdate) ClearUsageLogs() *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) ClearUsageLogs() *APIKeyUpdate {
|
||||||
_u.mutation.ClearUsageLogs()
|
_u.mutation.ClearUsageLogs()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
|
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
|
||||||
func (_u *ApiKeyUpdate) RemoveUsageLogIDs(ids ...int64) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) RemoveUsageLogIDs(ids ...int64) *APIKeyUpdate {
|
||||||
_u.mutation.RemoveUsageLogIDs(ids...)
|
_u.mutation.RemoveUsageLogIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
|
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
|
||||||
func (_u *ApiKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
|
func (_u *APIKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *APIKeyUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -197,7 +197,7 @@ func (_u *ApiKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||||
func (_u *ApiKeyUpdate) Save(ctx context.Context) (int, error) {
|
func (_u *APIKeyUpdate) Save(ctx context.Context) (int, error) {
|
||||||
if err := _u.defaults(); err != nil {
|
if err := _u.defaults(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ func (_u *ApiKeyUpdate) Save(ctx context.Context) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveX is like Save, but panics if an error occurs.
|
// SaveX is like Save, but panics if an error occurs.
|
||||||
func (_u *ApiKeyUpdate) SaveX(ctx context.Context) int {
|
func (_u *APIKeyUpdate) SaveX(ctx context.Context) int {
|
||||||
affected, err := _u.Save(ctx)
|
affected, err := _u.Save(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -214,20 +214,20 @@ func (_u *ApiKeyUpdate) SaveX(ctx context.Context) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (_u *ApiKeyUpdate) Exec(ctx context.Context) error {
|
func (_u *APIKeyUpdate) Exec(ctx context.Context) error {
|
||||||
_, err := _u.Save(ctx)
|
_, err := _u.Save(ctx)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_u *ApiKeyUpdate) ExecX(ctx context.Context) {
|
func (_u *APIKeyUpdate) ExecX(ctx context.Context) {
|
||||||
if err := _u.Exec(ctx); err != nil {
|
if err := _u.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults sets the default values of the builder before save.
|
// defaults sets the default values of the builder before save.
|
||||||
func (_u *ApiKeyUpdate) defaults() error {
|
func (_u *APIKeyUpdate) defaults() error {
|
||||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||||
if apikey.UpdateDefaultUpdatedAt == nil {
|
if apikey.UpdateDefaultUpdatedAt == nil {
|
||||||
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
||||||
@@ -239,29 +239,29 @@ func (_u *ApiKeyUpdate) defaults() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check runs all checks and user-defined validators on the builder.
|
// check runs all checks and user-defined validators on the builder.
|
||||||
func (_u *ApiKeyUpdate) check() error {
|
func (_u *APIKeyUpdate) check() error {
|
||||||
if v, ok := _u.mutation.Key(); ok {
|
if v, ok := _u.mutation.Key(); ok {
|
||||||
if err := apikey.KeyValidator(v); err != nil {
|
if err := apikey.KeyValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
|
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := _u.mutation.Name(); ok {
|
if v, ok := _u.mutation.Name(); ok {
|
||||||
if err := apikey.NameValidator(v); err != nil {
|
if err := apikey.NameValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
|
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := _u.mutation.Status(); ok {
|
if v, ok := _u.mutation.Status(); ok {
|
||||||
if err := apikey.StatusValidator(v); err != nil {
|
if err := apikey.StatusValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
|
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||||
return errors.New(`ent: clearing a required unique edge "ApiKey.user"`)
|
return errors.New(`ent: clearing a required unique edge "APIKey.user"`)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_u *ApiKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
func (_u *APIKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||||
if err := _u.check(); err != nil {
|
if err := _u.check(); err != nil {
|
||||||
return _node, err
|
return _node, err
|
||||||
}
|
}
|
||||||
@@ -406,28 +406,28 @@ func (_u *ApiKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
|||||||
return _node, nil
|
return _node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyUpdateOne is the builder for updating a single ApiKey entity.
|
// APIKeyUpdateOne is the builder for updating a single APIKey entity.
|
||||||
type ApiKeyUpdateOne struct {
|
type APIKeyUpdateOne struct {
|
||||||
config
|
config
|
||||||
fields []string
|
fields []string
|
||||||
hooks []Hook
|
hooks []Hook
|
||||||
mutation *ApiKeyMutation
|
mutation *APIKeyMutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUpdatedAt sets the "updated_at" field.
|
// SetUpdatedAt sets the "updated_at" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetUpdatedAt(v time.Time) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetUpdatedAt(v time.Time) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetUpdatedAt(v)
|
_u.mutation.SetUpdatedAt(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeletedAt sets the "deleted_at" field.
|
// SetDeletedAt sets the "deleted_at" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetDeletedAt(v time.Time) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetDeletedAt(v time.Time) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetDeletedAt(v)
|
_u.mutation.SetDeletedAt(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetDeletedAt(*v)
|
_u.SetDeletedAt(*v)
|
||||||
}
|
}
|
||||||
@@ -435,19 +435,19 @@ func (_u *ApiKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||||
func (_u *ApiKeyUpdateOne) ClearDeletedAt() *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) ClearDeletedAt() *APIKeyUpdateOne {
|
||||||
_u.mutation.ClearDeletedAt()
|
_u.mutation.ClearDeletedAt()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserID sets the "user_id" field.
|
// SetUserID sets the "user_id" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetUserID(v int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetUserID(v int64) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetUserID(v)
|
_u.mutation.SetUserID(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableUserID(v *int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableUserID(v *int64) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetUserID(*v)
|
_u.SetUserID(*v)
|
||||||
}
|
}
|
||||||
@@ -455,13 +455,13 @@ func (_u *ApiKeyUpdateOne) SetNillableUserID(v *int64) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetKey sets the "key" field.
|
// SetKey sets the "key" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetKey(v string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetKey(v string) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetKey(v)
|
_u.mutation.SetKey(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableKey sets the "key" field if the given value is not nil.
|
// SetNillableKey sets the "key" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableKey(v *string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableKey(v *string) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetKey(*v)
|
_u.SetKey(*v)
|
||||||
}
|
}
|
||||||
@@ -469,13 +469,13 @@ func (_u *ApiKeyUpdateOne) SetNillableKey(v *string) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the "name" field.
|
// SetName sets the "name" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetName(v string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetName(v string) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetName(v)
|
_u.mutation.SetName(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableName sets the "name" field if the given value is not nil.
|
// SetNillableName sets the "name" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableName(v *string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableName(v *string) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetName(*v)
|
_u.SetName(*v)
|
||||||
}
|
}
|
||||||
@@ -483,13 +483,13 @@ func (_u *ApiKeyUpdateOne) SetNillableName(v *string) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetGroupID sets the "group_id" field.
|
// SetGroupID sets the "group_id" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetGroupID(v int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetGroupID(v int64) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetGroupID(v)
|
_u.mutation.SetGroupID(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableGroupID(v *int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableGroupID(v *int64) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetGroupID(*v)
|
_u.SetGroupID(*v)
|
||||||
}
|
}
|
||||||
@@ -497,19 +497,19 @@ func (_u *ApiKeyUpdateOne) SetNillableGroupID(v *int64) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroupID clears the value of the "group_id" field.
|
// ClearGroupID clears the value of the "group_id" field.
|
||||||
func (_u *ApiKeyUpdateOne) ClearGroupID() *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) ClearGroupID() *APIKeyUpdateOne {
|
||||||
_u.mutation.ClearGroupID()
|
_u.mutation.ClearGroupID()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (_u *ApiKeyUpdateOne) SetStatus(v string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetStatus(v string) *APIKeyUpdateOne {
|
||||||
_u.mutation.SetStatus(v)
|
_u.mutation.SetStatus(v)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNillableStatus sets the "status" field if the given value is not nil.
|
// SetNillableStatus sets the "status" field if the given value is not nil.
|
||||||
func (_u *ApiKeyUpdateOne) SetNillableStatus(v *string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetNillableStatus(v *string) *APIKeyUpdateOne {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
_u.SetStatus(*v)
|
_u.SetStatus(*v)
|
||||||
}
|
}
|
||||||
@@ -517,23 +517,23 @@ func (_u *ApiKeyUpdateOne) SetNillableStatus(v *string) *ApiKeyUpdateOne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUser sets the "user" edge to the User entity.
|
// SetUser sets the "user" edge to the User entity.
|
||||||
func (_u *ApiKeyUpdateOne) SetUser(v *User) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetUser(v *User) *APIKeyUpdateOne {
|
||||||
return _u.SetUserID(v.ID)
|
return _u.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGroup sets the "group" edge to the Group entity.
|
// SetGroup sets the "group" edge to the Group entity.
|
||||||
func (_u *ApiKeyUpdateOne) SetGroup(v *Group) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) SetGroup(v *Group) *APIKeyUpdateOne {
|
||||||
return _u.SetGroupID(v.ID)
|
return _u.SetGroupID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
|
||||||
func (_u *ApiKeyUpdateOne) AddUsageLogIDs(ids ...int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) AddUsageLogIDs(ids ...int64) *APIKeyUpdateOne {
|
||||||
_u.mutation.AddUsageLogIDs(ids...)
|
_u.mutation.AddUsageLogIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
|
||||||
func (_u *ApiKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *APIKeyUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -541,37 +541,37 @@ func (_u *ApiKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
|
|||||||
return _u.AddUsageLogIDs(ids...)
|
return _u.AddUsageLogIDs(ids...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutation returns the ApiKeyMutation object of the builder.
|
// Mutation returns the APIKeyMutation object of the builder.
|
||||||
func (_u *ApiKeyUpdateOne) Mutation() *ApiKeyMutation {
|
func (_u *APIKeyUpdateOne) Mutation() *APIKeyMutation {
|
||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearUser clears the "user" edge to the User entity.
|
// ClearUser clears the "user" edge to the User entity.
|
||||||
func (_u *ApiKeyUpdateOne) ClearUser() *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) ClearUser() *APIKeyUpdateOne {
|
||||||
_u.mutation.ClearUser()
|
_u.mutation.ClearUser()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearGroup clears the "group" edge to the Group entity.
|
// ClearGroup clears the "group" edge to the Group entity.
|
||||||
func (_u *ApiKeyUpdateOne) ClearGroup() *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) ClearGroup() *APIKeyUpdateOne {
|
||||||
_u.mutation.ClearGroup()
|
_u.mutation.ClearGroup()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
|
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
|
||||||
func (_u *ApiKeyUpdateOne) ClearUsageLogs() *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) ClearUsageLogs() *APIKeyUpdateOne {
|
||||||
_u.mutation.ClearUsageLogs()
|
_u.mutation.ClearUsageLogs()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
|
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
|
||||||
func (_u *ApiKeyUpdateOne) RemoveUsageLogIDs(ids ...int64) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) RemoveUsageLogIDs(ids ...int64) *APIKeyUpdateOne {
|
||||||
_u.mutation.RemoveUsageLogIDs(ids...)
|
_u.mutation.RemoveUsageLogIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
|
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
|
||||||
func (_u *ApiKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *APIKeyUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -579,21 +579,21 @@ func (_u *ApiKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
|
|||||||
return _u.RemoveUsageLogIDs(ids...)
|
return _u.RemoveUsageLogIDs(ids...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where appends a list predicates to the ApiKeyUpdate builder.
|
// Where appends a list predicates to the APIKeyUpdate builder.
|
||||||
func (_u *ApiKeyUpdateOne) Where(ps ...predicate.ApiKey) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) Where(ps ...predicate.APIKey) *APIKeyUpdateOne {
|
||||||
_u.mutation.Where(ps...)
|
_u.mutation.Where(ps...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||||
// The default is selecting all fields defined in the entity schema.
|
// The default is selecting all fields defined in the entity schema.
|
||||||
func (_u *ApiKeyUpdateOne) Select(field string, fields ...string) *ApiKeyUpdateOne {
|
func (_u *APIKeyUpdateOne) Select(field string, fields ...string) *APIKeyUpdateOne {
|
||||||
_u.fields = append([]string{field}, fields...)
|
_u.fields = append([]string{field}, fields...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save executes the query and returns the updated ApiKey entity.
|
// Save executes the query and returns the updated APIKey entity.
|
||||||
func (_u *ApiKeyUpdateOne) Save(ctx context.Context) (*ApiKey, error) {
|
func (_u *APIKeyUpdateOne) Save(ctx context.Context) (*APIKey, error) {
|
||||||
if err := _u.defaults(); err != nil {
|
if err := _u.defaults(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -601,7 +601,7 @@ func (_u *ApiKeyUpdateOne) Save(ctx context.Context) (*ApiKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveX is like Save, but panics if an error occurs.
|
// SaveX is like Save, but panics if an error occurs.
|
||||||
func (_u *ApiKeyUpdateOne) SaveX(ctx context.Context) *ApiKey {
|
func (_u *APIKeyUpdateOne) SaveX(ctx context.Context) *APIKey {
|
||||||
node, err := _u.Save(ctx)
|
node, err := _u.Save(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -610,20 +610,20 @@ func (_u *ApiKeyUpdateOne) SaveX(ctx context.Context) *ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the query on the entity.
|
// Exec executes the query on the entity.
|
||||||
func (_u *ApiKeyUpdateOne) Exec(ctx context.Context) error {
|
func (_u *APIKeyUpdateOne) Exec(ctx context.Context) error {
|
||||||
_, err := _u.Save(ctx)
|
_, err := _u.Save(ctx)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecX is like Exec, but panics if an error occurs.
|
// ExecX is like Exec, but panics if an error occurs.
|
||||||
func (_u *ApiKeyUpdateOne) ExecX(ctx context.Context) {
|
func (_u *APIKeyUpdateOne) ExecX(ctx context.Context) {
|
||||||
if err := _u.Exec(ctx); err != nil {
|
if err := _u.Exec(ctx); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults sets the default values of the builder before save.
|
// defaults sets the default values of the builder before save.
|
||||||
func (_u *ApiKeyUpdateOne) defaults() error {
|
func (_u *APIKeyUpdateOne) defaults() error {
|
||||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||||
if apikey.UpdateDefaultUpdatedAt == nil {
|
if apikey.UpdateDefaultUpdatedAt == nil {
|
||||||
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
||||||
@@ -635,36 +635,36 @@ func (_u *ApiKeyUpdateOne) defaults() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check runs all checks and user-defined validators on the builder.
|
// check runs all checks and user-defined validators on the builder.
|
||||||
func (_u *ApiKeyUpdateOne) check() error {
|
func (_u *APIKeyUpdateOne) check() error {
|
||||||
if v, ok := _u.mutation.Key(); ok {
|
if v, ok := _u.mutation.Key(); ok {
|
||||||
if err := apikey.KeyValidator(v); err != nil {
|
if err := apikey.KeyValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
|
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := _u.mutation.Name(); ok {
|
if v, ok := _u.mutation.Name(); ok {
|
||||||
if err := apikey.NameValidator(v); err != nil {
|
if err := apikey.NameValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
|
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := _u.mutation.Status(); ok {
|
if v, ok := _u.mutation.Status(); ok {
|
||||||
if err := apikey.StatusValidator(v); err != nil {
|
if err := apikey.StatusValidator(v); err != nil {
|
||||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
|
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||||
return errors.New(`ent: clearing a required unique edge "ApiKey.user"`)
|
return errors.New(`ent: clearing a required unique edge "APIKey.user"`)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_u *ApiKeyUpdateOne) sqlSave(ctx context.Context) (_node *ApiKey, err error) {
|
func (_u *APIKeyUpdateOne) sqlSave(ctx context.Context) (_node *APIKey, err error) {
|
||||||
if err := _u.check(); err != nil {
|
if err := _u.check(); err != nil {
|
||||||
return _node, err
|
return _node, err
|
||||||
}
|
}
|
||||||
_spec := sqlgraph.NewUpdateSpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
_spec := sqlgraph.NewUpdateSpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
|
||||||
id, ok := _u.mutation.ID()
|
id, ok := _u.mutation.ID()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ApiKey.id" for update`)}
|
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "APIKey.id" for update`)}
|
||||||
}
|
}
|
||||||
_spec.Node.ID.Value = id
|
_spec.Node.ID.Value = id
|
||||||
if fields := _u.fields; len(fields) > 0 {
|
if fields := _u.fields; len(fields) > 0 {
|
||||||
@@ -807,7 +807,7 @@ func (_u *ApiKeyUpdateOne) sqlSave(ctx context.Context) (_node *ApiKey, err erro
|
|||||||
}
|
}
|
||||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||||
}
|
}
|
||||||
_node = &ApiKey{config: _u.config}
|
_node = &APIKey{config: _u.config}
|
||||||
_spec.Assign = _node.assignValues
|
_spec.Assign = _node.assignValues
|
||||||
_spec.ScanValues = _node.scanValues
|
_spec.ScanValues = _node.scanValues
|
||||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ type Client struct {
|
|||||||
config
|
config
|
||||||
// Schema is the client for creating, migrating and dropping schema.
|
// Schema is the client for creating, migrating and dropping schema.
|
||||||
Schema *migrate.Schema
|
Schema *migrate.Schema
|
||||||
|
// APIKey is the client for interacting with the APIKey builders.
|
||||||
|
APIKey *APIKeyClient
|
||||||
// Account is the client for interacting with the Account builders.
|
// Account is the client for interacting with the Account builders.
|
||||||
Account *AccountClient
|
Account *AccountClient
|
||||||
// AccountGroup is the client for interacting with the AccountGroup builders.
|
// AccountGroup is the client for interacting with the AccountGroup builders.
|
||||||
AccountGroup *AccountGroupClient
|
AccountGroup *AccountGroupClient
|
||||||
// ApiKey is the client for interacting with the ApiKey builders.
|
|
||||||
ApiKey *ApiKeyClient
|
|
||||||
// Group is the client for interacting with the Group builders.
|
// Group is the client for interacting with the Group builders.
|
||||||
Group *GroupClient
|
Group *GroupClient
|
||||||
// Proxy is the client for interacting with the Proxy builders.
|
// Proxy is the client for interacting with the Proxy builders.
|
||||||
@@ -74,9 +74,9 @@ func NewClient(opts ...Option) *Client {
|
|||||||
|
|
||||||
func (c *Client) init() {
|
func (c *Client) init() {
|
||||||
c.Schema = migrate.NewSchema(c.driver)
|
c.Schema = migrate.NewSchema(c.driver)
|
||||||
|
c.APIKey = NewAPIKeyClient(c.config)
|
||||||
c.Account = NewAccountClient(c.config)
|
c.Account = NewAccountClient(c.config)
|
||||||
c.AccountGroup = NewAccountGroupClient(c.config)
|
c.AccountGroup = NewAccountGroupClient(c.config)
|
||||||
c.ApiKey = NewApiKeyClient(c.config)
|
|
||||||
c.Group = NewGroupClient(c.config)
|
c.Group = NewGroupClient(c.config)
|
||||||
c.Proxy = NewProxyClient(c.config)
|
c.Proxy = NewProxyClient(c.config)
|
||||||
c.RedeemCode = NewRedeemCodeClient(c.config)
|
c.RedeemCode = NewRedeemCodeClient(c.config)
|
||||||
@@ -179,9 +179,9 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
|||||||
return &Tx{
|
return &Tx{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
|
APIKey: NewAPIKeyClient(cfg),
|
||||||
Account: NewAccountClient(cfg),
|
Account: NewAccountClient(cfg),
|
||||||
AccountGroup: NewAccountGroupClient(cfg),
|
AccountGroup: NewAccountGroupClient(cfg),
|
||||||
ApiKey: NewApiKeyClient(cfg),
|
|
||||||
Group: NewGroupClient(cfg),
|
Group: NewGroupClient(cfg),
|
||||||
Proxy: NewProxyClient(cfg),
|
Proxy: NewProxyClient(cfg),
|
||||||
RedeemCode: NewRedeemCodeClient(cfg),
|
RedeemCode: NewRedeemCodeClient(cfg),
|
||||||
@@ -211,9 +211,9 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
|
|||||||
return &Tx{
|
return &Tx{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
|
APIKey: NewAPIKeyClient(cfg),
|
||||||
Account: NewAccountClient(cfg),
|
Account: NewAccountClient(cfg),
|
||||||
AccountGroup: NewAccountGroupClient(cfg),
|
AccountGroup: NewAccountGroupClient(cfg),
|
||||||
ApiKey: NewApiKeyClient(cfg),
|
|
||||||
Group: NewGroupClient(cfg),
|
Group: NewGroupClient(cfg),
|
||||||
Proxy: NewProxyClient(cfg),
|
Proxy: NewProxyClient(cfg),
|
||||||
RedeemCode: NewRedeemCodeClient(cfg),
|
RedeemCode: NewRedeemCodeClient(cfg),
|
||||||
@@ -230,7 +230,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
|
|||||||
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
|
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
|
||||||
//
|
//
|
||||||
// client.Debug().
|
// client.Debug().
|
||||||
// Account.
|
// APIKey.
|
||||||
// Query().
|
// Query().
|
||||||
// Count(ctx)
|
// Count(ctx)
|
||||||
func (c *Client) Debug() *Client {
|
func (c *Client) Debug() *Client {
|
||||||
@@ -253,7 +253,7 @@ func (c *Client) Close() error {
|
|||||||
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
|
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
|
||||||
func (c *Client) Use(hooks ...Hook) {
|
func (c *Client) Use(hooks ...Hook) {
|
||||||
for _, n := range []interface{ Use(...Hook) }{
|
for _, n := range []interface{ Use(...Hook) }{
|
||||||
c.Account, c.AccountGroup, c.ApiKey, c.Group, c.Proxy, c.RedeemCode, c.Setting,
|
c.APIKey, c.Account, c.AccountGroup, c.Group, c.Proxy, c.RedeemCode, c.Setting,
|
||||||
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
|
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
|
||||||
c.UserAttributeValue, c.UserSubscription,
|
c.UserAttributeValue, c.UserSubscription,
|
||||||
} {
|
} {
|
||||||
@@ -265,7 +265,7 @@ func (c *Client) Use(hooks ...Hook) {
|
|||||||
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
|
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
|
||||||
func (c *Client) Intercept(interceptors ...Interceptor) {
|
func (c *Client) Intercept(interceptors ...Interceptor) {
|
||||||
for _, n := range []interface{ Intercept(...Interceptor) }{
|
for _, n := range []interface{ Intercept(...Interceptor) }{
|
||||||
c.Account, c.AccountGroup, c.ApiKey, c.Group, c.Proxy, c.RedeemCode, c.Setting,
|
c.APIKey, c.Account, c.AccountGroup, c.Group, c.Proxy, c.RedeemCode, c.Setting,
|
||||||
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
|
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
|
||||||
c.UserAttributeValue, c.UserSubscription,
|
c.UserAttributeValue, c.UserSubscription,
|
||||||
} {
|
} {
|
||||||
@@ -276,12 +276,12 @@ func (c *Client) Intercept(interceptors ...Interceptor) {
|
|||||||
// Mutate implements the ent.Mutator interface.
|
// Mutate implements the ent.Mutator interface.
|
||||||
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
||||||
switch m := m.(type) {
|
switch m := m.(type) {
|
||||||
|
case *APIKeyMutation:
|
||||||
|
return c.APIKey.mutate(ctx, m)
|
||||||
case *AccountMutation:
|
case *AccountMutation:
|
||||||
return c.Account.mutate(ctx, m)
|
return c.Account.mutate(ctx, m)
|
||||||
case *AccountGroupMutation:
|
case *AccountGroupMutation:
|
||||||
return c.AccountGroup.mutate(ctx, m)
|
return c.AccountGroup.mutate(ctx, m)
|
||||||
case *ApiKeyMutation:
|
|
||||||
return c.ApiKey.mutate(ctx, m)
|
|
||||||
case *GroupMutation:
|
case *GroupMutation:
|
||||||
return c.Group.mutate(ctx, m)
|
return c.Group.mutate(ctx, m)
|
||||||
case *ProxyMutation:
|
case *ProxyMutation:
|
||||||
@@ -307,6 +307,189 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIKeyClient is a client for the APIKey schema.
|
||||||
|
type APIKeyClient struct {
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAPIKeyClient returns a client for the APIKey from the given config.
|
||||||
|
func NewAPIKeyClient(c config) *APIKeyClient {
|
||||||
|
return &APIKeyClient{config: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use adds a list of mutation hooks to the hooks stack.
|
||||||
|
// A call to `Use(f, g, h)` equals to `apikey.Hooks(f(g(h())))`.
|
||||||
|
func (c *APIKeyClient) Use(hooks ...Hook) {
|
||||||
|
c.hooks.APIKey = append(c.hooks.APIKey, hooks...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||||
|
// A call to `Intercept(f, g, h)` equals to `apikey.Intercept(f(g(h())))`.
|
||||||
|
func (c *APIKeyClient) Intercept(interceptors ...Interceptor) {
|
||||||
|
c.inters.APIKey = append(c.inters.APIKey, interceptors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create returns a builder for creating a APIKey entity.
|
||||||
|
func (c *APIKeyClient) Create() *APIKeyCreate {
|
||||||
|
mutation := newAPIKeyMutation(c.config, OpCreate)
|
||||||
|
return &APIKeyCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBulk returns a builder for creating a bulk of APIKey entities.
|
||||||
|
func (c *APIKeyClient) CreateBulk(builders ...*APIKeyCreate) *APIKeyCreateBulk {
|
||||||
|
return &APIKeyCreateBulk{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 *APIKeyClient) MapCreateBulk(slice any, setFunc func(*APIKeyCreate, int)) *APIKeyCreateBulk {
|
||||||
|
rv := reflect.ValueOf(slice)
|
||||||
|
if rv.Kind() != reflect.Slice {
|
||||||
|
return &APIKeyCreateBulk{err: fmt.Errorf("calling to APIKeyClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||||
|
}
|
||||||
|
builders := make([]*APIKeyCreate, rv.Len())
|
||||||
|
for i := 0; i < rv.Len(); i++ {
|
||||||
|
builders[i] = c.Create()
|
||||||
|
setFunc(builders[i], i)
|
||||||
|
}
|
||||||
|
return &APIKeyCreateBulk{config: c.config, builders: builders}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update returns an update builder for APIKey.
|
||||||
|
func (c *APIKeyClient) Update() *APIKeyUpdate {
|
||||||
|
mutation := newAPIKeyMutation(c.config, OpUpdate)
|
||||||
|
return &APIKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOne returns an update builder for the given entity.
|
||||||
|
func (c *APIKeyClient) UpdateOne(_m *APIKey) *APIKeyUpdateOne {
|
||||||
|
mutation := newAPIKeyMutation(c.config, OpUpdateOne, withAPIKey(_m))
|
||||||
|
return &APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOneID returns an update builder for the given id.
|
||||||
|
func (c *APIKeyClient) UpdateOneID(id int64) *APIKeyUpdateOne {
|
||||||
|
mutation := newAPIKeyMutation(c.config, OpUpdateOne, withAPIKeyID(id))
|
||||||
|
return &APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete returns a delete builder for APIKey.
|
||||||
|
func (c *APIKeyClient) Delete() *APIKeyDelete {
|
||||||
|
mutation := newAPIKeyMutation(c.config, OpDelete)
|
||||||
|
return &APIKeyDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOne returns a builder for deleting the given entity.
|
||||||
|
func (c *APIKeyClient) DeleteOne(_m *APIKey) *APIKeyDeleteOne {
|
||||||
|
return c.DeleteOneID(_m.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||||
|
func (c *APIKeyClient) DeleteOneID(id int64) *APIKeyDeleteOne {
|
||||||
|
builder := c.Delete().Where(apikey.ID(id))
|
||||||
|
builder.mutation.id = &id
|
||||||
|
builder.mutation.op = OpDeleteOne
|
||||||
|
return &APIKeyDeleteOne{builder}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query returns a query builder for APIKey.
|
||||||
|
func (c *APIKeyClient) Query() *APIKeyQuery {
|
||||||
|
return &APIKeyQuery{
|
||||||
|
config: c.config,
|
||||||
|
ctx: &QueryContext{Type: TypeAPIKey},
|
||||||
|
inters: c.Interceptors(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a APIKey entity by its id.
|
||||||
|
func (c *APIKeyClient) Get(ctx context.Context, id int64) (*APIKey, error) {
|
||||||
|
return c.Query().Where(apikey.ID(id)).Only(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetX is like Get, but panics if an error occurs.
|
||||||
|
func (c *APIKeyClient) GetX(ctx context.Context, id int64) *APIKey {
|
||||||
|
obj, err := c.Get(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUser queries the user edge of a APIKey.
|
||||||
|
func (c *APIKeyClient) QueryUser(_m *APIKey) *UserQuery {
|
||||||
|
query := (&UserClient{config: c.config}).Query()
|
||||||
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
|
id := _m.ID
|
||||||
|
step := sqlgraph.NewStep(
|
||||||
|
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
||||||
|
sqlgraph.To(user.Table, user.FieldID),
|
||||||
|
sqlgraph.Edge(sqlgraph.M2O, true, apikey.UserTable, apikey.UserColumn),
|
||||||
|
)
|
||||||
|
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||||
|
return fromV, nil
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGroup queries the group edge of a APIKey.
|
||||||
|
func (c *APIKeyClient) QueryGroup(_m *APIKey) *GroupQuery {
|
||||||
|
query := (&GroupClient{config: c.config}).Query()
|
||||||
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
|
id := _m.ID
|
||||||
|
step := sqlgraph.NewStep(
|
||||||
|
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
||||||
|
sqlgraph.To(group.Table, group.FieldID),
|
||||||
|
sqlgraph.Edge(sqlgraph.M2O, true, apikey.GroupTable, apikey.GroupColumn),
|
||||||
|
)
|
||||||
|
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||||
|
return fromV, nil
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUsageLogs queries the usage_logs edge of a APIKey.
|
||||||
|
func (c *APIKeyClient) QueryUsageLogs(_m *APIKey) *UsageLogQuery {
|
||||||
|
query := (&UsageLogClient{config: c.config}).Query()
|
||||||
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
|
id := _m.ID
|
||||||
|
step := sqlgraph.NewStep(
|
||||||
|
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
||||||
|
sqlgraph.To(usagelog.Table, usagelog.FieldID),
|
||||||
|
sqlgraph.Edge(sqlgraph.O2M, false, apikey.UsageLogsTable, apikey.UsageLogsColumn),
|
||||||
|
)
|
||||||
|
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||||
|
return fromV, nil
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hooks returns the client hooks.
|
||||||
|
func (c *APIKeyClient) Hooks() []Hook {
|
||||||
|
hooks := c.hooks.APIKey
|
||||||
|
return append(hooks[:len(hooks):len(hooks)], apikey.Hooks[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interceptors returns the client interceptors.
|
||||||
|
func (c *APIKeyClient) Interceptors() []Interceptor {
|
||||||
|
inters := c.inters.APIKey
|
||||||
|
return append(inters[:len(inters):len(inters)], apikey.Interceptors[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIKeyClient) mutate(ctx context.Context, m *APIKeyMutation) (Value, error) {
|
||||||
|
switch m.Op() {
|
||||||
|
case OpCreate:
|
||||||
|
return (&APIKeyCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||||
|
case OpUpdate:
|
||||||
|
return (&APIKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||||
|
case OpUpdateOne:
|
||||||
|
return (&APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||||
|
case OpDelete, OpDeleteOne:
|
||||||
|
return (&APIKeyDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ent: unknown APIKey mutation op: %q", m.Op())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AccountClient is a client for the Account schema.
|
// AccountClient is a client for the Account schema.
|
||||||
type AccountClient struct {
|
type AccountClient struct {
|
||||||
config
|
config
|
||||||
@@ -622,189 +805,6 @@ func (c *AccountGroupClient) mutate(ctx context.Context, m *AccountGroupMutation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiKeyClient is a client for the ApiKey schema.
|
|
||||||
type ApiKeyClient struct {
|
|
||||||
config
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewApiKeyClient returns a client for the ApiKey from the given config.
|
|
||||||
func NewApiKeyClient(c config) *ApiKeyClient {
|
|
||||||
return &ApiKeyClient{config: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use adds a list of mutation hooks to the hooks stack.
|
|
||||||
// A call to `Use(f, g, h)` equals to `apikey.Hooks(f(g(h())))`.
|
|
||||||
func (c *ApiKeyClient) Use(hooks ...Hook) {
|
|
||||||
c.hooks.ApiKey = append(c.hooks.ApiKey, hooks...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
|
||||||
// A call to `Intercept(f, g, h)` equals to `apikey.Intercept(f(g(h())))`.
|
|
||||||
func (c *ApiKeyClient) Intercept(interceptors ...Interceptor) {
|
|
||||||
c.inters.ApiKey = append(c.inters.ApiKey, interceptors...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create returns a builder for creating a ApiKey entity.
|
|
||||||
func (c *ApiKeyClient) Create() *ApiKeyCreate {
|
|
||||||
mutation := newApiKeyMutation(c.config, OpCreate)
|
|
||||||
return &ApiKeyCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBulk returns a builder for creating a bulk of ApiKey entities.
|
|
||||||
func (c *ApiKeyClient) CreateBulk(builders ...*ApiKeyCreate) *ApiKeyCreateBulk {
|
|
||||||
return &ApiKeyCreateBulk{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 *ApiKeyClient) MapCreateBulk(slice any, setFunc func(*ApiKeyCreate, int)) *ApiKeyCreateBulk {
|
|
||||||
rv := reflect.ValueOf(slice)
|
|
||||||
if rv.Kind() != reflect.Slice {
|
|
||||||
return &ApiKeyCreateBulk{err: fmt.Errorf("calling to ApiKeyClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
|
||||||
}
|
|
||||||
builders := make([]*ApiKeyCreate, rv.Len())
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
|
||||||
builders[i] = c.Create()
|
|
||||||
setFunc(builders[i], i)
|
|
||||||
}
|
|
||||||
return &ApiKeyCreateBulk{config: c.config, builders: builders}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update returns an update builder for ApiKey.
|
|
||||||
func (c *ApiKeyClient) Update() *ApiKeyUpdate {
|
|
||||||
mutation := newApiKeyMutation(c.config, OpUpdate)
|
|
||||||
return &ApiKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOne returns an update builder for the given entity.
|
|
||||||
func (c *ApiKeyClient) UpdateOne(_m *ApiKey) *ApiKeyUpdateOne {
|
|
||||||
mutation := newApiKeyMutation(c.config, OpUpdateOne, withApiKey(_m))
|
|
||||||
return &ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOneID returns an update builder for the given id.
|
|
||||||
func (c *ApiKeyClient) UpdateOneID(id int64) *ApiKeyUpdateOne {
|
|
||||||
mutation := newApiKeyMutation(c.config, OpUpdateOne, withApiKeyID(id))
|
|
||||||
return &ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete returns a delete builder for ApiKey.
|
|
||||||
func (c *ApiKeyClient) Delete() *ApiKeyDelete {
|
|
||||||
mutation := newApiKeyMutation(c.config, OpDelete)
|
|
||||||
return &ApiKeyDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteOne returns a builder for deleting the given entity.
|
|
||||||
func (c *ApiKeyClient) DeleteOne(_m *ApiKey) *ApiKeyDeleteOne {
|
|
||||||
return c.DeleteOneID(_m.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
|
||||||
func (c *ApiKeyClient) DeleteOneID(id int64) *ApiKeyDeleteOne {
|
|
||||||
builder := c.Delete().Where(apikey.ID(id))
|
|
||||||
builder.mutation.id = &id
|
|
||||||
builder.mutation.op = OpDeleteOne
|
|
||||||
return &ApiKeyDeleteOne{builder}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query returns a query builder for ApiKey.
|
|
||||||
func (c *ApiKeyClient) Query() *ApiKeyQuery {
|
|
||||||
return &ApiKeyQuery{
|
|
||||||
config: c.config,
|
|
||||||
ctx: &QueryContext{Type: TypeApiKey},
|
|
||||||
inters: c.Interceptors(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns a ApiKey entity by its id.
|
|
||||||
func (c *ApiKeyClient) Get(ctx context.Context, id int64) (*ApiKey, error) {
|
|
||||||
return c.Query().Where(apikey.ID(id)).Only(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetX is like Get, but panics if an error occurs.
|
|
||||||
func (c *ApiKeyClient) GetX(ctx context.Context, id int64) *ApiKey {
|
|
||||||
obj, err := c.Get(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryUser queries the user edge of a ApiKey.
|
|
||||||
func (c *ApiKeyClient) QueryUser(_m *ApiKey) *UserQuery {
|
|
||||||
query := (&UserClient{config: c.config}).Query()
|
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
|
||||||
id := _m.ID
|
|
||||||
step := sqlgraph.NewStep(
|
|
||||||
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
|
||||||
sqlgraph.To(user.Table, user.FieldID),
|
|
||||||
sqlgraph.Edge(sqlgraph.M2O, true, apikey.UserTable, apikey.UserColumn),
|
|
||||||
)
|
|
||||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
|
||||||
return fromV, nil
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryGroup queries the group edge of a ApiKey.
|
|
||||||
func (c *ApiKeyClient) QueryGroup(_m *ApiKey) *GroupQuery {
|
|
||||||
query := (&GroupClient{config: c.config}).Query()
|
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
|
||||||
id := _m.ID
|
|
||||||
step := sqlgraph.NewStep(
|
|
||||||
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
|
||||||
sqlgraph.To(group.Table, group.FieldID),
|
|
||||||
sqlgraph.Edge(sqlgraph.M2O, true, apikey.GroupTable, apikey.GroupColumn),
|
|
||||||
)
|
|
||||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
|
||||||
return fromV, nil
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryUsageLogs queries the usage_logs edge of a ApiKey.
|
|
||||||
func (c *ApiKeyClient) QueryUsageLogs(_m *ApiKey) *UsageLogQuery {
|
|
||||||
query := (&UsageLogClient{config: c.config}).Query()
|
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
|
||||||
id := _m.ID
|
|
||||||
step := sqlgraph.NewStep(
|
|
||||||
sqlgraph.From(apikey.Table, apikey.FieldID, id),
|
|
||||||
sqlgraph.To(usagelog.Table, usagelog.FieldID),
|
|
||||||
sqlgraph.Edge(sqlgraph.O2M, false, apikey.UsageLogsTable, apikey.UsageLogsColumn),
|
|
||||||
)
|
|
||||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
|
||||||
return fromV, nil
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hooks returns the client hooks.
|
|
||||||
func (c *ApiKeyClient) Hooks() []Hook {
|
|
||||||
hooks := c.hooks.ApiKey
|
|
||||||
return append(hooks[:len(hooks):len(hooks)], apikey.Hooks[:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interceptors returns the client interceptors.
|
|
||||||
func (c *ApiKeyClient) Interceptors() []Interceptor {
|
|
||||||
inters := c.inters.ApiKey
|
|
||||||
return append(inters[:len(inters):len(inters)], apikey.Interceptors[:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ApiKeyClient) mutate(ctx context.Context, m *ApiKeyMutation) (Value, error) {
|
|
||||||
switch m.Op() {
|
|
||||||
case OpCreate:
|
|
||||||
return (&ApiKeyCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
|
||||||
case OpUpdate:
|
|
||||||
return (&ApiKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
|
||||||
case OpUpdateOne:
|
|
||||||
return (&ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
|
||||||
case OpDelete, OpDeleteOne:
|
|
||||||
return (&ApiKeyDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("ent: unknown ApiKey mutation op: %q", m.Op())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GroupClient is a client for the Group schema.
|
// GroupClient is a client for the Group schema.
|
||||||
type GroupClient struct {
|
type GroupClient struct {
|
||||||
config
|
config
|
||||||
@@ -914,8 +914,8 @@ func (c *GroupClient) GetX(ctx context.Context, id int64) *Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys queries the api_keys edge of a Group.
|
// QueryAPIKeys queries the api_keys edge of a Group.
|
||||||
func (c *GroupClient) QueryAPIKeys(_m *Group) *ApiKeyQuery {
|
func (c *GroupClient) QueryAPIKeys(_m *Group) *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: c.config}).Query()
|
query := (&APIKeyClient{config: c.config}).Query()
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
id := _m.ID
|
id := _m.ID
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
@@ -1642,8 +1642,8 @@ func (c *UsageLogClient) QueryUser(_m *UsageLog) *UserQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKey queries the api_key edge of a UsageLog.
|
// QueryAPIKey queries the api_key edge of a UsageLog.
|
||||||
func (c *UsageLogClient) QueryAPIKey(_m *UsageLog) *ApiKeyQuery {
|
func (c *UsageLogClient) QueryAPIKey(_m *UsageLog) *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: c.config}).Query()
|
query := (&APIKeyClient{config: c.config}).Query()
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
id := _m.ID
|
id := _m.ID
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
@@ -1839,8 +1839,8 @@ func (c *UserClient) GetX(ctx context.Context, id int64) *User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys queries the api_keys edge of a User.
|
// QueryAPIKeys queries the api_keys edge of a User.
|
||||||
func (c *UserClient) QueryAPIKeys(_m *User) *ApiKeyQuery {
|
func (c *UserClient) QueryAPIKeys(_m *User) *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: c.config}).Query()
|
query := (&APIKeyClient{config: c.config}).Query()
|
||||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||||
id := _m.ID
|
id := _m.ID
|
||||||
step := sqlgraph.NewStep(
|
step := sqlgraph.NewStep(
|
||||||
@@ -2627,12 +2627,12 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription
|
|||||||
// hooks and interceptors per client, for fast access.
|
// hooks and interceptors per client, for fast access.
|
||||||
type (
|
type (
|
||||||
hooks struct {
|
hooks struct {
|
||||||
Account, AccountGroup, ApiKey, Group, Proxy, RedeemCode, Setting, UsageLog,
|
APIKey, Account, AccountGroup, Group, Proxy, RedeemCode, Setting, UsageLog,
|
||||||
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
|
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
|
||||||
UserSubscription []ent.Hook
|
UserSubscription []ent.Hook
|
||||||
}
|
}
|
||||||
inters struct {
|
inters struct {
|
||||||
Account, AccountGroup, ApiKey, Group, Proxy, RedeemCode, Setting, UsageLog,
|
APIKey, Account, AccountGroup, Group, Proxy, RedeemCode, Setting, UsageLog,
|
||||||
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
|
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
|
||||||
UserSubscription []ent.Interceptor
|
UserSubscription []ent.Interceptor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,9 +85,9 @@ var (
|
|||||||
func checkColumn(t, c string) error {
|
func checkColumn(t, c string) error {
|
||||||
initCheck.Do(func() {
|
initCheck.Do(func() {
|
||||||
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
|
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
|
||||||
|
apikey.Table: apikey.ValidColumn,
|
||||||
account.Table: account.ValidColumn,
|
account.Table: account.ValidColumn,
|
||||||
accountgroup.Table: accountgroup.ValidColumn,
|
accountgroup.Table: accountgroup.ValidColumn,
|
||||||
apikey.Table: apikey.ValidColumn,
|
|
||||||
group.Table: group.ValidColumn,
|
group.Table: group.ValidColumn,
|
||||||
proxy.Table: proxy.ValidColumn,
|
proxy.Table: proxy.ValidColumn,
|
||||||
redeemcode.Table: redeemcode.ValidColumn,
|
redeemcode.Table: redeemcode.ValidColumn,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package ent provides the generated ORM code for database entities.
|
||||||
package ent
|
package ent
|
||||||
|
|
||||||
// 启用 sql/execquery 以生成 ExecContext/QueryContext 的透传接口,便于事务内执行原生 SQL。
|
// 启用 sql/execquery 以生成 ExecContext/QueryContext 的透传接口,便于事务内执行原生 SQL。
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ type Group struct {
|
|||||||
MonthlyLimitUsd *float64 `json:"monthly_limit_usd,omitempty"`
|
MonthlyLimitUsd *float64 `json:"monthly_limit_usd,omitempty"`
|
||||||
// DefaultValidityDays holds the value of the "default_validity_days" field.
|
// DefaultValidityDays holds the value of the "default_validity_days" field.
|
||||||
DefaultValidityDays int `json:"default_validity_days,omitempty"`
|
DefaultValidityDays int `json:"default_validity_days,omitempty"`
|
||||||
|
// ImagePrice1k holds the value of the "image_price_1k" field.
|
||||||
|
ImagePrice1k *float64 `json:"image_price_1k,omitempty"`
|
||||||
|
// ImagePrice2k holds the value of the "image_price_2k" field.
|
||||||
|
ImagePrice2k *float64 `json:"image_price_2k,omitempty"`
|
||||||
|
// ImagePrice4k holds the value of the "image_price_4k" field.
|
||||||
|
ImagePrice4k *float64 `json:"image_price_4k,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
// The values are being populated by the GroupQuery when eager-loading is set.
|
// The values are being populated by the GroupQuery when eager-loading is set.
|
||||||
Edges GroupEdges `json:"edges"`
|
Edges GroupEdges `json:"edges"`
|
||||||
@@ -54,7 +60,7 @@ type Group struct {
|
|||||||
// GroupEdges holds the relations/edges for other nodes in the graph.
|
// GroupEdges holds the relations/edges for other nodes in the graph.
|
||||||
type GroupEdges struct {
|
type GroupEdges struct {
|
||||||
// APIKeys holds the value of the api_keys edge.
|
// APIKeys holds the value of the api_keys edge.
|
||||||
APIKeys []*ApiKey `json:"api_keys,omitempty"`
|
APIKeys []*APIKey `json:"api_keys,omitempty"`
|
||||||
// RedeemCodes holds the value of the redeem_codes edge.
|
// RedeemCodes holds the value of the redeem_codes edge.
|
||||||
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
|
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
|
||||||
// Subscriptions holds the value of the subscriptions edge.
|
// Subscriptions holds the value of the subscriptions edge.
|
||||||
@@ -76,7 +82,7 @@ type GroupEdges struct {
|
|||||||
|
|
||||||
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
||||||
// was not loaded in eager-loading.
|
// was not loaded in eager-loading.
|
||||||
func (e GroupEdges) APIKeysOrErr() ([]*ApiKey, error) {
|
func (e GroupEdges) APIKeysOrErr() ([]*APIKey, error) {
|
||||||
if e.loadedTypes[0] {
|
if e.loadedTypes[0] {
|
||||||
return e.APIKeys, nil
|
return e.APIKeys, nil
|
||||||
}
|
}
|
||||||
@@ -153,7 +159,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
|
|||||||
switch columns[i] {
|
switch columns[i] {
|
||||||
case group.FieldIsExclusive:
|
case group.FieldIsExclusive:
|
||||||
values[i] = new(sql.NullBool)
|
values[i] = new(sql.NullBool)
|
||||||
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd:
|
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd, group.FieldImagePrice1k, group.FieldImagePrice2k, group.FieldImagePrice4k:
|
||||||
values[i] = new(sql.NullFloat64)
|
values[i] = new(sql.NullFloat64)
|
||||||
case group.FieldID, group.FieldDefaultValidityDays:
|
case group.FieldID, group.FieldDefaultValidityDays:
|
||||||
values[i] = new(sql.NullInt64)
|
values[i] = new(sql.NullInt64)
|
||||||
@@ -271,6 +277,27 @@ func (_m *Group) assignValues(columns []string, values []any) error {
|
|||||||
} else if value.Valid {
|
} else if value.Valid {
|
||||||
_m.DefaultValidityDays = int(value.Int64)
|
_m.DefaultValidityDays = int(value.Int64)
|
||||||
}
|
}
|
||||||
|
case group.FieldImagePrice1k:
|
||||||
|
if value, ok := values[i].(*sql.NullFloat64); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field image_price_1k", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.ImagePrice1k = new(float64)
|
||||||
|
*_m.ImagePrice1k = value.Float64
|
||||||
|
}
|
||||||
|
case group.FieldImagePrice2k:
|
||||||
|
if value, ok := values[i].(*sql.NullFloat64); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field image_price_2k", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.ImagePrice2k = new(float64)
|
||||||
|
*_m.ImagePrice2k = value.Float64
|
||||||
|
}
|
||||||
|
case group.FieldImagePrice4k:
|
||||||
|
if value, ok := values[i].(*sql.NullFloat64); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field image_price_4k", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.ImagePrice4k = new(float64)
|
||||||
|
*_m.ImagePrice4k = value.Float64
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
_m.selectValues.Set(columns[i], values[i])
|
_m.selectValues.Set(columns[i], values[i])
|
||||||
}
|
}
|
||||||
@@ -285,7 +312,7 @@ func (_m *Group) Value(name string) (ent.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys queries the "api_keys" edge of the Group entity.
|
// QueryAPIKeys queries the "api_keys" edge of the Group entity.
|
||||||
func (_m *Group) QueryAPIKeys() *ApiKeyQuery {
|
func (_m *Group) QueryAPIKeys() *APIKeyQuery {
|
||||||
return NewGroupClient(_m.config).QueryAPIKeys(_m)
|
return NewGroupClient(_m.config).QueryAPIKeys(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +425,21 @@ func (_m *Group) String() string {
|
|||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
builder.WriteString("default_validity_days=")
|
builder.WriteString("default_validity_days=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", _m.DefaultValidityDays))
|
builder.WriteString(fmt.Sprintf("%v", _m.DefaultValidityDays))
|
||||||
|
builder.WriteString(", ")
|
||||||
|
if v := _m.ImagePrice1k; v != nil {
|
||||||
|
builder.WriteString("image_price_1k=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
|
if v := _m.ImagePrice2k; v != nil {
|
||||||
|
builder.WriteString("image_price_2k=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
|
if v := _m.ImagePrice4k; v != nil {
|
||||||
|
builder.WriteString("image_price_4k=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||||
|
}
|
||||||
builder.WriteByte(')')
|
builder.WriteByte(')')
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ const (
|
|||||||
FieldMonthlyLimitUsd = "monthly_limit_usd"
|
FieldMonthlyLimitUsd = "monthly_limit_usd"
|
||||||
// FieldDefaultValidityDays holds the string denoting the default_validity_days field in the database.
|
// FieldDefaultValidityDays holds the string denoting the default_validity_days field in the database.
|
||||||
FieldDefaultValidityDays = "default_validity_days"
|
FieldDefaultValidityDays = "default_validity_days"
|
||||||
|
// FieldImagePrice1k holds the string denoting the image_price_1k field in the database.
|
||||||
|
FieldImagePrice1k = "image_price_1k"
|
||||||
|
// FieldImagePrice2k holds the string denoting the image_price_2k field in the database.
|
||||||
|
FieldImagePrice2k = "image_price_2k"
|
||||||
|
// FieldImagePrice4k holds the string denoting the image_price_4k field in the database.
|
||||||
|
FieldImagePrice4k = "image_price_4k"
|
||||||
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
|
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
|
||||||
EdgeAPIKeys = "api_keys"
|
EdgeAPIKeys = "api_keys"
|
||||||
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
||||||
@@ -63,7 +69,7 @@ const (
|
|||||||
Table = "groups"
|
Table = "groups"
|
||||||
// APIKeysTable is the table that holds the api_keys relation/edge.
|
// APIKeysTable is the table that holds the api_keys relation/edge.
|
||||||
APIKeysTable = "api_keys"
|
APIKeysTable = "api_keys"
|
||||||
// APIKeysInverseTable is the table name for the ApiKey entity.
|
// APIKeysInverseTable is the table name for the APIKey entity.
|
||||||
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
||||||
APIKeysInverseTable = "api_keys"
|
APIKeysInverseTable = "api_keys"
|
||||||
// APIKeysColumn is the table column denoting the api_keys relation/edge.
|
// APIKeysColumn is the table column denoting the api_keys relation/edge.
|
||||||
@@ -132,6 +138,9 @@ var Columns = []string{
|
|||||||
FieldWeeklyLimitUsd,
|
FieldWeeklyLimitUsd,
|
||||||
FieldMonthlyLimitUsd,
|
FieldMonthlyLimitUsd,
|
||||||
FieldDefaultValidityDays,
|
FieldDefaultValidityDays,
|
||||||
|
FieldImagePrice1k,
|
||||||
|
FieldImagePrice2k,
|
||||||
|
FieldImagePrice4k,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -267,6 +276,21 @@ func ByDefaultValidityDays(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldDefaultValidityDays, opts...).ToFunc()
|
return sql.OrderByField(FieldDefaultValidityDays, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByImagePrice1k orders the results by the image_price_1k field.
|
||||||
|
func ByImagePrice1k(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldImagePrice1k, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByImagePrice2k orders the results by the image_price_2k field.
|
||||||
|
func ByImagePrice2k(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldImagePrice2k, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByImagePrice4k orders the results by the image_price_4k field.
|
||||||
|
func ByImagePrice4k(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldImagePrice4k, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// ByAPIKeysCount orders the results by api_keys count.
|
// ByAPIKeysCount orders the results by api_keys count.
|
||||||
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return func(s *sql.Selector) {
|
return func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -125,6 +125,21 @@ func DefaultValidityDays(v int) predicate.Group {
|
|||||||
return predicate.Group(sql.FieldEQ(FieldDefaultValidityDays, v))
|
return predicate.Group(sql.FieldEQ(FieldDefaultValidityDays, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImagePrice1k applies equality check predicate on the "image_price_1k" field. It's identical to ImagePrice1kEQ.
|
||||||
|
func ImagePrice1k(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2k applies equality check predicate on the "image_price_2k" field. It's identical to ImagePrice2kEQ.
|
||||||
|
func ImagePrice2k(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4k applies equality check predicate on the "image_price_4k" field. It's identical to ImagePrice4kEQ.
|
||||||
|
func ImagePrice4k(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||||
func CreatedAtEQ(v time.Time) predicate.Group {
|
func CreatedAtEQ(v time.Time) predicate.Group {
|
||||||
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
@@ -830,6 +845,156 @@ func DefaultValidityDaysLTE(v int) predicate.Group {
|
|||||||
return predicate.Group(sql.FieldLTE(FieldDefaultValidityDays, v))
|
return predicate.Group(sql.FieldLTE(FieldDefaultValidityDays, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kEQ applies the EQ predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kNEQ applies the NEQ predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kNEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNEQ(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kIn applies the In predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIn(FieldImagePrice1k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kNotIn applies the NotIn predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kNotIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotIn(FieldImagePrice1k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kGT applies the GT predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kGT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGT(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kGTE applies the GTE predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kGTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGTE(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kLT applies the LT predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kLT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLT(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kLTE applies the LTE predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kLTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLTE(FieldImagePrice1k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kIsNil applies the IsNil predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kIsNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIsNull(FieldImagePrice1k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice1kNotNil applies the NotNil predicate on the "image_price_1k" field.
|
||||||
|
func ImagePrice1kNotNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotNull(FieldImagePrice1k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kEQ applies the EQ predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kNEQ applies the NEQ predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kNEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNEQ(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kIn applies the In predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIn(FieldImagePrice2k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kNotIn applies the NotIn predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kNotIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotIn(FieldImagePrice2k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kGT applies the GT predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kGT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGT(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kGTE applies the GTE predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kGTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGTE(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kLT applies the LT predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kLT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLT(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kLTE applies the LTE predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kLTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLTE(FieldImagePrice2k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kIsNil applies the IsNil predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kIsNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIsNull(FieldImagePrice2k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice2kNotNil applies the NotNil predicate on the "image_price_2k" field.
|
||||||
|
func ImagePrice2kNotNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotNull(FieldImagePrice2k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kEQ applies the EQ predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldEQ(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kNEQ applies the NEQ predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kNEQ(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNEQ(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kIn applies the In predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIn(FieldImagePrice4k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kNotIn applies the NotIn predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kNotIn(vs ...float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotIn(FieldImagePrice4k, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kGT applies the GT predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kGT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGT(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kGTE applies the GTE predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kGTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldGTE(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kLT applies the LT predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kLT(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLT(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kLTE applies the LTE predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kLTE(v float64) predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldLTE(FieldImagePrice4k, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kIsNil applies the IsNil predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kIsNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldIsNull(FieldImagePrice4k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePrice4kNotNil applies the NotNil predicate on the "image_price_4k" field.
|
||||||
|
func ImagePrice4kNotNil() predicate.Group {
|
||||||
|
return predicate.Group(sql.FieldNotNull(FieldImagePrice4k))
|
||||||
|
}
|
||||||
|
|
||||||
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
|
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
|
||||||
func HasAPIKeys() predicate.Group {
|
func HasAPIKeys() predicate.Group {
|
||||||
return predicate.Group(func(s *sql.Selector) {
|
return predicate.Group(func(s *sql.Selector) {
|
||||||
@@ -842,7 +1007,7 @@ func HasAPIKeys() predicate.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
|
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
|
||||||
func HasAPIKeysWith(preds ...predicate.ApiKey) predicate.Group {
|
func HasAPIKeysWith(preds ...predicate.APIKey) predicate.Group {
|
||||||
return predicate.Group(func(s *sql.Selector) {
|
return predicate.Group(func(s *sql.Selector) {
|
||||||
step := newAPIKeysStep()
|
step := newAPIKeysStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -216,14 +216,56 @@ func (_c *GroupCreate) SetNillableDefaultValidityDays(v *int) *GroupCreate {
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (_c *GroupCreate) SetImagePrice1k(v float64) *GroupCreate {
|
||||||
|
_c.mutation.SetImagePrice1k(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice1k sets the "image_price_1k" field if the given value is not nil.
|
||||||
|
func (_c *GroupCreate) SetNillableImagePrice1k(v *float64) *GroupCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetImagePrice1k(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (_c *GroupCreate) SetImagePrice2k(v float64) *GroupCreate {
|
||||||
|
_c.mutation.SetImagePrice2k(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice2k sets the "image_price_2k" field if the given value is not nil.
|
||||||
|
func (_c *GroupCreate) SetNillableImagePrice2k(v *float64) *GroupCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetImagePrice2k(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (_c *GroupCreate) SetImagePrice4k(v float64) *GroupCreate {
|
||||||
|
_c.mutation.SetImagePrice4k(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice4k sets the "image_price_4k" field if the given value is not nil.
|
||||||
|
func (_c *GroupCreate) SetNillableImagePrice4k(v *float64) *GroupCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetImagePrice4k(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
||||||
_c.mutation.AddAPIKeyIDs(ids...)
|
_c.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_c *GroupCreate) AddAPIKeys(v ...*ApiKey) *GroupCreate {
|
func (_c *GroupCreate) AddAPIKeys(v ...*APIKey) *GroupCreate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -516,6 +558,18 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
_spec.SetField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
||||||
_node.DefaultValidityDays = value
|
_node.DefaultValidityDays = value
|
||||||
}
|
}
|
||||||
|
if value, ok := _c.mutation.ImagePrice1k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice1k, field.TypeFloat64, value)
|
||||||
|
_node.ImagePrice1k = &value
|
||||||
|
}
|
||||||
|
if value, ok := _c.mutation.ImagePrice2k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice2k, field.TypeFloat64, value)
|
||||||
|
_node.ImagePrice2k = &value
|
||||||
|
}
|
||||||
|
if value, ok := _c.mutation.ImagePrice4k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice4k, field.TypeFloat64, value)
|
||||||
|
_node.ImagePrice4k = &value
|
||||||
|
}
|
||||||
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
@@ -888,6 +942,78 @@ func (u *GroupUpsert) AddDefaultValidityDays(v int) *GroupUpsert {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsert) SetImagePrice1k(v float64) *GroupUpsert {
|
||||||
|
u.Set(group.FieldImagePrice1k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice1k sets the "image_price_1k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsert) UpdateImagePrice1k() *GroupUpsert {
|
||||||
|
u.SetExcluded(group.FieldImagePrice1k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice1k adds v to the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsert) AddImagePrice1k(v float64) *GroupUpsert {
|
||||||
|
u.Add(group.FieldImagePrice1k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice1k clears the value of the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsert) ClearImagePrice1k() *GroupUpsert {
|
||||||
|
u.SetNull(group.FieldImagePrice1k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsert) SetImagePrice2k(v float64) *GroupUpsert {
|
||||||
|
u.Set(group.FieldImagePrice2k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice2k sets the "image_price_2k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsert) UpdateImagePrice2k() *GroupUpsert {
|
||||||
|
u.SetExcluded(group.FieldImagePrice2k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice2k adds v to the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsert) AddImagePrice2k(v float64) *GroupUpsert {
|
||||||
|
u.Add(group.FieldImagePrice2k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice2k clears the value of the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsert) ClearImagePrice2k() *GroupUpsert {
|
||||||
|
u.SetNull(group.FieldImagePrice2k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsert) SetImagePrice4k(v float64) *GroupUpsert {
|
||||||
|
u.Set(group.FieldImagePrice4k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice4k sets the "image_price_4k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsert) UpdateImagePrice4k() *GroupUpsert {
|
||||||
|
u.SetExcluded(group.FieldImagePrice4k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice4k adds v to the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsert) AddImagePrice4k(v float64) *GroupUpsert {
|
||||||
|
u.Add(group.FieldImagePrice4k, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice4k clears the value of the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsert) ClearImagePrice4k() *GroupUpsert {
|
||||||
|
u.SetNull(group.FieldImagePrice4k)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||||
// Using this option is equivalent to using:
|
// Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
@@ -1185,6 +1311,90 @@ func (u *GroupUpsertOne) UpdateDefaultValidityDays() *GroupUpsertOne {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertOne) SetImagePrice1k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice1k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice1k adds v to the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertOne) AddImagePrice1k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice1k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice1k sets the "image_price_1k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertOne) UpdateImagePrice1k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice1k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice1k clears the value of the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertOne) ClearImagePrice1k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice1k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertOne) SetImagePrice2k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice2k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice2k adds v to the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertOne) AddImagePrice2k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice2k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice2k sets the "image_price_2k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertOne) UpdateImagePrice2k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice2k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice2k clears the value of the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertOne) ClearImagePrice2k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice2k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertOne) SetImagePrice4k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice4k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice4k adds v to the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertOne) AddImagePrice4k(v float64) *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice4k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice4k sets the "image_price_4k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertOne) UpdateImagePrice4k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice4k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice4k clears the value of the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertOne) ClearImagePrice4k() *GroupUpsertOne {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice4k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
||||||
if len(u.create.conflict) == 0 {
|
if len(u.create.conflict) == 0 {
|
||||||
@@ -1648,6 +1858,90 @@ func (u *GroupUpsertBulk) UpdateDefaultValidityDays() *GroupUpsertBulk {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertBulk) SetImagePrice1k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice1k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice1k adds v to the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertBulk) AddImagePrice1k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice1k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice1k sets the "image_price_1k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertBulk) UpdateImagePrice1k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice1k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice1k clears the value of the "image_price_1k" field.
|
||||||
|
func (u *GroupUpsertBulk) ClearImagePrice1k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice1k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertBulk) SetImagePrice2k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice2k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice2k adds v to the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertBulk) AddImagePrice2k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice2k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice2k sets the "image_price_2k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertBulk) UpdateImagePrice2k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice2k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice2k clears the value of the "image_price_2k" field.
|
||||||
|
func (u *GroupUpsertBulk) ClearImagePrice2k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice2k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertBulk) SetImagePrice4k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.SetImagePrice4k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice4k adds v to the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertBulk) AddImagePrice4k(v float64) *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.AddImagePrice4k(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImagePrice4k sets the "image_price_4k" field to the value that was provided on create.
|
||||||
|
func (u *GroupUpsertBulk) UpdateImagePrice4k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.UpdateImagePrice4k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice4k clears the value of the "image_price_4k" field.
|
||||||
|
func (u *GroupUpsertBulk) ClearImagePrice4k() *GroupUpsertBulk {
|
||||||
|
return u.Update(func(s *GroupUpsert) {
|
||||||
|
s.ClearImagePrice4k()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
||||||
if u.create.err != nil {
|
if u.create.err != nil {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ type GroupQuery struct {
|
|||||||
order []group.OrderOption
|
order []group.OrderOption
|
||||||
inters []Interceptor
|
inters []Interceptor
|
||||||
predicates []predicate.Group
|
predicates []predicate.Group
|
||||||
withAPIKeys *ApiKeyQuery
|
withAPIKeys *APIKeyQuery
|
||||||
withRedeemCodes *RedeemCodeQuery
|
withRedeemCodes *RedeemCodeQuery
|
||||||
withSubscriptions *UserSubscriptionQuery
|
withSubscriptions *UserSubscriptionQuery
|
||||||
withUsageLogs *UsageLogQuery
|
withUsageLogs *UsageLogQuery
|
||||||
@@ -76,8 +76,8 @@ func (_q *GroupQuery) Order(o ...group.OrderOption) *GroupQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys chains the current query on the "api_keys" edge.
|
// QueryAPIKeys chains the current query on the "api_keys" edge.
|
||||||
func (_q *GroupQuery) QueryAPIKeys() *ApiKeyQuery {
|
func (_q *GroupQuery) QueryAPIKeys() *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -459,8 +459,8 @@ func (_q *GroupQuery) Clone() *GroupQuery {
|
|||||||
|
|
||||||
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
|
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
|
||||||
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
|
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *GroupQuery) WithAPIKeys(opts ...func(*ApiKeyQuery)) *GroupQuery {
|
func (_q *GroupQuery) WithAPIKeys(opts ...func(*APIKeyQuery)) *GroupQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
}
|
}
|
||||||
@@ -654,8 +654,8 @@ func (_q *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
|
|||||||
}
|
}
|
||||||
if query := _q.withAPIKeys; query != nil {
|
if query := _q.withAPIKeys; query != nil {
|
||||||
if err := _q.loadAPIKeys(ctx, query, nodes,
|
if err := _q.loadAPIKeys(ctx, query, nodes,
|
||||||
func(n *Group) { n.Edges.APIKeys = []*ApiKey{} },
|
func(n *Group) { n.Edges.APIKeys = []*APIKey{} },
|
||||||
func(n *Group, e *ApiKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
|
func(n *Group, e *APIKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +711,7 @@ func (_q *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
|
|||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes []*Group, init func(*Group), assign func(*Group, *ApiKey)) error {
|
func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *APIKeyQuery, nodes []*Group, init func(*Group), assign func(*Group, *APIKey)) error {
|
||||||
fks := make([]driver.Value, 0, len(nodes))
|
fks := make([]driver.Value, 0, len(nodes))
|
||||||
nodeids := make(map[int64]*Group)
|
nodeids := make(map[int64]*Group)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
@@ -724,7 +724,7 @@ func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes
|
|||||||
if len(query.ctx.Fields) > 0 {
|
if len(query.ctx.Fields) > 0 {
|
||||||
query.ctx.AppendFieldOnce(apikey.FieldGroupID)
|
query.ctx.AppendFieldOnce(apikey.FieldGroupID)
|
||||||
}
|
}
|
||||||
query.Where(predicate.ApiKey(func(s *sql.Selector) {
|
query.Where(predicate.APIKey(func(s *sql.Selector) {
|
||||||
s.Where(sql.InValues(s.C(group.APIKeysColumn), fks...))
|
s.Where(sql.InValues(s.C(group.APIKeysColumn), fks...))
|
||||||
}))
|
}))
|
||||||
neighbors, err := query.All(ctx)
|
neighbors, err := query.All(ctx)
|
||||||
|
|||||||
@@ -273,14 +273,95 @@ func (_u *GroupUpdate) AddDefaultValidityDays(v int) *GroupUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdate) SetImagePrice1k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.ResetImagePrice1k()
|
||||||
|
_u.mutation.SetImagePrice1k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice1k sets the "image_price_1k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdate) SetNillableImagePrice1k(v *float64) *GroupUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice1k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice1k adds value to the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdate) AddImagePrice1k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.AddImagePrice1k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice1k clears the value of the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdate) ClearImagePrice1k() *GroupUpdate {
|
||||||
|
_u.mutation.ClearImagePrice1k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdate) SetImagePrice2k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.ResetImagePrice2k()
|
||||||
|
_u.mutation.SetImagePrice2k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice2k sets the "image_price_2k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdate) SetNillableImagePrice2k(v *float64) *GroupUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice2k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice2k adds value to the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdate) AddImagePrice2k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.AddImagePrice2k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice2k clears the value of the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdate) ClearImagePrice2k() *GroupUpdate {
|
||||||
|
_u.mutation.ClearImagePrice2k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdate) SetImagePrice4k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.ResetImagePrice4k()
|
||||||
|
_u.mutation.SetImagePrice4k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice4k sets the "image_price_4k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdate) SetNillableImagePrice4k(v *float64) *GroupUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice4k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice4k adds value to the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdate) AddImagePrice4k(v float64) *GroupUpdate {
|
||||||
|
_u.mutation.AddImagePrice4k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice4k clears the value of the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdate) ClearImagePrice4k() *GroupUpdate {
|
||||||
|
_u.mutation.ClearImagePrice4k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_u.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_u *GroupUpdate) AddAPIKeys(v ...*ApiKey) *GroupUpdate {
|
func (_u *GroupUpdate) AddAPIKeys(v ...*APIKey) *GroupUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -368,20 +449,20 @@ func (_u *GroupUpdate) Mutation() *GroupMutation {
|
|||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
|
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
|
||||||
func (_u *GroupUpdate) ClearAPIKeys() *GroupUpdate {
|
func (_u *GroupUpdate) ClearAPIKeys() *GroupUpdate {
|
||||||
_u.mutation.ClearAPIKeys()
|
_u.mutation.ClearAPIKeys()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
|
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
|
||||||
func (_u *GroupUpdate) RemoveAPIKeyIDs(ids ...int64) *GroupUpdate {
|
func (_u *GroupUpdate) RemoveAPIKeyIDs(ids ...int64) *GroupUpdate {
|
||||||
_u.mutation.RemoveAPIKeyIDs(ids...)
|
_u.mutation.RemoveAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
|
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
|
||||||
func (_u *GroupUpdate) RemoveAPIKeys(v ...*ApiKey) *GroupUpdate {
|
func (_u *GroupUpdate) RemoveAPIKeys(v ...*APIKey) *GroupUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -642,6 +723,33 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
|||||||
if value, ok := _u.mutation.AddedDefaultValidityDays(); ok {
|
if value, ok := _u.mutation.AddedDefaultValidityDays(); ok {
|
||||||
_spec.AddField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
_spec.AddField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice1k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice1k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice1k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice1k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice1kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice1k, field.TypeFloat64)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice2k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice2k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice2k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice2k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice2kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice2k, field.TypeFloat64)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice4k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice4k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice4k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice4k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice4kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice4k, field.TypeFloat64)
|
||||||
|
}
|
||||||
if _u.mutation.APIKeysCleared() {
|
if _u.mutation.APIKeysCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
@@ -1195,14 +1303,95 @@ func (_u *GroupUpdateOne) AddDefaultValidityDays(v int) *GroupUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// SetImagePrice1k sets the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdateOne) SetImagePrice1k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.ResetImagePrice1k()
|
||||||
|
_u.mutation.SetImagePrice1k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice1k sets the "image_price_1k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdateOne) SetNillableImagePrice1k(v *float64) *GroupUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice1k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice1k adds value to the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdateOne) AddImagePrice1k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.AddImagePrice1k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice1k clears the value of the "image_price_1k" field.
|
||||||
|
func (_u *GroupUpdateOne) ClearImagePrice1k() *GroupUpdateOne {
|
||||||
|
_u.mutation.ClearImagePrice1k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice2k sets the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdateOne) SetImagePrice2k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.ResetImagePrice2k()
|
||||||
|
_u.mutation.SetImagePrice2k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice2k sets the "image_price_2k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdateOne) SetNillableImagePrice2k(v *float64) *GroupUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice2k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice2k adds value to the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdateOne) AddImagePrice2k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.AddImagePrice2k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice2k clears the value of the "image_price_2k" field.
|
||||||
|
func (_u *GroupUpdateOne) ClearImagePrice2k() *GroupUpdateOne {
|
||||||
|
_u.mutation.ClearImagePrice2k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImagePrice4k sets the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdateOne) SetImagePrice4k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.ResetImagePrice4k()
|
||||||
|
_u.mutation.SetImagePrice4k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImagePrice4k sets the "image_price_4k" field if the given value is not nil.
|
||||||
|
func (_u *GroupUpdateOne) SetNillableImagePrice4k(v *float64) *GroupUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImagePrice4k(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImagePrice4k adds value to the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdateOne) AddImagePrice4k(v float64) *GroupUpdateOne {
|
||||||
|
_u.mutation.AddImagePrice4k(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImagePrice4k clears the value of the "image_price_4k" field.
|
||||||
|
func (_u *GroupUpdateOne) ClearImagePrice4k() *GroupUpdateOne {
|
||||||
|
_u.mutation.ClearImagePrice4k()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_u.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_u *GroupUpdateOne) AddAPIKeys(v ...*ApiKey) *GroupUpdateOne {
|
func (_u *GroupUpdateOne) AddAPIKeys(v ...*APIKey) *GroupUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -1290,20 +1479,20 @@ func (_u *GroupUpdateOne) Mutation() *GroupMutation {
|
|||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
|
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
|
||||||
func (_u *GroupUpdateOne) ClearAPIKeys() *GroupUpdateOne {
|
func (_u *GroupUpdateOne) ClearAPIKeys() *GroupUpdateOne {
|
||||||
_u.mutation.ClearAPIKeys()
|
_u.mutation.ClearAPIKeys()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
|
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
|
||||||
func (_u *GroupUpdateOne) RemoveAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
func (_u *GroupUpdateOne) RemoveAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
||||||
_u.mutation.RemoveAPIKeyIDs(ids...)
|
_u.mutation.RemoveAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
|
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
|
||||||
func (_u *GroupUpdateOne) RemoveAPIKeys(v ...*ApiKey) *GroupUpdateOne {
|
func (_u *GroupUpdateOne) RemoveAPIKeys(v ...*APIKey) *GroupUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -1594,6 +1783,33 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
|
|||||||
if value, ok := _u.mutation.AddedDefaultValidityDays(); ok {
|
if value, ok := _u.mutation.AddedDefaultValidityDays(); ok {
|
||||||
_spec.AddField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
_spec.AddField(group.FieldDefaultValidityDays, field.TypeInt, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice1k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice1k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice1k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice1k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice1kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice1k, field.TypeFloat64)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice2k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice2k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice2k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice2k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice2kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice2k, field.TypeFloat64)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImagePrice4k(); ok {
|
||||||
|
_spec.SetField(group.FieldImagePrice4k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImagePrice4k(); ok {
|
||||||
|
_spec.AddField(group.FieldImagePrice4k, field.TypeFloat64, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImagePrice4kCleared() {
|
||||||
|
_spec.ClearField(group.FieldImagePrice4k, field.TypeFloat64)
|
||||||
|
}
|
||||||
if _u.mutation.APIKeysCleared() {
|
if _u.mutation.APIKeysCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
|
|||||||
@@ -9,6 +9,18 @@ import (
|
|||||||
"github.com/Wei-Shaw/sub2api/ent"
|
"github.com/Wei-Shaw/sub2api/ent"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The APIKeyFunc type is an adapter to allow the use of ordinary
|
||||||
|
// function as APIKey mutator.
|
||||||
|
type APIKeyFunc func(context.Context, *ent.APIKeyMutation) (ent.Value, error)
|
||||||
|
|
||||||
|
// Mutate calls f(ctx, m).
|
||||||
|
func (f APIKeyFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||||
|
if mv, ok := m.(*ent.APIKeyMutation); ok {
|
||||||
|
return f(ctx, mv)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.APIKeyMutation", m)
|
||||||
|
}
|
||||||
|
|
||||||
// The AccountFunc type is an adapter to allow the use of ordinary
|
// The AccountFunc type is an adapter to allow the use of ordinary
|
||||||
// function as Account mutator.
|
// function as Account mutator.
|
||||||
type AccountFunc func(context.Context, *ent.AccountMutation) (ent.Value, error)
|
type AccountFunc func(context.Context, *ent.AccountMutation) (ent.Value, error)
|
||||||
@@ -33,18 +45,6 @@ func (f AccountGroupFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value
|
|||||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AccountGroupMutation", m)
|
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AccountGroupMutation", m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ApiKeyFunc type is an adapter to allow the use of ordinary
|
|
||||||
// function as ApiKey mutator.
|
|
||||||
type ApiKeyFunc func(context.Context, *ent.ApiKeyMutation) (ent.Value, error)
|
|
||||||
|
|
||||||
// Mutate calls f(ctx, m).
|
|
||||||
func (f ApiKeyFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
|
||||||
if mv, ok := m.(*ent.ApiKeyMutation); ok {
|
|
||||||
return f(ctx, mv)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ApiKeyMutation", m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The GroupFunc type is an adapter to allow the use of ordinary
|
// The GroupFunc type is an adapter to allow the use of ordinary
|
||||||
// function as Group mutator.
|
// function as Group mutator.
|
||||||
type GroupFunc func(context.Context, *ent.GroupMutation) (ent.Value, error)
|
type GroupFunc func(context.Context, *ent.GroupMutation) (ent.Value, error)
|
||||||
|
|||||||
@@ -80,6 +80,33 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error {
|
|||||||
return f(ctx, query)
|
return f(ctx, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The APIKeyFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||||
|
type APIKeyFunc func(context.Context, *ent.APIKeyQuery) (ent.Value, error)
|
||||||
|
|
||||||
|
// Query calls f(ctx, q).
|
||||||
|
func (f APIKeyFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||||
|
if q, ok := q.(*ent.APIKeyQuery); ok {
|
||||||
|
return f(ctx, q)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unexpected query type %T. expect *ent.APIKeyQuery", q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The TraverseAPIKey type is an adapter to allow the use of ordinary function as Traverser.
|
||||||
|
type TraverseAPIKey func(context.Context, *ent.APIKeyQuery) error
|
||||||
|
|
||||||
|
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||||
|
func (f TraverseAPIKey) Intercept(next ent.Querier) ent.Querier {
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverse calls f(ctx, q).
|
||||||
|
func (f TraverseAPIKey) Traverse(ctx context.Context, q ent.Query) error {
|
||||||
|
if q, ok := q.(*ent.APIKeyQuery); ok {
|
||||||
|
return f(ctx, q)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected query type %T. expect *ent.APIKeyQuery", q)
|
||||||
|
}
|
||||||
|
|
||||||
// The AccountFunc type is an adapter to allow the use of ordinary function as a Querier.
|
// The AccountFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||||
type AccountFunc func(context.Context, *ent.AccountQuery) (ent.Value, error)
|
type AccountFunc func(context.Context, *ent.AccountQuery) (ent.Value, error)
|
||||||
|
|
||||||
@@ -134,33 +161,6 @@ func (f TraverseAccountGroup) Traverse(ctx context.Context, q ent.Query) error {
|
|||||||
return fmt.Errorf("unexpected query type %T. expect *ent.AccountGroupQuery", q)
|
return fmt.Errorf("unexpected query type %T. expect *ent.AccountGroupQuery", q)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ApiKeyFunc type is an adapter to allow the use of ordinary function as a Querier.
|
|
||||||
type ApiKeyFunc func(context.Context, *ent.ApiKeyQuery) (ent.Value, error)
|
|
||||||
|
|
||||||
// Query calls f(ctx, q).
|
|
||||||
func (f ApiKeyFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
|
||||||
if q, ok := q.(*ent.ApiKeyQuery); ok {
|
|
||||||
return f(ctx, q)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.ApiKeyQuery", q)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The TraverseApiKey type is an adapter to allow the use of ordinary function as Traverser.
|
|
||||||
type TraverseApiKey func(context.Context, *ent.ApiKeyQuery) error
|
|
||||||
|
|
||||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
|
||||||
func (f TraverseApiKey) Intercept(next ent.Querier) ent.Querier {
|
|
||||||
return next
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traverse calls f(ctx, q).
|
|
||||||
func (f TraverseApiKey) Traverse(ctx context.Context, q ent.Query) error {
|
|
||||||
if q, ok := q.(*ent.ApiKeyQuery); ok {
|
|
||||||
return f(ctx, q)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("unexpected query type %T. expect *ent.ApiKeyQuery", q)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The GroupFunc type is an adapter to allow the use of ordinary function as a Querier.
|
// 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)
|
type GroupFunc func(context.Context, *ent.GroupQuery) (ent.Value, error)
|
||||||
|
|
||||||
@@ -434,12 +434,12 @@ func (f TraverseUserSubscription) Traverse(ctx context.Context, q ent.Query) err
|
|||||||
// NewQuery returns the generic Query interface for the given typed query.
|
// NewQuery returns the generic Query interface for the given typed query.
|
||||||
func NewQuery(q ent.Query) (Query, error) {
|
func NewQuery(q ent.Query) (Query, error) {
|
||||||
switch q := q.(type) {
|
switch q := q.(type) {
|
||||||
|
case *ent.APIKeyQuery:
|
||||||
|
return &query[*ent.APIKeyQuery, predicate.APIKey, apikey.OrderOption]{typ: ent.TypeAPIKey, tq: q}, nil
|
||||||
case *ent.AccountQuery:
|
case *ent.AccountQuery:
|
||||||
return &query[*ent.AccountQuery, predicate.Account, account.OrderOption]{typ: ent.TypeAccount, tq: q}, nil
|
return &query[*ent.AccountQuery, predicate.Account, account.OrderOption]{typ: ent.TypeAccount, tq: q}, nil
|
||||||
case *ent.AccountGroupQuery:
|
case *ent.AccountGroupQuery:
|
||||||
return &query[*ent.AccountGroupQuery, predicate.AccountGroup, accountgroup.OrderOption]{typ: ent.TypeAccountGroup, tq: q}, nil
|
return &query[*ent.AccountGroupQuery, predicate.AccountGroup, accountgroup.OrderOption]{typ: ent.TypeAccountGroup, tq: q}, nil
|
||||||
case *ent.ApiKeyQuery:
|
|
||||||
return &query[*ent.ApiKeyQuery, predicate.ApiKey, apikey.OrderOption]{typ: ent.TypeApiKey, tq: q}, nil
|
|
||||||
case *ent.GroupQuery:
|
case *ent.GroupQuery:
|
||||||
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
|
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
|
||||||
case *ent.ProxyQuery:
|
case *ent.ProxyQuery:
|
||||||
|
|||||||
@@ -9,141 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// AccountsColumns holds the columns for the "accounts" table.
|
|
||||||
AccountsColumns = []*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: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "name", Type: field.TypeString, Size: 100},
|
|
||||||
{Name: "platform", Type: field.TypeString, Size: 50},
|
|
||||||
{Name: "type", Type: field.TypeString, Size: 20},
|
|
||||||
{Name: "credentials", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
|
||||||
{Name: "extra", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
|
||||||
{Name: "concurrency", Type: field.TypeInt, Default: 3},
|
|
||||||
{Name: "priority", Type: field.TypeInt, Default: 50},
|
|
||||||
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
|
|
||||||
{Name: "error_message", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
|
||||||
{Name: "last_used_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "schedulable", Type: field.TypeBool, Default: true},
|
|
||||||
{Name: "rate_limited_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "rate_limit_reset_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "overload_until", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "session_window_start", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "session_window_end", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "session_window_status", Type: field.TypeString, Nullable: true, Size: 20},
|
|
||||||
{Name: "proxy_id", Type: field.TypeInt64, Nullable: true},
|
|
||||||
}
|
|
||||||
// AccountsTable holds the schema information for the "accounts" table.
|
|
||||||
AccountsTable = &schema.Table{
|
|
||||||
Name: "accounts",
|
|
||||||
Columns: AccountsColumns,
|
|
||||||
PrimaryKey: []*schema.Column{AccountsColumns[0]},
|
|
||||||
ForeignKeys: []*schema.ForeignKey{
|
|
||||||
{
|
|
||||||
Symbol: "accounts_proxies_proxy",
|
|
||||||
Columns: []*schema.Column{AccountsColumns[21]},
|
|
||||||
RefColumns: []*schema.Column{ProxiesColumns[0]},
|
|
||||||
OnDelete: schema.SetNull,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Indexes: []*schema.Index{
|
|
||||||
{
|
|
||||||
Name: "account_platform",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[5]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_type",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[6]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_status",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[11]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_proxy_id",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[21]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_priority",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[10]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_last_used_at",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[13]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_schedulable",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[14]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_rate_limited_at",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[15]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_rate_limit_reset_at",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[16]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_overload_until",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[17]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "account_deleted_at",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountsColumns[3]},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// AccountGroupsColumns holds the columns for the "account_groups" table.
|
|
||||||
AccountGroupsColumns = []*schema.Column{
|
|
||||||
{Name: "priority", Type: field.TypeInt, Default: 50},
|
|
||||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
|
||||||
{Name: "account_id", Type: field.TypeInt64},
|
|
||||||
{Name: "group_id", Type: field.TypeInt64},
|
|
||||||
}
|
|
||||||
// AccountGroupsTable holds the schema information for the "account_groups" table.
|
|
||||||
AccountGroupsTable = &schema.Table{
|
|
||||||
Name: "account_groups",
|
|
||||||
Columns: AccountGroupsColumns,
|
|
||||||
PrimaryKey: []*schema.Column{AccountGroupsColumns[2], AccountGroupsColumns[3]},
|
|
||||||
ForeignKeys: []*schema.ForeignKey{
|
|
||||||
{
|
|
||||||
Symbol: "account_groups_accounts_account",
|
|
||||||
Columns: []*schema.Column{AccountGroupsColumns[2]},
|
|
||||||
RefColumns: []*schema.Column{AccountsColumns[0]},
|
|
||||||
OnDelete: schema.NoAction,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Symbol: "account_groups_groups_group",
|
|
||||||
Columns: []*schema.Column{AccountGroupsColumns[3]},
|
|
||||||
RefColumns: []*schema.Column{GroupsColumns[0]},
|
|
||||||
OnDelete: schema.NoAction,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Indexes: []*schema.Index{
|
|
||||||
{
|
|
||||||
Name: "accountgroup_group_id",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountGroupsColumns[3]},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "accountgroup_priority",
|
|
||||||
Unique: false,
|
|
||||||
Columns: []*schema.Column{AccountGroupsColumns[0]},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// APIKeysColumns holds the columns for the "api_keys" table.
|
// APIKeysColumns holds the columns for the "api_keys" table.
|
||||||
APIKeysColumns = []*schema.Column{
|
APIKeysColumns = []*schema.Column{
|
||||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||||
@@ -198,6 +63,144 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// AccountsColumns holds the columns for the "accounts" table.
|
||||||
|
AccountsColumns = []*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: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "name", Type: field.TypeString, Size: 100},
|
||||||
|
{Name: "notes", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||||
|
{Name: "platform", Type: field.TypeString, Size: 50},
|
||||||
|
{Name: "type", Type: field.TypeString, Size: 20},
|
||||||
|
{Name: "credentials", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||||
|
{Name: "extra", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||||
|
{Name: "concurrency", Type: field.TypeInt, Default: 3},
|
||||||
|
{Name: "priority", Type: field.TypeInt, Default: 50},
|
||||||
|
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
|
||||||
|
{Name: "error_message", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||||
|
{Name: "last_used_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "expires_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "auto_pause_on_expired", Type: field.TypeBool, Default: true},
|
||||||
|
{Name: "schedulable", Type: field.TypeBool, Default: true},
|
||||||
|
{Name: "rate_limited_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "rate_limit_reset_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "overload_until", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "session_window_start", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "session_window_end", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "session_window_status", Type: field.TypeString, Nullable: true, Size: 20},
|
||||||
|
{Name: "proxy_id", Type: field.TypeInt64, Nullable: true},
|
||||||
|
}
|
||||||
|
// AccountsTable holds the schema information for the "accounts" table.
|
||||||
|
AccountsTable = &schema.Table{
|
||||||
|
Name: "accounts",
|
||||||
|
Columns: AccountsColumns,
|
||||||
|
PrimaryKey: []*schema.Column{AccountsColumns[0]},
|
||||||
|
ForeignKeys: []*schema.ForeignKey{
|
||||||
|
{
|
||||||
|
Symbol: "accounts_proxies_proxy",
|
||||||
|
Columns: []*schema.Column{AccountsColumns[24]},
|
||||||
|
RefColumns: []*schema.Column{ProxiesColumns[0]},
|
||||||
|
OnDelete: schema.SetNull,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Indexes: []*schema.Index{
|
||||||
|
{
|
||||||
|
Name: "account_platform",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[6]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_type",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[7]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_status",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[12]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_proxy_id",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[24]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_priority",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[11]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_last_used_at",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[14]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_schedulable",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[17]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_rate_limited_at",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[18]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_rate_limit_reset_at",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[19]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_overload_until",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[20]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "account_deleted_at",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountsColumns[3]},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// AccountGroupsColumns holds the columns for the "account_groups" table.
|
||||||
|
AccountGroupsColumns = []*schema.Column{
|
||||||
|
{Name: "priority", Type: field.TypeInt, Default: 50},
|
||||||
|
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
|
{Name: "account_id", Type: field.TypeInt64},
|
||||||
|
{Name: "group_id", Type: field.TypeInt64},
|
||||||
|
}
|
||||||
|
// AccountGroupsTable holds the schema information for the "account_groups" table.
|
||||||
|
AccountGroupsTable = &schema.Table{
|
||||||
|
Name: "account_groups",
|
||||||
|
Columns: AccountGroupsColumns,
|
||||||
|
PrimaryKey: []*schema.Column{AccountGroupsColumns[2], AccountGroupsColumns[3]},
|
||||||
|
ForeignKeys: []*schema.ForeignKey{
|
||||||
|
{
|
||||||
|
Symbol: "account_groups_accounts_account",
|
||||||
|
Columns: []*schema.Column{AccountGroupsColumns[2]},
|
||||||
|
RefColumns: []*schema.Column{AccountsColumns[0]},
|
||||||
|
OnDelete: schema.NoAction,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Symbol: "account_groups_groups_group",
|
||||||
|
Columns: []*schema.Column{AccountGroupsColumns[3]},
|
||||||
|
RefColumns: []*schema.Column{GroupsColumns[0]},
|
||||||
|
OnDelete: schema.NoAction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Indexes: []*schema.Index{
|
||||||
|
{
|
||||||
|
Name: "accountgroup_group_id",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountGroupsColumns[3]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "accountgroup_priority",
|
||||||
|
Unique: false,
|
||||||
|
Columns: []*schema.Column{AccountGroupsColumns[0]},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
// GroupsColumns holds the columns for the "groups" table.
|
// GroupsColumns holds the columns for the "groups" table.
|
||||||
GroupsColumns = []*schema.Column{
|
GroupsColumns = []*schema.Column{
|
||||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||||
@@ -215,6 +218,9 @@ var (
|
|||||||
{Name: "weekly_limit_usd", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
{Name: "weekly_limit_usd", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||||
{Name: "monthly_limit_usd", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
{Name: "monthly_limit_usd", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||||
{Name: "default_validity_days", Type: field.TypeInt, Default: 30},
|
{Name: "default_validity_days", Type: field.TypeInt, Default: 30},
|
||||||
|
{Name: "image_price_1k", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||||
|
{Name: "image_price_2k", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||||
|
{Name: "image_price_4k", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||||
}
|
}
|
||||||
// GroupsTable holds the schema information for the "groups" table.
|
// GroupsTable holds the schema information for the "groups" table.
|
||||||
GroupsTable = &schema.Table{
|
GroupsTable = &schema.Table{
|
||||||
@@ -367,9 +373,12 @@ var (
|
|||||||
{Name: "stream", Type: field.TypeBool, Default: false},
|
{Name: "stream", Type: field.TypeBool, Default: false},
|
||||||
{Name: "duration_ms", Type: field.TypeInt, Nullable: true},
|
{Name: "duration_ms", Type: field.TypeInt, Nullable: true},
|
||||||
{Name: "first_token_ms", Type: field.TypeInt, Nullable: true},
|
{Name: "first_token_ms", Type: field.TypeInt, Nullable: true},
|
||||||
|
{Name: "user_agent", Type: field.TypeString, Nullable: true, Size: 512},
|
||||||
|
{Name: "image_count", Type: field.TypeInt, Default: 0},
|
||||||
|
{Name: "image_size", Type: field.TypeString, Nullable: true, Size: 10},
|
||||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||||
{Name: "account_id", Type: field.TypeInt64},
|
|
||||||
{Name: "api_key_id", Type: field.TypeInt64},
|
{Name: "api_key_id", Type: field.TypeInt64},
|
||||||
|
{Name: "account_id", Type: field.TypeInt64},
|
||||||
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
|
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
|
||||||
{Name: "user_id", Type: field.TypeInt64},
|
{Name: "user_id", Type: field.TypeInt64},
|
||||||
{Name: "subscription_id", Type: field.TypeInt64, Nullable: true},
|
{Name: "subscription_id", Type: field.TypeInt64, Nullable: true},
|
||||||
@@ -380,33 +389,33 @@ var (
|
|||||||
Columns: UsageLogsColumns,
|
Columns: UsageLogsColumns,
|
||||||
PrimaryKey: []*schema.Column{UsageLogsColumns[0]},
|
PrimaryKey: []*schema.Column{UsageLogsColumns[0]},
|
||||||
ForeignKeys: []*schema.ForeignKey{
|
ForeignKeys: []*schema.ForeignKey{
|
||||||
{
|
|
||||||
Symbol: "usage_logs_accounts_usage_logs",
|
|
||||||
Columns: []*schema.Column{UsageLogsColumns[21]},
|
|
||||||
RefColumns: []*schema.Column{AccountsColumns[0]},
|
|
||||||
OnDelete: schema.NoAction,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Symbol: "usage_logs_api_keys_usage_logs",
|
Symbol: "usage_logs_api_keys_usage_logs",
|
||||||
Columns: []*schema.Column{UsageLogsColumns[22]},
|
Columns: []*schema.Column{UsageLogsColumns[24]},
|
||||||
RefColumns: []*schema.Column{APIKeysColumns[0]},
|
RefColumns: []*schema.Column{APIKeysColumns[0]},
|
||||||
OnDelete: schema.NoAction,
|
OnDelete: schema.NoAction,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Symbol: "usage_logs_accounts_usage_logs",
|
||||||
|
Columns: []*schema.Column{UsageLogsColumns[25]},
|
||||||
|
RefColumns: []*schema.Column{AccountsColumns[0]},
|
||||||
|
OnDelete: schema.NoAction,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Symbol: "usage_logs_groups_usage_logs",
|
Symbol: "usage_logs_groups_usage_logs",
|
||||||
Columns: []*schema.Column{UsageLogsColumns[23]},
|
Columns: []*schema.Column{UsageLogsColumns[26]},
|
||||||
RefColumns: []*schema.Column{GroupsColumns[0]},
|
RefColumns: []*schema.Column{GroupsColumns[0]},
|
||||||
OnDelete: schema.SetNull,
|
OnDelete: schema.SetNull,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Symbol: "usage_logs_users_usage_logs",
|
Symbol: "usage_logs_users_usage_logs",
|
||||||
Columns: []*schema.Column{UsageLogsColumns[24]},
|
Columns: []*schema.Column{UsageLogsColumns[27]},
|
||||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||||
OnDelete: schema.NoAction,
|
OnDelete: schema.NoAction,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Symbol: "usage_logs_user_subscriptions_usage_logs",
|
Symbol: "usage_logs_user_subscriptions_usage_logs",
|
||||||
Columns: []*schema.Column{UsageLogsColumns[25]},
|
Columns: []*schema.Column{UsageLogsColumns[28]},
|
||||||
RefColumns: []*schema.Column{UserSubscriptionsColumns[0]},
|
RefColumns: []*schema.Column{UserSubscriptionsColumns[0]},
|
||||||
OnDelete: schema.SetNull,
|
OnDelete: schema.SetNull,
|
||||||
},
|
},
|
||||||
@@ -415,32 +424,32 @@ var (
|
|||||||
{
|
{
|
||||||
Name: "usagelog_user_id",
|
Name: "usagelog_user_id",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[24]},
|
Columns: []*schema.Column{UsageLogsColumns[27]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_api_key_id",
|
Name: "usagelog_api_key_id",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[22]},
|
Columns: []*schema.Column{UsageLogsColumns[24]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_account_id",
|
Name: "usagelog_account_id",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[21]},
|
Columns: []*schema.Column{UsageLogsColumns[25]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_group_id",
|
Name: "usagelog_group_id",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[23]},
|
Columns: []*schema.Column{UsageLogsColumns[26]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_subscription_id",
|
Name: "usagelog_subscription_id",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[25]},
|
Columns: []*schema.Column{UsageLogsColumns[28]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_created_at",
|
Name: "usagelog_created_at",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[20]},
|
Columns: []*schema.Column{UsageLogsColumns[23]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_model",
|
Name: "usagelog_model",
|
||||||
@@ -455,12 +464,12 @@ var (
|
|||||||
{
|
{
|
||||||
Name: "usagelog_user_id_created_at",
|
Name: "usagelog_user_id_created_at",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[24], UsageLogsColumns[20]},
|
Columns: []*schema.Column{UsageLogsColumns[27], UsageLogsColumns[23]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "usagelog_api_key_id_created_at",
|
Name: "usagelog_api_key_id_created_at",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Columns: []*schema.Column{UsageLogsColumns[22], UsageLogsColumns[20]},
|
Columns: []*schema.Column{UsageLogsColumns[24], UsageLogsColumns[23]},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -702,9 +711,9 @@ var (
|
|||||||
}
|
}
|
||||||
// Tables holds all the tables in the schema.
|
// Tables holds all the tables in the schema.
|
||||||
Tables = []*schema.Table{
|
Tables = []*schema.Table{
|
||||||
|
APIKeysTable,
|
||||||
AccountsTable,
|
AccountsTable,
|
||||||
AccountGroupsTable,
|
AccountGroupsTable,
|
||||||
APIKeysTable,
|
|
||||||
GroupsTable,
|
GroupsTable,
|
||||||
ProxiesTable,
|
ProxiesTable,
|
||||||
RedeemCodesTable,
|
RedeemCodesTable,
|
||||||
@@ -719,6 +728,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
APIKeysTable.ForeignKeys[0].RefTable = GroupsTable
|
||||||
|
APIKeysTable.ForeignKeys[1].RefTable = UsersTable
|
||||||
|
APIKeysTable.Annotation = &entsql.Annotation{
|
||||||
|
Table: "api_keys",
|
||||||
|
}
|
||||||
AccountsTable.ForeignKeys[0].RefTable = ProxiesTable
|
AccountsTable.ForeignKeys[0].RefTable = ProxiesTable
|
||||||
AccountsTable.Annotation = &entsql.Annotation{
|
AccountsTable.Annotation = &entsql.Annotation{
|
||||||
Table: "accounts",
|
Table: "accounts",
|
||||||
@@ -728,11 +742,6 @@ func init() {
|
|||||||
AccountGroupsTable.Annotation = &entsql.Annotation{
|
AccountGroupsTable.Annotation = &entsql.Annotation{
|
||||||
Table: "account_groups",
|
Table: "account_groups",
|
||||||
}
|
}
|
||||||
APIKeysTable.ForeignKeys[0].RefTable = GroupsTable
|
|
||||||
APIKeysTable.ForeignKeys[1].RefTable = UsersTable
|
|
||||||
APIKeysTable.Annotation = &entsql.Annotation{
|
|
||||||
Table: "api_keys",
|
|
||||||
}
|
|
||||||
GroupsTable.Annotation = &entsql.Annotation{
|
GroupsTable.Annotation = &entsql.Annotation{
|
||||||
Table: "groups",
|
Table: "groups",
|
||||||
}
|
}
|
||||||
@@ -747,8 +756,8 @@ func init() {
|
|||||||
SettingsTable.Annotation = &entsql.Annotation{
|
SettingsTable.Annotation = &entsql.Annotation{
|
||||||
Table: "settings",
|
Table: "settings",
|
||||||
}
|
}
|
||||||
UsageLogsTable.ForeignKeys[0].RefTable = AccountsTable
|
UsageLogsTable.ForeignKeys[0].RefTable = APIKeysTable
|
||||||
UsageLogsTable.ForeignKeys[1].RefTable = APIKeysTable
|
UsageLogsTable.ForeignKeys[1].RefTable = AccountsTable
|
||||||
UsageLogsTable.ForeignKeys[2].RefTable = GroupsTable
|
UsageLogsTable.ForeignKeys[2].RefTable = GroupsTable
|
||||||
UsageLogsTable.ForeignKeys[3].RefTable = UsersTable
|
UsageLogsTable.ForeignKeys[3].RefTable = UsersTable
|
||||||
UsageLogsTable.ForeignKeys[4].RefTable = UserSubscriptionsTable
|
UsageLogsTable.ForeignKeys[4].RefTable = UserSubscriptionsTable
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,15 +6,15 @@ import (
|
|||||||
"entgo.io/ent/dialect/sql"
|
"entgo.io/ent/dialect/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// APIKey is the predicate function for apikey builders.
|
||||||
|
type APIKey func(*sql.Selector)
|
||||||
|
|
||||||
// Account is the predicate function for account builders.
|
// Account is the predicate function for account builders.
|
||||||
type Account func(*sql.Selector)
|
type Account func(*sql.Selector)
|
||||||
|
|
||||||
// AccountGroup is the predicate function for accountgroup builders.
|
// AccountGroup is the predicate function for accountgroup builders.
|
||||||
type AccountGroup func(*sql.Selector)
|
type AccountGroup func(*sql.Selector)
|
||||||
|
|
||||||
// ApiKey is the predicate function for apikey builders.
|
|
||||||
type ApiKey func(*sql.Selector)
|
|
||||||
|
|
||||||
// Group is the predicate function for group builders.
|
// Group is the predicate function for group builders.
|
||||||
type Group func(*sql.Selector)
|
type Group func(*sql.Selector)
|
||||||
|
|
||||||
|
|||||||
@@ -25,127 +25,14 @@ import (
|
|||||||
// (default values, validators, hooks and policies) and stitches it
|
// (default values, validators, hooks and policies) and stitches it
|
||||||
// to their package variables.
|
// to their package variables.
|
||||||
func init() {
|
func init() {
|
||||||
accountMixin := schema.Account{}.Mixin()
|
apikeyMixin := schema.APIKey{}.Mixin()
|
||||||
accountMixinHooks1 := accountMixin[1].Hooks()
|
|
||||||
account.Hooks[0] = accountMixinHooks1[0]
|
|
||||||
accountMixinInters1 := accountMixin[1].Interceptors()
|
|
||||||
account.Interceptors[0] = accountMixinInters1[0]
|
|
||||||
accountMixinFields0 := accountMixin[0].Fields()
|
|
||||||
_ = accountMixinFields0
|
|
||||||
accountFields := schema.Account{}.Fields()
|
|
||||||
_ = accountFields
|
|
||||||
// accountDescCreatedAt is the schema descriptor for created_at field.
|
|
||||||
accountDescCreatedAt := accountMixinFields0[0].Descriptor()
|
|
||||||
// account.DefaultCreatedAt holds the default value on creation for the created_at field.
|
|
||||||
account.DefaultCreatedAt = accountDescCreatedAt.Default.(func() time.Time)
|
|
||||||
// accountDescUpdatedAt is the schema descriptor for updated_at field.
|
|
||||||
accountDescUpdatedAt := accountMixinFields0[1].Descriptor()
|
|
||||||
// account.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
|
||||||
account.DefaultUpdatedAt = accountDescUpdatedAt.Default.(func() time.Time)
|
|
||||||
// account.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
|
||||||
account.UpdateDefaultUpdatedAt = accountDescUpdatedAt.UpdateDefault.(func() time.Time)
|
|
||||||
// accountDescName is the schema descriptor for name field.
|
|
||||||
accountDescName := accountFields[0].Descriptor()
|
|
||||||
// account.NameValidator is a validator for the "name" field. It is called by the builders before save.
|
|
||||||
account.NameValidator = func() func(string) error {
|
|
||||||
validators := accountDescName.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
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// accountDescPlatform is the schema descriptor for platform field.
|
|
||||||
accountDescPlatform := accountFields[1].Descriptor()
|
|
||||||
// account.PlatformValidator is a validator for the "platform" field. It is called by the builders before save.
|
|
||||||
account.PlatformValidator = func() func(string) error {
|
|
||||||
validators := accountDescPlatform.Validators
|
|
||||||
fns := [...]func(string) error{
|
|
||||||
validators[0].(func(string) error),
|
|
||||||
validators[1].(func(string) error),
|
|
||||||
}
|
|
||||||
return func(platform string) error {
|
|
||||||
for _, fn := range fns {
|
|
||||||
if err := fn(platform); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// accountDescType is the schema descriptor for type field.
|
|
||||||
accountDescType := accountFields[2].Descriptor()
|
|
||||||
// account.TypeValidator is a validator for the "type" field. It is called by the builders before save.
|
|
||||||
account.TypeValidator = func() func(string) error {
|
|
||||||
validators := accountDescType.Validators
|
|
||||||
fns := [...]func(string) error{
|
|
||||||
validators[0].(func(string) error),
|
|
||||||
validators[1].(func(string) error),
|
|
||||||
}
|
|
||||||
return func(_type string) error {
|
|
||||||
for _, fn := range fns {
|
|
||||||
if err := fn(_type); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// accountDescCredentials is the schema descriptor for credentials field.
|
|
||||||
accountDescCredentials := accountFields[3].Descriptor()
|
|
||||||
// account.DefaultCredentials holds the default value on creation for the credentials field.
|
|
||||||
account.DefaultCredentials = accountDescCredentials.Default.(func() map[string]interface{})
|
|
||||||
// accountDescExtra is the schema descriptor for extra field.
|
|
||||||
accountDescExtra := accountFields[4].Descriptor()
|
|
||||||
// account.DefaultExtra holds the default value on creation for the extra field.
|
|
||||||
account.DefaultExtra = accountDescExtra.Default.(func() map[string]interface{})
|
|
||||||
// accountDescConcurrency is the schema descriptor for concurrency field.
|
|
||||||
accountDescConcurrency := accountFields[6].Descriptor()
|
|
||||||
// account.DefaultConcurrency holds the default value on creation for the concurrency field.
|
|
||||||
account.DefaultConcurrency = accountDescConcurrency.Default.(int)
|
|
||||||
// accountDescPriority is the schema descriptor for priority field.
|
|
||||||
accountDescPriority := accountFields[7].Descriptor()
|
|
||||||
// account.DefaultPriority holds the default value on creation for the priority field.
|
|
||||||
account.DefaultPriority = accountDescPriority.Default.(int)
|
|
||||||
// accountDescStatus is the schema descriptor for status field.
|
|
||||||
accountDescStatus := accountFields[8].Descriptor()
|
|
||||||
// account.DefaultStatus holds the default value on creation for the status field.
|
|
||||||
account.DefaultStatus = accountDescStatus.Default.(string)
|
|
||||||
// account.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
|
||||||
account.StatusValidator = accountDescStatus.Validators[0].(func(string) error)
|
|
||||||
// accountDescSchedulable is the schema descriptor for schedulable field.
|
|
||||||
accountDescSchedulable := accountFields[11].Descriptor()
|
|
||||||
// account.DefaultSchedulable holds the default value on creation for the schedulable field.
|
|
||||||
account.DefaultSchedulable = accountDescSchedulable.Default.(bool)
|
|
||||||
// accountDescSessionWindowStatus is the schema descriptor for session_window_status field.
|
|
||||||
accountDescSessionWindowStatus := accountFields[17].Descriptor()
|
|
||||||
// account.SessionWindowStatusValidator is a validator for the "session_window_status" field. It is called by the builders before save.
|
|
||||||
account.SessionWindowStatusValidator = accountDescSessionWindowStatus.Validators[0].(func(string) error)
|
|
||||||
accountgroupFields := schema.AccountGroup{}.Fields()
|
|
||||||
_ = accountgroupFields
|
|
||||||
// accountgroupDescPriority is the schema descriptor for priority field.
|
|
||||||
accountgroupDescPriority := accountgroupFields[2].Descriptor()
|
|
||||||
// accountgroup.DefaultPriority holds the default value on creation for the priority field.
|
|
||||||
accountgroup.DefaultPriority = accountgroupDescPriority.Default.(int)
|
|
||||||
// accountgroupDescCreatedAt is the schema descriptor for created_at field.
|
|
||||||
accountgroupDescCreatedAt := accountgroupFields[3].Descriptor()
|
|
||||||
// accountgroup.DefaultCreatedAt holds the default value on creation for the created_at field.
|
|
||||||
accountgroup.DefaultCreatedAt = accountgroupDescCreatedAt.Default.(func() time.Time)
|
|
||||||
apikeyMixin := schema.ApiKey{}.Mixin()
|
|
||||||
apikeyMixinHooks1 := apikeyMixin[1].Hooks()
|
apikeyMixinHooks1 := apikeyMixin[1].Hooks()
|
||||||
apikey.Hooks[0] = apikeyMixinHooks1[0]
|
apikey.Hooks[0] = apikeyMixinHooks1[0]
|
||||||
apikeyMixinInters1 := apikeyMixin[1].Interceptors()
|
apikeyMixinInters1 := apikeyMixin[1].Interceptors()
|
||||||
apikey.Interceptors[0] = apikeyMixinInters1[0]
|
apikey.Interceptors[0] = apikeyMixinInters1[0]
|
||||||
apikeyMixinFields0 := apikeyMixin[0].Fields()
|
apikeyMixinFields0 := apikeyMixin[0].Fields()
|
||||||
_ = apikeyMixinFields0
|
_ = apikeyMixinFields0
|
||||||
apikeyFields := schema.ApiKey{}.Fields()
|
apikeyFields := schema.APIKey{}.Fields()
|
||||||
_ = apikeyFields
|
_ = apikeyFields
|
||||||
// apikeyDescCreatedAt is the schema descriptor for created_at field.
|
// apikeyDescCreatedAt is the schema descriptor for created_at field.
|
||||||
apikeyDescCreatedAt := apikeyMixinFields0[0].Descriptor()
|
apikeyDescCreatedAt := apikeyMixinFields0[0].Descriptor()
|
||||||
@@ -199,6 +86,123 @@ func init() {
|
|||||||
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
|
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
|
||||||
// apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
// 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)
|
apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error)
|
||||||
|
accountMixin := schema.Account{}.Mixin()
|
||||||
|
accountMixinHooks1 := accountMixin[1].Hooks()
|
||||||
|
account.Hooks[0] = accountMixinHooks1[0]
|
||||||
|
accountMixinInters1 := accountMixin[1].Interceptors()
|
||||||
|
account.Interceptors[0] = accountMixinInters1[0]
|
||||||
|
accountMixinFields0 := accountMixin[0].Fields()
|
||||||
|
_ = accountMixinFields0
|
||||||
|
accountFields := schema.Account{}.Fields()
|
||||||
|
_ = accountFields
|
||||||
|
// accountDescCreatedAt is the schema descriptor for created_at field.
|
||||||
|
accountDescCreatedAt := accountMixinFields0[0].Descriptor()
|
||||||
|
// account.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||||
|
account.DefaultCreatedAt = accountDescCreatedAt.Default.(func() time.Time)
|
||||||
|
// accountDescUpdatedAt is the schema descriptor for updated_at field.
|
||||||
|
accountDescUpdatedAt := accountMixinFields0[1].Descriptor()
|
||||||
|
// account.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||||
|
account.DefaultUpdatedAt = accountDescUpdatedAt.Default.(func() time.Time)
|
||||||
|
// account.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||||
|
account.UpdateDefaultUpdatedAt = accountDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||||
|
// accountDescName is the schema descriptor for name field.
|
||||||
|
accountDescName := accountFields[0].Descriptor()
|
||||||
|
// account.NameValidator is a validator for the "name" field. It is called by the builders before save.
|
||||||
|
account.NameValidator = func() func(string) error {
|
||||||
|
validators := accountDescName.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
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// accountDescPlatform is the schema descriptor for platform field.
|
||||||
|
accountDescPlatform := accountFields[2].Descriptor()
|
||||||
|
// account.PlatformValidator is a validator for the "platform" field. It is called by the builders before save.
|
||||||
|
account.PlatformValidator = func() func(string) error {
|
||||||
|
validators := accountDescPlatform.Validators
|
||||||
|
fns := [...]func(string) error{
|
||||||
|
validators[0].(func(string) error),
|
||||||
|
validators[1].(func(string) error),
|
||||||
|
}
|
||||||
|
return func(platform string) error {
|
||||||
|
for _, fn := range fns {
|
||||||
|
if err := fn(platform); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// accountDescType is the schema descriptor for type field.
|
||||||
|
accountDescType := accountFields[3].Descriptor()
|
||||||
|
// account.TypeValidator is a validator for the "type" field. It is called by the builders before save.
|
||||||
|
account.TypeValidator = func() func(string) error {
|
||||||
|
validators := accountDescType.Validators
|
||||||
|
fns := [...]func(string) error{
|
||||||
|
validators[0].(func(string) error),
|
||||||
|
validators[1].(func(string) error),
|
||||||
|
}
|
||||||
|
return func(_type string) error {
|
||||||
|
for _, fn := range fns {
|
||||||
|
if err := fn(_type); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// accountDescCredentials is the schema descriptor for credentials field.
|
||||||
|
accountDescCredentials := accountFields[4].Descriptor()
|
||||||
|
// account.DefaultCredentials holds the default value on creation for the credentials field.
|
||||||
|
account.DefaultCredentials = accountDescCredentials.Default.(func() map[string]interface{})
|
||||||
|
// accountDescExtra is the schema descriptor for extra field.
|
||||||
|
accountDescExtra := accountFields[5].Descriptor()
|
||||||
|
// account.DefaultExtra holds the default value on creation for the extra field.
|
||||||
|
account.DefaultExtra = accountDescExtra.Default.(func() map[string]interface{})
|
||||||
|
// accountDescConcurrency is the schema descriptor for concurrency field.
|
||||||
|
accountDescConcurrency := accountFields[7].Descriptor()
|
||||||
|
// account.DefaultConcurrency holds the default value on creation for the concurrency field.
|
||||||
|
account.DefaultConcurrency = accountDescConcurrency.Default.(int)
|
||||||
|
// accountDescPriority is the schema descriptor for priority field.
|
||||||
|
accountDescPriority := accountFields[8].Descriptor()
|
||||||
|
// account.DefaultPriority holds the default value on creation for the priority field.
|
||||||
|
account.DefaultPriority = accountDescPriority.Default.(int)
|
||||||
|
// accountDescStatus is the schema descriptor for status field.
|
||||||
|
accountDescStatus := accountFields[9].Descriptor()
|
||||||
|
// account.DefaultStatus holds the default value on creation for the status field.
|
||||||
|
account.DefaultStatus = accountDescStatus.Default.(string)
|
||||||
|
// account.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||||
|
account.StatusValidator = accountDescStatus.Validators[0].(func(string) error)
|
||||||
|
// accountDescAutoPauseOnExpired is the schema descriptor for auto_pause_on_expired field.
|
||||||
|
accountDescAutoPauseOnExpired := accountFields[13].Descriptor()
|
||||||
|
// account.DefaultAutoPauseOnExpired holds the default value on creation for the auto_pause_on_expired field.
|
||||||
|
account.DefaultAutoPauseOnExpired = accountDescAutoPauseOnExpired.Default.(bool)
|
||||||
|
// accountDescSchedulable is the schema descriptor for schedulable field.
|
||||||
|
accountDescSchedulable := accountFields[14].Descriptor()
|
||||||
|
// account.DefaultSchedulable holds the default value on creation for the schedulable field.
|
||||||
|
account.DefaultSchedulable = accountDescSchedulable.Default.(bool)
|
||||||
|
// accountDescSessionWindowStatus is the schema descriptor for session_window_status field.
|
||||||
|
accountDescSessionWindowStatus := accountFields[20].Descriptor()
|
||||||
|
// account.SessionWindowStatusValidator is a validator for the "session_window_status" field. It is called by the builders before save.
|
||||||
|
account.SessionWindowStatusValidator = accountDescSessionWindowStatus.Validators[0].(func(string) error)
|
||||||
|
accountgroupFields := schema.AccountGroup{}.Fields()
|
||||||
|
_ = accountgroupFields
|
||||||
|
// accountgroupDescPriority is the schema descriptor for priority field.
|
||||||
|
accountgroupDescPriority := accountgroupFields[2].Descriptor()
|
||||||
|
// accountgroup.DefaultPriority holds the default value on creation for the priority field.
|
||||||
|
accountgroup.DefaultPriority = accountgroupDescPriority.Default.(int)
|
||||||
|
// accountgroupDescCreatedAt is the schema descriptor for created_at field.
|
||||||
|
accountgroupDescCreatedAt := accountgroupFields[3].Descriptor()
|
||||||
|
// accountgroup.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||||
|
accountgroup.DefaultCreatedAt = accountgroupDescCreatedAt.Default.(func() time.Time)
|
||||||
groupMixin := schema.Group{}.Mixin()
|
groupMixin := schema.Group{}.Mixin()
|
||||||
groupMixinHooks1 := groupMixin[1].Hooks()
|
groupMixinHooks1 := groupMixin[1].Hooks()
|
||||||
group.Hooks[0] = groupMixinHooks1[0]
|
group.Hooks[0] = groupMixinHooks1[0]
|
||||||
@@ -521,8 +525,20 @@ func init() {
|
|||||||
usagelogDescStream := usagelogFields[21].Descriptor()
|
usagelogDescStream := usagelogFields[21].Descriptor()
|
||||||
// usagelog.DefaultStream holds the default value on creation for the stream field.
|
// usagelog.DefaultStream holds the default value on creation for the stream field.
|
||||||
usagelog.DefaultStream = usagelogDescStream.Default.(bool)
|
usagelog.DefaultStream = usagelogDescStream.Default.(bool)
|
||||||
|
// usagelogDescUserAgent is the schema descriptor for user_agent field.
|
||||||
|
usagelogDescUserAgent := usagelogFields[24].Descriptor()
|
||||||
|
// usagelog.UserAgentValidator is a validator for the "user_agent" field. It is called by the builders before save.
|
||||||
|
usagelog.UserAgentValidator = usagelogDescUserAgent.Validators[0].(func(string) error)
|
||||||
|
// usagelogDescImageCount is the schema descriptor for image_count field.
|
||||||
|
usagelogDescImageCount := usagelogFields[25].Descriptor()
|
||||||
|
// usagelog.DefaultImageCount holds the default value on creation for the image_count field.
|
||||||
|
usagelog.DefaultImageCount = usagelogDescImageCount.Default.(int)
|
||||||
|
// usagelogDescImageSize is the schema descriptor for image_size field.
|
||||||
|
usagelogDescImageSize := usagelogFields[26].Descriptor()
|
||||||
|
// usagelog.ImageSizeValidator is a validator for the "image_size" field. It is called by the builders before save.
|
||||||
|
usagelog.ImageSizeValidator = usagelogDescImageSize.Validators[0].(func(string) error)
|
||||||
// usagelogDescCreatedAt is the schema descriptor for created_at field.
|
// usagelogDescCreatedAt is the schema descriptor for created_at field.
|
||||||
usagelogDescCreatedAt := usagelogFields[24].Descriptor()
|
usagelogDescCreatedAt := usagelogFields[27].Descriptor()
|
||||||
// usagelog.DefaultCreatedAt holds the default value on creation for the created_at field.
|
// usagelog.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||||
usagelog.DefaultCreatedAt = usagelogDescCreatedAt.Default.(func() time.Time)
|
usagelog.DefaultCreatedAt = usagelogDescCreatedAt.Default.(func() time.Time)
|
||||||
userMixin := schema.User{}.Mixin()
|
userMixin := schema.User{}.Mixin()
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ func (Account) Fields() []ent.Field {
|
|||||||
field.String("name").
|
field.String("name").
|
||||||
MaxLen(100).
|
MaxLen(100).
|
||||||
NotEmpty(),
|
NotEmpty(),
|
||||||
|
// notes: 管理员备注(可为空)
|
||||||
|
field.String("notes").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||||
|
|
||||||
// platform: 所属平台,如 "claude", "gemini", "openai" 等
|
// platform: 所属平台,如 "claude", "gemini", "openai" 等
|
||||||
field.String("platform").
|
field.String("platform").
|
||||||
@@ -113,6 +118,16 @@ func (Account) Fields() []ent.Field {
|
|||||||
Optional().
|
Optional().
|
||||||
Nillable().
|
Nillable().
|
||||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||||
|
// expires_at: 账户过期时间(可为空)
|
||||||
|
field.Time("expires_at").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
Comment("Account expiration time (NULL means no expiration).").
|
||||||
|
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||||
|
// auto_pause_on_expired: 过期后自动暂停调度
|
||||||
|
field.Bool("auto_pause_on_expired").
|
||||||
|
Default(true).
|
||||||
|
Comment("Auto pause scheduling when account expires."),
|
||||||
|
|
||||||
// ========== 调度和速率限制相关字段 ==========
|
// ========== 调度和速率限制相关字段 ==========
|
||||||
// 这些字段在 migrations/005_schema_parity.sql 中添加
|
// 这些字段在 migrations/005_schema_parity.sql 中添加
|
||||||
|
|||||||
@@ -12,25 +12,25 @@ import (
|
|||||||
"entgo.io/ent/schema/index"
|
"entgo.io/ent/schema/index"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiKey holds the schema definition for the ApiKey entity.
|
// APIKey holds the schema definition for the APIKey entity.
|
||||||
type ApiKey struct {
|
type APIKey struct {
|
||||||
ent.Schema
|
ent.Schema
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ApiKey) Annotations() []schema.Annotation {
|
func (APIKey) Annotations() []schema.Annotation {
|
||||||
return []schema.Annotation{
|
return []schema.Annotation{
|
||||||
entsql.Annotation{Table: "api_keys"},
|
entsql.Annotation{Table: "api_keys"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ApiKey) Mixin() []ent.Mixin {
|
func (APIKey) Mixin() []ent.Mixin {
|
||||||
return []ent.Mixin{
|
return []ent.Mixin{
|
||||||
mixins.TimeMixin{},
|
mixins.TimeMixin{},
|
||||||
mixins.SoftDeleteMixin{},
|
mixins.SoftDeleteMixin{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ApiKey) Fields() []ent.Field {
|
func (APIKey) Fields() []ent.Field {
|
||||||
return []ent.Field{
|
return []ent.Field{
|
||||||
field.Int64("user_id"),
|
field.Int64("user_id"),
|
||||||
field.String("key").
|
field.String("key").
|
||||||
@@ -49,7 +49,7 @@ func (ApiKey) Fields() []ent.Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ApiKey) Edges() []ent.Edge {
|
func (APIKey) Edges() []ent.Edge {
|
||||||
return []ent.Edge{
|
return []ent.Edge{
|
||||||
edge.From("user", User.Type).
|
edge.From("user", User.Type).
|
||||||
Ref("api_keys").
|
Ref("api_keys").
|
||||||
@@ -64,7 +64,7 @@ func (ApiKey) Edges() []ent.Edge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ApiKey) Indexes() []ent.Index {
|
func (APIKey) Indexes() []ent.Index {
|
||||||
return []ent.Index{
|
return []ent.Index{
|
||||||
// key 字段已在 Fields() 中声明 Unique(),无需重复索引
|
// key 字段已在 Fields() 中声明 Unique(),无需重复索引
|
||||||
index.Fields("user_id"),
|
index.Fields("user_id"),
|
||||||
|
|||||||
@@ -72,12 +72,26 @@ func (Group) Fields() []ent.Field {
|
|||||||
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}),
|
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}),
|
||||||
field.Int("default_validity_days").
|
field.Int("default_validity_days").
|
||||||
Default(30),
|
Default(30),
|
||||||
|
|
||||||
|
// 图片生成计费配置(antigravity 和 gemini 平台使用)
|
||||||
|
field.Float("image_price_1k").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}),
|
||||||
|
field.Float("image_price_2k").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}),
|
||||||
|
field.Float("image_price_4k").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Group) Edges() []ent.Edge {
|
func (Group) Edges() []ent.Edge {
|
||||||
return []ent.Edge{
|
return []ent.Edge{
|
||||||
edge.To("api_keys", ApiKey.Type),
|
edge.To("api_keys", APIKey.Type),
|
||||||
edge.To("redeem_codes", RedeemCode.Type),
|
edge.To("redeem_codes", RedeemCode.Type),
|
||||||
edge.To("subscriptions", UserSubscription.Type),
|
edge.To("subscriptions", UserSubscription.Type),
|
||||||
edge.To("usage_logs", UsageLog.Type),
|
edge.To("usage_logs", UsageLog.Type),
|
||||||
|
|||||||
@@ -96,6 +96,18 @@ func (UsageLog) Fields() []ent.Field {
|
|||||||
field.Int("first_token_ms").
|
field.Int("first_token_ms").
|
||||||
Optional().
|
Optional().
|
||||||
Nillable(),
|
Nillable(),
|
||||||
|
field.String("user_agent").
|
||||||
|
MaxLen(512).
|
||||||
|
Optional().
|
||||||
|
Nillable(),
|
||||||
|
|
||||||
|
// 图片生成字段(仅 gemini-3-pro-image 等图片模型使用)
|
||||||
|
field.Int("image_count").
|
||||||
|
Default(0),
|
||||||
|
field.String("image_size").
|
||||||
|
MaxLen(10).
|
||||||
|
Optional().
|
||||||
|
Nillable(),
|
||||||
|
|
||||||
// 时间戳(只有 created_at,日志不可修改)
|
// 时间戳(只有 created_at,日志不可修改)
|
||||||
field.Time("created_at").
|
field.Time("created_at").
|
||||||
@@ -113,7 +125,7 @@ func (UsageLog) Edges() []ent.Edge {
|
|||||||
Field("user_id").
|
Field("user_id").
|
||||||
Required().
|
Required().
|
||||||
Unique(),
|
Unique(),
|
||||||
edge.From("api_key", ApiKey.Type).
|
edge.From("api_key", APIKey.Type).
|
||||||
Ref("usage_logs").
|
Ref("usage_logs").
|
||||||
Field("api_key_id").
|
Field("api_key_id").
|
||||||
Required().
|
Required().
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func (User) Fields() []ent.Field {
|
|||||||
|
|
||||||
func (User) Edges() []ent.Edge {
|
func (User) Edges() []ent.Edge {
|
||||||
return []ent.Edge{
|
return []ent.Edge{
|
||||||
edge.To("api_keys", ApiKey.Type),
|
edge.To("api_keys", APIKey.Type),
|
||||||
edge.To("redeem_codes", RedeemCode.Type),
|
edge.To("redeem_codes", RedeemCode.Type),
|
||||||
edge.To("subscriptions", UserSubscription.Type),
|
edge.To("subscriptions", UserSubscription.Type),
|
||||||
edge.To("assigned_subscriptions", UserSubscription.Type),
|
edge.To("assigned_subscriptions", UserSubscription.Type),
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ import (
|
|||||||
// Tx is a transactional client that is created by calling Client.Tx().
|
// Tx is a transactional client that is created by calling Client.Tx().
|
||||||
type Tx struct {
|
type Tx struct {
|
||||||
config
|
config
|
||||||
|
// APIKey is the client for interacting with the APIKey builders.
|
||||||
|
APIKey *APIKeyClient
|
||||||
// Account is the client for interacting with the Account builders.
|
// Account is the client for interacting with the Account builders.
|
||||||
Account *AccountClient
|
Account *AccountClient
|
||||||
// AccountGroup is the client for interacting with the AccountGroup builders.
|
// AccountGroup is the client for interacting with the AccountGroup builders.
|
||||||
AccountGroup *AccountGroupClient
|
AccountGroup *AccountGroupClient
|
||||||
// ApiKey is the client for interacting with the ApiKey builders.
|
|
||||||
ApiKey *ApiKeyClient
|
|
||||||
// Group is the client for interacting with the Group builders.
|
// Group is the client for interacting with the Group builders.
|
||||||
Group *GroupClient
|
Group *GroupClient
|
||||||
// Proxy is the client for interacting with the Proxy builders.
|
// Proxy is the client for interacting with the Proxy builders.
|
||||||
@@ -171,9 +171,9 @@ func (tx *Tx) Client() *Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) init() {
|
func (tx *Tx) init() {
|
||||||
|
tx.APIKey = NewAPIKeyClient(tx.config)
|
||||||
tx.Account = NewAccountClient(tx.config)
|
tx.Account = NewAccountClient(tx.config)
|
||||||
tx.AccountGroup = NewAccountGroupClient(tx.config)
|
tx.AccountGroup = NewAccountGroupClient(tx.config)
|
||||||
tx.ApiKey = NewApiKeyClient(tx.config)
|
|
||||||
tx.Group = NewGroupClient(tx.config)
|
tx.Group = NewGroupClient(tx.config)
|
||||||
tx.Proxy = NewProxyClient(tx.config)
|
tx.Proxy = NewProxyClient(tx.config)
|
||||||
tx.RedeemCode = NewRedeemCodeClient(tx.config)
|
tx.RedeemCode = NewRedeemCodeClient(tx.config)
|
||||||
@@ -193,7 +193,7 @@ func (tx *Tx) init() {
|
|||||||
// of them in order to commit or rollback the transaction.
|
// of them in order to commit or rollback the transaction.
|
||||||
//
|
//
|
||||||
// If a closed transaction is embedded in one of the generated entities, and the entity
|
// If a closed transaction is embedded in one of the generated entities, and the entity
|
||||||
// applies a query, for example: Account.QueryXXX(), the query will be executed
|
// applies a query, for example: APIKey.QueryXXX(), the query will be executed
|
||||||
// through the driver which created this transaction.
|
// through the driver which created this transaction.
|
||||||
//
|
//
|
||||||
// Note that txDriver is not goroutine safe.
|
// Note that txDriver is not goroutine safe.
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ type UsageLog struct {
|
|||||||
DurationMs *int `json:"duration_ms,omitempty"`
|
DurationMs *int `json:"duration_ms,omitempty"`
|
||||||
// FirstTokenMs holds the value of the "first_token_ms" field.
|
// FirstTokenMs holds the value of the "first_token_ms" field.
|
||||||
FirstTokenMs *int `json:"first_token_ms,omitempty"`
|
FirstTokenMs *int `json:"first_token_ms,omitempty"`
|
||||||
|
// UserAgent holds the value of the "user_agent" field.
|
||||||
|
UserAgent *string `json:"user_agent,omitempty"`
|
||||||
|
// ImageCount holds the value of the "image_count" field.
|
||||||
|
ImageCount int `json:"image_count,omitempty"`
|
||||||
|
// ImageSize holds the value of the "image_size" field.
|
||||||
|
ImageSize *string `json:"image_size,omitempty"`
|
||||||
// CreatedAt holds the value of the "created_at" field.
|
// CreatedAt holds the value of the "created_at" field.
|
||||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
@@ -83,7 +89,7 @@ type UsageLogEdges struct {
|
|||||||
// User holds the value of the user edge.
|
// User holds the value of the user edge.
|
||||||
User *User `json:"user,omitempty"`
|
User *User `json:"user,omitempty"`
|
||||||
// APIKey holds the value of the api_key edge.
|
// APIKey holds the value of the api_key edge.
|
||||||
APIKey *ApiKey `json:"api_key,omitempty"`
|
APIKey *APIKey `json:"api_key,omitempty"`
|
||||||
// Account holds the value of the account edge.
|
// Account holds the value of the account edge.
|
||||||
Account *Account `json:"account,omitempty"`
|
Account *Account `json:"account,omitempty"`
|
||||||
// Group holds the value of the group edge.
|
// Group holds the value of the group edge.
|
||||||
@@ -108,7 +114,7 @@ func (e UsageLogEdges) UserOrErr() (*User, error) {
|
|||||||
|
|
||||||
// APIKeyOrErr returns the APIKey value or an error if the edge
|
// APIKeyOrErr returns the APIKey value or an error if the edge
|
||||||
// was not loaded in eager-loading, or loaded but was not found.
|
// was not loaded in eager-loading, or loaded but was not found.
|
||||||
func (e UsageLogEdges) APIKeyOrErr() (*ApiKey, error) {
|
func (e UsageLogEdges) APIKeyOrErr() (*APIKey, error) {
|
||||||
if e.APIKey != nil {
|
if e.APIKey != nil {
|
||||||
return e.APIKey, nil
|
return e.APIKey, nil
|
||||||
} else if e.loadedTypes[1] {
|
} else if e.loadedTypes[1] {
|
||||||
@@ -159,9 +165,9 @@ func (*UsageLog) scanValues(columns []string) ([]any, error) {
|
|||||||
values[i] = new(sql.NullBool)
|
values[i] = new(sql.NullBool)
|
||||||
case usagelog.FieldInputCost, usagelog.FieldOutputCost, usagelog.FieldCacheCreationCost, usagelog.FieldCacheReadCost, usagelog.FieldTotalCost, usagelog.FieldActualCost, usagelog.FieldRateMultiplier:
|
case usagelog.FieldInputCost, usagelog.FieldOutputCost, usagelog.FieldCacheCreationCost, usagelog.FieldCacheReadCost, usagelog.FieldTotalCost, usagelog.FieldActualCost, usagelog.FieldRateMultiplier:
|
||||||
values[i] = new(sql.NullFloat64)
|
values[i] = new(sql.NullFloat64)
|
||||||
case usagelog.FieldID, usagelog.FieldUserID, usagelog.FieldAPIKeyID, usagelog.FieldAccountID, usagelog.FieldGroupID, usagelog.FieldSubscriptionID, usagelog.FieldInputTokens, usagelog.FieldOutputTokens, usagelog.FieldCacheCreationTokens, usagelog.FieldCacheReadTokens, usagelog.FieldCacheCreation5mTokens, usagelog.FieldCacheCreation1hTokens, usagelog.FieldBillingType, usagelog.FieldDurationMs, usagelog.FieldFirstTokenMs:
|
case usagelog.FieldID, usagelog.FieldUserID, usagelog.FieldAPIKeyID, usagelog.FieldAccountID, usagelog.FieldGroupID, usagelog.FieldSubscriptionID, usagelog.FieldInputTokens, usagelog.FieldOutputTokens, usagelog.FieldCacheCreationTokens, usagelog.FieldCacheReadTokens, usagelog.FieldCacheCreation5mTokens, usagelog.FieldCacheCreation1hTokens, usagelog.FieldBillingType, usagelog.FieldDurationMs, usagelog.FieldFirstTokenMs, usagelog.FieldImageCount:
|
||||||
values[i] = new(sql.NullInt64)
|
values[i] = new(sql.NullInt64)
|
||||||
case usagelog.FieldRequestID, usagelog.FieldModel:
|
case usagelog.FieldRequestID, usagelog.FieldModel, usagelog.FieldUserAgent, usagelog.FieldImageSize:
|
||||||
values[i] = new(sql.NullString)
|
values[i] = new(sql.NullString)
|
||||||
case usagelog.FieldCreatedAt:
|
case usagelog.FieldCreatedAt:
|
||||||
values[i] = new(sql.NullTime)
|
values[i] = new(sql.NullTime)
|
||||||
@@ -334,6 +340,26 @@ func (_m *UsageLog) assignValues(columns []string, values []any) error {
|
|||||||
_m.FirstTokenMs = new(int)
|
_m.FirstTokenMs = new(int)
|
||||||
*_m.FirstTokenMs = int(value.Int64)
|
*_m.FirstTokenMs = int(value.Int64)
|
||||||
}
|
}
|
||||||
|
case usagelog.FieldUserAgent:
|
||||||
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field user_agent", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.UserAgent = new(string)
|
||||||
|
*_m.UserAgent = value.String
|
||||||
|
}
|
||||||
|
case usagelog.FieldImageCount:
|
||||||
|
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field image_count", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.ImageCount = int(value.Int64)
|
||||||
|
}
|
||||||
|
case usagelog.FieldImageSize:
|
||||||
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field image_size", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
_m.ImageSize = new(string)
|
||||||
|
*_m.ImageSize = value.String
|
||||||
|
}
|
||||||
case usagelog.FieldCreatedAt:
|
case usagelog.FieldCreatedAt:
|
||||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||||
@@ -359,7 +385,7 @@ func (_m *UsageLog) QueryUser() *UserQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKey queries the "api_key" edge of the UsageLog entity.
|
// QueryAPIKey queries the "api_key" edge of the UsageLog entity.
|
||||||
func (_m *UsageLog) QueryAPIKey() *ApiKeyQuery {
|
func (_m *UsageLog) QueryAPIKey() *APIKeyQuery {
|
||||||
return NewUsageLogClient(_m.config).QueryAPIKey(_m)
|
return NewUsageLogClient(_m.config).QueryAPIKey(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,6 +507,19 @@ func (_m *UsageLog) String() string {
|
|||||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||||
}
|
}
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
if v := _m.UserAgent; v != nil {
|
||||||
|
builder.WriteString("user_agent=")
|
||||||
|
builder.WriteString(*v)
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
|
builder.WriteString("image_count=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", _m.ImageCount))
|
||||||
|
builder.WriteString(", ")
|
||||||
|
if v := _m.ImageSize; v != nil {
|
||||||
|
builder.WriteString("image_size=")
|
||||||
|
builder.WriteString(*v)
|
||||||
|
}
|
||||||
|
builder.WriteString(", ")
|
||||||
builder.WriteString("created_at=")
|
builder.WriteString("created_at=")
|
||||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||||
builder.WriteByte(')')
|
builder.WriteByte(')')
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ const (
|
|||||||
FieldDurationMs = "duration_ms"
|
FieldDurationMs = "duration_ms"
|
||||||
// FieldFirstTokenMs holds the string denoting the first_token_ms field in the database.
|
// FieldFirstTokenMs holds the string denoting the first_token_ms field in the database.
|
||||||
FieldFirstTokenMs = "first_token_ms"
|
FieldFirstTokenMs = "first_token_ms"
|
||||||
|
// FieldUserAgent holds the string denoting the user_agent field in the database.
|
||||||
|
FieldUserAgent = "user_agent"
|
||||||
|
// FieldImageCount holds the string denoting the image_count field in the database.
|
||||||
|
FieldImageCount = "image_count"
|
||||||
|
// FieldImageSize holds the string denoting the image_size field in the database.
|
||||||
|
FieldImageSize = "image_size"
|
||||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||||
FieldCreatedAt = "created_at"
|
FieldCreatedAt = "created_at"
|
||||||
// EdgeUser holds the string denoting the user edge name in mutations.
|
// EdgeUser holds the string denoting the user edge name in mutations.
|
||||||
@@ -85,7 +91,7 @@ const (
|
|||||||
UserColumn = "user_id"
|
UserColumn = "user_id"
|
||||||
// APIKeyTable is the table that holds the api_key relation/edge.
|
// APIKeyTable is the table that holds the api_key relation/edge.
|
||||||
APIKeyTable = "usage_logs"
|
APIKeyTable = "usage_logs"
|
||||||
// APIKeyInverseTable is the table name for the ApiKey entity.
|
// APIKeyInverseTable is the table name for the APIKey entity.
|
||||||
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
||||||
APIKeyInverseTable = "api_keys"
|
APIKeyInverseTable = "api_keys"
|
||||||
// APIKeyColumn is the table column denoting the api_key relation/edge.
|
// APIKeyColumn is the table column denoting the api_key relation/edge.
|
||||||
@@ -140,6 +146,9 @@ var Columns = []string{
|
|||||||
FieldStream,
|
FieldStream,
|
||||||
FieldDurationMs,
|
FieldDurationMs,
|
||||||
FieldFirstTokenMs,
|
FieldFirstTokenMs,
|
||||||
|
FieldUserAgent,
|
||||||
|
FieldImageCount,
|
||||||
|
FieldImageSize,
|
||||||
FieldCreatedAt,
|
FieldCreatedAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +197,12 @@ var (
|
|||||||
DefaultBillingType int8
|
DefaultBillingType int8
|
||||||
// DefaultStream holds the default value on creation for the "stream" field.
|
// DefaultStream holds the default value on creation for the "stream" field.
|
||||||
DefaultStream bool
|
DefaultStream bool
|
||||||
|
// UserAgentValidator is a validator for the "user_agent" field. It is called by the builders before save.
|
||||||
|
UserAgentValidator func(string) error
|
||||||
|
// DefaultImageCount holds the default value on creation for the "image_count" field.
|
||||||
|
DefaultImageCount int
|
||||||
|
// ImageSizeValidator is a validator for the "image_size" field. It is called by the builders before save.
|
||||||
|
ImageSizeValidator func(string) error
|
||||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||||
DefaultCreatedAt func() time.Time
|
DefaultCreatedAt func() time.Time
|
||||||
)
|
)
|
||||||
@@ -320,6 +335,21 @@ func ByFirstTokenMs(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldFirstTokenMs, opts...).ToFunc()
|
return sql.OrderByField(FieldFirstTokenMs, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByUserAgent orders the results by the user_agent field.
|
||||||
|
func ByUserAgent(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldUserAgent, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByImageCount orders the results by the image_count field.
|
||||||
|
func ByImageCount(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldImageCount, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByImageSize orders the results by the image_size field.
|
||||||
|
func ByImageSize(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldImageSize, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// ByCreatedAt orders the results by the created_at field.
|
// ByCreatedAt orders the results by the created_at field.
|
||||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||||
|
|||||||
@@ -175,6 +175,21 @@ func FirstTokenMs(v int) predicate.UsageLog {
|
|||||||
return predicate.UsageLog(sql.FieldEQ(FieldFirstTokenMs, v))
|
return predicate.UsageLog(sql.FieldEQ(FieldFirstTokenMs, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserAgent applies equality check predicate on the "user_agent" field. It's identical to UserAgentEQ.
|
||||||
|
func UserAgent(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCount applies equality check predicate on the "image_count" field. It's identical to ImageCountEQ.
|
||||||
|
func ImageCount(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSize applies equality check predicate on the "image_size" field. It's identical to ImageSizeEQ.
|
||||||
|
func ImageSize(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||||
func CreatedAt(v time.Time) predicate.UsageLog {
|
func CreatedAt(v time.Time) predicate.UsageLog {
|
||||||
return predicate.UsageLog(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.UsageLog(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
@@ -1100,6 +1115,196 @@ func FirstTokenMsNotNil() predicate.UsageLog {
|
|||||||
return predicate.UsageLog(sql.FieldNotNull(FieldFirstTokenMs))
|
return predicate.UsageLog(sql.FieldNotNull(FieldFirstTokenMs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserAgentEQ applies the EQ predicate on the "user_agent" field.
|
||||||
|
func UserAgentEQ(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentNEQ applies the NEQ predicate on the "user_agent" field.
|
||||||
|
func UserAgentNEQ(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNEQ(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentIn applies the In predicate on the "user_agent" field.
|
||||||
|
func UserAgentIn(vs ...string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldIn(FieldUserAgent, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentNotIn applies the NotIn predicate on the "user_agent" field.
|
||||||
|
func UserAgentNotIn(vs ...string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNotIn(FieldUserAgent, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentGT applies the GT predicate on the "user_agent" field.
|
||||||
|
func UserAgentGT(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGT(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentGTE applies the GTE predicate on the "user_agent" field.
|
||||||
|
func UserAgentGTE(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGTE(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentLT applies the LT predicate on the "user_agent" field.
|
||||||
|
func UserAgentLT(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLT(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentLTE applies the LTE predicate on the "user_agent" field.
|
||||||
|
func UserAgentLTE(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLTE(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentContains applies the Contains predicate on the "user_agent" field.
|
||||||
|
func UserAgentContains(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldContains(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentHasPrefix applies the HasPrefix predicate on the "user_agent" field.
|
||||||
|
func UserAgentHasPrefix(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldHasPrefix(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentHasSuffix applies the HasSuffix predicate on the "user_agent" field.
|
||||||
|
func UserAgentHasSuffix(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldHasSuffix(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentIsNil applies the IsNil predicate on the "user_agent" field.
|
||||||
|
func UserAgentIsNil() predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldIsNull(FieldUserAgent))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentNotNil applies the NotNil predicate on the "user_agent" field.
|
||||||
|
func UserAgentNotNil() predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNotNull(FieldUserAgent))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentEqualFold applies the EqualFold predicate on the "user_agent" field.
|
||||||
|
func UserAgentEqualFold(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEqualFold(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAgentContainsFold applies the ContainsFold predicate on the "user_agent" field.
|
||||||
|
func UserAgentContainsFold(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldContainsFold(FieldUserAgent, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountEQ applies the EQ predicate on the "image_count" field.
|
||||||
|
func ImageCountEQ(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountNEQ applies the NEQ predicate on the "image_count" field.
|
||||||
|
func ImageCountNEQ(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNEQ(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountIn applies the In predicate on the "image_count" field.
|
||||||
|
func ImageCountIn(vs ...int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldIn(FieldImageCount, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountNotIn applies the NotIn predicate on the "image_count" field.
|
||||||
|
func ImageCountNotIn(vs ...int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNotIn(FieldImageCount, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountGT applies the GT predicate on the "image_count" field.
|
||||||
|
func ImageCountGT(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGT(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountGTE applies the GTE predicate on the "image_count" field.
|
||||||
|
func ImageCountGTE(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGTE(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountLT applies the LT predicate on the "image_count" field.
|
||||||
|
func ImageCountLT(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLT(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageCountLTE applies the LTE predicate on the "image_count" field.
|
||||||
|
func ImageCountLTE(v int) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLTE(FieldImageCount, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeEQ applies the EQ predicate on the "image_size" field.
|
||||||
|
func ImageSizeEQ(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEQ(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeNEQ applies the NEQ predicate on the "image_size" field.
|
||||||
|
func ImageSizeNEQ(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNEQ(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeIn applies the In predicate on the "image_size" field.
|
||||||
|
func ImageSizeIn(vs ...string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldIn(FieldImageSize, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeNotIn applies the NotIn predicate on the "image_size" field.
|
||||||
|
func ImageSizeNotIn(vs ...string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNotIn(FieldImageSize, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeGT applies the GT predicate on the "image_size" field.
|
||||||
|
func ImageSizeGT(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGT(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeGTE applies the GTE predicate on the "image_size" field.
|
||||||
|
func ImageSizeGTE(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldGTE(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeLT applies the LT predicate on the "image_size" field.
|
||||||
|
func ImageSizeLT(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLT(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeLTE applies the LTE predicate on the "image_size" field.
|
||||||
|
func ImageSizeLTE(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldLTE(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeContains applies the Contains predicate on the "image_size" field.
|
||||||
|
func ImageSizeContains(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldContains(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeHasPrefix applies the HasPrefix predicate on the "image_size" field.
|
||||||
|
func ImageSizeHasPrefix(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldHasPrefix(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeHasSuffix applies the HasSuffix predicate on the "image_size" field.
|
||||||
|
func ImageSizeHasSuffix(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldHasSuffix(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeIsNil applies the IsNil predicate on the "image_size" field.
|
||||||
|
func ImageSizeIsNil() predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldIsNull(FieldImageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeNotNil applies the NotNil predicate on the "image_size" field.
|
||||||
|
func ImageSizeNotNil() predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldNotNull(FieldImageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeEqualFold applies the EqualFold predicate on the "image_size" field.
|
||||||
|
func ImageSizeEqualFold(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldEqualFold(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageSizeContainsFold applies the ContainsFold predicate on the "image_size" field.
|
||||||
|
func ImageSizeContainsFold(v string) predicate.UsageLog {
|
||||||
|
return predicate.UsageLog(sql.FieldContainsFold(FieldImageSize, v))
|
||||||
|
}
|
||||||
|
|
||||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||||
func CreatedAtEQ(v time.Time) predicate.UsageLog {
|
func CreatedAtEQ(v time.Time) predicate.UsageLog {
|
||||||
return predicate.UsageLog(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.UsageLog(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
@@ -1175,7 +1380,7 @@ func HasAPIKey() predicate.UsageLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasAPIKeyWith applies the HasEdge predicate on the "api_key" edge with a given conditions (other predicates).
|
// HasAPIKeyWith applies the HasEdge predicate on the "api_key" edge with a given conditions (other predicates).
|
||||||
func HasAPIKeyWith(preds ...predicate.ApiKey) predicate.UsageLog {
|
func HasAPIKeyWith(preds ...predicate.APIKey) predicate.UsageLog {
|
||||||
return predicate.UsageLog(func(s *sql.Selector) {
|
return predicate.UsageLog(func(s *sql.Selector) {
|
||||||
step := newAPIKeyStep()
|
step := newAPIKeyStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -323,6 +323,48 @@ func (_c *UsageLogCreate) SetNillableFirstTokenMs(v *int) *UsageLogCreate {
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (_c *UsageLogCreate) SetUserAgent(v string) *UsageLogCreate {
|
||||||
|
_c.mutation.SetUserAgent(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableUserAgent sets the "user_agent" field if the given value is not nil.
|
||||||
|
func (_c *UsageLogCreate) SetNillableUserAgent(v *string) *UsageLogCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetUserAgent(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (_c *UsageLogCreate) SetImageCount(v int) *UsageLogCreate {
|
||||||
|
_c.mutation.SetImageCount(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageCount sets the "image_count" field if the given value is not nil.
|
||||||
|
func (_c *UsageLogCreate) SetNillableImageCount(v *int) *UsageLogCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetImageCount(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (_c *UsageLogCreate) SetImageSize(v string) *UsageLogCreate {
|
||||||
|
_c.mutation.SetImageSize(v)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageSize sets the "image_size" field if the given value is not nil.
|
||||||
|
func (_c *UsageLogCreate) SetNillableImageSize(v *string) *UsageLogCreate {
|
||||||
|
if v != nil {
|
||||||
|
_c.SetImageSize(*v)
|
||||||
|
}
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
// SetCreatedAt sets the "created_at" field.
|
// SetCreatedAt sets the "created_at" field.
|
||||||
func (_c *UsageLogCreate) SetCreatedAt(v time.Time) *UsageLogCreate {
|
func (_c *UsageLogCreate) SetCreatedAt(v time.Time) *UsageLogCreate {
|
||||||
_c.mutation.SetCreatedAt(v)
|
_c.mutation.SetCreatedAt(v)
|
||||||
@@ -342,8 +384,8 @@ func (_c *UsageLogCreate) SetUser(v *User) *UsageLogCreate {
|
|||||||
return _c.SetUserID(v.ID)
|
return _c.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
|
// SetAPIKey sets the "api_key" edge to the APIKey entity.
|
||||||
func (_c *UsageLogCreate) SetAPIKey(v *ApiKey) *UsageLogCreate {
|
func (_c *UsageLogCreate) SetAPIKey(v *APIKey) *UsageLogCreate {
|
||||||
return _c.SetAPIKeyID(v.ID)
|
return _c.SetAPIKeyID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,6 +499,10 @@ func (_c *UsageLogCreate) defaults() {
|
|||||||
v := usagelog.DefaultStream
|
v := usagelog.DefaultStream
|
||||||
_c.mutation.SetStream(v)
|
_c.mutation.SetStream(v)
|
||||||
}
|
}
|
||||||
|
if _, ok := _c.mutation.ImageCount(); !ok {
|
||||||
|
v := usagelog.DefaultImageCount
|
||||||
|
_c.mutation.SetImageCount(v)
|
||||||
|
}
|
||||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||||
v := usagelog.DefaultCreatedAt()
|
v := usagelog.DefaultCreatedAt()
|
||||||
_c.mutation.SetCreatedAt(v)
|
_c.mutation.SetCreatedAt(v)
|
||||||
@@ -535,6 +581,19 @@ func (_c *UsageLogCreate) check() error {
|
|||||||
if _, ok := _c.mutation.Stream(); !ok {
|
if _, ok := _c.mutation.Stream(); !ok {
|
||||||
return &ValidationError{Name: "stream", err: errors.New(`ent: missing required field "UsageLog.stream"`)}
|
return &ValidationError{Name: "stream", err: errors.New(`ent: missing required field "UsageLog.stream"`)}
|
||||||
}
|
}
|
||||||
|
if v, ok := _c.mutation.UserAgent(); ok {
|
||||||
|
if err := usagelog.UserAgentValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "user_agent", err: fmt.Errorf(`ent: validator failed for field "UsageLog.user_agent": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := _c.mutation.ImageCount(); !ok {
|
||||||
|
return &ValidationError{Name: "image_count", err: errors.New(`ent: missing required field "UsageLog.image_count"`)}
|
||||||
|
}
|
||||||
|
if v, ok := _c.mutation.ImageSize(); ok {
|
||||||
|
if err := usagelog.ImageSizeValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "image_size", err: fmt.Errorf(`ent: validator failed for field "UsageLog.image_size": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "UsageLog.created_at"`)}
|
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "UsageLog.created_at"`)}
|
||||||
}
|
}
|
||||||
@@ -650,6 +709,18 @@ func (_c *UsageLogCreate) createSpec() (*UsageLog, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(usagelog.FieldFirstTokenMs, field.TypeInt, value)
|
_spec.SetField(usagelog.FieldFirstTokenMs, field.TypeInt, value)
|
||||||
_node.FirstTokenMs = &value
|
_node.FirstTokenMs = &value
|
||||||
}
|
}
|
||||||
|
if value, ok := _c.mutation.UserAgent(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldUserAgent, field.TypeString, value)
|
||||||
|
_node.UserAgent = &value
|
||||||
|
}
|
||||||
|
if value, ok := _c.mutation.ImageCount(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageCount, field.TypeInt, value)
|
||||||
|
_node.ImageCount = value
|
||||||
|
}
|
||||||
|
if value, ok := _c.mutation.ImageSize(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageSize, field.TypeString, value)
|
||||||
|
_node.ImageSize = &value
|
||||||
|
}
|
||||||
if value, ok := _c.mutation.CreatedAt(); ok {
|
if value, ok := _c.mutation.CreatedAt(); ok {
|
||||||
_spec.SetField(usagelog.FieldCreatedAt, field.TypeTime, value)
|
_spec.SetField(usagelog.FieldCreatedAt, field.TypeTime, value)
|
||||||
_node.CreatedAt = value
|
_node.CreatedAt = value
|
||||||
@@ -1199,6 +1270,60 @@ func (u *UsageLogUpsert) ClearFirstTokenMs() *UsageLogUpsert {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsert) SetUserAgent(v string) *UsageLogUpsert {
|
||||||
|
u.Set(usagelog.FieldUserAgent, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserAgent sets the "user_agent" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsert) UpdateUserAgent() *UsageLogUpsert {
|
||||||
|
u.SetExcluded(usagelog.FieldUserAgent)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearUserAgent clears the value of the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsert) ClearUserAgent() *UsageLogUpsert {
|
||||||
|
u.SetNull(usagelog.FieldUserAgent)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (u *UsageLogUpsert) SetImageCount(v int) *UsageLogUpsert {
|
||||||
|
u.Set(usagelog.FieldImageCount, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageCount sets the "image_count" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsert) UpdateImageCount() *UsageLogUpsert {
|
||||||
|
u.SetExcluded(usagelog.FieldImageCount)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImageCount adds v to the "image_count" field.
|
||||||
|
func (u *UsageLogUpsert) AddImageCount(v int) *UsageLogUpsert {
|
||||||
|
u.Add(usagelog.FieldImageCount, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (u *UsageLogUpsert) SetImageSize(v string) *UsageLogUpsert {
|
||||||
|
u.Set(usagelog.FieldImageSize, v)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageSize sets the "image_size" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsert) UpdateImageSize() *UsageLogUpsert {
|
||||||
|
u.SetExcluded(usagelog.FieldImageSize)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImageSize clears the value of the "image_size" field.
|
||||||
|
func (u *UsageLogUpsert) ClearImageSize() *UsageLogUpsert {
|
||||||
|
u.SetNull(usagelog.FieldImageSize)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||||
// Using this option is equivalent to using:
|
// Using this option is equivalent to using:
|
||||||
//
|
//
|
||||||
@@ -1720,6 +1845,69 @@ func (u *UsageLogUpsertOne) ClearFirstTokenMs() *UsageLogUpsertOne {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsertOne) SetUserAgent(v string) *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetUserAgent(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserAgent sets the "user_agent" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertOne) UpdateUserAgent() *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateUserAgent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearUserAgent clears the value of the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsertOne) ClearUserAgent() *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.ClearUserAgent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (u *UsageLogUpsertOne) SetImageCount(v int) *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetImageCount(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImageCount adds v to the "image_count" field.
|
||||||
|
func (u *UsageLogUpsertOne) AddImageCount(v int) *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.AddImageCount(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageCount sets the "image_count" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertOne) UpdateImageCount() *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateImageCount()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (u *UsageLogUpsertOne) SetImageSize(v string) *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetImageSize(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageSize sets the "image_size" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertOne) UpdateImageSize() *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateImageSize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImageSize clears the value of the "image_size" field.
|
||||||
|
func (u *UsageLogUpsertOne) ClearImageSize() *UsageLogUpsertOne {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.ClearImageSize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *UsageLogUpsertOne) Exec(ctx context.Context) error {
|
func (u *UsageLogUpsertOne) Exec(ctx context.Context) error {
|
||||||
if len(u.create.conflict) == 0 {
|
if len(u.create.conflict) == 0 {
|
||||||
@@ -2407,6 +2595,69 @@ func (u *UsageLogUpsertBulk) ClearFirstTokenMs() *UsageLogUpsertBulk {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsertBulk) SetUserAgent(v string) *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetUserAgent(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserAgent sets the "user_agent" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertBulk) UpdateUserAgent() *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateUserAgent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearUserAgent clears the value of the "user_agent" field.
|
||||||
|
func (u *UsageLogUpsertBulk) ClearUserAgent() *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.ClearUserAgent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (u *UsageLogUpsertBulk) SetImageCount(v int) *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetImageCount(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImageCount adds v to the "image_count" field.
|
||||||
|
func (u *UsageLogUpsertBulk) AddImageCount(v int) *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.AddImageCount(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageCount sets the "image_count" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertBulk) UpdateImageCount() *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateImageCount()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (u *UsageLogUpsertBulk) SetImageSize(v string) *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.SetImageSize(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateImageSize sets the "image_size" field to the value that was provided on create.
|
||||||
|
func (u *UsageLogUpsertBulk) UpdateImageSize() *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.UpdateImageSize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImageSize clears the value of the "image_size" field.
|
||||||
|
func (u *UsageLogUpsertBulk) ClearImageSize() *UsageLogUpsertBulk {
|
||||||
|
return u.Update(func(s *UsageLogUpsert) {
|
||||||
|
s.ClearImageSize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Exec executes the query.
|
// Exec executes the query.
|
||||||
func (u *UsageLogUpsertBulk) Exec(ctx context.Context) error {
|
func (u *UsageLogUpsertBulk) Exec(ctx context.Context) error {
|
||||||
if u.create.err != nil {
|
if u.create.err != nil {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type UsageLogQuery struct {
|
|||||||
inters []Interceptor
|
inters []Interceptor
|
||||||
predicates []predicate.UsageLog
|
predicates []predicate.UsageLog
|
||||||
withUser *UserQuery
|
withUser *UserQuery
|
||||||
withAPIKey *ApiKeyQuery
|
withAPIKey *APIKeyQuery
|
||||||
withAccount *AccountQuery
|
withAccount *AccountQuery
|
||||||
withGroup *GroupQuery
|
withGroup *GroupQuery
|
||||||
withSubscription *UserSubscriptionQuery
|
withSubscription *UserSubscriptionQuery
|
||||||
@@ -91,8 +91,8 @@ func (_q *UsageLogQuery) QueryUser() *UserQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKey chains the current query on the "api_key" edge.
|
// QueryAPIKey chains the current query on the "api_key" edge.
|
||||||
func (_q *UsageLogQuery) QueryAPIKey() *ApiKeyQuery {
|
func (_q *UsageLogQuery) QueryAPIKey() *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -394,8 +394,8 @@ func (_q *UsageLogQuery) WithUser(opts ...func(*UserQuery)) *UsageLogQuery {
|
|||||||
|
|
||||||
// WithAPIKey tells the query-builder to eager-load the nodes that are connected to
|
// WithAPIKey tells the query-builder to eager-load the nodes that are connected to
|
||||||
// the "api_key" edge. The optional arguments are used to configure the query builder of the edge.
|
// the "api_key" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *UsageLogQuery) WithAPIKey(opts ...func(*ApiKeyQuery)) *UsageLogQuery {
|
func (_q *UsageLogQuery) WithAPIKey(opts ...func(*APIKeyQuery)) *UsageLogQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
}
|
}
|
||||||
@@ -548,7 +548,7 @@ func (_q *UsageLogQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Usa
|
|||||||
}
|
}
|
||||||
if query := _q.withAPIKey; query != nil {
|
if query := _q.withAPIKey; query != nil {
|
||||||
if err := _q.loadAPIKey(ctx, query, nodes, nil,
|
if err := _q.loadAPIKey(ctx, query, nodes, nil,
|
||||||
func(n *UsageLog, e *ApiKey) { n.Edges.APIKey = e }); err != nil {
|
func(n *UsageLog, e *APIKey) { n.Edges.APIKey = e }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -602,7 +602,7 @@ func (_q *UsageLogQuery) loadUser(ctx context.Context, query *UserQuery, nodes [
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (_q *UsageLogQuery) loadAPIKey(ctx context.Context, query *ApiKeyQuery, nodes []*UsageLog, init func(*UsageLog), assign func(*UsageLog, *ApiKey)) error {
|
func (_q *UsageLogQuery) loadAPIKey(ctx context.Context, query *APIKeyQuery, nodes []*UsageLog, init func(*UsageLog), assign func(*UsageLog, *APIKey)) error {
|
||||||
ids := make([]int64, 0, len(nodes))
|
ids := make([]int64, 0, len(nodes))
|
||||||
nodeids := make(map[int64][]*UsageLog)
|
nodeids := make(map[int64][]*UsageLog)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
|
|||||||
@@ -504,13 +504,74 @@ func (_u *UsageLogUpdate) ClearFirstTokenMs() *UsageLogUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (_u *UsageLogUpdate) SetUserAgent(v string) *UsageLogUpdate {
|
||||||
|
_u.mutation.SetUserAgent(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableUserAgent sets the "user_agent" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdate) SetNillableUserAgent(v *string) *UsageLogUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetUserAgent(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearUserAgent clears the value of the "user_agent" field.
|
||||||
|
func (_u *UsageLogUpdate) ClearUserAgent() *UsageLogUpdate {
|
||||||
|
_u.mutation.ClearUserAgent()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (_u *UsageLogUpdate) SetImageCount(v int) *UsageLogUpdate {
|
||||||
|
_u.mutation.ResetImageCount()
|
||||||
|
_u.mutation.SetImageCount(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageCount sets the "image_count" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdate) SetNillableImageCount(v *int) *UsageLogUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImageCount(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImageCount adds value to the "image_count" field.
|
||||||
|
func (_u *UsageLogUpdate) AddImageCount(v int) *UsageLogUpdate {
|
||||||
|
_u.mutation.AddImageCount(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (_u *UsageLogUpdate) SetImageSize(v string) *UsageLogUpdate {
|
||||||
|
_u.mutation.SetImageSize(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageSize sets the "image_size" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdate) SetNillableImageSize(v *string) *UsageLogUpdate {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImageSize(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImageSize clears the value of the "image_size" field.
|
||||||
|
func (_u *UsageLogUpdate) ClearImageSize() *UsageLogUpdate {
|
||||||
|
_u.mutation.ClearImageSize()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetUser sets the "user" edge to the User entity.
|
// SetUser sets the "user" edge to the User entity.
|
||||||
func (_u *UsageLogUpdate) SetUser(v *User) *UsageLogUpdate {
|
func (_u *UsageLogUpdate) SetUser(v *User) *UsageLogUpdate {
|
||||||
return _u.SetUserID(v.ID)
|
return _u.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
|
// SetAPIKey sets the "api_key" edge to the APIKey entity.
|
||||||
func (_u *UsageLogUpdate) SetAPIKey(v *ApiKey) *UsageLogUpdate {
|
func (_u *UsageLogUpdate) SetAPIKey(v *APIKey) *UsageLogUpdate {
|
||||||
return _u.SetAPIKeyID(v.ID)
|
return _u.SetAPIKeyID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +601,7 @@ func (_u *UsageLogUpdate) ClearUser() *UsageLogUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKey clears the "api_key" edge to the ApiKey entity.
|
// ClearAPIKey clears the "api_key" edge to the APIKey entity.
|
||||||
func (_u *UsageLogUpdate) ClearAPIKey() *UsageLogUpdate {
|
func (_u *UsageLogUpdate) ClearAPIKey() *UsageLogUpdate {
|
||||||
_u.mutation.ClearAPIKey()
|
_u.mutation.ClearAPIKey()
|
||||||
return _u
|
return _u
|
||||||
@@ -603,6 +664,16 @@ func (_u *UsageLogUpdate) check() error {
|
|||||||
return &ValidationError{Name: "model", err: fmt.Errorf(`ent: validator failed for field "UsageLog.model": %w`, err)}
|
return &ValidationError{Name: "model", err: fmt.Errorf(`ent: validator failed for field "UsageLog.model": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if v, ok := _u.mutation.UserAgent(); ok {
|
||||||
|
if err := usagelog.UserAgentValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "user_agent", err: fmt.Errorf(`ent: validator failed for field "UsageLog.user_agent": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := _u.mutation.ImageSize(); ok {
|
||||||
|
if err := usagelog.ImageSizeValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "image_size", err: fmt.Errorf(`ent: validator failed for field "UsageLog.image_size": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||||
return errors.New(`ent: clearing a required unique edge "UsageLog.user"`)
|
return errors.New(`ent: clearing a required unique edge "UsageLog.user"`)
|
||||||
}
|
}
|
||||||
@@ -738,6 +809,24 @@ func (_u *UsageLogUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
|||||||
if _u.mutation.FirstTokenMsCleared() {
|
if _u.mutation.FirstTokenMsCleared() {
|
||||||
_spec.ClearField(usagelog.FieldFirstTokenMs, field.TypeInt)
|
_spec.ClearField(usagelog.FieldFirstTokenMs, field.TypeInt)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.UserAgent(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldUserAgent, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.UserAgentCleared() {
|
||||||
|
_spec.ClearField(usagelog.FieldUserAgent, field.TypeString)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImageCount(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageCount, field.TypeInt, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImageCount(); ok {
|
||||||
|
_spec.AddField(usagelog.FieldImageCount, field.TypeInt, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImageSize(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageSize, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImageSizeCleared() {
|
||||||
|
_spec.ClearField(usagelog.FieldImageSize, field.TypeString)
|
||||||
|
}
|
||||||
if _u.mutation.UserCleared() {
|
if _u.mutation.UserCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.M2O,
|
Rel: sqlgraph.M2O,
|
||||||
@@ -1375,13 +1464,74 @@ func (_u *UsageLogUpdateOne) ClearFirstTokenMs() *UsageLogUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUserAgent sets the "user_agent" field.
|
||||||
|
func (_u *UsageLogUpdateOne) SetUserAgent(v string) *UsageLogUpdateOne {
|
||||||
|
_u.mutation.SetUserAgent(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableUserAgent sets the "user_agent" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdateOne) SetNillableUserAgent(v *string) *UsageLogUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetUserAgent(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearUserAgent clears the value of the "user_agent" field.
|
||||||
|
func (_u *UsageLogUpdateOne) ClearUserAgent() *UsageLogUpdateOne {
|
||||||
|
_u.mutation.ClearUserAgent()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageCount sets the "image_count" field.
|
||||||
|
func (_u *UsageLogUpdateOne) SetImageCount(v int) *UsageLogUpdateOne {
|
||||||
|
_u.mutation.ResetImageCount()
|
||||||
|
_u.mutation.SetImageCount(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageCount sets the "image_count" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdateOne) SetNillableImageCount(v *int) *UsageLogUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImageCount(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddImageCount adds value to the "image_count" field.
|
||||||
|
func (_u *UsageLogUpdateOne) AddImageCount(v int) *UsageLogUpdateOne {
|
||||||
|
_u.mutation.AddImageCount(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImageSize sets the "image_size" field.
|
||||||
|
func (_u *UsageLogUpdateOne) SetImageSize(v string) *UsageLogUpdateOne {
|
||||||
|
_u.mutation.SetImageSize(v)
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableImageSize sets the "image_size" field if the given value is not nil.
|
||||||
|
func (_u *UsageLogUpdateOne) SetNillableImageSize(v *string) *UsageLogUpdateOne {
|
||||||
|
if v != nil {
|
||||||
|
_u.SetImageSize(*v)
|
||||||
|
}
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearImageSize clears the value of the "image_size" field.
|
||||||
|
func (_u *UsageLogUpdateOne) ClearImageSize() *UsageLogUpdateOne {
|
||||||
|
_u.mutation.ClearImageSize()
|
||||||
|
return _u
|
||||||
|
}
|
||||||
|
|
||||||
// SetUser sets the "user" edge to the User entity.
|
// SetUser sets the "user" edge to the User entity.
|
||||||
func (_u *UsageLogUpdateOne) SetUser(v *User) *UsageLogUpdateOne {
|
func (_u *UsageLogUpdateOne) SetUser(v *User) *UsageLogUpdateOne {
|
||||||
return _u.SetUserID(v.ID)
|
return _u.SetUserID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
|
// SetAPIKey sets the "api_key" edge to the APIKey entity.
|
||||||
func (_u *UsageLogUpdateOne) SetAPIKey(v *ApiKey) *UsageLogUpdateOne {
|
func (_u *UsageLogUpdateOne) SetAPIKey(v *APIKey) *UsageLogUpdateOne {
|
||||||
return _u.SetAPIKeyID(v.ID)
|
return _u.SetAPIKeyID(v.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1411,7 +1561,7 @@ func (_u *UsageLogUpdateOne) ClearUser() *UsageLogUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKey clears the "api_key" edge to the ApiKey entity.
|
// ClearAPIKey clears the "api_key" edge to the APIKey entity.
|
||||||
func (_u *UsageLogUpdateOne) ClearAPIKey() *UsageLogUpdateOne {
|
func (_u *UsageLogUpdateOne) ClearAPIKey() *UsageLogUpdateOne {
|
||||||
_u.mutation.ClearAPIKey()
|
_u.mutation.ClearAPIKey()
|
||||||
return _u
|
return _u
|
||||||
@@ -1487,6 +1637,16 @@ func (_u *UsageLogUpdateOne) check() error {
|
|||||||
return &ValidationError{Name: "model", err: fmt.Errorf(`ent: validator failed for field "UsageLog.model": %w`, err)}
|
return &ValidationError{Name: "model", err: fmt.Errorf(`ent: validator failed for field "UsageLog.model": %w`, err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if v, ok := _u.mutation.UserAgent(); ok {
|
||||||
|
if err := usagelog.UserAgentValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "user_agent", err: fmt.Errorf(`ent: validator failed for field "UsageLog.user_agent": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := _u.mutation.ImageSize(); ok {
|
||||||
|
if err := usagelog.ImageSizeValidator(v); err != nil {
|
||||||
|
return &ValidationError{Name: "image_size", err: fmt.Errorf(`ent: validator failed for field "UsageLog.image_size": %w`, err)}
|
||||||
|
}
|
||||||
|
}
|
||||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||||
return errors.New(`ent: clearing a required unique edge "UsageLog.user"`)
|
return errors.New(`ent: clearing a required unique edge "UsageLog.user"`)
|
||||||
}
|
}
|
||||||
@@ -1639,6 +1799,24 @@ func (_u *UsageLogUpdateOne) sqlSave(ctx context.Context) (_node *UsageLog, err
|
|||||||
if _u.mutation.FirstTokenMsCleared() {
|
if _u.mutation.FirstTokenMsCleared() {
|
||||||
_spec.ClearField(usagelog.FieldFirstTokenMs, field.TypeInt)
|
_spec.ClearField(usagelog.FieldFirstTokenMs, field.TypeInt)
|
||||||
}
|
}
|
||||||
|
if value, ok := _u.mutation.UserAgent(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldUserAgent, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.UserAgentCleared() {
|
||||||
|
_spec.ClearField(usagelog.FieldUserAgent, field.TypeString)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImageCount(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageCount, field.TypeInt, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.AddedImageCount(); ok {
|
||||||
|
_spec.AddField(usagelog.FieldImageCount, field.TypeInt, value)
|
||||||
|
}
|
||||||
|
if value, ok := _u.mutation.ImageSize(); ok {
|
||||||
|
_spec.SetField(usagelog.FieldImageSize, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if _u.mutation.ImageSizeCleared() {
|
||||||
|
_spec.ClearField(usagelog.FieldImageSize, field.TypeString)
|
||||||
|
}
|
||||||
if _u.mutation.UserCleared() {
|
if _u.mutation.UserCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.M2O,
|
Rel: sqlgraph.M2O,
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ type User struct {
|
|||||||
// UserEdges holds the relations/edges for other nodes in the graph.
|
// UserEdges holds the relations/edges for other nodes in the graph.
|
||||||
type UserEdges struct {
|
type UserEdges struct {
|
||||||
// APIKeys holds the value of the api_keys edge.
|
// APIKeys holds the value of the api_keys edge.
|
||||||
APIKeys []*ApiKey `json:"api_keys,omitempty"`
|
APIKeys []*APIKey `json:"api_keys,omitempty"`
|
||||||
// RedeemCodes holds the value of the redeem_codes edge.
|
// RedeemCodes holds the value of the redeem_codes edge.
|
||||||
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
|
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
|
||||||
// Subscriptions holds the value of the subscriptions edge.
|
// Subscriptions holds the value of the subscriptions edge.
|
||||||
@@ -70,7 +70,7 @@ type UserEdges struct {
|
|||||||
|
|
||||||
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
||||||
// was not loaded in eager-loading.
|
// was not loaded in eager-loading.
|
||||||
func (e UserEdges) APIKeysOrErr() ([]*ApiKey, error) {
|
func (e UserEdges) APIKeysOrErr() ([]*APIKey, error) {
|
||||||
if e.loadedTypes[0] {
|
if e.loadedTypes[0] {
|
||||||
return e.APIKeys, nil
|
return e.APIKeys, nil
|
||||||
}
|
}
|
||||||
@@ -255,7 +255,7 @@ func (_m *User) Value(name string) (ent.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys queries the "api_keys" edge of the User entity.
|
// QueryAPIKeys queries the "api_keys" edge of the User entity.
|
||||||
func (_m *User) QueryAPIKeys() *ApiKeyQuery {
|
func (_m *User) QueryAPIKeys() *APIKeyQuery {
|
||||||
return NewUserClient(_m.config).QueryAPIKeys(_m)
|
return NewUserClient(_m.config).QueryAPIKeys(_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const (
|
|||||||
Table = "users"
|
Table = "users"
|
||||||
// APIKeysTable is the table that holds the api_keys relation/edge.
|
// APIKeysTable is the table that holds the api_keys relation/edge.
|
||||||
APIKeysTable = "api_keys"
|
APIKeysTable = "api_keys"
|
||||||
// APIKeysInverseTable is the table name for the ApiKey entity.
|
// APIKeysInverseTable is the table name for the APIKey entity.
|
||||||
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
// It exists in this package in order to avoid circular dependency with the "apikey" package.
|
||||||
APIKeysInverseTable = "api_keys"
|
APIKeysInverseTable = "api_keys"
|
||||||
// APIKeysColumn is the table column denoting the api_keys relation/edge.
|
// APIKeysColumn is the table column denoting the api_keys relation/edge.
|
||||||
|
|||||||
@@ -722,7 +722,7 @@ func HasAPIKeys() predicate.User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
|
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
|
||||||
func HasAPIKeysWith(preds ...predicate.ApiKey) predicate.User {
|
func HasAPIKeysWith(preds ...predicate.APIKey) predicate.User {
|
||||||
return predicate.User(func(s *sql.Selector) {
|
return predicate.User(func(s *sql.Selector) {
|
||||||
step := newAPIKeysStep()
|
step := newAPIKeysStep()
|
||||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -166,14 +166,14 @@ func (_c *UserCreate) SetNillableNotes(v *string) *UserCreate {
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_c *UserCreate) AddAPIKeyIDs(ids ...int64) *UserCreate {
|
func (_c *UserCreate) AddAPIKeyIDs(ids ...int64) *UserCreate {
|
||||||
_c.mutation.AddAPIKeyIDs(ids...)
|
_c.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_c *UserCreate) AddAPIKeys(v ...*ApiKey) *UserCreate {
|
func (_c *UserCreate) AddAPIKeys(v ...*APIKey) *UserCreate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type UserQuery struct {
|
|||||||
order []user.OrderOption
|
order []user.OrderOption
|
||||||
inters []Interceptor
|
inters []Interceptor
|
||||||
predicates []predicate.User
|
predicates []predicate.User
|
||||||
withAPIKeys *ApiKeyQuery
|
withAPIKeys *APIKeyQuery
|
||||||
withRedeemCodes *RedeemCodeQuery
|
withRedeemCodes *RedeemCodeQuery
|
||||||
withSubscriptions *UserSubscriptionQuery
|
withSubscriptions *UserSubscriptionQuery
|
||||||
withAssignedSubscriptions *UserSubscriptionQuery
|
withAssignedSubscriptions *UserSubscriptionQuery
|
||||||
@@ -75,8 +75,8 @@ func (_q *UserQuery) Order(o ...user.OrderOption) *UserQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryAPIKeys chains the current query on the "api_keys" edge.
|
// QueryAPIKeys chains the current query on the "api_keys" edge.
|
||||||
func (_q *UserQuery) QueryAPIKeys() *ApiKeyQuery {
|
func (_q *UserQuery) QueryAPIKeys() *APIKeyQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||||
if err := _q.prepareQuery(ctx); err != nil {
|
if err := _q.prepareQuery(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -458,8 +458,8 @@ func (_q *UserQuery) Clone() *UserQuery {
|
|||||||
|
|
||||||
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
|
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
|
||||||
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
|
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
|
||||||
func (_q *UserQuery) WithAPIKeys(opts ...func(*ApiKeyQuery)) *UserQuery {
|
func (_q *UserQuery) WithAPIKeys(opts ...func(*APIKeyQuery)) *UserQuery {
|
||||||
query := (&ApiKeyClient{config: _q.config}).Query()
|
query := (&APIKeyClient{config: _q.config}).Query()
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(query)
|
opt(query)
|
||||||
}
|
}
|
||||||
@@ -653,8 +653,8 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
|||||||
}
|
}
|
||||||
if query := _q.withAPIKeys; query != nil {
|
if query := _q.withAPIKeys; query != nil {
|
||||||
if err := _q.loadAPIKeys(ctx, query, nodes,
|
if err := _q.loadAPIKeys(ctx, query, nodes,
|
||||||
func(n *User) { n.Edges.APIKeys = []*ApiKey{} },
|
func(n *User) { n.Edges.APIKeys = []*APIKey{} },
|
||||||
func(n *User, e *ApiKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
|
func(n *User, e *APIKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -712,7 +712,7 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
|||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes []*User, init func(*User), assign func(*User, *ApiKey)) error {
|
func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *APIKeyQuery, nodes []*User, init func(*User), assign func(*User, *APIKey)) error {
|
||||||
fks := make([]driver.Value, 0, len(nodes))
|
fks := make([]driver.Value, 0, len(nodes))
|
||||||
nodeids := make(map[int64]*User)
|
nodeids := make(map[int64]*User)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
@@ -725,7 +725,7 @@ func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes
|
|||||||
if len(query.ctx.Fields) > 0 {
|
if len(query.ctx.Fields) > 0 {
|
||||||
query.ctx.AppendFieldOnce(apikey.FieldUserID)
|
query.ctx.AppendFieldOnce(apikey.FieldUserID)
|
||||||
}
|
}
|
||||||
query.Where(predicate.ApiKey(func(s *sql.Selector) {
|
query.Where(predicate.APIKey(func(s *sql.Selector) {
|
||||||
s.Where(sql.InValues(s.C(user.APIKeysColumn), fks...))
|
s.Where(sql.InValues(s.C(user.APIKeysColumn), fks...))
|
||||||
}))
|
}))
|
||||||
neighbors, err := query.All(ctx)
|
neighbors, err := query.All(ctx)
|
||||||
|
|||||||
@@ -186,14 +186,14 @@ func (_u *UserUpdate) SetNillableNotes(v *string) *UserUpdate {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *UserUpdate) AddAPIKeyIDs(ids ...int64) *UserUpdate {
|
func (_u *UserUpdate) AddAPIKeyIDs(ids ...int64) *UserUpdate {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_u.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_u *UserUpdate) AddAPIKeys(v ...*ApiKey) *UserUpdate {
|
func (_u *UserUpdate) AddAPIKeys(v ...*APIKey) *UserUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -296,20 +296,20 @@ func (_u *UserUpdate) Mutation() *UserMutation {
|
|||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
|
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
|
||||||
func (_u *UserUpdate) ClearAPIKeys() *UserUpdate {
|
func (_u *UserUpdate) ClearAPIKeys() *UserUpdate {
|
||||||
_u.mutation.ClearAPIKeys()
|
_u.mutation.ClearAPIKeys()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
|
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
|
||||||
func (_u *UserUpdate) RemoveAPIKeyIDs(ids ...int64) *UserUpdate {
|
func (_u *UserUpdate) RemoveAPIKeyIDs(ids ...int64) *UserUpdate {
|
||||||
_u.mutation.RemoveAPIKeyIDs(ids...)
|
_u.mutation.RemoveAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
|
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
|
||||||
func (_u *UserUpdate) RemoveAPIKeys(v ...*ApiKey) *UserUpdate {
|
func (_u *UserUpdate) RemoveAPIKeys(v ...*APIKey) *UserUpdate {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -1065,14 +1065,14 @@ func (_u *UserUpdateOne) SetNillableNotes(v *string) *UserUpdateOne {
|
|||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *UserUpdateOne) AddAPIKeyIDs(ids ...int64) *UserUpdateOne {
|
func (_u *UserUpdateOne) AddAPIKeyIDs(ids ...int64) *UserUpdateOne {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_u.mutation.AddAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
|
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
|
||||||
func (_u *UserUpdateOne) AddAPIKeys(v ...*ApiKey) *UserUpdateOne {
|
func (_u *UserUpdateOne) AddAPIKeys(v ...*APIKey) *UserUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
@@ -1175,20 +1175,20 @@ func (_u *UserUpdateOne) Mutation() *UserMutation {
|
|||||||
return _u.mutation
|
return _u.mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
|
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
|
||||||
func (_u *UserUpdateOne) ClearAPIKeys() *UserUpdateOne {
|
func (_u *UserUpdateOne) ClearAPIKeys() *UserUpdateOne {
|
||||||
_u.mutation.ClearAPIKeys()
|
_u.mutation.ClearAPIKeys()
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
|
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
|
||||||
func (_u *UserUpdateOne) RemoveAPIKeyIDs(ids ...int64) *UserUpdateOne {
|
func (_u *UserUpdateOne) RemoveAPIKeyIDs(ids ...int64) *UserUpdateOne {
|
||||||
_u.mutation.RemoveAPIKeyIDs(ids...)
|
_u.mutation.RemoveAPIKeyIDs(ids...)
|
||||||
return _u
|
return _u
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
|
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
|
||||||
func (_u *UserUpdateOne) RemoveAPIKeys(v ...*ApiKey) *UserUpdateOne {
|
func (_u *UserUpdateOne) RemoveAPIKeys(v ...*APIKey) *UserUpdateOne {
|
||||||
ids := make([]int64, len(v))
|
ids := make([]int64, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
ids[i] = v[i].ID
|
ids[i] = v[i].ID
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
module github.com/Wei-Shaw/sub2api
|
module github.com/Wei-Shaw/sub2api
|
||||||
|
|
||||||
go 1.24.0
|
go 1.25.5
|
||||||
|
|
||||||
toolchain go1.24.11
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
entgo.io/ent v0.14.5
|
entgo.io/ent v0.14.5
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/google/wire v0.7.0
|
github.com/google/wire v0.7.0
|
||||||
github.com/imroc/req/v3 v3.56.0
|
github.com/imroc/req/v3 v3.57.0
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/redis/go-redis/v9 v9.17.2
|
github.com/redis/go-redis/v9 v9.17.2
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.18.2
|
||||||
@@ -20,16 +18,16 @@ require (
|
|||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
github.com/tidwall/sjson v1.2.5
|
github.com/tidwall/sjson v1.2.5
|
||||||
github.com/zeromicro/go-zero v1.9.4
|
github.com/zeromicro/go-zero v1.9.4
|
||||||
golang.org/x/crypto v0.44.0
|
golang.org/x/crypto v0.46.0
|
||||||
golang.org/x/net v0.47.0
|
golang.org/x/net v0.48.0
|
||||||
golang.org/x/term v0.37.0
|
golang.org/x/sync v0.19.0
|
||||||
|
golang.org/x/term v0.38.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect
|
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect
|
||||||
dario.cat/mergo v1.0.2 // indirect
|
dario.cat/mergo v1.0.2 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/agext/levenshtein v1.2.3 // indirect
|
github.com/agext/levenshtein v1.2.3 // indirect
|
||||||
@@ -64,7 +62,6 @@ require (
|
|||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.9.0 // indirect
|
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
@@ -74,10 +71,8 @@ require (
|
|||||||
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
|
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
|
||||||
github.com/icholy/digest v1.1.0 // indirect
|
github.com/icholy/digest v1.1.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.18.1 // indirect
|
github.com/klauspost/compress v1.18.2 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
@@ -105,8 +100,8 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/quic-go/quic-go v0.56.0 // indirect
|
github.com/quic-go/quic-go v0.57.1 // indirect
|
||||||
github.com/refraction-networking/utls v1.8.1 // indirect
|
github.com/refraction-networking/utls v1.8.1 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
@@ -141,16 +136,12 @@ require (
|
|||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/mod v0.29.0 // indirect
|
golang.org/x/mod v0.30.0 // indirect
|
||||||
golang.org/x/sync v0.18.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
golang.org/x/sys v0.38.0 // indirect
|
golang.org/x/text v0.32.0 // indirect
|
||||||
golang.org/x/text v0.31.0 // indirect
|
golang.org/x/tools v0.39.0 // indirect
|
||||||
golang.org/x/tools v0.38.0 // indirect
|
|
||||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
|
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
|
||||||
google.golang.org/grpc v1.75.1 // indirect
|
google.golang.org/grpc v1.75.1 // indirect
|
||||||
google.golang.org/protobuf v1.36.10 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gorm.io/datatypes v1.2.7 // indirect
|
|
||||||
gorm.io/driver/mysql v1.5.6 // indirect
|
|
||||||
gorm.io/gorm v1.30.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
|||||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||||
entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=
|
entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=
|
||||||
entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U=
|
entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U=
|
||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
@@ -96,15 +94,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
|
||||||
github.com/go-sql-driver/mysql v1.9.0 h1:Y0zIbQXhQKmQgTp44Y1dp3wTXcn804QoTptLZT1vtvo=
|
|
||||||
github.com/go-sql-driver/mysql v1.9.0/go.mod h1:pDetrLJeA3oMujJuvXc8RJoasr589B6A9fwzD3QMrqw=
|
|
||||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
@@ -126,8 +121,8 @@ github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZY
|
|||||||
github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
|
github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
|
||||||
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
|
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
|
||||||
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
|
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
|
||||||
github.com/imroc/req/v3 v3.56.0 h1:t6YdqqerYBXhZ9+VjqsQs5wlKxdUNEvsgBhxWc1AEEo=
|
github.com/imroc/req/v3 v3.57.0 h1:LMTUjNRUybUkTPn8oJDq8Kg3JRBOBTcnDhKu7mzupKI=
|
||||||
github.com/imroc/req/v3 v3.56.0/go.mod h1:cUZSooE8hhzFNOrAbdxuemXDQxFXLQTnu3066jr7ZGk=
|
github.com/imroc/req/v3 v3.57.0/go.mod h1:JL62ey1nvSLq81HORNcosvlf7SxZStONNqOprg0Pz00=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
@@ -138,14 +133,10 @@ github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg=
|
|||||||
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
@@ -219,10 +210,10 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
|
|||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
github.com/quic-go/quic-go v0.56.0 h1:q/TW+OLismmXAehgFLczhCDTYB3bFmua4D9lsNBWxvY=
|
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
|
||||||
github.com/quic-go/quic-go v0.56.0/go.mod h1:9gx5KsFQtw2oZ6GZTyh+7YEvOxWCL9WZAepnHxgAo6c=
|
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
||||||
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
|
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
|
||||||
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
|
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
|
||||||
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
|
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
|
||||||
@@ -335,16 +326,16 @@ 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.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 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
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 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -354,16 +345,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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.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.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
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/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
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 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.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||||
@@ -386,13 +377,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/datatypes v1.2.7 h1:ww9GAhF1aGXZY3EB3cJPJ7//JiuQo7DlQA7NNlVaTdk=
|
|
||||||
gorm.io/datatypes v1.2.7/go.mod h1:M2iO+6S3hhi4nAyYe444Pcb0dcIiOMJ7QHaUXxyiNZY=
|
|
||||||
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
|
|
||||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
|
||||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
|
||||||
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
|
||||||
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
|
||||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
|
// Package config provides configuration loading, defaults, and validation.
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,6 +18,8 @@ const (
|
|||||||
RunModeSimple = "simple"
|
RunModeSimple = "simple"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DefaultCSPPolicy = "default-src 'self'; script-src 'self' https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https:; frame-src https://challenges.cloudflare.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
|
||||||
|
|
||||||
// 连接池隔离策略常量
|
// 连接池隔离策略常量
|
||||||
// 用于控制上游 HTTP 连接池的隔离粒度,影响连接复用和资源消耗
|
// 用于控制上游 HTTP 连接池的隔离粒度,影响连接复用和资源消耗
|
||||||
const (
|
const (
|
||||||
@@ -29,6 +36,10 @@ const (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Server ServerConfig `mapstructure:"server"`
|
Server ServerConfig `mapstructure:"server"`
|
||||||
|
CORS CORSConfig `mapstructure:"cors"`
|
||||||
|
Security SecurityConfig `mapstructure:"security"`
|
||||||
|
Billing BillingConfig `mapstructure:"billing"`
|
||||||
|
Turnstile TurnstileConfig `mapstructure:"turnstile"`
|
||||||
Database DatabaseConfig `mapstructure:"database"`
|
Database DatabaseConfig `mapstructure:"database"`
|
||||||
Redis RedisConfig `mapstructure:"redis"`
|
Redis RedisConfig `mapstructure:"redis"`
|
||||||
JWT JWTConfig `mapstructure:"jwt"`
|
JWT JWTConfig `mapstructure:"jwt"`
|
||||||
@@ -36,10 +47,20 @@ type Config struct {
|
|||||||
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
||||||
Pricing PricingConfig `mapstructure:"pricing"`
|
Pricing PricingConfig `mapstructure:"pricing"`
|
||||||
Gateway GatewayConfig `mapstructure:"gateway"`
|
Gateway GatewayConfig `mapstructure:"gateway"`
|
||||||
|
Concurrency ConcurrencyConfig `mapstructure:"concurrency"`
|
||||||
TokenRefresh TokenRefreshConfig `mapstructure:"token_refresh"`
|
TokenRefresh TokenRefreshConfig `mapstructure:"token_refresh"`
|
||||||
RunMode string `mapstructure:"run_mode" yaml:"run_mode"`
|
RunMode string `mapstructure:"run_mode" yaml:"run_mode"`
|
||||||
Timezone string `mapstructure:"timezone"` // e.g. "Asia/Shanghai", "UTC"
|
Timezone string `mapstructure:"timezone"` // e.g. "Asia/Shanghai", "UTC"
|
||||||
Gemini GeminiConfig `mapstructure:"gemini"`
|
Gemini GeminiConfig `mapstructure:"gemini"`
|
||||||
|
Update UpdateConfig `mapstructure:"update"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfig 在线更新相关配置
|
||||||
|
type UpdateConfig struct {
|
||||||
|
// ProxyURL 用于访问 GitHub 的代理地址
|
||||||
|
// 支持 http/https/socks5/socks5h 协议
|
||||||
|
// 例如: "http://127.0.0.1:7890", "socks5://127.0.0.1:1080"
|
||||||
|
ProxyURL string `mapstructure:"proxy_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeminiConfig struct {
|
type GeminiConfig struct {
|
||||||
@@ -94,11 +115,65 @@ type PricingConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
Host string `mapstructure:"host"`
|
Host string `mapstructure:"host"`
|
||||||
Port int `mapstructure:"port"`
|
Port int `mapstructure:"port"`
|
||||||
Mode string `mapstructure:"mode"` // debug/release
|
Mode string `mapstructure:"mode"` // debug/release
|
||||||
ReadHeaderTimeout int `mapstructure:"read_header_timeout"` // 读取请求头超时(秒)
|
ReadHeaderTimeout int `mapstructure:"read_header_timeout"` // 读取请求头超时(秒)
|
||||||
IdleTimeout int `mapstructure:"idle_timeout"` // 空闲连接超时(秒)
|
IdleTimeout int `mapstructure:"idle_timeout"` // 空闲连接超时(秒)
|
||||||
|
TrustedProxies []string `mapstructure:"trusted_proxies"` // 可信代理列表(CIDR/IP)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CORSConfig struct {
|
||||||
|
AllowedOrigins []string `mapstructure:"allowed_origins"`
|
||||||
|
AllowCredentials bool `mapstructure:"allow_credentials"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecurityConfig struct {
|
||||||
|
URLAllowlist URLAllowlistConfig `mapstructure:"url_allowlist"`
|
||||||
|
ResponseHeaders ResponseHeaderConfig `mapstructure:"response_headers"`
|
||||||
|
CSP CSPConfig `mapstructure:"csp"`
|
||||||
|
ProxyProbe ProxyProbeConfig `mapstructure:"proxy_probe"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type URLAllowlistConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
UpstreamHosts []string `mapstructure:"upstream_hosts"`
|
||||||
|
PricingHosts []string `mapstructure:"pricing_hosts"`
|
||||||
|
CRSHosts []string `mapstructure:"crs_hosts"`
|
||||||
|
AllowPrivateHosts bool `mapstructure:"allow_private_hosts"`
|
||||||
|
// 关闭 URL 白名单校验时,是否允许 http URL(默认只允许 https)
|
||||||
|
AllowInsecureHTTP bool `mapstructure:"allow_insecure_http"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseHeaderConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
AdditionalAllowed []string `mapstructure:"additional_allowed"`
|
||||||
|
ForceRemove []string `mapstructure:"force_remove"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CSPConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Policy string `mapstructure:"policy"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProxyProbeConfig struct {
|
||||||
|
InsecureSkipVerify bool `mapstructure:"insecure_skip_verify"` // 已禁用:禁止跳过 TLS 证书验证
|
||||||
|
}
|
||||||
|
|
||||||
|
type BillingConfig struct {
|
||||||
|
CircuitBreaker CircuitBreakerConfig `mapstructure:"circuit_breaker"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CircuitBreakerConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
FailureThreshold int `mapstructure:"failure_threshold"`
|
||||||
|
ResetTimeoutSeconds int `mapstructure:"reset_timeout_seconds"`
|
||||||
|
HalfOpenRequests int `mapstructure:"half_open_requests"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConcurrencyConfig struct {
|
||||||
|
// PingInterval: 并发等待期间的 SSE ping 间隔(秒)
|
||||||
|
PingInterval int `mapstructure:"ping_interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GatewayConfig API网关相关配置
|
// GatewayConfig API网关相关配置
|
||||||
@@ -133,13 +208,20 @@ type GatewayConfig struct {
|
|||||||
// 应大于最长 LLM 请求时间,防止请求完成前槽位过期
|
// 应大于最长 LLM 请求时间,防止请求完成前槽位过期
|
||||||
ConcurrencySlotTTLMinutes int `mapstructure:"concurrency_slot_ttl_minutes"`
|
ConcurrencySlotTTLMinutes int `mapstructure:"concurrency_slot_ttl_minutes"`
|
||||||
|
|
||||||
|
// StreamDataIntervalTimeout: 流数据间隔超时(秒),0表示禁用
|
||||||
|
StreamDataIntervalTimeout int `mapstructure:"stream_data_interval_timeout"`
|
||||||
|
// StreamKeepaliveInterval: 流式 keepalive 间隔(秒),0表示禁用
|
||||||
|
StreamKeepaliveInterval int `mapstructure:"stream_keepalive_interval"`
|
||||||
|
// MaxLineSize: 上游 SSE 单行最大字节数(0使用默认值)
|
||||||
|
MaxLineSize int `mapstructure:"max_line_size"`
|
||||||
|
|
||||||
// 是否记录上游错误响应体摘要(避免输出请求内容)
|
// 是否记录上游错误响应体摘要(避免输出请求内容)
|
||||||
LogUpstreamErrorBody bool `mapstructure:"log_upstream_error_body"`
|
LogUpstreamErrorBody bool `mapstructure:"log_upstream_error_body"`
|
||||||
// 上游错误响应体记录最大字节数(超过会截断)
|
// 上游错误响应体记录最大字节数(超过会截断)
|
||||||
LogUpstreamErrorBodyMaxBytes int `mapstructure:"log_upstream_error_body_max_bytes"`
|
LogUpstreamErrorBodyMaxBytes int `mapstructure:"log_upstream_error_body_max_bytes"`
|
||||||
|
|
||||||
// API-key 账号在客户端未提供 anthropic-beta 时,是否按需自动补齐(默认关闭以保持兼容)
|
// API-key 账号在客户端未提供 anthropic-beta 时,是否按需自动补齐(默认关闭以保持兼容)
|
||||||
InjectBetaForApiKey bool `mapstructure:"inject_beta_for_apikey"`
|
InjectBetaForAPIKey bool `mapstructure:"inject_beta_for_apikey"`
|
||||||
|
|
||||||
// 是否允许对部分 400 错误触发 failover(默认关闭以避免改变语义)
|
// 是否允许对部分 400 错误触发 failover(默认关闭以避免改变语义)
|
||||||
FailoverOn400 bool `mapstructure:"failover_on_400"`
|
FailoverOn400 bool `mapstructure:"failover_on_400"`
|
||||||
@@ -236,12 +318,16 @@ type JWTConfig struct {
|
|||||||
ExpireHour int `mapstructure:"expire_hour"`
|
ExpireHour int `mapstructure:"expire_hour"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TurnstileConfig struct {
|
||||||
|
Required bool `mapstructure:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type DefaultConfig struct {
|
type DefaultConfig struct {
|
||||||
AdminEmail string `mapstructure:"admin_email"`
|
AdminEmail string `mapstructure:"admin_email"`
|
||||||
AdminPassword string `mapstructure:"admin_password"`
|
AdminPassword string `mapstructure:"admin_password"`
|
||||||
UserConcurrency int `mapstructure:"user_concurrency"`
|
UserConcurrency int `mapstructure:"user_concurrency"`
|
||||||
UserBalance float64 `mapstructure:"user_balance"`
|
UserBalance float64 `mapstructure:"user_balance"`
|
||||||
ApiKeyPrefix string `mapstructure:"api_key_prefix"`
|
APIKeyPrefix string `mapstructure:"api_key_prefix"`
|
||||||
RateMultiplier float64 `mapstructure:"rate_multiplier"`
|
RateMultiplier float64 `mapstructure:"rate_multiplier"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,8 +348,19 @@ func NormalizeRunMode(value string) string {
|
|||||||
func Load() (*Config, error) {
|
func Load() (*Config, error) {
|
||||||
viper.SetConfigName("config")
|
viper.SetConfigName("config")
|
||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yaml")
|
||||||
|
|
||||||
|
// Add config paths in priority order
|
||||||
|
// 1. DATA_DIR environment variable (highest priority)
|
||||||
|
if dataDir := os.Getenv("DATA_DIR"); dataDir != "" {
|
||||||
|
viper.AddConfigPath(dataDir)
|
||||||
|
}
|
||||||
|
// 2. Docker data directory
|
||||||
|
viper.AddConfigPath("/app/data")
|
||||||
|
// 3. Current directory
|
||||||
viper.AddConfigPath(".")
|
viper.AddConfigPath(".")
|
||||||
|
// 4. Config subdirectory
|
||||||
viper.AddConfigPath("./config")
|
viper.AddConfigPath("./config")
|
||||||
|
// 5. System config directory
|
||||||
viper.AddConfigPath("/etc/sub2api")
|
viper.AddConfigPath("/etc/sub2api")
|
||||||
|
|
||||||
// 环境变量支持
|
// 环境变量支持
|
||||||
@@ -286,11 +383,46 @@ func Load() (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg.RunMode = NormalizeRunMode(cfg.RunMode)
|
cfg.RunMode = NormalizeRunMode(cfg.RunMode)
|
||||||
|
cfg.Server.Mode = strings.ToLower(strings.TrimSpace(cfg.Server.Mode))
|
||||||
|
if cfg.Server.Mode == "" {
|
||||||
|
cfg.Server.Mode = "debug"
|
||||||
|
}
|
||||||
|
cfg.JWT.Secret = strings.TrimSpace(cfg.JWT.Secret)
|
||||||
|
cfg.CORS.AllowedOrigins = normalizeStringSlice(cfg.CORS.AllowedOrigins)
|
||||||
|
cfg.Security.ResponseHeaders.AdditionalAllowed = normalizeStringSlice(cfg.Security.ResponseHeaders.AdditionalAllowed)
|
||||||
|
cfg.Security.ResponseHeaders.ForceRemove = normalizeStringSlice(cfg.Security.ResponseHeaders.ForceRemove)
|
||||||
|
cfg.Security.CSP.Policy = strings.TrimSpace(cfg.Security.CSP.Policy)
|
||||||
|
|
||||||
|
if cfg.JWT.Secret == "" {
|
||||||
|
secret, err := generateJWTSecret(64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("generate jwt secret error: %w", err)
|
||||||
|
}
|
||||||
|
cfg.JWT.Secret = secret
|
||||||
|
log.Println("Warning: JWT secret auto-generated. Consider setting a fixed secret for production.")
|
||||||
|
}
|
||||||
|
|
||||||
if err := cfg.Validate(); err != nil {
|
if err := cfg.Validate(); err != nil {
|
||||||
return nil, fmt.Errorf("validate config error: %w", err)
|
return nil, fmt.Errorf("validate config error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !cfg.Security.URLAllowlist.Enabled {
|
||||||
|
log.Println("Warning: security.url_allowlist.enabled=false; allowlist/SSRF checks disabled (minimal format validation only).")
|
||||||
|
}
|
||||||
|
if !cfg.Security.ResponseHeaders.Enabled {
|
||||||
|
log.Println("Warning: security.response_headers.enabled=false; configurable header filtering disabled (default allowlist only).")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.JWT.Secret != "" && isWeakJWTSecret(cfg.JWT.Secret) {
|
||||||
|
log.Println("Warning: JWT secret appears weak; use a 32+ character random secret in production.")
|
||||||
|
}
|
||||||
|
if len(cfg.Security.ResponseHeaders.AdditionalAllowed) > 0 || len(cfg.Security.ResponseHeaders.ForceRemove) > 0 {
|
||||||
|
log.Printf("AUDIT: response header policy configured additional_allowed=%v force_remove=%v",
|
||||||
|
cfg.Security.ResponseHeaders.AdditionalAllowed,
|
||||||
|
cfg.Security.ResponseHeaders.ForceRemove,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return &cfg, nil
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,6 +435,45 @@ func setDefaults() {
|
|||||||
viper.SetDefault("server.mode", "debug")
|
viper.SetDefault("server.mode", "debug")
|
||||||
viper.SetDefault("server.read_header_timeout", 30) // 30秒读取请求头
|
viper.SetDefault("server.read_header_timeout", 30) // 30秒读取请求头
|
||||||
viper.SetDefault("server.idle_timeout", 120) // 120秒空闲超时
|
viper.SetDefault("server.idle_timeout", 120) // 120秒空闲超时
|
||||||
|
viper.SetDefault("server.trusted_proxies", []string{})
|
||||||
|
|
||||||
|
// CORS
|
||||||
|
viper.SetDefault("cors.allowed_origins", []string{})
|
||||||
|
viper.SetDefault("cors.allow_credentials", true)
|
||||||
|
|
||||||
|
// Security
|
||||||
|
viper.SetDefault("security.url_allowlist.enabled", false)
|
||||||
|
viper.SetDefault("security.url_allowlist.upstream_hosts", []string{
|
||||||
|
"api.openai.com",
|
||||||
|
"api.anthropic.com",
|
||||||
|
"api.kimi.com",
|
||||||
|
"open.bigmodel.cn",
|
||||||
|
"api.minimaxi.com",
|
||||||
|
"generativelanguage.googleapis.com",
|
||||||
|
"cloudcode-pa.googleapis.com",
|
||||||
|
"*.openai.azure.com",
|
||||||
|
})
|
||||||
|
viper.SetDefault("security.url_allowlist.pricing_hosts", []string{
|
||||||
|
"raw.githubusercontent.com",
|
||||||
|
})
|
||||||
|
viper.SetDefault("security.url_allowlist.crs_hosts", []string{})
|
||||||
|
viper.SetDefault("security.url_allowlist.allow_private_hosts", true)
|
||||||
|
viper.SetDefault("security.url_allowlist.allow_insecure_http", true)
|
||||||
|
viper.SetDefault("security.response_headers.enabled", false)
|
||||||
|
viper.SetDefault("security.response_headers.additional_allowed", []string{})
|
||||||
|
viper.SetDefault("security.response_headers.force_remove", []string{})
|
||||||
|
viper.SetDefault("security.csp.enabled", true)
|
||||||
|
viper.SetDefault("security.csp.policy", DefaultCSPPolicy)
|
||||||
|
viper.SetDefault("security.proxy_probe.insecure_skip_verify", false)
|
||||||
|
|
||||||
|
// Billing
|
||||||
|
viper.SetDefault("billing.circuit_breaker.enabled", true)
|
||||||
|
viper.SetDefault("billing.circuit_breaker.failure_threshold", 5)
|
||||||
|
viper.SetDefault("billing.circuit_breaker.reset_timeout_seconds", 30)
|
||||||
|
viper.SetDefault("billing.circuit_breaker.half_open_requests", 3)
|
||||||
|
|
||||||
|
// Turnstile
|
||||||
|
viper.SetDefault("turnstile.required", false)
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
viper.SetDefault("database.host", "localhost")
|
viper.SetDefault("database.host", "localhost")
|
||||||
@@ -328,7 +499,7 @@ func setDefaults() {
|
|||||||
viper.SetDefault("redis.min_idle_conns", 10)
|
viper.SetDefault("redis.min_idle_conns", 10)
|
||||||
|
|
||||||
// JWT
|
// JWT
|
||||||
viper.SetDefault("jwt.secret", "change-me-in-production")
|
viper.SetDefault("jwt.secret", "")
|
||||||
viper.SetDefault("jwt.expire_hour", 24)
|
viper.SetDefault("jwt.expire_hour", 24)
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
@@ -356,7 +527,7 @@ func setDefaults() {
|
|||||||
viper.SetDefault("timezone", "Asia/Shanghai")
|
viper.SetDefault("timezone", "Asia/Shanghai")
|
||||||
|
|
||||||
// Gateway
|
// Gateway
|
||||||
viper.SetDefault("gateway.response_header_timeout", 300) // 300秒(5分钟)等待上游响应头,LLM高负载时可能排队较久
|
viper.SetDefault("gateway.response_header_timeout", 600) // 600秒(10分钟)等待上游响应头,LLM高负载时可能排队较久
|
||||||
viper.SetDefault("gateway.log_upstream_error_body", false)
|
viper.SetDefault("gateway.log_upstream_error_body", false)
|
||||||
viper.SetDefault("gateway.log_upstream_error_body_max_bytes", 2048)
|
viper.SetDefault("gateway.log_upstream_error_body_max_bytes", 2048)
|
||||||
viper.SetDefault("gateway.inject_beta_for_apikey", false)
|
viper.SetDefault("gateway.inject_beta_for_apikey", false)
|
||||||
@@ -364,19 +535,23 @@ func setDefaults() {
|
|||||||
viper.SetDefault("gateway.max_body_size", int64(100*1024*1024))
|
viper.SetDefault("gateway.max_body_size", int64(100*1024*1024))
|
||||||
viper.SetDefault("gateway.connection_pool_isolation", ConnectionPoolIsolationAccountProxy)
|
viper.SetDefault("gateway.connection_pool_isolation", ConnectionPoolIsolationAccountProxy)
|
||||||
// HTTP 上游连接池配置(针对 5000+ 并发用户优化)
|
// HTTP 上游连接池配置(针对 5000+ 并发用户优化)
|
||||||
viper.SetDefault("gateway.max_idle_conns", 240) // 最大空闲连接总数(HTTP/2 场景默认)
|
viper.SetDefault("gateway.max_idle_conns", 240) // 最大空闲连接总数(HTTP/2 场景默认)
|
||||||
viper.SetDefault("gateway.max_idle_conns_per_host", 120) // 每主机最大空闲连接(HTTP/2 场景默认)
|
viper.SetDefault("gateway.max_idle_conns_per_host", 120) // 每主机最大空闲连接(HTTP/2 场景默认)
|
||||||
viper.SetDefault("gateway.max_conns_per_host", 240) // 每主机最大连接数(含活跃,HTTP/2 场景默认)
|
viper.SetDefault("gateway.max_conns_per_host", 240) // 每主机最大连接数(含活跃,HTTP/2 场景默认)
|
||||||
viper.SetDefault("gateway.idle_conn_timeout_seconds", 300) // 空闲连接超时(秒)
|
viper.SetDefault("gateway.idle_conn_timeout_seconds", 90) // 空闲连接超时(秒)
|
||||||
viper.SetDefault("gateway.max_upstream_clients", 5000)
|
viper.SetDefault("gateway.max_upstream_clients", 5000)
|
||||||
viper.SetDefault("gateway.client_idle_ttl_seconds", 900)
|
viper.SetDefault("gateway.client_idle_ttl_seconds", 900)
|
||||||
viper.SetDefault("gateway.concurrency_slot_ttl_minutes", 15) // 并发槽位过期时间(支持超长请求)
|
viper.SetDefault("gateway.concurrency_slot_ttl_minutes", 30) // 并发槽位过期时间(支持超长请求)
|
||||||
|
viper.SetDefault("gateway.stream_data_interval_timeout", 180)
|
||||||
|
viper.SetDefault("gateway.stream_keepalive_interval", 10)
|
||||||
|
viper.SetDefault("gateway.max_line_size", 10*1024*1024)
|
||||||
viper.SetDefault("gateway.scheduling.sticky_session_max_waiting", 3)
|
viper.SetDefault("gateway.scheduling.sticky_session_max_waiting", 3)
|
||||||
viper.SetDefault("gateway.scheduling.sticky_session_wait_timeout", 45*time.Second)
|
viper.SetDefault("gateway.scheduling.sticky_session_wait_timeout", 45*time.Second)
|
||||||
viper.SetDefault("gateway.scheduling.fallback_wait_timeout", 30*time.Second)
|
viper.SetDefault("gateway.scheduling.fallback_wait_timeout", 30*time.Second)
|
||||||
viper.SetDefault("gateway.scheduling.fallback_max_waiting", 100)
|
viper.SetDefault("gateway.scheduling.fallback_max_waiting", 100)
|
||||||
viper.SetDefault("gateway.scheduling.load_batch_enabled", true)
|
viper.SetDefault("gateway.scheduling.load_batch_enabled", true)
|
||||||
viper.SetDefault("gateway.scheduling.slot_cleanup_interval", 30*time.Second)
|
viper.SetDefault("gateway.scheduling.slot_cleanup_interval", 30*time.Second)
|
||||||
|
viper.SetDefault("concurrency.ping_interval", 10)
|
||||||
|
|
||||||
// TokenRefresh
|
// TokenRefresh
|
||||||
viper.SetDefault("token_refresh.enabled", true)
|
viper.SetDefault("token_refresh.enabled", true)
|
||||||
@@ -392,14 +567,35 @@ func setDefaults() {
|
|||||||
viper.SetDefault("gemini.oauth.client_secret", "")
|
viper.SetDefault("gemini.oauth.client_secret", "")
|
||||||
viper.SetDefault("gemini.oauth.scopes", "")
|
viper.SetDefault("gemini.oauth.scopes", "")
|
||||||
viper.SetDefault("gemini.quota.policy", "")
|
viper.SetDefault("gemini.quota.policy", "")
|
||||||
|
|
||||||
|
// Update - 在线更新配置
|
||||||
|
// 代理地址为空表示直连 GitHub(适用于海外服务器)
|
||||||
|
viper.SetDefault("update.proxy_url", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c *Config) Validate() error {
|
||||||
if c.JWT.Secret == "" {
|
if c.JWT.ExpireHour <= 0 {
|
||||||
return fmt.Errorf("jwt.secret is required")
|
return fmt.Errorf("jwt.expire_hour must be positive")
|
||||||
}
|
}
|
||||||
if c.JWT.Secret == "change-me-in-production" && c.Server.Mode == "release" {
|
if c.JWT.ExpireHour > 168 {
|
||||||
return fmt.Errorf("jwt.secret must be changed in production")
|
return fmt.Errorf("jwt.expire_hour must be <= 168 (7 days)")
|
||||||
|
}
|
||||||
|
if c.JWT.ExpireHour > 24 {
|
||||||
|
log.Printf("Warning: jwt.expire_hour is %d hours (> 24). Consider shorter expiration for security.", c.JWT.ExpireHour)
|
||||||
|
}
|
||||||
|
if c.Security.CSP.Enabled && strings.TrimSpace(c.Security.CSP.Policy) == "" {
|
||||||
|
return fmt.Errorf("security.csp.policy is required when CSP is enabled")
|
||||||
|
}
|
||||||
|
if c.Billing.CircuitBreaker.Enabled {
|
||||||
|
if c.Billing.CircuitBreaker.FailureThreshold <= 0 {
|
||||||
|
return fmt.Errorf("billing.circuit_breaker.failure_threshold must be positive")
|
||||||
|
}
|
||||||
|
if c.Billing.CircuitBreaker.ResetTimeoutSeconds <= 0 {
|
||||||
|
return fmt.Errorf("billing.circuit_breaker.reset_timeout_seconds must be positive")
|
||||||
|
}
|
||||||
|
if c.Billing.CircuitBreaker.HalfOpenRequests <= 0 {
|
||||||
|
return fmt.Errorf("billing.circuit_breaker.half_open_requests must be positive")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if c.Database.MaxOpenConns <= 0 {
|
if c.Database.MaxOpenConns <= 0 {
|
||||||
return fmt.Errorf("database.max_open_conns must be positive")
|
return fmt.Errorf("database.max_open_conns must be positive")
|
||||||
@@ -457,6 +653,9 @@ func (c *Config) Validate() error {
|
|||||||
if c.Gateway.IdleConnTimeoutSeconds <= 0 {
|
if c.Gateway.IdleConnTimeoutSeconds <= 0 {
|
||||||
return fmt.Errorf("gateway.idle_conn_timeout_seconds must be positive")
|
return fmt.Errorf("gateway.idle_conn_timeout_seconds must be positive")
|
||||||
}
|
}
|
||||||
|
if c.Gateway.IdleConnTimeoutSeconds > 180 {
|
||||||
|
log.Printf("Warning: gateway.idle_conn_timeout_seconds is %d (> 180). Consider 60-120 seconds for better connection reuse.", c.Gateway.IdleConnTimeoutSeconds)
|
||||||
|
}
|
||||||
if c.Gateway.MaxUpstreamClients <= 0 {
|
if c.Gateway.MaxUpstreamClients <= 0 {
|
||||||
return fmt.Errorf("gateway.max_upstream_clients must be positive")
|
return fmt.Errorf("gateway.max_upstream_clients must be positive")
|
||||||
}
|
}
|
||||||
@@ -466,6 +665,26 @@ func (c *Config) Validate() error {
|
|||||||
if c.Gateway.ConcurrencySlotTTLMinutes <= 0 {
|
if c.Gateway.ConcurrencySlotTTLMinutes <= 0 {
|
||||||
return fmt.Errorf("gateway.concurrency_slot_ttl_minutes must be positive")
|
return fmt.Errorf("gateway.concurrency_slot_ttl_minutes must be positive")
|
||||||
}
|
}
|
||||||
|
if c.Gateway.StreamDataIntervalTimeout < 0 {
|
||||||
|
return fmt.Errorf("gateway.stream_data_interval_timeout must be non-negative")
|
||||||
|
}
|
||||||
|
if c.Gateway.StreamDataIntervalTimeout != 0 &&
|
||||||
|
(c.Gateway.StreamDataIntervalTimeout < 30 || c.Gateway.StreamDataIntervalTimeout > 300) {
|
||||||
|
return fmt.Errorf("gateway.stream_data_interval_timeout must be 0 or between 30-300 seconds")
|
||||||
|
}
|
||||||
|
if c.Gateway.StreamKeepaliveInterval < 0 {
|
||||||
|
return fmt.Errorf("gateway.stream_keepalive_interval must be non-negative")
|
||||||
|
}
|
||||||
|
if c.Gateway.StreamKeepaliveInterval != 0 &&
|
||||||
|
(c.Gateway.StreamKeepaliveInterval < 5 || c.Gateway.StreamKeepaliveInterval > 30) {
|
||||||
|
return fmt.Errorf("gateway.stream_keepalive_interval must be 0 or between 5-30 seconds")
|
||||||
|
}
|
||||||
|
if c.Gateway.MaxLineSize < 0 {
|
||||||
|
return fmt.Errorf("gateway.max_line_size must be non-negative")
|
||||||
|
}
|
||||||
|
if c.Gateway.MaxLineSize != 0 && c.Gateway.MaxLineSize < 1024*1024 {
|
||||||
|
return fmt.Errorf("gateway.max_line_size must be at least 1MB")
|
||||||
|
}
|
||||||
if c.Gateway.Scheduling.StickySessionMaxWaiting <= 0 {
|
if c.Gateway.Scheduling.StickySessionMaxWaiting <= 0 {
|
||||||
return fmt.Errorf("gateway.scheduling.sticky_session_max_waiting must be positive")
|
return fmt.Errorf("gateway.scheduling.sticky_session_max_waiting must be positive")
|
||||||
}
|
}
|
||||||
@@ -481,9 +700,57 @@ func (c *Config) Validate() error {
|
|||||||
if c.Gateway.Scheduling.SlotCleanupInterval < 0 {
|
if c.Gateway.Scheduling.SlotCleanupInterval < 0 {
|
||||||
return fmt.Errorf("gateway.scheduling.slot_cleanup_interval must be non-negative")
|
return fmt.Errorf("gateway.scheduling.slot_cleanup_interval must be non-negative")
|
||||||
}
|
}
|
||||||
|
if c.Concurrency.PingInterval < 5 || c.Concurrency.PingInterval > 30 {
|
||||||
|
return fmt.Errorf("concurrency.ping_interval must be between 5-30 seconds")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeStringSlice(values []string) []string {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
normalized := make([]string, 0, len(values))
|
||||||
|
for _, v := range values {
|
||||||
|
trimmed := strings.TrimSpace(v)
|
||||||
|
if trimmed == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
normalized = append(normalized, trimmed)
|
||||||
|
}
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWeakJWTSecret(secret string) bool {
|
||||||
|
lower := strings.ToLower(strings.TrimSpace(secret))
|
||||||
|
if lower == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
weak := map[string]struct{}{
|
||||||
|
"change-me-in-production": {},
|
||||||
|
"changeme": {},
|
||||||
|
"secret": {},
|
||||||
|
"password": {},
|
||||||
|
"123456": {},
|
||||||
|
"12345678": {},
|
||||||
|
"admin": {},
|
||||||
|
"jwt-secret": {},
|
||||||
|
}
|
||||||
|
_, exists := weak[lower]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateJWTSecret(byteLength int) (string, error) {
|
||||||
|
if byteLength <= 0 {
|
||||||
|
byteLength = 32
|
||||||
|
}
|
||||||
|
buf := make([]byte, byteLength)
|
||||||
|
if _, err := rand.Read(buf); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetServerAddress returns the server address (host:port) from config file or environment variable.
|
// GetServerAddress returns the server address (host:port) from config file or environment variable.
|
||||||
// This is a lightweight function that can be used before full config validation,
|
// This is a lightweight function that can be used before full config validation,
|
||||||
// such as during setup wizard startup.
|
// such as during setup wizard startup.
|
||||||
|
|||||||
@@ -68,3 +68,25 @@ func TestLoadSchedulingConfigFromEnv(t *testing.T) {
|
|||||||
t.Fatalf("StickySessionMaxWaiting = %d, want 5", cfg.Gateway.Scheduling.StickySessionMaxWaiting)
|
t.Fatalf("StickySessionMaxWaiting = %d, want 5", cfg.Gateway.Scheduling.StickySessionMaxWaiting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadDefaultSecurityToggles(t *testing.T) {
|
||||||
|
viper.Reset()
|
||||||
|
|
||||||
|
cfg, err := Load()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Load() error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Security.URLAllowlist.Enabled {
|
||||||
|
t.Fatalf("URLAllowlist.Enabled = true, want false")
|
||||||
|
}
|
||||||
|
if !cfg.Security.URLAllowlist.AllowInsecureHTTP {
|
||||||
|
t.Fatalf("URLAllowlist.AllowInsecureHTTP = false, want true")
|
||||||
|
}
|
||||||
|
if !cfg.Security.URLAllowlist.AllowPrivateHosts {
|
||||||
|
t.Fatalf("URLAllowlist.AllowPrivateHosts = false, want true")
|
||||||
|
}
|
||||||
|
if cfg.Security.ResponseHeaders.Enabled {
|
||||||
|
t.Fatalf("ResponseHeaders.Enabled = true, want false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
// Package admin provides HTTP handlers for administrative operations.
|
||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
||||||
@@ -31,15 +34,16 @@ func NewOAuthHandler(oauthService *service.OAuthService) *OAuthHandler {
|
|||||||
|
|
||||||
// AccountHandler handles admin account management
|
// AccountHandler handles admin account management
|
||||||
type AccountHandler struct {
|
type AccountHandler struct {
|
||||||
adminService service.AdminService
|
adminService service.AdminService
|
||||||
oauthService *service.OAuthService
|
oauthService *service.OAuthService
|
||||||
openaiOAuthService *service.OpenAIOAuthService
|
openaiOAuthService *service.OpenAIOAuthService
|
||||||
geminiOAuthService *service.GeminiOAuthService
|
geminiOAuthService *service.GeminiOAuthService
|
||||||
rateLimitService *service.RateLimitService
|
antigravityOAuthService *service.AntigravityOAuthService
|
||||||
accountUsageService *service.AccountUsageService
|
rateLimitService *service.RateLimitService
|
||||||
accountTestService *service.AccountTestService
|
accountUsageService *service.AccountUsageService
|
||||||
concurrencyService *service.ConcurrencyService
|
accountTestService *service.AccountTestService
|
||||||
crsSyncService *service.CRSSyncService
|
concurrencyService *service.ConcurrencyService
|
||||||
|
crsSyncService *service.CRSSyncService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccountHandler creates a new admin account handler
|
// NewAccountHandler creates a new admin account handler
|
||||||
@@ -48,6 +52,7 @@ func NewAccountHandler(
|
|||||||
oauthService *service.OAuthService,
|
oauthService *service.OAuthService,
|
||||||
openaiOAuthService *service.OpenAIOAuthService,
|
openaiOAuthService *service.OpenAIOAuthService,
|
||||||
geminiOAuthService *service.GeminiOAuthService,
|
geminiOAuthService *service.GeminiOAuthService,
|
||||||
|
antigravityOAuthService *service.AntigravityOAuthService,
|
||||||
rateLimitService *service.RateLimitService,
|
rateLimitService *service.RateLimitService,
|
||||||
accountUsageService *service.AccountUsageService,
|
accountUsageService *service.AccountUsageService,
|
||||||
accountTestService *service.AccountTestService,
|
accountTestService *service.AccountTestService,
|
||||||
@@ -55,56 +60,66 @@ func NewAccountHandler(
|
|||||||
crsSyncService *service.CRSSyncService,
|
crsSyncService *service.CRSSyncService,
|
||||||
) *AccountHandler {
|
) *AccountHandler {
|
||||||
return &AccountHandler{
|
return &AccountHandler{
|
||||||
adminService: adminService,
|
adminService: adminService,
|
||||||
oauthService: oauthService,
|
oauthService: oauthService,
|
||||||
openaiOAuthService: openaiOAuthService,
|
openaiOAuthService: openaiOAuthService,
|
||||||
geminiOAuthService: geminiOAuthService,
|
geminiOAuthService: geminiOAuthService,
|
||||||
rateLimitService: rateLimitService,
|
antigravityOAuthService: antigravityOAuthService,
|
||||||
accountUsageService: accountUsageService,
|
rateLimitService: rateLimitService,
|
||||||
accountTestService: accountTestService,
|
accountUsageService: accountUsageService,
|
||||||
concurrencyService: concurrencyService,
|
accountTestService: accountTestService,
|
||||||
crsSyncService: crsSyncService,
|
concurrencyService: concurrencyService,
|
||||||
|
crsSyncService: crsSyncService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAccountRequest represents create account request
|
// CreateAccountRequest represents create account request
|
||||||
type CreateAccountRequest struct {
|
type CreateAccountRequest struct {
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Platform string `json:"platform" binding:"required"`
|
Notes *string `json:"notes"`
|
||||||
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey"`
|
Platform string `json:"platform" binding:"required"`
|
||||||
Credentials map[string]any `json:"credentials" binding:"required"`
|
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey"`
|
||||||
Extra map[string]any `json:"extra"`
|
Credentials map[string]any `json:"credentials" binding:"required"`
|
||||||
ProxyID *int64 `json:"proxy_id"`
|
Extra map[string]any `json:"extra"`
|
||||||
Concurrency int `json:"concurrency"`
|
ProxyID *int64 `json:"proxy_id"`
|
||||||
Priority int `json:"priority"`
|
Concurrency int `json:"concurrency"`
|
||||||
GroupIDs []int64 `json:"group_ids"`
|
Priority int `json:"priority"`
|
||||||
|
GroupIDs []int64 `json:"group_ids"`
|
||||||
|
ExpiresAt *int64 `json:"expires_at"`
|
||||||
|
AutoPauseOnExpired *bool `json:"auto_pause_on_expired"`
|
||||||
|
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateAccountRequest represents update account request
|
// UpdateAccountRequest represents update account request
|
||||||
// 使用指针类型来区分"未提供"和"设置为0"
|
// 使用指针类型来区分"未提供"和"设置为0"
|
||||||
type UpdateAccountRequest struct {
|
type UpdateAccountRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
|
Notes *string `json:"notes"`
|
||||||
Credentials map[string]any `json:"credentials"`
|
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
|
||||||
Extra map[string]any `json:"extra"`
|
Credentials map[string]any `json:"credentials"`
|
||||||
ProxyID *int64 `json:"proxy_id"`
|
Extra map[string]any `json:"extra"`
|
||||||
Concurrency *int `json:"concurrency"`
|
ProxyID *int64 `json:"proxy_id"`
|
||||||
Priority *int `json:"priority"`
|
Concurrency *int `json:"concurrency"`
|
||||||
Status string `json:"status" binding:"omitempty,oneof=active inactive"`
|
Priority *int `json:"priority"`
|
||||||
GroupIDs *[]int64 `json:"group_ids"`
|
Status string `json:"status" binding:"omitempty,oneof=active inactive"`
|
||||||
|
GroupIDs *[]int64 `json:"group_ids"`
|
||||||
|
ExpiresAt *int64 `json:"expires_at"`
|
||||||
|
AutoPauseOnExpired *bool `json:"auto_pause_on_expired"`
|
||||||
|
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
|
||||||
}
|
}
|
||||||
|
|
||||||
// BulkUpdateAccountsRequest represents the payload for bulk editing accounts
|
// BulkUpdateAccountsRequest represents the payload for bulk editing accounts
|
||||||
type BulkUpdateAccountsRequest struct {
|
type BulkUpdateAccountsRequest struct {
|
||||||
AccountIDs []int64 `json:"account_ids" binding:"required,min=1"`
|
AccountIDs []int64 `json:"account_ids" binding:"required,min=1"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ProxyID *int64 `json:"proxy_id"`
|
ProxyID *int64 `json:"proxy_id"`
|
||||||
Concurrency *int `json:"concurrency"`
|
Concurrency *int `json:"concurrency"`
|
||||||
Priority *int `json:"priority"`
|
Priority *int `json:"priority"`
|
||||||
Status string `json:"status" binding:"omitempty,oneof=active inactive error"`
|
Status string `json:"status" binding:"omitempty,oneof=active inactive error"`
|
||||||
GroupIDs *[]int64 `json:"group_ids"`
|
GroupIDs *[]int64 `json:"group_ids"`
|
||||||
Credentials map[string]any `json:"credentials"`
|
Credentials map[string]any `json:"credentials"`
|
||||||
Extra map[string]any `json:"extra"`
|
Extra map[string]any `json:"extra"`
|
||||||
|
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountWithConcurrency extends Account with real-time concurrency info
|
// AccountWithConcurrency extends Account with real-time concurrency info
|
||||||
@@ -179,18 +194,43 @@ func (h *AccountHandler) Create(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确定是否跳过混合渠道检查
|
||||||
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
||||||
|
|
||||||
account, err := h.adminService.CreateAccount(c.Request.Context(), &service.CreateAccountInput{
|
account, err := h.adminService.CreateAccount(c.Request.Context(), &service.CreateAccountInput{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Platform: req.Platform,
|
Notes: req.Notes,
|
||||||
Type: req.Type,
|
Platform: req.Platform,
|
||||||
Credentials: req.Credentials,
|
Type: req.Type,
|
||||||
Extra: req.Extra,
|
Credentials: req.Credentials,
|
||||||
ProxyID: req.ProxyID,
|
Extra: req.Extra,
|
||||||
Concurrency: req.Concurrency,
|
ProxyID: req.ProxyID,
|
||||||
Priority: req.Priority,
|
Concurrency: req.Concurrency,
|
||||||
GroupIDs: req.GroupIDs,
|
Priority: req.Priority,
|
||||||
|
GroupIDs: req.GroupIDs,
|
||||||
|
ExpiresAt: req.ExpiresAt,
|
||||||
|
AutoPauseOnExpired: req.AutoPauseOnExpired,
|
||||||
|
SkipMixedChannelCheck: skipCheck,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 检查是否为混合渠道错误
|
||||||
|
var mixedErr *service.MixedChannelError
|
||||||
|
if errors.As(err, &mixedErr) {
|
||||||
|
// 返回特殊错误码要求确认
|
||||||
|
c.JSON(409, gin.H{
|
||||||
|
"error": "mixed_channel_warning",
|
||||||
|
"message": mixedErr.Error(),
|
||||||
|
"details": gin.H{
|
||||||
|
"group_id": mixedErr.GroupID,
|
||||||
|
"group_name": mixedErr.GroupName,
|
||||||
|
"current_platform": mixedErr.CurrentPlatform,
|
||||||
|
"other_platform": mixedErr.OtherPlatform,
|
||||||
|
},
|
||||||
|
"require_confirmation": true,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -213,18 +253,43 @@ func (h *AccountHandler) Update(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确定是否跳过混合渠道检查
|
||||||
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
||||||
|
|
||||||
account, err := h.adminService.UpdateAccount(c.Request.Context(), accountID, &service.UpdateAccountInput{
|
account, err := h.adminService.UpdateAccount(c.Request.Context(), accountID, &service.UpdateAccountInput{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Type: req.Type,
|
Notes: req.Notes,
|
||||||
Credentials: req.Credentials,
|
Type: req.Type,
|
||||||
Extra: req.Extra,
|
Credentials: req.Credentials,
|
||||||
ProxyID: req.ProxyID,
|
Extra: req.Extra,
|
||||||
Concurrency: req.Concurrency, // 指针类型,nil 表示未提供
|
ProxyID: req.ProxyID,
|
||||||
Priority: req.Priority, // 指针类型,nil 表示未提供
|
Concurrency: req.Concurrency, // 指针类型,nil 表示未提供
|
||||||
Status: req.Status,
|
Priority: req.Priority, // 指针类型,nil 表示未提供
|
||||||
GroupIDs: req.GroupIDs,
|
Status: req.Status,
|
||||||
|
GroupIDs: req.GroupIDs,
|
||||||
|
ExpiresAt: req.ExpiresAt,
|
||||||
|
AutoPauseOnExpired: req.AutoPauseOnExpired,
|
||||||
|
SkipMixedChannelCheck: skipCheck,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 检查是否为混合渠道错误
|
||||||
|
var mixedErr *service.MixedChannelError
|
||||||
|
if errors.As(err, &mixedErr) {
|
||||||
|
// 返回特殊错误码要求确认
|
||||||
|
c.JSON(409, gin.H{
|
||||||
|
"error": "mixed_channel_warning",
|
||||||
|
"message": mixedErr.Error(),
|
||||||
|
"details": gin.H{
|
||||||
|
"group_id": mixedErr.GroupID,
|
||||||
|
"group_name": mixedErr.GroupName,
|
||||||
|
"current_platform": mixedErr.CurrentPlatform,
|
||||||
|
"other_platform": mixedErr.OtherPlatform,
|
||||||
|
},
|
||||||
|
"require_confirmation": true,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -304,7 +369,8 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
|
|||||||
SyncProxies: syncProxies,
|
SyncProxies: syncProxies,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
// Provide detailed error message for CRS sync failures
|
||||||
|
response.InternalError(c, "CRS sync failed: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +431,19 @@ func (h *AccountHandler) Refresh(c *gin.Context) {
|
|||||||
newCredentials[k] = v
|
newCredentials[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if account.Platform == service.PlatformAntigravity {
|
||||||
|
tokenInfo, err := h.antigravityOAuthService.RefreshAccountToken(c.Request.Context(), account)
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorFrom(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newCredentials = h.antigravityOAuthService.BuildAccountCredentials(tokenInfo)
|
||||||
|
for k, v := range account.Credentials {
|
||||||
|
if _, exists := newCredentials[k]; !exists {
|
||||||
|
newCredentials[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use Anthropic/Claude OAuth service to refresh token
|
// Use Anthropic/Claude OAuth service to refresh token
|
||||||
tokenInfo, err := h.oauthService.RefreshAccountToken(c.Request.Context(), account)
|
tokenInfo, err := h.oauthService.RefreshAccountToken(c.Request.Context(), account)
|
||||||
@@ -568,6 +647,9 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确定是否跳过混合渠道检查
|
||||||
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
||||||
|
|
||||||
hasUpdates := req.Name != "" ||
|
hasUpdates := req.Name != "" ||
|
||||||
req.ProxyID != nil ||
|
req.ProxyID != nil ||
|
||||||
req.Concurrency != nil ||
|
req.Concurrency != nil ||
|
||||||
@@ -583,15 +665,16 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result, err := h.adminService.BulkUpdateAccounts(c.Request.Context(), &service.BulkUpdateAccountsInput{
|
result, err := h.adminService.BulkUpdateAccounts(c.Request.Context(), &service.BulkUpdateAccountsInput{
|
||||||
AccountIDs: req.AccountIDs,
|
AccountIDs: req.AccountIDs,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
ProxyID: req.ProxyID,
|
ProxyID: req.ProxyID,
|
||||||
Concurrency: req.Concurrency,
|
Concurrency: req.Concurrency,
|
||||||
Priority: req.Priority,
|
Priority: req.Priority,
|
||||||
Status: req.Status,
|
Status: req.Status,
|
||||||
GroupIDs: req.GroupIDs,
|
GroupIDs: req.GroupIDs,
|
||||||
Credentials: req.Credentials,
|
Credentials: req.Credentials,
|
||||||
Extra: req.Extra,
|
Extra: req.Extra,
|
||||||
|
SkipMixedChannelCheck: skipCheck,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
@@ -781,6 +864,49 @@ func (h *AccountHandler) ClearRateLimit(c *gin.Context) {
|
|||||||
response.Success(c, gin.H{"message": "Rate limit cleared successfully"})
|
response.Success(c, gin.H{"message": "Rate limit cleared successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTempUnschedulable handles getting temporary unschedulable status
|
||||||
|
// GET /api/v1/admin/accounts/:id/temp-unschedulable
|
||||||
|
func (h *AccountHandler) GetTempUnschedulable(c *gin.Context) {
|
||||||
|
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid account ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err := h.rateLimitService.GetTempUnschedStatus(c.Request.Context(), accountID)
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorFrom(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if state == nil || state.UntilUnix <= time.Now().Unix() {
|
||||||
|
response.Success(c, gin.H{"active": false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, gin.H{
|
||||||
|
"active": true,
|
||||||
|
"state": state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearTempUnschedulable handles clearing temporary unschedulable status
|
||||||
|
// DELETE /api/v1/admin/accounts/:id/temp-unschedulable
|
||||||
|
func (h *AccountHandler) ClearTempUnschedulable(c *gin.Context) {
|
||||||
|
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid account ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.rateLimitService.ClearTempUnschedulable(c.Request.Context(), accountID); err != nil {
|
||||||
|
response.ErrorFrom(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, gin.H{"message": "Temp unschedulable cleared successfully"})
|
||||||
|
}
|
||||||
|
|
||||||
// GetTodayStats handles getting account today statistics
|
// GetTodayStats handles getting account today statistics
|
||||||
// GET /api/v1/admin/accounts/:id/today-stats
|
// GET /api/v1/admin/accounts/:id/today-stats
|
||||||
func (h *AccountHandler) GetTodayStats(c *gin.Context) {
|
func (h *AccountHandler) GetTodayStats(c *gin.Context) {
|
||||||
|
|||||||
@@ -26,31 +26,33 @@ func NewDashboardHandler(dashboardService *service.DashboardService) *DashboardH
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseTimeRange parses start_date, end_date query parameters
|
// parseTimeRange parses start_date, end_date query parameters
|
||||||
|
// Uses user's timezone if provided, otherwise falls back to server timezone
|
||||||
func parseTimeRange(c *gin.Context) (time.Time, time.Time) {
|
func parseTimeRange(c *gin.Context) (time.Time, time.Time) {
|
||||||
now := timezone.Now()
|
userTZ := c.Query("timezone") // Get user's timezone from request
|
||||||
|
now := timezone.NowInUserLocation(userTZ)
|
||||||
startDate := c.Query("start_date")
|
startDate := c.Query("start_date")
|
||||||
endDate := c.Query("end_date")
|
endDate := c.Query("end_date")
|
||||||
|
|
||||||
var startTime, endTime time.Time
|
var startTime, endTime time.Time
|
||||||
|
|
||||||
if startDate != "" {
|
if startDate != "" {
|
||||||
if t, err := timezone.ParseInLocation("2006-01-02", startDate); err == nil {
|
if t, err := timezone.ParseInUserLocation("2006-01-02", startDate, userTZ); err == nil {
|
||||||
startTime = t
|
startTime = t
|
||||||
} else {
|
} else {
|
||||||
startTime = timezone.StartOfDay(now.AddDate(0, 0, -7))
|
startTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, -7), userTZ)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startTime = timezone.StartOfDay(now.AddDate(0, 0, -7))
|
startTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, -7), userTZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
if endDate != "" {
|
if endDate != "" {
|
||||||
if t, err := timezone.ParseInLocation("2006-01-02", endDate); err == nil {
|
if t, err := timezone.ParseInUserLocation("2006-01-02", endDate, userTZ); err == nil {
|
||||||
endTime = t.Add(24 * time.Hour) // Include the end date
|
endTime = t.Add(24 * time.Hour) // Include the end date
|
||||||
} else {
|
} else {
|
||||||
endTime = timezone.StartOfDay(now.AddDate(0, 0, 1))
|
endTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, 1), userTZ)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
endTime = timezone.StartOfDay(now.AddDate(0, 0, 1))
|
endTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, 1), userTZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
return startTime, endTime
|
return startTime, endTime
|
||||||
@@ -75,8 +77,8 @@ func (h *DashboardHandler) GetStats(c *gin.Context) {
|
|||||||
"active_users": stats.ActiveUsers,
|
"active_users": stats.ActiveUsers,
|
||||||
|
|
||||||
// API Key 统计
|
// API Key 统计
|
||||||
"total_api_keys": stats.TotalApiKeys,
|
"total_api_keys": stats.TotalAPIKeys,
|
||||||
"active_api_keys": stats.ActiveApiKeys,
|
"active_api_keys": stats.ActiveAPIKeys,
|
||||||
|
|
||||||
// 账户统计
|
// 账户统计
|
||||||
"total_accounts": stats.TotalAccounts,
|
"total_accounts": stats.TotalAccounts,
|
||||||
@@ -193,10 +195,10 @@ func (h *DashboardHandler) GetModelStats(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetApiKeyUsageTrend handles getting API key usage trend data
|
// GetAPIKeyUsageTrend handles getting API key usage trend data
|
||||||
// GET /api/v1/admin/dashboard/api-keys-trend
|
// GET /api/v1/admin/dashboard/api-keys-trend
|
||||||
// Query params: start_date, end_date (YYYY-MM-DD), granularity (day/hour), limit (default 5)
|
// Query params: start_date, end_date (YYYY-MM-DD), granularity (day/hour), limit (default 5)
|
||||||
func (h *DashboardHandler) GetApiKeyUsageTrend(c *gin.Context) {
|
func (h *DashboardHandler) GetAPIKeyUsageTrend(c *gin.Context) {
|
||||||
startTime, endTime := parseTimeRange(c)
|
startTime, endTime := parseTimeRange(c)
|
||||||
granularity := c.DefaultQuery("granularity", "day")
|
granularity := c.DefaultQuery("granularity", "day")
|
||||||
limitStr := c.DefaultQuery("limit", "5")
|
limitStr := c.DefaultQuery("limit", "5")
|
||||||
@@ -205,7 +207,7 @@ func (h *DashboardHandler) GetApiKeyUsageTrend(c *gin.Context) {
|
|||||||
limit = 5
|
limit = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
trend, err := h.dashboardService.GetApiKeyUsageTrend(c.Request.Context(), startTime, endTime, granularity, limit)
|
trend, err := h.dashboardService.GetAPIKeyUsageTrend(c.Request.Context(), startTime, endTime, granularity, limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, 500, "Failed to get API key usage trend")
|
response.Error(c, 500, "Failed to get API key usage trend")
|
||||||
return
|
return
|
||||||
@@ -273,26 +275,26 @@ func (h *DashboardHandler) GetBatchUsersUsage(c *gin.Context) {
|
|||||||
response.Success(c, gin.H{"stats": stats})
|
response.Success(c, gin.H{"stats": stats})
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchApiKeysUsageRequest represents the request body for batch api key usage stats
|
// BatchAPIKeysUsageRequest represents the request body for batch api key usage stats
|
||||||
type BatchApiKeysUsageRequest struct {
|
type BatchAPIKeysUsageRequest struct {
|
||||||
ApiKeyIDs []int64 `json:"api_key_ids" binding:"required"`
|
APIKeyIDs []int64 `json:"api_key_ids" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBatchApiKeysUsage handles getting usage stats for multiple API keys
|
// GetBatchAPIKeysUsage handles getting usage stats for multiple API keys
|
||||||
// POST /api/v1/admin/dashboard/api-keys-usage
|
// POST /api/v1/admin/dashboard/api-keys-usage
|
||||||
func (h *DashboardHandler) GetBatchApiKeysUsage(c *gin.Context) {
|
func (h *DashboardHandler) GetBatchAPIKeysUsage(c *gin.Context) {
|
||||||
var req BatchApiKeysUsageRequest
|
var req BatchAPIKeysUsageRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(req.ApiKeyIDs) == 0 {
|
if len(req.APIKeyIDs) == 0 {
|
||||||
response.Success(c, gin.H{"stats": map[string]any{}})
|
response.Success(c, gin.H{"stats": map[string]any{}})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := h.dashboardService.GetBatchApiKeyUsageStats(c.Request.Context(), req.ApiKeyIDs)
|
stats, err := h.dashboardService.GetBatchAPIKeyUsageStats(c.Request.Context(), req.APIKeyIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, 500, "Failed to get API key usage stats")
|
response.Error(c, 500, "Failed to get API key usage stats")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func NewGeminiOAuthHandler(geminiOAuthService *service.GeminiOAuthService) *Gemi
|
|||||||
return &GeminiOAuthHandler{geminiOAuthService: geminiOAuthService}
|
return &GeminiOAuthHandler{geminiOAuthService: geminiOAuthService}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCapabilities returns the Gemini OAuth configuration capabilities.
|
||||||
// GET /api/v1/admin/gemini/oauth/capabilities
|
// GET /api/v1/admin/gemini/oauth/capabilities
|
||||||
func (h *GeminiOAuthHandler) GetCapabilities(c *gin.Context) {
|
func (h *GeminiOAuthHandler) GetCapabilities(c *gin.Context) {
|
||||||
cfg := h.geminiOAuthService.GetOAuthConfig()
|
cfg := h.geminiOAuthService.GetOAuthConfig()
|
||||||
@@ -30,6 +31,8 @@ type GeminiGenerateAuthURLRequest struct {
|
|||||||
// OAuth 类型: "code_assist" (需要 project_id) 或 "ai_studio" (不需要 project_id)
|
// OAuth 类型: "code_assist" (需要 project_id) 或 "ai_studio" (不需要 project_id)
|
||||||
// 默认为 "code_assist" 以保持向后兼容
|
// 默认为 "code_assist" 以保持向后兼容
|
||||||
OAuthType string `json:"oauth_type"`
|
OAuthType string `json:"oauth_type"`
|
||||||
|
// TierID is a user-selected tier to be used when auto detection is unavailable or fails.
|
||||||
|
TierID string `json:"tier_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateAuthURL generates Google OAuth authorization URL for Gemini.
|
// GenerateAuthURL generates Google OAuth authorization URL for Gemini.
|
||||||
@@ -54,7 +57,7 @@ func (h *GeminiOAuthHandler) GenerateAuthURL(c *gin.Context) {
|
|||||||
// Always pass the "hosted" callback URI; the OAuth service may override it depending on
|
// Always pass the "hosted" callback URI; the OAuth service may override it depending on
|
||||||
// oauth_type and whether the built-in Gemini CLI OAuth client is used.
|
// oauth_type and whether the built-in Gemini CLI OAuth client is used.
|
||||||
redirectURI := deriveGeminiRedirectURI(c)
|
redirectURI := deriveGeminiRedirectURI(c)
|
||||||
result, err := h.geminiOAuthService.GenerateAuthURL(c.Request.Context(), req.ProxyID, redirectURI, req.ProjectID, oauthType)
|
result, err := h.geminiOAuthService.GenerateAuthURL(c.Request.Context(), req.ProxyID, redirectURI, req.ProjectID, oauthType, req.TierID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := err.Error()
|
msg := err.Error()
|
||||||
// Treat missing/invalid OAuth client configuration as a user/config error.
|
// Treat missing/invalid OAuth client configuration as a user/config error.
|
||||||
@@ -76,6 +79,9 @@ type GeminiExchangeCodeRequest struct {
|
|||||||
ProxyID *int64 `json:"proxy_id"`
|
ProxyID *int64 `json:"proxy_id"`
|
||||||
// OAuth 类型: "code_assist" 或 "ai_studio",需要与 GenerateAuthURL 时的类型一致
|
// OAuth 类型: "code_assist" 或 "ai_studio",需要与 GenerateAuthURL 时的类型一致
|
||||||
OAuthType string `json:"oauth_type"`
|
OAuthType string `json:"oauth_type"`
|
||||||
|
// TierID is a user-selected tier to be used when auto detection is unavailable or fails.
|
||||||
|
// This field is optional; when omitted, the server uses the tier stored in the OAuth session.
|
||||||
|
TierID string `json:"tier_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeCode exchanges authorization code for tokens.
|
// ExchangeCode exchanges authorization code for tokens.
|
||||||
@@ -103,6 +109,7 @@ func (h *GeminiOAuthHandler) ExchangeCode(c *gin.Context) {
|
|||||||
Code: req.Code,
|
Code: req.Code,
|
||||||
ProxyID: req.ProxyID,
|
ProxyID: req.ProxyID,
|
||||||
OAuthType: oauthType,
|
OAuthType: oauthType,
|
||||||
|
TierID: req.TierID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Failed to exchange code: "+err.Error())
|
response.BadRequest(c, "Failed to exchange code: "+err.Error())
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ type CreateGroupRequest struct {
|
|||||||
DailyLimitUSD *float64 `json:"daily_limit_usd"`
|
DailyLimitUSD *float64 `json:"daily_limit_usd"`
|
||||||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
||||||
MonthlyLimitUSD *float64 `json:"monthly_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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupRequest represents update group request
|
// UpdateGroupRequest represents update group request
|
||||||
@@ -47,6 +51,10 @@ type UpdateGroupRequest struct {
|
|||||||
DailyLimitUSD *float64 `json:"daily_limit_usd"`
|
DailyLimitUSD *float64 `json:"daily_limit_usd"`
|
||||||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
||||||
MonthlyLimitUSD *float64 `json:"monthly_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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List handles listing all groups with pagination
|
// List handles listing all groups with pagination
|
||||||
@@ -139,6 +147,9 @@ func (h *GroupHandler) Create(c *gin.Context) {
|
|||||||
DailyLimitUSD: req.DailyLimitUSD,
|
DailyLimitUSD: req.DailyLimitUSD,
|
||||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||||
|
ImagePrice1K: req.ImagePrice1K,
|
||||||
|
ImagePrice2K: req.ImagePrice2K,
|
||||||
|
ImagePrice4K: req.ImagePrice4K,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
@@ -174,6 +185,9 @@ func (h *GroupHandler) Update(c *gin.Context) {
|
|||||||
DailyLimitUSD: req.DailyLimitUSD,
|
DailyLimitUSD: req.DailyLimitUSD,
|
||||||
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
WeeklyLimitUSD: req.WeeklyLimitUSD,
|
||||||
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
MonthlyLimitUSD: req.MonthlyLimitUSD,
|
||||||
|
ImagePrice1K: req.ImagePrice1K,
|
||||||
|
ImagePrice2K: req.ImagePrice2K,
|
||||||
|
ImagePrice4K: req.ImagePrice4K,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
@@ -237,9 +251,9 @@ func (h *GroupHandler) GetGroupAPIKeys(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outKeys := make([]dto.ApiKey, 0, len(keys))
|
outKeys := make([]dto.APIKey, 0, len(keys))
|
||||||
for i := range keys {
|
for i := range keys {
|
||||||
outKeys = append(outKeys, *dto.ApiKeyFromService(&keys[i]))
|
outKeys = append(outKeys, *dto.APIKeyFromService(&keys[i]))
|
||||||
}
|
}
|
||||||
response.Paginated(c, outKeys, total, page, pageSize)
|
response.Paginated(c, outKeys, total, page, pageSize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -34,26 +38,33 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, dto.SystemSettings{
|
response.Success(c, dto.SystemSettings{
|
||||||
RegistrationEnabled: settings.RegistrationEnabled,
|
RegistrationEnabled: settings.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
||||||
SmtpHost: settings.SmtpHost,
|
SMTPHost: settings.SMTPHost,
|
||||||
SmtpPort: settings.SmtpPort,
|
SMTPPort: settings.SMTPPort,
|
||||||
SmtpUsername: settings.SmtpUsername,
|
SMTPUsername: settings.SMTPUsername,
|
||||||
SmtpPassword: settings.SmtpPassword,
|
SMTPPasswordConfigured: settings.SMTPPasswordConfigured,
|
||||||
SmtpFrom: settings.SmtpFrom,
|
SMTPFrom: settings.SMTPFrom,
|
||||||
SmtpFromName: settings.SmtpFromName,
|
SMTPFromName: settings.SMTPFromName,
|
||||||
SmtpUseTLS: settings.SmtpUseTLS,
|
SMTPUseTLS: settings.SMTPUseTLS,
|
||||||
TurnstileEnabled: settings.TurnstileEnabled,
|
TurnstileEnabled: settings.TurnstileEnabled,
|
||||||
TurnstileSiteKey: settings.TurnstileSiteKey,
|
TurnstileSiteKey: settings.TurnstileSiteKey,
|
||||||
TurnstileSecretKey: settings.TurnstileSecretKey,
|
TurnstileSecretKeyConfigured: settings.TurnstileSecretKeyConfigured,
|
||||||
SiteName: settings.SiteName,
|
SiteName: settings.SiteName,
|
||||||
SiteLogo: settings.SiteLogo,
|
SiteLogo: settings.SiteLogo,
|
||||||
SiteSubtitle: settings.SiteSubtitle,
|
SiteSubtitle: settings.SiteSubtitle,
|
||||||
ApiBaseUrl: settings.ApiBaseUrl,
|
APIBaseURL: settings.APIBaseURL,
|
||||||
ContactInfo: settings.ContactInfo,
|
ContactInfo: settings.ContactInfo,
|
||||||
DocUrl: settings.DocUrl,
|
DocURL: settings.DocURL,
|
||||||
DefaultConcurrency: settings.DefaultConcurrency,
|
DefaultConcurrency: settings.DefaultConcurrency,
|
||||||
DefaultBalance: settings.DefaultBalance,
|
DefaultBalance: settings.DefaultBalance,
|
||||||
|
EnableModelFallback: settings.EnableModelFallback,
|
||||||
|
FallbackModelAnthropic: settings.FallbackModelAnthropic,
|
||||||
|
FallbackModelOpenAI: settings.FallbackModelOpenAI,
|
||||||
|
FallbackModelGemini: settings.FallbackModelGemini,
|
||||||
|
FallbackModelAntigravity: settings.FallbackModelAntigravity,
|
||||||
|
EnableIdentityPatch: settings.EnableIdentityPatch,
|
||||||
|
IdentityPatchPrompt: settings.IdentityPatchPrompt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,13 +75,13 @@ type UpdateSettingsRequest struct {
|
|||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
|
||||||
// 邮件服务设置
|
// 邮件服务设置
|
||||||
SmtpHost string `json:"smtp_host"`
|
SMTPHost string `json:"smtp_host"`
|
||||||
SmtpPort int `json:"smtp_port"`
|
SMTPPort int `json:"smtp_port"`
|
||||||
SmtpUsername string `json:"smtp_username"`
|
SMTPUsername string `json:"smtp_username"`
|
||||||
SmtpPassword string `json:"smtp_password"`
|
SMTPPassword string `json:"smtp_password"`
|
||||||
SmtpFrom string `json:"smtp_from_email"`
|
SMTPFrom string `json:"smtp_from_email"`
|
||||||
SmtpFromName string `json:"smtp_from_name"`
|
SMTPFromName string `json:"smtp_from_name"`
|
||||||
SmtpUseTLS bool `json:"smtp_use_tls"`
|
SMTPUseTLS bool `json:"smtp_use_tls"`
|
||||||
|
|
||||||
// Cloudflare Turnstile 设置
|
// Cloudflare Turnstile 设置
|
||||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||||
@@ -81,13 +92,24 @@ type UpdateSettingsRequest struct {
|
|||||||
SiteName string `json:"site_name"`
|
SiteName string `json:"site_name"`
|
||||||
SiteLogo string `json:"site_logo"`
|
SiteLogo string `json:"site_logo"`
|
||||||
SiteSubtitle string `json:"site_subtitle"`
|
SiteSubtitle string `json:"site_subtitle"`
|
||||||
ApiBaseUrl string `json:"api_base_url"`
|
APIBaseURL string `json:"api_base_url"`
|
||||||
ContactInfo string `json:"contact_info"`
|
ContactInfo string `json:"contact_info"`
|
||||||
DocUrl string `json:"doc_url"`
|
DocURL string `json:"doc_url"`
|
||||||
|
|
||||||
// 默认配置
|
// 默认配置
|
||||||
DefaultConcurrency int `json:"default_concurrency"`
|
DefaultConcurrency int `json:"default_concurrency"`
|
||||||
DefaultBalance float64 `json:"default_balance"`
|
DefaultBalance float64 `json:"default_balance"`
|
||||||
|
|
||||||
|
// Model fallback configuration
|
||||||
|
EnableModelFallback bool `json:"enable_model_fallback"`
|
||||||
|
FallbackModelAnthropic string `json:"fallback_model_anthropic"`
|
||||||
|
FallbackModelOpenAI string `json:"fallback_model_openai"`
|
||||||
|
FallbackModelGemini string `json:"fallback_model_gemini"`
|
||||||
|
FallbackModelAntigravity string `json:"fallback_model_antigravity"`
|
||||||
|
|
||||||
|
// Identity patch configuration (Claude -> Gemini)
|
||||||
|
EnableIdentityPatch bool `json:"enable_identity_patch"`
|
||||||
|
IdentityPatchPrompt string `json:"identity_patch_prompt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSettings 更新系统设置
|
// UpdateSettings 更新系统设置
|
||||||
@@ -99,6 +121,12 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousSettings, err := h.settingService.GetAllSettings(c.Request.Context())
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorFrom(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 验证参数
|
// 验证参数
|
||||||
if req.DefaultConcurrency < 1 {
|
if req.DefaultConcurrency < 1 {
|
||||||
req.DefaultConcurrency = 1
|
req.DefaultConcurrency = 1
|
||||||
@@ -106,8 +134,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
if req.DefaultBalance < 0 {
|
if req.DefaultBalance < 0 {
|
||||||
req.DefaultBalance = 0
|
req.DefaultBalance = 0
|
||||||
}
|
}
|
||||||
if req.SmtpPort <= 0 {
|
if req.SMTPPort <= 0 {
|
||||||
req.SmtpPort = 587
|
req.SMTPPort = 587
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turnstile 参数验证
|
// Turnstile 参数验证
|
||||||
@@ -117,21 +145,18 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
response.BadRequest(c, "Turnstile Site Key is required when enabled")
|
response.BadRequest(c, "Turnstile Site Key is required when enabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 如果未提供 secret key,使用已保存的值(留空保留当前值)
|
||||||
if req.TurnstileSecretKey == "" {
|
if req.TurnstileSecretKey == "" {
|
||||||
response.BadRequest(c, "Turnstile Secret Key is required when enabled")
|
if previousSettings.TurnstileSecretKey == "" {
|
||||||
return
|
response.BadRequest(c, "Turnstile Secret Key is required when enabled")
|
||||||
}
|
return
|
||||||
|
}
|
||||||
// 获取当前设置,检查参数是否有变化
|
req.TurnstileSecretKey = previousSettings.TurnstileSecretKey
|
||||||
currentSettings, err := h.settingService.GetAllSettings(c.Request.Context())
|
|
||||||
if err != nil {
|
|
||||||
response.ErrorFrom(c, err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当 site_key 或 secret_key 任一变化时验证(避免配置错误导致无法登录)
|
// 当 site_key 或 secret_key 任一变化时验证(避免配置错误导致无法登录)
|
||||||
siteKeyChanged := currentSettings.TurnstileSiteKey != req.TurnstileSiteKey
|
siteKeyChanged := previousSettings.TurnstileSiteKey != req.TurnstileSiteKey
|
||||||
secretKeyChanged := currentSettings.TurnstileSecretKey != req.TurnstileSecretKey
|
secretKeyChanged := previousSettings.TurnstileSecretKey != req.TurnstileSecretKey
|
||||||
if siteKeyChanged || secretKeyChanged {
|
if siteKeyChanged || secretKeyChanged {
|
||||||
if err := h.turnstileService.ValidateSecretKey(c.Request.Context(), req.TurnstileSecretKey); err != nil {
|
if err := h.turnstileService.ValidateSecretKey(c.Request.Context(), req.TurnstileSecretKey); err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
@@ -141,26 +166,33 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
settings := &service.SystemSettings{
|
settings := &service.SystemSettings{
|
||||||
RegistrationEnabled: req.RegistrationEnabled,
|
RegistrationEnabled: req.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
||||||
SmtpHost: req.SmtpHost,
|
SMTPHost: req.SMTPHost,
|
||||||
SmtpPort: req.SmtpPort,
|
SMTPPort: req.SMTPPort,
|
||||||
SmtpUsername: req.SmtpUsername,
|
SMTPUsername: req.SMTPUsername,
|
||||||
SmtpPassword: req.SmtpPassword,
|
SMTPPassword: req.SMTPPassword,
|
||||||
SmtpFrom: req.SmtpFrom,
|
SMTPFrom: req.SMTPFrom,
|
||||||
SmtpFromName: req.SmtpFromName,
|
SMTPFromName: req.SMTPFromName,
|
||||||
SmtpUseTLS: req.SmtpUseTLS,
|
SMTPUseTLS: req.SMTPUseTLS,
|
||||||
TurnstileEnabled: req.TurnstileEnabled,
|
TurnstileEnabled: req.TurnstileEnabled,
|
||||||
TurnstileSiteKey: req.TurnstileSiteKey,
|
TurnstileSiteKey: req.TurnstileSiteKey,
|
||||||
TurnstileSecretKey: req.TurnstileSecretKey,
|
TurnstileSecretKey: req.TurnstileSecretKey,
|
||||||
SiteName: req.SiteName,
|
SiteName: req.SiteName,
|
||||||
SiteLogo: req.SiteLogo,
|
SiteLogo: req.SiteLogo,
|
||||||
SiteSubtitle: req.SiteSubtitle,
|
SiteSubtitle: req.SiteSubtitle,
|
||||||
ApiBaseUrl: req.ApiBaseUrl,
|
APIBaseURL: req.APIBaseURL,
|
||||||
ContactInfo: req.ContactInfo,
|
ContactInfo: req.ContactInfo,
|
||||||
DocUrl: req.DocUrl,
|
DocURL: req.DocURL,
|
||||||
DefaultConcurrency: req.DefaultConcurrency,
|
DefaultConcurrency: req.DefaultConcurrency,
|
||||||
DefaultBalance: req.DefaultBalance,
|
DefaultBalance: req.DefaultBalance,
|
||||||
|
EnableModelFallback: req.EnableModelFallback,
|
||||||
|
FallbackModelAnthropic: req.FallbackModelAnthropic,
|
||||||
|
FallbackModelOpenAI: req.FallbackModelOpenAI,
|
||||||
|
FallbackModelGemini: req.FallbackModelGemini,
|
||||||
|
FallbackModelAntigravity: req.FallbackModelAntigravity,
|
||||||
|
EnableIdentityPatch: req.EnableIdentityPatch,
|
||||||
|
IdentityPatchPrompt: req.IdentityPatchPrompt,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.settingService.UpdateSettings(c.Request.Context(), settings); err != nil {
|
if err := h.settingService.UpdateSettings(c.Request.Context(), settings); err != nil {
|
||||||
@@ -168,6 +200,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.auditSettingsUpdate(c, previousSettings, settings, req)
|
||||||
|
|
||||||
// 重新获取设置返回
|
// 重新获取设置返回
|
||||||
updatedSettings, err := h.settingService.GetAllSettings(c.Request.Context())
|
updatedSettings, err := h.settingService.GetAllSettings(c.Request.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -176,69 +210,176 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, dto.SystemSettings{
|
response.Success(c, dto.SystemSettings{
|
||||||
RegistrationEnabled: updatedSettings.RegistrationEnabled,
|
RegistrationEnabled: updatedSettings.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
|
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
|
||||||
SmtpHost: updatedSettings.SmtpHost,
|
SMTPHost: updatedSettings.SMTPHost,
|
||||||
SmtpPort: updatedSettings.SmtpPort,
|
SMTPPort: updatedSettings.SMTPPort,
|
||||||
SmtpUsername: updatedSettings.SmtpUsername,
|
SMTPUsername: updatedSettings.SMTPUsername,
|
||||||
SmtpPassword: updatedSettings.SmtpPassword,
|
SMTPPasswordConfigured: updatedSettings.SMTPPasswordConfigured,
|
||||||
SmtpFrom: updatedSettings.SmtpFrom,
|
SMTPFrom: updatedSettings.SMTPFrom,
|
||||||
SmtpFromName: updatedSettings.SmtpFromName,
|
SMTPFromName: updatedSettings.SMTPFromName,
|
||||||
SmtpUseTLS: updatedSettings.SmtpUseTLS,
|
SMTPUseTLS: updatedSettings.SMTPUseTLS,
|
||||||
TurnstileEnabled: updatedSettings.TurnstileEnabled,
|
TurnstileEnabled: updatedSettings.TurnstileEnabled,
|
||||||
TurnstileSiteKey: updatedSettings.TurnstileSiteKey,
|
TurnstileSiteKey: updatedSettings.TurnstileSiteKey,
|
||||||
TurnstileSecretKey: updatedSettings.TurnstileSecretKey,
|
TurnstileSecretKeyConfigured: updatedSettings.TurnstileSecretKeyConfigured,
|
||||||
SiteName: updatedSettings.SiteName,
|
SiteName: updatedSettings.SiteName,
|
||||||
SiteLogo: updatedSettings.SiteLogo,
|
SiteLogo: updatedSettings.SiteLogo,
|
||||||
SiteSubtitle: updatedSettings.SiteSubtitle,
|
SiteSubtitle: updatedSettings.SiteSubtitle,
|
||||||
ApiBaseUrl: updatedSettings.ApiBaseUrl,
|
APIBaseURL: updatedSettings.APIBaseURL,
|
||||||
ContactInfo: updatedSettings.ContactInfo,
|
ContactInfo: updatedSettings.ContactInfo,
|
||||||
DocUrl: updatedSettings.DocUrl,
|
DocURL: updatedSettings.DocURL,
|
||||||
DefaultConcurrency: updatedSettings.DefaultConcurrency,
|
DefaultConcurrency: updatedSettings.DefaultConcurrency,
|
||||||
DefaultBalance: updatedSettings.DefaultBalance,
|
DefaultBalance: updatedSettings.DefaultBalance,
|
||||||
|
EnableModelFallback: updatedSettings.EnableModelFallback,
|
||||||
|
FallbackModelAnthropic: updatedSettings.FallbackModelAnthropic,
|
||||||
|
FallbackModelOpenAI: updatedSettings.FallbackModelOpenAI,
|
||||||
|
FallbackModelGemini: updatedSettings.FallbackModelGemini,
|
||||||
|
FallbackModelAntigravity: updatedSettings.FallbackModelAntigravity,
|
||||||
|
EnableIdentityPatch: updatedSettings.EnableIdentityPatch,
|
||||||
|
IdentityPatchPrompt: updatedSettings.IdentityPatchPrompt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSmtpRequest 测试SMTP连接请求
|
func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) {
|
||||||
type TestSmtpRequest struct {
|
if before == nil || after == nil {
|
||||||
SmtpHost string `json:"smtp_host" binding:"required"`
|
return
|
||||||
SmtpPort int `json:"smtp_port"`
|
}
|
||||||
SmtpUsername string `json:"smtp_username"`
|
|
||||||
SmtpPassword string `json:"smtp_password"`
|
changed := diffSettings(before, after, req)
|
||||||
SmtpUseTLS bool `json:"smtp_use_tls"`
|
if len(changed) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subject, _ := middleware.GetAuthSubjectFromContext(c)
|
||||||
|
role, _ := middleware.GetUserRoleFromContext(c)
|
||||||
|
log.Printf("AUDIT: settings updated at=%s user_id=%d role=%s changed=%v",
|
||||||
|
time.Now().UTC().Format(time.RFC3339),
|
||||||
|
subject.UserID,
|
||||||
|
role,
|
||||||
|
changed,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSmtpConnection 测试SMTP连接
|
func diffSettings(before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) []string {
|
||||||
|
changed := make([]string, 0, 20)
|
||||||
|
if before.RegistrationEnabled != after.RegistrationEnabled {
|
||||||
|
changed = append(changed, "registration_enabled")
|
||||||
|
}
|
||||||
|
if before.EmailVerifyEnabled != after.EmailVerifyEnabled {
|
||||||
|
changed = append(changed, "email_verify_enabled")
|
||||||
|
}
|
||||||
|
if before.SMTPHost != after.SMTPHost {
|
||||||
|
changed = append(changed, "smtp_host")
|
||||||
|
}
|
||||||
|
if before.SMTPPort != after.SMTPPort {
|
||||||
|
changed = append(changed, "smtp_port")
|
||||||
|
}
|
||||||
|
if before.SMTPUsername != after.SMTPUsername {
|
||||||
|
changed = append(changed, "smtp_username")
|
||||||
|
}
|
||||||
|
if req.SMTPPassword != "" {
|
||||||
|
changed = append(changed, "smtp_password")
|
||||||
|
}
|
||||||
|
if before.SMTPFrom != after.SMTPFrom {
|
||||||
|
changed = append(changed, "smtp_from_email")
|
||||||
|
}
|
||||||
|
if before.SMTPFromName != after.SMTPFromName {
|
||||||
|
changed = append(changed, "smtp_from_name")
|
||||||
|
}
|
||||||
|
if before.SMTPUseTLS != after.SMTPUseTLS {
|
||||||
|
changed = append(changed, "smtp_use_tls")
|
||||||
|
}
|
||||||
|
if before.TurnstileEnabled != after.TurnstileEnabled {
|
||||||
|
changed = append(changed, "turnstile_enabled")
|
||||||
|
}
|
||||||
|
if before.TurnstileSiteKey != after.TurnstileSiteKey {
|
||||||
|
changed = append(changed, "turnstile_site_key")
|
||||||
|
}
|
||||||
|
if req.TurnstileSecretKey != "" {
|
||||||
|
changed = append(changed, "turnstile_secret_key")
|
||||||
|
}
|
||||||
|
if before.SiteName != after.SiteName {
|
||||||
|
changed = append(changed, "site_name")
|
||||||
|
}
|
||||||
|
if before.SiteLogo != after.SiteLogo {
|
||||||
|
changed = append(changed, "site_logo")
|
||||||
|
}
|
||||||
|
if before.SiteSubtitle != after.SiteSubtitle {
|
||||||
|
changed = append(changed, "site_subtitle")
|
||||||
|
}
|
||||||
|
if before.APIBaseURL != after.APIBaseURL {
|
||||||
|
changed = append(changed, "api_base_url")
|
||||||
|
}
|
||||||
|
if before.ContactInfo != after.ContactInfo {
|
||||||
|
changed = append(changed, "contact_info")
|
||||||
|
}
|
||||||
|
if before.DocURL != after.DocURL {
|
||||||
|
changed = append(changed, "doc_url")
|
||||||
|
}
|
||||||
|
if before.DefaultConcurrency != after.DefaultConcurrency {
|
||||||
|
changed = append(changed, "default_concurrency")
|
||||||
|
}
|
||||||
|
if before.DefaultBalance != after.DefaultBalance {
|
||||||
|
changed = append(changed, "default_balance")
|
||||||
|
}
|
||||||
|
if before.EnableModelFallback != after.EnableModelFallback {
|
||||||
|
changed = append(changed, "enable_model_fallback")
|
||||||
|
}
|
||||||
|
if before.FallbackModelAnthropic != after.FallbackModelAnthropic {
|
||||||
|
changed = append(changed, "fallback_model_anthropic")
|
||||||
|
}
|
||||||
|
if before.FallbackModelOpenAI != after.FallbackModelOpenAI {
|
||||||
|
changed = append(changed, "fallback_model_openai")
|
||||||
|
}
|
||||||
|
if before.FallbackModelGemini != after.FallbackModelGemini {
|
||||||
|
changed = append(changed, "fallback_model_gemini")
|
||||||
|
}
|
||||||
|
if before.FallbackModelAntigravity != after.FallbackModelAntigravity {
|
||||||
|
changed = append(changed, "fallback_model_antigravity")
|
||||||
|
}
|
||||||
|
return changed
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSMTPRequest 测试SMTP连接请求
|
||||||
|
type TestSMTPRequest struct {
|
||||||
|
SMTPHost string `json:"smtp_host" binding:"required"`
|
||||||
|
SMTPPort int `json:"smtp_port"`
|
||||||
|
SMTPUsername string `json:"smtp_username"`
|
||||||
|
SMTPPassword string `json:"smtp_password"`
|
||||||
|
SMTPUseTLS bool `json:"smtp_use_tls"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSMTPConnection 测试SMTP连接
|
||||||
// POST /api/v1/admin/settings/test-smtp
|
// POST /api/v1/admin/settings/test-smtp
|
||||||
func (h *SettingHandler) TestSmtpConnection(c *gin.Context) {
|
func (h *SettingHandler) TestSMTPConnection(c *gin.Context) {
|
||||||
var req TestSmtpRequest
|
var req TestSMTPRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.SmtpPort <= 0 {
|
if req.SMTPPort <= 0 {
|
||||||
req.SmtpPort = 587
|
req.SMTPPort = 587
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果未提供密码,从数据库获取已保存的密码
|
// 如果未提供密码,从数据库获取已保存的密码
|
||||||
password := req.SmtpPassword
|
password := req.SMTPPassword
|
||||||
if password == "" {
|
if password == "" {
|
||||||
savedConfig, err := h.emailService.GetSmtpConfig(c.Request.Context())
|
savedConfig, err := h.emailService.GetSMTPConfig(c.Request.Context())
|
||||||
if err == nil && savedConfig != nil {
|
if err == nil && savedConfig != nil {
|
||||||
password = savedConfig.Password
|
password = savedConfig.Password
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &service.SmtpConfig{
|
config := &service.SMTPConfig{
|
||||||
Host: req.SmtpHost,
|
Host: req.SMTPHost,
|
||||||
Port: req.SmtpPort,
|
Port: req.SMTPPort,
|
||||||
Username: req.SmtpUsername,
|
Username: req.SMTPUsername,
|
||||||
Password: password,
|
Password: password,
|
||||||
UseTLS: req.SmtpUseTLS,
|
UseTLS: req.SMTPUseTLS,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := h.emailService.TestSmtpConnectionWithConfig(config)
|
err := h.emailService.TestSMTPConnectionWithConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
@@ -250,13 +391,13 @@ func (h *SettingHandler) TestSmtpConnection(c *gin.Context) {
|
|||||||
// SendTestEmailRequest 发送测试邮件请求
|
// SendTestEmailRequest 发送测试邮件请求
|
||||||
type SendTestEmailRequest struct {
|
type SendTestEmailRequest struct {
|
||||||
Email string `json:"email" binding:"required,email"`
|
Email string `json:"email" binding:"required,email"`
|
||||||
SmtpHost string `json:"smtp_host" binding:"required"`
|
SMTPHost string `json:"smtp_host" binding:"required"`
|
||||||
SmtpPort int `json:"smtp_port"`
|
SMTPPort int `json:"smtp_port"`
|
||||||
SmtpUsername string `json:"smtp_username"`
|
SMTPUsername string `json:"smtp_username"`
|
||||||
SmtpPassword string `json:"smtp_password"`
|
SMTPPassword string `json:"smtp_password"`
|
||||||
SmtpFrom string `json:"smtp_from_email"`
|
SMTPFrom string `json:"smtp_from_email"`
|
||||||
SmtpFromName string `json:"smtp_from_name"`
|
SMTPFromName string `json:"smtp_from_name"`
|
||||||
SmtpUseTLS bool `json:"smtp_use_tls"`
|
SMTPUseTLS bool `json:"smtp_use_tls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTestEmail 发送测试邮件
|
// SendTestEmail 发送测试邮件
|
||||||
@@ -268,27 +409,27 @@ func (h *SettingHandler) SendTestEmail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.SmtpPort <= 0 {
|
if req.SMTPPort <= 0 {
|
||||||
req.SmtpPort = 587
|
req.SMTPPort = 587
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果未提供密码,从数据库获取已保存的密码
|
// 如果未提供密码,从数据库获取已保存的密码
|
||||||
password := req.SmtpPassword
|
password := req.SMTPPassword
|
||||||
if password == "" {
|
if password == "" {
|
||||||
savedConfig, err := h.emailService.GetSmtpConfig(c.Request.Context())
|
savedConfig, err := h.emailService.GetSMTPConfig(c.Request.Context())
|
||||||
if err == nil && savedConfig != nil {
|
if err == nil && savedConfig != nil {
|
||||||
password = savedConfig.Password
|
password = savedConfig.Password
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &service.SmtpConfig{
|
config := &service.SMTPConfig{
|
||||||
Host: req.SmtpHost,
|
Host: req.SMTPHost,
|
||||||
Port: req.SmtpPort,
|
Port: req.SMTPPort,
|
||||||
Username: req.SmtpUsername,
|
Username: req.SMTPUsername,
|
||||||
Password: password,
|
Password: password,
|
||||||
From: req.SmtpFrom,
|
From: req.SMTPFrom,
|
||||||
FromName: req.SmtpFromName,
|
FromName: req.SMTPFromName,
|
||||||
UseTLS: req.SmtpUseTLS,
|
UseTLS: req.SMTPUseTLS,
|
||||||
}
|
}
|
||||||
|
|
||||||
siteName := h.settingService.GetSiteName(c.Request.Context())
|
siteName := h.settingService.GetSiteName(c.Request.Context())
|
||||||
@@ -333,10 +474,10 @@ func (h *SettingHandler) SendTestEmail(c *gin.Context) {
|
|||||||
response.Success(c, gin.H{"message": "Test email sent successfully"})
|
response.Success(c, gin.H{"message": "Test email sent successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAdminApiKey 获取管理员 API Key 状态
|
// GetAdminAPIKey 获取管理员 API Key 状态
|
||||||
// GET /api/v1/admin/settings/admin-api-key
|
// GET /api/v1/admin/settings/admin-api-key
|
||||||
func (h *SettingHandler) GetAdminApiKey(c *gin.Context) {
|
func (h *SettingHandler) GetAdminAPIKey(c *gin.Context) {
|
||||||
maskedKey, exists, err := h.settingService.GetAdminApiKeyStatus(c.Request.Context())
|
maskedKey, exists, err := h.settingService.GetAdminAPIKeyStatus(c.Request.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
@@ -348,10 +489,10 @@ func (h *SettingHandler) GetAdminApiKey(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegenerateAdminApiKey 生成/重新生成管理员 API Key
|
// RegenerateAdminAPIKey 生成/重新生成管理员 API Key
|
||||||
// POST /api/v1/admin/settings/admin-api-key/regenerate
|
// POST /api/v1/admin/settings/admin-api-key/regenerate
|
||||||
func (h *SettingHandler) RegenerateAdminApiKey(c *gin.Context) {
|
func (h *SettingHandler) RegenerateAdminAPIKey(c *gin.Context) {
|
||||||
key, err := h.settingService.GenerateAdminApiKey(c.Request.Context())
|
key, err := h.settingService.GenerateAdminAPIKey(c.Request.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
@@ -362,10 +503,10 @@ func (h *SettingHandler) RegenerateAdminApiKey(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAdminApiKey 删除管理员 API Key
|
// DeleteAdminAPIKey 删除管理员 API Key
|
||||||
// DELETE /api/v1/admin/settings/admin-api-key
|
// DELETE /api/v1/admin/settings/admin-api-key
|
||||||
func (h *SettingHandler) DeleteAdminApiKey(c *gin.Context) {
|
func (h *SettingHandler) DeleteAdminAPIKey(c *gin.Context) {
|
||||||
if err := h.settingService.DeleteAdminApiKey(c.Request.Context()); err != nil {
|
if err := h.settingService.DeleteAdminAPIKey(c.Request.Context()); err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ import (
|
|||||||
// UsageHandler handles admin usage-related requests
|
// UsageHandler handles admin usage-related requests
|
||||||
type UsageHandler struct {
|
type UsageHandler struct {
|
||||||
usageService *service.UsageService
|
usageService *service.UsageService
|
||||||
apiKeyService *service.ApiKeyService
|
apiKeyService *service.APIKeyService
|
||||||
adminService service.AdminService
|
adminService service.AdminService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUsageHandler creates a new admin usage handler
|
// NewUsageHandler creates a new admin usage handler
|
||||||
func NewUsageHandler(
|
func NewUsageHandler(
|
||||||
usageService *service.UsageService,
|
usageService *service.UsageService,
|
||||||
apiKeyService *service.ApiKeyService,
|
apiKeyService *service.APIKeyService,
|
||||||
adminService service.AdminService,
|
adminService service.AdminService,
|
||||||
) *UsageHandler {
|
) *UsageHandler {
|
||||||
return &UsageHandler{
|
return &UsageHandler{
|
||||||
@@ -102,8 +102,9 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
|
|
||||||
// Parse date range
|
// Parse date range
|
||||||
var startTime, endTime *time.Time
|
var startTime, endTime *time.Time
|
||||||
|
userTZ := c.Query("timezone") // Get user's timezone from request
|
||||||
if startDateStr := c.Query("start_date"); startDateStr != "" {
|
if startDateStr := c.Query("start_date"); startDateStr != "" {
|
||||||
t, err := timezone.ParseInLocation("2006-01-02", startDateStr)
|
t, err := timezone.ParseInUserLocation("2006-01-02", startDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -112,7 +113,7 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if endDateStr := c.Query("end_date"); endDateStr != "" {
|
if endDateStr := c.Query("end_date"); endDateStr != "" {
|
||||||
t, err := timezone.ParseInLocation("2006-01-02", endDateStr)
|
t, err := timezone.ParseInUserLocation("2006-01-02", endDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -125,7 +126,7 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
|
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
|
||||||
filters := usagestats.UsageLogFilters{
|
filters := usagestats.UsageLogFilters{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
ApiKeyID: apiKeyID,
|
APIKeyID: apiKeyID,
|
||||||
AccountID: accountID,
|
AccountID: accountID,
|
||||||
GroupID: groupID,
|
GroupID: groupID,
|
||||||
Model: model,
|
Model: model,
|
||||||
@@ -143,7 +144,7 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
|
|
||||||
out := make([]dto.UsageLog, 0, len(records))
|
out := make([]dto.UsageLog, 0, len(records))
|
||||||
for i := range records {
|
for i := range records {
|
||||||
out = append(out, *dto.UsageLogFromService(&records[i]))
|
out = append(out, *dto.UsageLogFromServiceAdmin(&records[i]))
|
||||||
}
|
}
|
||||||
response.Paginated(c, out, result.Total, page, pageSize)
|
response.Paginated(c, out, result.Total, page, pageSize)
|
||||||
}
|
}
|
||||||
@@ -151,8 +152,8 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
// Stats handles getting usage statistics with filters
|
// Stats handles getting usage statistics with filters
|
||||||
// GET /api/v1/admin/usage/stats
|
// GET /api/v1/admin/usage/stats
|
||||||
func (h *UsageHandler) Stats(c *gin.Context) {
|
func (h *UsageHandler) Stats(c *gin.Context) {
|
||||||
// Parse filters
|
// Parse filters - same as List endpoint
|
||||||
var userID, apiKeyID int64
|
var userID, apiKeyID, accountID, groupID int64
|
||||||
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
||||||
id, err := strconv.ParseInt(userIDStr, 10, 64)
|
id, err := strconv.ParseInt(userIDStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -171,8 +172,50 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
apiKeyID = id
|
apiKeyID = id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if accountIDStr := c.Query("account_id"); accountIDStr != "" {
|
||||||
|
id, err := strconv.ParseInt(accountIDStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid account_id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
accountID = id
|
||||||
|
}
|
||||||
|
|
||||||
|
if groupIDStr := c.Query("group_id"); groupIDStr != "" {
|
||||||
|
id, err := strconv.ParseInt(groupIDStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid group_id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
groupID = id
|
||||||
|
}
|
||||||
|
|
||||||
|
model := c.Query("model")
|
||||||
|
|
||||||
|
var stream *bool
|
||||||
|
if streamStr := c.Query("stream"); streamStr != "" {
|
||||||
|
val, err := strconv.ParseBool(streamStr)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid stream value, use true or false")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stream = &val
|
||||||
|
}
|
||||||
|
|
||||||
|
var billingType *int8
|
||||||
|
if billingTypeStr := c.Query("billing_type"); billingTypeStr != "" {
|
||||||
|
val, err := strconv.ParseInt(billingTypeStr, 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid billing_type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bt := int8(val)
|
||||||
|
billingType = &bt
|
||||||
|
}
|
||||||
|
|
||||||
// Parse date range
|
// Parse date range
|
||||||
now := timezone.Now()
|
userTZ := c.Query("timezone")
|
||||||
|
now := timezone.NowInUserLocation(userTZ)
|
||||||
var startTime, endTime time.Time
|
var startTime, endTime time.Time
|
||||||
|
|
||||||
startDateStr := c.Query("start_date")
|
startDateStr := c.Query("start_date")
|
||||||
@@ -180,12 +223,12 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
|
|
||||||
if startDateStr != "" && endDateStr != "" {
|
if startDateStr != "" && endDateStr != "" {
|
||||||
var err error
|
var err error
|
||||||
startTime, err = timezone.ParseInLocation("2006-01-02", startDateStr)
|
startTime, err = timezone.ParseInUserLocation("2006-01-02", startDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
endTime, err = timezone.ParseInLocation("2006-01-02", endDateStr)
|
endTime, err = timezone.ParseInUserLocation("2006-01-02", endDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -195,39 +238,31 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
period := c.DefaultQuery("period", "today")
|
period := c.DefaultQuery("period", "today")
|
||||||
switch period {
|
switch period {
|
||||||
case "today":
|
case "today":
|
||||||
startTime = timezone.StartOfDay(now)
|
startTime = timezone.StartOfDayInUserLocation(now, userTZ)
|
||||||
case "week":
|
case "week":
|
||||||
startTime = now.AddDate(0, 0, -7)
|
startTime = now.AddDate(0, 0, -7)
|
||||||
case "month":
|
case "month":
|
||||||
startTime = now.AddDate(0, -1, 0)
|
startTime = now.AddDate(0, -1, 0)
|
||||||
default:
|
default:
|
||||||
startTime = timezone.StartOfDay(now)
|
startTime = timezone.StartOfDayInUserLocation(now, userTZ)
|
||||||
}
|
}
|
||||||
endTime = now
|
endTime = now
|
||||||
}
|
}
|
||||||
|
|
||||||
if apiKeyID > 0 {
|
// Build filters and call GetStatsWithFilters
|
||||||
stats, err := h.usageService.GetStatsByApiKey(c.Request.Context(), apiKeyID, startTime, endTime)
|
filters := usagestats.UsageLogFilters{
|
||||||
if err != nil {
|
UserID: userID,
|
||||||
response.ErrorFrom(c, err)
|
APIKeyID: apiKeyID,
|
||||||
return
|
AccountID: accountID,
|
||||||
}
|
GroupID: groupID,
|
||||||
response.Success(c, stats)
|
Model: model,
|
||||||
return
|
Stream: stream,
|
||||||
|
BillingType: billingType,
|
||||||
|
StartTime: &startTime,
|
||||||
|
EndTime: &endTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
if userID > 0 {
|
stats, err := h.usageService.GetStatsWithFilters(c.Request.Context(), filters)
|
||||||
stats, err := h.usageService.GetStatsByUser(c.Request.Context(), userID, startTime, endTime)
|
|
||||||
if err != nil {
|
|
||||||
response.ErrorFrom(c, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Success(c, stats)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get global stats
|
|
||||||
stats, err := h.usageService.GetGlobalStats(c.Request.Context(), startTime, endTime)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
@@ -269,9 +304,9 @@ func (h *UsageHandler) SearchUsers(c *gin.Context) {
|
|||||||
response.Success(c, result)
|
response.Success(c, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchApiKeys handles searching API keys by user
|
// SearchAPIKeys handles searching API keys by user
|
||||||
// GET /api/v1/admin/usage/search-api-keys
|
// GET /api/v1/admin/usage/search-api-keys
|
||||||
func (h *UsageHandler) SearchApiKeys(c *gin.Context) {
|
func (h *UsageHandler) SearchAPIKeys(c *gin.Context) {
|
||||||
userIDStr := c.Query("user_id")
|
userIDStr := c.Query("user_id")
|
||||||
keyword := c.Query("q")
|
keyword := c.Query("q")
|
||||||
|
|
||||||
@@ -285,22 +320,22 @@ func (h *UsageHandler) SearchApiKeys(c *gin.Context) {
|
|||||||
userID = id
|
userID = id
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, err := h.apiKeyService.SearchApiKeys(c.Request.Context(), userID, keyword, 30)
|
keys, err := h.apiKeyService.SearchAPIKeys(c.Request.Context(), userID, keyword, 30)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return simplified API key list (only id and name)
|
// Return simplified API key list (only id and name)
|
||||||
type SimpleApiKey struct {
|
type SimpleAPIKey struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]SimpleApiKey, len(keys))
|
result := make([]SimpleAPIKey, len(keys))
|
||||||
for i, k := range keys {
|
for i, k := range keys {
|
||||||
result[i] = SimpleApiKey{
|
result[i] = SimpleAPIKey{
|
||||||
ID: k.ID,
|
ID: k.ID,
|
||||||
Name: k.Name,
|
Name: k.Name,
|
||||||
UserID: k.UserID,
|
UserID: k.UserID,
|
||||||
|
|||||||
@@ -243,9 +243,9 @@ func (h *UserHandler) GetUserAPIKeys(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]dto.ApiKey, 0, len(keys))
|
out := make([]dto.APIKey, 0, len(keys))
|
||||||
for i := range keys {
|
for i := range keys {
|
||||||
out = append(out, *dto.ApiKeyFromService(&keys[i]))
|
out = append(out, *dto.APIKeyFromService(&keys[i]))
|
||||||
}
|
}
|
||||||
response.Paginated(c, out, total, page, pageSize)
|
response.Paginated(c, out, total, page, pageSize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package handler provides HTTP request handlers for the application.
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -14,11 +15,11 @@ import (
|
|||||||
|
|
||||||
// APIKeyHandler handles API key-related requests
|
// APIKeyHandler handles API key-related requests
|
||||||
type APIKeyHandler struct {
|
type APIKeyHandler struct {
|
||||||
apiKeyService *service.ApiKeyService
|
apiKeyService *service.APIKeyService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPIKeyHandler creates a new APIKeyHandler
|
// NewAPIKeyHandler creates a new APIKeyHandler
|
||||||
func NewAPIKeyHandler(apiKeyService *service.ApiKeyService) *APIKeyHandler {
|
func NewAPIKeyHandler(apiKeyService *service.APIKeyService) *APIKeyHandler {
|
||||||
return &APIKeyHandler{
|
return &APIKeyHandler{
|
||||||
apiKeyService: apiKeyService,
|
apiKeyService: apiKeyService,
|
||||||
}
|
}
|
||||||
@@ -56,9 +57,9 @@ func (h *APIKeyHandler) List(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]dto.ApiKey, 0, len(keys))
|
out := make([]dto.APIKey, 0, len(keys))
|
||||||
for i := range keys {
|
for i := range keys {
|
||||||
out = append(out, *dto.ApiKeyFromService(&keys[i]))
|
out = append(out, *dto.APIKeyFromService(&keys[i]))
|
||||||
}
|
}
|
||||||
response.Paginated(c, out, result.Total, page, pageSize)
|
response.Paginated(c, out, result.Total, page, pageSize)
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ func (h *APIKeyHandler) GetByID(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, dto.ApiKeyFromService(key))
|
response.Success(c, dto.APIKeyFromService(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create handles creating a new API key
|
// Create handles creating a new API key
|
||||||
@@ -108,7 +109,7 @@ func (h *APIKeyHandler) Create(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svcReq := service.CreateApiKeyRequest{
|
svcReq := service.CreateAPIKeyRequest{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
GroupID: req.GroupID,
|
GroupID: req.GroupID,
|
||||||
CustomKey: req.CustomKey,
|
CustomKey: req.CustomKey,
|
||||||
@@ -119,7 +120,7 @@ func (h *APIKeyHandler) Create(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, dto.ApiKeyFromService(key))
|
response.Success(c, dto.APIKeyFromService(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update handles updating an API key
|
// Update handles updating an API key
|
||||||
@@ -143,7 +144,7 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svcReq := service.UpdateApiKeyRequest{}
|
svcReq := service.UpdateAPIKeyRequest{}
|
||||||
if req.Name != "" {
|
if req.Name != "" {
|
||||||
svcReq.Name = &req.Name
|
svcReq.Name = &req.Name
|
||||||
}
|
}
|
||||||
@@ -158,7 +159,7 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, dto.ApiKeyFromService(key))
|
response.Success(c, dto.APIKeyFromService(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete handles deleting an API key
|
// Delete handles deleting an API key
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
// Package dto provides data transfer objects for HTTP handlers.
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
import "github.com/Wei-Shaw/sub2api/internal/service"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
|
)
|
||||||
|
|
||||||
func UserFromServiceShallow(u *service.User) *User {
|
func UserFromServiceShallow(u *service.User) *User {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
@@ -26,11 +31,11 @@ func UserFromService(u *service.User) *User {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := UserFromServiceShallow(u)
|
out := UserFromServiceShallow(u)
|
||||||
if len(u.ApiKeys) > 0 {
|
if len(u.APIKeys) > 0 {
|
||||||
out.ApiKeys = make([]ApiKey, 0, len(u.ApiKeys))
|
out.APIKeys = make([]APIKey, 0, len(u.APIKeys))
|
||||||
for i := range u.ApiKeys {
|
for i := range u.APIKeys {
|
||||||
k := u.ApiKeys[i]
|
k := u.APIKeys[i]
|
||||||
out.ApiKeys = append(out.ApiKeys, *ApiKeyFromService(&k))
|
out.APIKeys = append(out.APIKeys, *APIKeyFromService(&k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(u.Subscriptions) > 0 {
|
if len(u.Subscriptions) > 0 {
|
||||||
@@ -43,11 +48,11 @@ func UserFromService(u *service.User) *User {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApiKeyFromService(k *service.ApiKey) *ApiKey {
|
func APIKeyFromService(k *service.APIKey) *APIKey {
|
||||||
if k == nil {
|
if k == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &ApiKey{
|
return &APIKey{
|
||||||
ID: k.ID,
|
ID: k.ID,
|
||||||
UserID: k.UserID,
|
UserID: k.UserID,
|
||||||
Key: k.Key,
|
Key: k.Key,
|
||||||
@@ -77,6 +82,9 @@ func GroupFromServiceShallow(g *service.Group) *Group {
|
|||||||
DailyLimitUSD: g.DailyLimitUSD,
|
DailyLimitUSD: g.DailyLimitUSD,
|
||||||
WeeklyLimitUSD: g.WeeklyLimitUSD,
|
WeeklyLimitUSD: g.WeeklyLimitUSD,
|
||||||
MonthlyLimitUSD: g.MonthlyLimitUSD,
|
MonthlyLimitUSD: g.MonthlyLimitUSD,
|
||||||
|
ImagePrice1K: g.ImagePrice1K,
|
||||||
|
ImagePrice2K: g.ImagePrice2K,
|
||||||
|
ImagePrice4K: g.ImagePrice4K,
|
||||||
CreatedAt: g.CreatedAt,
|
CreatedAt: g.CreatedAt,
|
||||||
UpdatedAt: g.UpdatedAt,
|
UpdatedAt: g.UpdatedAt,
|
||||||
AccountCount: g.AccountCount,
|
AccountCount: g.AccountCount,
|
||||||
@@ -103,28 +111,33 @@ func AccountFromServiceShallow(a *service.Account) *Account {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &Account{
|
return &Account{
|
||||||
ID: a.ID,
|
ID: a.ID,
|
||||||
Name: a.Name,
|
Name: a.Name,
|
||||||
Platform: a.Platform,
|
Notes: a.Notes,
|
||||||
Type: a.Type,
|
Platform: a.Platform,
|
||||||
Credentials: a.Credentials,
|
Type: a.Type,
|
||||||
Extra: a.Extra,
|
Credentials: a.Credentials,
|
||||||
ProxyID: a.ProxyID,
|
Extra: a.Extra,
|
||||||
Concurrency: a.Concurrency,
|
ProxyID: a.ProxyID,
|
||||||
Priority: a.Priority,
|
Concurrency: a.Concurrency,
|
||||||
Status: a.Status,
|
Priority: a.Priority,
|
||||||
ErrorMessage: a.ErrorMessage,
|
Status: a.Status,
|
||||||
LastUsedAt: a.LastUsedAt,
|
ErrorMessage: a.ErrorMessage,
|
||||||
CreatedAt: a.CreatedAt,
|
LastUsedAt: a.LastUsedAt,
|
||||||
UpdatedAt: a.UpdatedAt,
|
ExpiresAt: timeToUnixSeconds(a.ExpiresAt),
|
||||||
Schedulable: a.Schedulable,
|
AutoPauseOnExpired: a.AutoPauseOnExpired,
|
||||||
RateLimitedAt: a.RateLimitedAt,
|
CreatedAt: a.CreatedAt,
|
||||||
RateLimitResetAt: a.RateLimitResetAt,
|
UpdatedAt: a.UpdatedAt,
|
||||||
OverloadUntil: a.OverloadUntil,
|
Schedulable: a.Schedulable,
|
||||||
SessionWindowStart: a.SessionWindowStart,
|
RateLimitedAt: a.RateLimitedAt,
|
||||||
SessionWindowEnd: a.SessionWindowEnd,
|
RateLimitResetAt: a.RateLimitResetAt,
|
||||||
SessionWindowStatus: a.SessionWindowStatus,
|
OverloadUntil: a.OverloadUntil,
|
||||||
GroupIDs: a.GroupIDs,
|
TempUnschedulableUntil: a.TempUnschedulableUntil,
|
||||||
|
TempUnschedulableReason: a.TempUnschedulableReason,
|
||||||
|
SessionWindowStart: a.SessionWindowStart,
|
||||||
|
SessionWindowEnd: a.SessionWindowEnd,
|
||||||
|
SessionWindowStatus: a.SessionWindowStatus,
|
||||||
|
GroupIDs: a.GroupIDs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +163,14 @@ func AccountFromService(a *service.Account) *Account {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func timeToUnixSeconds(value *time.Time) *int64 {
|
||||||
|
if value == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ts := value.Unix()
|
||||||
|
return &ts
|
||||||
|
}
|
||||||
|
|
||||||
func AccountGroupFromService(ag *service.AccountGroup) *AccountGroup {
|
func AccountGroupFromService(ag *service.AccountGroup) *AccountGroup {
|
||||||
if ag == nil {
|
if ag == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -213,14 +234,28 @@ func RedeemCodeFromService(rc *service.RedeemCode) *RedeemCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UsageLogFromService(l *service.UsageLog) *UsageLog {
|
// AccountSummaryFromService returns a minimal AccountSummary for usage log display.
|
||||||
|
// Only includes ID and Name - no sensitive fields like Credentials, Proxy, etc.
|
||||||
|
func AccountSummaryFromService(a *service.Account) *AccountSummary {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &AccountSummary{
|
||||||
|
ID: a.ID,
|
||||||
|
Name: a.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// usageLogFromServiceBase is a helper that converts service UsageLog to DTO.
|
||||||
|
// The account parameter allows caller to control what Account info is included.
|
||||||
|
func usageLogFromServiceBase(l *service.UsageLog, account *AccountSummary) *UsageLog {
|
||||||
if l == nil {
|
if l == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &UsageLog{
|
return &UsageLog{
|
||||||
ID: l.ID,
|
ID: l.ID,
|
||||||
UserID: l.UserID,
|
UserID: l.UserID,
|
||||||
ApiKeyID: l.ApiKeyID,
|
APIKeyID: l.APIKeyID,
|
||||||
AccountID: l.AccountID,
|
AccountID: l.AccountID,
|
||||||
RequestID: l.RequestID,
|
RequestID: l.RequestID,
|
||||||
Model: l.Model,
|
Model: l.Model,
|
||||||
@@ -243,15 +278,32 @@ func UsageLogFromService(l *service.UsageLog) *UsageLog {
|
|||||||
Stream: l.Stream,
|
Stream: l.Stream,
|
||||||
DurationMs: l.DurationMs,
|
DurationMs: l.DurationMs,
|
||||||
FirstTokenMs: l.FirstTokenMs,
|
FirstTokenMs: l.FirstTokenMs,
|
||||||
|
ImageCount: l.ImageCount,
|
||||||
|
ImageSize: l.ImageSize,
|
||||||
CreatedAt: l.CreatedAt,
|
CreatedAt: l.CreatedAt,
|
||||||
User: UserFromServiceShallow(l.User),
|
User: UserFromServiceShallow(l.User),
|
||||||
ApiKey: ApiKeyFromService(l.ApiKey),
|
APIKey: APIKeyFromService(l.APIKey),
|
||||||
Account: AccountFromService(l.Account),
|
Account: account,
|
||||||
Group: GroupFromServiceShallow(l.Group),
|
Group: GroupFromServiceShallow(l.Group),
|
||||||
Subscription: UserSubscriptionFromService(l.Subscription),
|
Subscription: UserSubscriptionFromService(l.Subscription),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UsageLogFromService converts a service UsageLog to DTO for regular users.
|
||||||
|
// It excludes Account details - users should not see account information.
|
||||||
|
func UsageLogFromService(l *service.UsageLog) *UsageLog {
|
||||||
|
return usageLogFromServiceBase(l, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsageLogFromServiceAdmin converts a service UsageLog to DTO for admin users.
|
||||||
|
// It includes minimal Account info (ID, Name only).
|
||||||
|
func UsageLogFromServiceAdmin(l *service.UsageLog) *UsageLog {
|
||||||
|
if l == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return usageLogFromServiceBase(l, AccountSummaryFromService(l.Account))
|
||||||
|
}
|
||||||
|
|
||||||
func SettingFromService(s *service.Setting) *Setting {
|
func SettingFromService(s *service.Setting) *Setting {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,27 +5,38 @@ type SystemSettings struct {
|
|||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
RegistrationEnabled bool `json:"registration_enabled"`
|
||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
|
||||||
SmtpHost string `json:"smtp_host"`
|
SMTPHost string `json:"smtp_host"`
|
||||||
SmtpPort int `json:"smtp_port"`
|
SMTPPort int `json:"smtp_port"`
|
||||||
SmtpUsername string `json:"smtp_username"`
|
SMTPUsername string `json:"smtp_username"`
|
||||||
SmtpPassword string `json:"smtp_password,omitempty"`
|
SMTPPasswordConfigured bool `json:"smtp_password_configured"`
|
||||||
SmtpFrom string `json:"smtp_from_email"`
|
SMTPFrom string `json:"smtp_from_email"`
|
||||||
SmtpFromName string `json:"smtp_from_name"`
|
SMTPFromName string `json:"smtp_from_name"`
|
||||||
SmtpUseTLS bool `json:"smtp_use_tls"`
|
SMTPUseTLS bool `json:"smtp_use_tls"`
|
||||||
|
|
||||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||||
TurnstileSecretKey string `json:"turnstile_secret_key,omitempty"`
|
TurnstileSecretKeyConfigured bool `json:"turnstile_secret_key_configured"`
|
||||||
|
|
||||||
SiteName string `json:"site_name"`
|
SiteName string `json:"site_name"`
|
||||||
SiteLogo string `json:"site_logo"`
|
SiteLogo string `json:"site_logo"`
|
||||||
SiteSubtitle string `json:"site_subtitle"`
|
SiteSubtitle string `json:"site_subtitle"`
|
||||||
ApiBaseUrl string `json:"api_base_url"`
|
APIBaseURL string `json:"api_base_url"`
|
||||||
ContactInfo string `json:"contact_info"`
|
ContactInfo string `json:"contact_info"`
|
||||||
DocUrl string `json:"doc_url"`
|
DocURL string `json:"doc_url"`
|
||||||
|
|
||||||
DefaultConcurrency int `json:"default_concurrency"`
|
DefaultConcurrency int `json:"default_concurrency"`
|
||||||
DefaultBalance float64 `json:"default_balance"`
|
DefaultBalance float64 `json:"default_balance"`
|
||||||
|
|
||||||
|
// Model fallback configuration
|
||||||
|
EnableModelFallback bool `json:"enable_model_fallback"`
|
||||||
|
FallbackModelAnthropic string `json:"fallback_model_anthropic"`
|
||||||
|
FallbackModelOpenAI string `json:"fallback_model_openai"`
|
||||||
|
FallbackModelGemini string `json:"fallback_model_gemini"`
|
||||||
|
FallbackModelAntigravity string `json:"fallback_model_antigravity"`
|
||||||
|
|
||||||
|
// Identity patch configuration (Claude -> Gemini)
|
||||||
|
EnableIdentityPatch bool `json:"enable_identity_patch"`
|
||||||
|
IdentityPatchPrompt string `json:"identity_patch_prompt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PublicSettings struct {
|
type PublicSettings struct {
|
||||||
@@ -36,8 +47,8 @@ type PublicSettings struct {
|
|||||||
SiteName string `json:"site_name"`
|
SiteName string `json:"site_name"`
|
||||||
SiteLogo string `json:"site_logo"`
|
SiteLogo string `json:"site_logo"`
|
||||||
SiteSubtitle string `json:"site_subtitle"`
|
SiteSubtitle string `json:"site_subtitle"`
|
||||||
ApiBaseUrl string `json:"api_base_url"`
|
APIBaseURL string `json:"api_base_url"`
|
||||||
ContactInfo string `json:"contact_info"`
|
ContactInfo string `json:"contact_info"`
|
||||||
DocUrl string `json:"doc_url"`
|
DocURL string `json:"doc_url"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ type User struct {
|
|||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
ApiKeys []ApiKey `json:"api_keys,omitempty"`
|
APIKeys []APIKey `json:"api_keys,omitempty"`
|
||||||
Subscriptions []UserSubscription `json:"subscriptions,omitempty"`
|
Subscriptions []UserSubscription `json:"subscriptions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiKey struct {
|
type APIKey struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
@@ -47,6 +47,11 @@ type Group struct {
|
|||||||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
WeeklyLimitUSD *float64 `json:"weekly_limit_usd"`
|
||||||
MonthlyLimitUSD *float64 `json:"monthly_limit_usd"`
|
MonthlyLimitUSD *float64 `json:"monthly_limit_usd"`
|
||||||
|
|
||||||
|
// 图片生成计费配置(仅 antigravity 平台使用)
|
||||||
|
ImagePrice1K *float64 `json:"image_price_1k"`
|
||||||
|
ImagePrice2K *float64 `json:"image_price_2k"`
|
||||||
|
ImagePrice4K *float64 `json:"image_price_4k"`
|
||||||
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
@@ -55,20 +60,23 @@ type Group struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Account struct {
|
type Account struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Platform string `json:"platform"`
|
Notes *string `json:"notes"`
|
||||||
Type string `json:"type"`
|
Platform string `json:"platform"`
|
||||||
Credentials map[string]any `json:"credentials"`
|
Type string `json:"type"`
|
||||||
Extra map[string]any `json:"extra"`
|
Credentials map[string]any `json:"credentials"`
|
||||||
ProxyID *int64 `json:"proxy_id"`
|
Extra map[string]any `json:"extra"`
|
||||||
Concurrency int `json:"concurrency"`
|
ProxyID *int64 `json:"proxy_id"`
|
||||||
Priority int `json:"priority"`
|
Concurrency int `json:"concurrency"`
|
||||||
Status string `json:"status"`
|
Priority int `json:"priority"`
|
||||||
ErrorMessage string `json:"error_message"`
|
Status string `json:"status"`
|
||||||
LastUsedAt *time.Time `json:"last_used_at"`
|
ErrorMessage string `json:"error_message"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
LastUsedAt *time.Time `json:"last_used_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
ExpiresAt *int64 `json:"expires_at"`
|
||||||
|
AutoPauseOnExpired bool `json:"auto_pause_on_expired"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
Schedulable bool `json:"schedulable"`
|
Schedulable bool `json:"schedulable"`
|
||||||
|
|
||||||
@@ -76,6 +84,9 @@ type Account struct {
|
|||||||
RateLimitResetAt *time.Time `json:"rate_limit_reset_at"`
|
RateLimitResetAt *time.Time `json:"rate_limit_reset_at"`
|
||||||
OverloadUntil *time.Time `json:"overload_until"`
|
OverloadUntil *time.Time `json:"overload_until"`
|
||||||
|
|
||||||
|
TempUnschedulableUntil *time.Time `json:"temp_unschedulable_until"`
|
||||||
|
TempUnschedulableReason string `json:"temp_unschedulable_reason"`
|
||||||
|
|
||||||
SessionWindowStart *time.Time `json:"session_window_start"`
|
SessionWindowStart *time.Time `json:"session_window_start"`
|
||||||
SessionWindowEnd *time.Time `json:"session_window_end"`
|
SessionWindowEnd *time.Time `json:"session_window_end"`
|
||||||
SessionWindowStatus string `json:"session_window_status"`
|
SessionWindowStatus string `json:"session_window_status"`
|
||||||
@@ -136,7 +147,7 @@ type RedeemCode struct {
|
|||||||
type UsageLog struct {
|
type UsageLog struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
ApiKeyID int64 `json:"api_key_id"`
|
APIKeyID int64 `json:"api_key_id"`
|
||||||
AccountID int64 `json:"account_id"`
|
AccountID int64 `json:"account_id"`
|
||||||
RequestID string `json:"request_id"`
|
RequestID string `json:"request_id"`
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
@@ -165,15 +176,26 @@ type UsageLog struct {
|
|||||||
DurationMs *int `json:"duration_ms"`
|
DurationMs *int `json:"duration_ms"`
|
||||||
FirstTokenMs *int `json:"first_token_ms"`
|
FirstTokenMs *int `json:"first_token_ms"`
|
||||||
|
|
||||||
|
// 图片生成字段
|
||||||
|
ImageCount int `json:"image_count"`
|
||||||
|
ImageSize *string `json:"image_size"`
|
||||||
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
User *User `json:"user,omitempty"`
|
User *User `json:"user,omitempty"`
|
||||||
ApiKey *ApiKey `json:"api_key,omitempty"`
|
APIKey *APIKey `json:"api_key,omitempty"`
|
||||||
Account *Account `json:"account,omitempty"`
|
Account *AccountSummary `json:"account,omitempty"` // Use minimal AccountSummary to prevent data leakage
|
||||||
Group *Group `json:"group,omitempty"`
|
Group *Group `json:"group,omitempty"`
|
||||||
Subscription *UserSubscription `json:"subscription,omitempty"`
|
Subscription *UserSubscription `json:"subscription,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AccountSummary is a minimal account info for usage log display.
|
||||||
|
// It intentionally excludes sensitive fields like Credentials, Proxy, etc.
|
||||||
|
type AccountSummary struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
type Setting struct {
|
type Setting struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
||||||
|
pkgerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
||||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
@@ -38,14 +40,19 @@ func NewGatewayHandler(
|
|||||||
userService *service.UserService,
|
userService *service.UserService,
|
||||||
concurrencyService *service.ConcurrencyService,
|
concurrencyService *service.ConcurrencyService,
|
||||||
billingCacheService *service.BillingCacheService,
|
billingCacheService *service.BillingCacheService,
|
||||||
|
cfg *config.Config,
|
||||||
) *GatewayHandler {
|
) *GatewayHandler {
|
||||||
|
pingInterval := time.Duration(0)
|
||||||
|
if cfg != nil {
|
||||||
|
pingInterval = time.Duration(cfg.Concurrency.PingInterval) * time.Second
|
||||||
|
}
|
||||||
return &GatewayHandler{
|
return &GatewayHandler{
|
||||||
gatewayService: gatewayService,
|
gatewayService: gatewayService,
|
||||||
geminiCompatService: geminiCompatService,
|
geminiCompatService: geminiCompatService,
|
||||||
antigravityGatewayService: antigravityGatewayService,
|
antigravityGatewayService: antigravityGatewayService,
|
||||||
userService: userService,
|
userService: userService,
|
||||||
billingCacheService: billingCacheService,
|
billingCacheService: billingCacheService,
|
||||||
concurrencyHelper: NewConcurrencyHelper(concurrencyService, SSEPingFormatClaude),
|
concurrencyHelper: NewConcurrencyHelper(concurrencyService, SSEPingFormatClaude, pingInterval),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +60,7 @@ func NewGatewayHandler(
|
|||||||
// POST /v1/messages
|
// POST /v1/messages
|
||||||
func (h *GatewayHandler) Messages(c *gin.Context) {
|
func (h *GatewayHandler) Messages(c *gin.Context) {
|
||||||
// 从context获取apiKey和user(ApiKeyAuth中间件已设置)
|
// 从context获取apiKey和user(ApiKeyAuth中间件已设置)
|
||||||
apiKey, ok := middleware2.GetApiKeyFromContext(c)
|
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -101,6 +108,9 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
// 获取订阅信息(可能为nil)- 提前获取用于后续检查
|
// 获取订阅信息(可能为nil)- 提前获取用于后续检查
|
||||||
subscription, _ := middleware2.GetSubscriptionFromContext(c)
|
subscription, _ := middleware2.GetSubscriptionFromContext(c)
|
||||||
|
|
||||||
|
// 获取 User-Agent
|
||||||
|
userAgent := c.Request.UserAgent()
|
||||||
|
|
||||||
// 0. 检查wait队列是否已满
|
// 0. 检查wait队列是否已满
|
||||||
maxWait := service.CalculateMaxWait(subject.Concurrency)
|
maxWait := service.CalculateMaxWait(subject.Concurrency)
|
||||||
canWait, err := h.concurrencyHelper.IncrementWaitCount(c.Request.Context(), subject.UserID, maxWait)
|
canWait, err := h.concurrencyHelper.IncrementWaitCount(c.Request.Context(), subject.UserID, maxWait)
|
||||||
@@ -121,6 +131,8 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
h.handleConcurrencyError(c, err, "user", streamStarted)
|
h.handleConcurrencyError(c, err, "user", streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 在请求结束或 Context 取消时确保释放槽位,避免客户端断开造成泄漏
|
||||||
|
userReleaseFunc = wrapReleaseOnDone(c.Request.Context(), userReleaseFunc)
|
||||||
if userReleaseFunc != nil {
|
if userReleaseFunc != nil {
|
||||||
defer userReleaseFunc()
|
defer userReleaseFunc()
|
||||||
}
|
}
|
||||||
@@ -128,7 +140,8 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
// 2. 【新增】Wait后二次检查余额/订阅
|
// 2. 【新增】Wait后二次检查余额/订阅
|
||||||
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
||||||
log.Printf("Billing eligibility check failed after wait: %v", err)
|
log.Printf("Billing eligibility check failed after wait: %v", err)
|
||||||
h.handleStreamingAwareError(c, http.StatusForbidden, "billing_error", err.Error(), streamStarted)
|
status, code, message := billingErrorDetails(err)
|
||||||
|
h.handleStreamingAwareError(c, status, code, message, streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +233,9 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
log.Printf("Bind sticky session failed: %v", err)
|
log.Printf("Bind sticky session failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 账号槽位/等待计数需要在超时或断开时安全回收
|
||||||
|
accountReleaseFunc = wrapReleaseOnDone(c.Request.Context(), accountReleaseFunc)
|
||||||
|
accountWaitRelease = wrapReleaseOnDone(c.Request.Context(), accountWaitRelease)
|
||||||
|
|
||||||
// 转发请求 - 根据账号平台分流
|
// 转发请求 - 根据账号平台分流
|
||||||
var result *service.ForwardResult
|
var result *service.ForwardResult
|
||||||
@@ -254,19 +270,20 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 异步记录使用量(subscription已在函数开头获取)
|
// 异步记录使用量(subscription已在函数开头获取)
|
||||||
go func(result *service.ForwardResult, usedAccount *service.Account) {
|
go func(result *service.ForwardResult, usedAccount *service.Account, ua string) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
||||||
Result: result,
|
Result: result,
|
||||||
ApiKey: apiKey,
|
APIKey: apiKey,
|
||||||
User: apiKey.User,
|
User: apiKey.User,
|
||||||
Account: usedAccount,
|
Account: usedAccount,
|
||||||
Subscription: subscription,
|
Subscription: subscription,
|
||||||
|
UserAgent: ua,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("Record usage failed: %v", err)
|
log.Printf("Record usage failed: %v", err)
|
||||||
}
|
}
|
||||||
}(result, account)
|
}(result, account, userAgent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,6 +361,9 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
log.Printf("Bind sticky session failed: %v", err)
|
log.Printf("Bind sticky session failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 账号槽位/等待计数需要在超时或断开时安全回收
|
||||||
|
accountReleaseFunc = wrapReleaseOnDone(c.Request.Context(), accountReleaseFunc)
|
||||||
|
accountWaitRelease = wrapReleaseOnDone(c.Request.Context(), accountWaitRelease)
|
||||||
|
|
||||||
// 转发请求 - 根据账号平台分流
|
// 转发请求 - 根据账号平台分流
|
||||||
var result *service.ForwardResult
|
var result *service.ForwardResult
|
||||||
@@ -373,24 +393,25 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 错误响应已在Forward中处理,这里只记录日志
|
// 错误响应已在Forward中处理,这里只记录日志
|
||||||
log.Printf("Forward request failed: %v", err)
|
log.Printf("Account %d: Forward request failed: %v", account.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 异步记录使用量(subscription已在函数开头获取)
|
// 异步记录使用量(subscription已在函数开头获取)
|
||||||
go func(result *service.ForwardResult, usedAccount *service.Account) {
|
go func(result *service.ForwardResult, usedAccount *service.Account, ua string) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
||||||
Result: result,
|
Result: result,
|
||||||
ApiKey: apiKey,
|
APIKey: apiKey,
|
||||||
User: apiKey.User,
|
User: apiKey.User,
|
||||||
Account: usedAccount,
|
Account: usedAccount,
|
||||||
Subscription: subscription,
|
Subscription: subscription,
|
||||||
|
UserAgent: ua,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("Record usage failed: %v", err)
|
log.Printf("Record usage failed: %v", err)
|
||||||
}
|
}
|
||||||
}(result, account)
|
}(result, account, userAgent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,7 +421,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
// Returns models based on account configurations (model_mapping whitelist)
|
// Returns models based on account configurations (model_mapping whitelist)
|
||||||
// Falls back to default models if no whitelist is configured
|
// Falls back to default models if no whitelist is configured
|
||||||
func (h *GatewayHandler) Models(c *gin.Context) {
|
func (h *GatewayHandler) Models(c *gin.Context) {
|
||||||
apiKey, _ := middleware2.GetApiKeyFromContext(c)
|
apiKey, _ := middleware2.GetAPIKeyFromContext(c)
|
||||||
|
|
||||||
var groupID *int64
|
var groupID *int64
|
||||||
var platform string
|
var platform string
|
||||||
@@ -458,7 +479,7 @@ func (h *GatewayHandler) AntigravityModels(c *gin.Context) {
|
|||||||
// Usage handles getting account balance for CC Switch integration
|
// Usage handles getting account balance for CC Switch integration
|
||||||
// GET /v1/usage
|
// GET /v1/usage
|
||||||
func (h *GatewayHandler) Usage(c *gin.Context) {
|
func (h *GatewayHandler) Usage(c *gin.Context) {
|
||||||
apiKey, ok := middleware2.GetApiKeyFromContext(c)
|
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -628,7 +649,7 @@ func (h *GatewayHandler) errorResponse(c *gin.Context, status int, errType, mess
|
|||||||
// 特点:校验订阅/余额,但不计算并发、不记录使用量
|
// 特点:校验订阅/余额,但不计算并发、不记录使用量
|
||||||
func (h *GatewayHandler) CountTokens(c *gin.Context) {
|
func (h *GatewayHandler) CountTokens(c *gin.Context) {
|
||||||
// 从context获取apiKey和user(ApiKeyAuth中间件已设置)
|
// 从context获取apiKey和user(ApiKeyAuth中间件已设置)
|
||||||
apiKey, ok := middleware2.GetApiKeyFromContext(c)
|
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -674,7 +695,8 @@ func (h *GatewayHandler) CountTokens(c *gin.Context) {
|
|||||||
// 校验 billing eligibility(订阅/余额)
|
// 校验 billing eligibility(订阅/余额)
|
||||||
// 【注意】不计算并发,但需要校验订阅/余额
|
// 【注意】不计算并发,但需要校验订阅/余额
|
||||||
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
||||||
h.errorResponse(c, http.StatusForbidden, "billing_error", err.Error())
|
status, code, message := billingErrorDetails(err)
|
||||||
|
h.errorResponse(c, status, code, message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,3 +822,18 @@ func sendMockWarmupResponse(c *gin.Context, model string) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func billingErrorDetails(err error) (status int, code, message string) {
|
||||||
|
if errors.Is(err, service.ErrBillingServiceUnavailable) {
|
||||||
|
msg := pkgerrors.Message(err)
|
||||||
|
if msg == "" {
|
||||||
|
msg = "Billing service temporarily unavailable. Please retry later."
|
||||||
|
}
|
||||||
|
return http.StatusServiceUnavailable, "billing_service_error", msg
|
||||||
|
}
|
||||||
|
msg := pkgerrors.Message(err)
|
||||||
|
if msg == "" {
|
||||||
|
msg = err.Error()
|
||||||
|
}
|
||||||
|
return http.StatusForbidden, "billing_error", msg
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
@@ -26,8 +27,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
// maxConcurrencyWait 等待并发槽位的最大时间
|
// maxConcurrencyWait 等待并发槽位的最大时间
|
||||||
maxConcurrencyWait = 30 * time.Second
|
maxConcurrencyWait = 30 * time.Second
|
||||||
// pingInterval 流式响应等待时发送 ping 的间隔
|
// defaultPingInterval 流式响应等待时发送 ping 的默认间隔
|
||||||
pingInterval = 15 * time.Second
|
defaultPingInterval = 10 * time.Second
|
||||||
// initialBackoff 初始退避时间
|
// initialBackoff 初始退避时间
|
||||||
initialBackoff = 100 * time.Millisecond
|
initialBackoff = 100 * time.Millisecond
|
||||||
// backoffMultiplier 退避时间乘数(指数退避)
|
// backoffMultiplier 退避时间乘数(指数退避)
|
||||||
@@ -44,6 +45,8 @@ const (
|
|||||||
SSEPingFormatClaude SSEPingFormat = "data: {\"type\": \"ping\"}\n\n"
|
SSEPingFormatClaude SSEPingFormat = "data: {\"type\": \"ping\"}\n\n"
|
||||||
// SSEPingFormatNone indicates no ping should be sent (e.g., OpenAI has no ping spec)
|
// SSEPingFormatNone indicates no ping should be sent (e.g., OpenAI has no ping spec)
|
||||||
SSEPingFormatNone SSEPingFormat = ""
|
SSEPingFormatNone SSEPingFormat = ""
|
||||||
|
// SSEPingFormatComment is an SSE comment ping for OpenAI/Codex CLI clients
|
||||||
|
SSEPingFormatComment SSEPingFormat = ":\n\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConcurrencyError represents a concurrency limit error with context
|
// ConcurrencyError represents a concurrency limit error with context
|
||||||
@@ -63,16 +66,52 @@ func (e *ConcurrencyError) Error() string {
|
|||||||
type ConcurrencyHelper struct {
|
type ConcurrencyHelper struct {
|
||||||
concurrencyService *service.ConcurrencyService
|
concurrencyService *service.ConcurrencyService
|
||||||
pingFormat SSEPingFormat
|
pingFormat SSEPingFormat
|
||||||
|
pingInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConcurrencyHelper creates a new ConcurrencyHelper
|
// NewConcurrencyHelper creates a new ConcurrencyHelper
|
||||||
func NewConcurrencyHelper(concurrencyService *service.ConcurrencyService, pingFormat SSEPingFormat) *ConcurrencyHelper {
|
func NewConcurrencyHelper(concurrencyService *service.ConcurrencyService, pingFormat SSEPingFormat, pingInterval time.Duration) *ConcurrencyHelper {
|
||||||
|
if pingInterval <= 0 {
|
||||||
|
pingInterval = defaultPingInterval
|
||||||
|
}
|
||||||
return &ConcurrencyHelper{
|
return &ConcurrencyHelper{
|
||||||
concurrencyService: concurrencyService,
|
concurrencyService: concurrencyService,
|
||||||
pingFormat: pingFormat,
|
pingFormat: pingFormat,
|
||||||
|
pingInterval: pingInterval,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrapReleaseOnDone ensures release runs at most once and still triggers on context cancellation.
|
||||||
|
// 用于避免客户端断开或上游超时导致的并发槽位泄漏。
|
||||||
|
// 修复:添加 quit channel 确保 goroutine 及时退出,避免泄露
|
||||||
|
func wrapReleaseOnDone(ctx context.Context, releaseFunc func()) func() {
|
||||||
|
if releaseFunc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var once sync.Once
|
||||||
|
quit := make(chan struct{})
|
||||||
|
|
||||||
|
release := func() {
|
||||||
|
once.Do(func() {
|
||||||
|
releaseFunc()
|
||||||
|
close(quit) // 通知监听 goroutine 退出
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Context 取消时释放资源
|
||||||
|
release()
|
||||||
|
case <-quit:
|
||||||
|
// 正常释放已完成,goroutine 退出
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return release
|
||||||
|
}
|
||||||
|
|
||||||
// IncrementWaitCount increments the wait count for a user
|
// IncrementWaitCount increments the wait count for a user
|
||||||
func (h *ConcurrencyHelper) IncrementWaitCount(ctx context.Context, userID int64, maxWait int) (bool, error) {
|
func (h *ConcurrencyHelper) IncrementWaitCount(ctx context.Context, userID int64, maxWait int) (bool, error) {
|
||||||
return h.concurrencyService.IncrementWaitCount(ctx, userID, maxWait)
|
return h.concurrencyService.IncrementWaitCount(ctx, userID, maxWait)
|
||||||
@@ -174,7 +213,7 @@ func (h *ConcurrencyHelper) waitForSlotWithPingTimeout(c *gin.Context, slotType
|
|||||||
// Only create ping ticker if ping is needed
|
// Only create ping ticker if ping is needed
|
||||||
var pingCh <-chan time.Time
|
var pingCh <-chan time.Time
|
||||||
if needPing {
|
if needPing {
|
||||||
pingTicker := time.NewTicker(pingInterval)
|
pingTicker := time.NewTicker(h.pingInterval)
|
||||||
defer pingTicker.Stop()
|
defer pingTicker.Stop()
|
||||||
pingCh = pingTicker.C
|
pingCh = pingTicker.C
|
||||||
}
|
}
|
||||||
|
|||||||
141
backend/internal/handler/gateway_helper_test.go
Normal file
141
backend/internal/handler/gateway_helper_test.go
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"runtime"
|
||||||
|
"sync/atomic"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestWrapReleaseOnDone_NoGoroutineLeak 验证 wrapReleaseOnDone 修复后不会泄露 goroutine
|
||||||
|
func TestWrapReleaseOnDone_NoGoroutineLeak(t *testing.T) {
|
||||||
|
// 记录测试开始时的 goroutine 数量
|
||||||
|
runtime.GC()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
initialGoroutines := runtime.NumGoroutine()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var releaseCount int32
|
||||||
|
release := wrapReleaseOnDone(ctx, func() {
|
||||||
|
atomic.AddInt32(&releaseCount, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 正常释放
|
||||||
|
release()
|
||||||
|
|
||||||
|
// 等待足够时间确保 goroutine 退出
|
||||||
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
|
||||||
|
// 验证只释放一次
|
||||||
|
if count := atomic.LoadInt32(&releaseCount); count != 1 {
|
||||||
|
t.Errorf("expected release count to be 1, got %d", count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制 GC,清理已退出的 goroutine
|
||||||
|
runtime.GC()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// 验证 goroutine 数量没有增加(允许±2的误差,考虑到测试框架本身可能创建的 goroutine)
|
||||||
|
finalGoroutines := runtime.NumGoroutine()
|
||||||
|
if finalGoroutines > initialGoroutines+2 {
|
||||||
|
t.Errorf("goroutine leak detected: initial=%d, final=%d, leaked=%d",
|
||||||
|
initialGoroutines, finalGoroutines, finalGoroutines-initialGoroutines)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestWrapReleaseOnDone_ContextCancellation 验证 context 取消时也能正确释放
|
||||||
|
func TestWrapReleaseOnDone_ContextCancellation(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
var releaseCount int32
|
||||||
|
_ = wrapReleaseOnDone(ctx, func() {
|
||||||
|
atomic.AddInt32(&releaseCount, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 取消 context,应该触发释放
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
// 等待释放完成
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// 验证释放被调用
|
||||||
|
if count := atomic.LoadInt32(&releaseCount); count != 1 {
|
||||||
|
t.Errorf("expected release count to be 1, got %d", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestWrapReleaseOnDone_MultipleCallsOnlyReleaseOnce 验证多次调用 release 只释放一次
|
||||||
|
func TestWrapReleaseOnDone_MultipleCallsOnlyReleaseOnce(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var releaseCount int32
|
||||||
|
release := wrapReleaseOnDone(ctx, func() {
|
||||||
|
atomic.AddInt32(&releaseCount, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 调用多次
|
||||||
|
release()
|
||||||
|
release()
|
||||||
|
release()
|
||||||
|
|
||||||
|
// 等待执行完成
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// 验证只释放一次
|
||||||
|
if count := atomic.LoadInt32(&releaseCount); count != 1 {
|
||||||
|
t.Errorf("expected release count to be 1, got %d", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestWrapReleaseOnDone_NilReleaseFunc 验证 nil releaseFunc 不会 panic
|
||||||
|
func TestWrapReleaseOnDone_NilReleaseFunc(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
release := wrapReleaseOnDone(ctx, nil)
|
||||||
|
|
||||||
|
if release != nil {
|
||||||
|
t.Error("expected nil release function when releaseFunc is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestWrapReleaseOnDone_ConcurrentCalls 验证并发调用的安全性
|
||||||
|
func TestWrapReleaseOnDone_ConcurrentCalls(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var releaseCount int32
|
||||||
|
release := wrapReleaseOnDone(ctx, func() {
|
||||||
|
atomic.AddInt32(&releaseCount, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 并发调用 release
|
||||||
|
const numGoroutines = 10
|
||||||
|
for i := 0; i < numGoroutines; i++ {
|
||||||
|
go release()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有 goroutine 完成
|
||||||
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
|
||||||
|
// 验证只释放一次
|
||||||
|
if count := atomic.LoadInt32(&releaseCount); count != 1 {
|
||||||
|
t.Errorf("expected release count to be 1, got %d", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkWrapReleaseOnDone 性能基准测试
|
||||||
|
func BenchmarkWrapReleaseOnDone(b *testing.B) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
release := wrapReleaseOnDone(ctx, func() {})
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
// GeminiV1BetaListModels proxies:
|
// GeminiV1BetaListModels proxies:
|
||||||
// GET /v1beta/models
|
// GET /v1beta/models
|
||||||
func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
|
func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
|
||||||
apiKey, ok := middleware.GetApiKeyFromContext(c)
|
apiKey, ok := middleware.GetAPIKeyFromContext(c)
|
||||||
if !ok || apiKey == nil {
|
if !ok || apiKey == nil {
|
||||||
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -67,7 +67,7 @@ func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
|
|||||||
// GeminiV1BetaGetModel proxies:
|
// GeminiV1BetaGetModel proxies:
|
||||||
// GET /v1beta/models/{model}
|
// GET /v1beta/models/{model}
|
||||||
func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
|
func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
|
||||||
apiKey, ok := middleware.GetApiKeyFromContext(c)
|
apiKey, ok := middleware.GetAPIKeyFromContext(c)
|
||||||
if !ok || apiKey == nil {
|
if !ok || apiKey == nil {
|
||||||
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -120,7 +120,7 @@ func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
|
|||||||
// POST /v1beta/models/{model}:generateContent
|
// POST /v1beta/models/{model}:generateContent
|
||||||
// POST /v1beta/models/{model}:streamGenerateContent?alt=sse
|
// POST /v1beta/models/{model}:streamGenerateContent?alt=sse
|
||||||
func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
||||||
apiKey, ok := middleware.GetApiKeyFromContext(c)
|
apiKey, ok := middleware.GetAPIKeyFromContext(c)
|
||||||
if !ok || apiKey == nil {
|
if !ok || apiKey == nil {
|
||||||
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
googleError(c, http.StatusUnauthorized, "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -164,8 +164,11 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
|||||||
// Get subscription (may be nil)
|
// Get subscription (may be nil)
|
||||||
subscription, _ := middleware.GetSubscriptionFromContext(c)
|
subscription, _ := middleware.GetSubscriptionFromContext(c)
|
||||||
|
|
||||||
|
// 获取 User-Agent
|
||||||
|
userAgent := c.Request.UserAgent()
|
||||||
|
|
||||||
// For Gemini native API, do not send Claude-style ping frames.
|
// For Gemini native API, do not send Claude-style ping frames.
|
||||||
geminiConcurrency := NewConcurrencyHelper(h.concurrencyHelper.concurrencyService, SSEPingFormatNone)
|
geminiConcurrency := NewConcurrencyHelper(h.concurrencyHelper.concurrencyService, SSEPingFormatNone, 0)
|
||||||
|
|
||||||
// 0) wait queue check
|
// 0) wait queue check
|
||||||
maxWait := service.CalculateMaxWait(authSubject.Concurrency)
|
maxWait := service.CalculateMaxWait(authSubject.Concurrency)
|
||||||
@@ -185,13 +188,16 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
|||||||
googleError(c, http.StatusTooManyRequests, err.Error())
|
googleError(c, http.StatusTooManyRequests, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 确保请求取消时也会释放槽位,避免长连接被动中断造成泄漏
|
||||||
|
userReleaseFunc = wrapReleaseOnDone(c.Request.Context(), userReleaseFunc)
|
||||||
if userReleaseFunc != nil {
|
if userReleaseFunc != nil {
|
||||||
defer userReleaseFunc()
|
defer userReleaseFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) billing eligibility check (after wait)
|
// 2) billing eligibility check (after wait)
|
||||||
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
||||||
googleError(c, http.StatusForbidden, err.Error())
|
status, _, message := billingErrorDetails(err)
|
||||||
|
googleError(c, status, message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +266,9 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
|||||||
log.Printf("Bind sticky session failed: %v", err)
|
log.Printf("Bind sticky session failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 账号槽位/等待计数需要在超时或断开时安全回收
|
||||||
|
accountReleaseFunc = wrapReleaseOnDone(c.Request.Context(), accountReleaseFunc)
|
||||||
|
accountWaitRelease = wrapReleaseOnDone(c.Request.Context(), accountWaitRelease)
|
||||||
|
|
||||||
// 5) forward (根据平台分流)
|
// 5) forward (根据平台分流)
|
||||||
var result *service.ForwardResult
|
var result *service.ForwardResult
|
||||||
@@ -294,19 +303,20 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 6) record usage async
|
// 6) record usage async
|
||||||
go func(result *service.ForwardResult, usedAccount *service.Account) {
|
go func(result *service.ForwardResult, usedAccount *service.Account, ua string) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
|
||||||
Result: result,
|
Result: result,
|
||||||
ApiKey: apiKey,
|
APIKey: apiKey,
|
||||||
User: apiKey.User,
|
User: apiKey.User,
|
||||||
Account: usedAccount,
|
Account: usedAccount,
|
||||||
Subscription: subscription,
|
Subscription: subscription,
|
||||||
|
UserAgent: ua,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("Record usage failed: %v", err)
|
log.Printf("Record usage failed: %v", err)
|
||||||
}
|
}
|
||||||
}(result, account)
|
}(result, account, userAgent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
||||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||||
@@ -29,11 +30,16 @@ func NewOpenAIGatewayHandler(
|
|||||||
gatewayService *service.OpenAIGatewayService,
|
gatewayService *service.OpenAIGatewayService,
|
||||||
concurrencyService *service.ConcurrencyService,
|
concurrencyService *service.ConcurrencyService,
|
||||||
billingCacheService *service.BillingCacheService,
|
billingCacheService *service.BillingCacheService,
|
||||||
|
cfg *config.Config,
|
||||||
) *OpenAIGatewayHandler {
|
) *OpenAIGatewayHandler {
|
||||||
|
pingInterval := time.Duration(0)
|
||||||
|
if cfg != nil {
|
||||||
|
pingInterval = time.Duration(cfg.Concurrency.PingInterval) * time.Second
|
||||||
|
}
|
||||||
return &OpenAIGatewayHandler{
|
return &OpenAIGatewayHandler{
|
||||||
gatewayService: gatewayService,
|
gatewayService: gatewayService,
|
||||||
billingCacheService: billingCacheService,
|
billingCacheService: billingCacheService,
|
||||||
concurrencyHelper: NewConcurrencyHelper(concurrencyService, SSEPingFormatNone),
|
concurrencyHelper: NewConcurrencyHelper(concurrencyService, SSEPingFormatComment, pingInterval),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +47,7 @@ func NewOpenAIGatewayHandler(
|
|||||||
// POST /openai/v1/responses
|
// POST /openai/v1/responses
|
||||||
func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
||||||
// Get apiKey and user from context (set by ApiKeyAuth middleware)
|
// Get apiKey and user from context (set by ApiKeyAuth middleware)
|
||||||
apiKey, ok := middleware2.GetApiKeyFromContext(c)
|
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
|
||||||
return
|
return
|
||||||
@@ -124,6 +130,8 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
|||||||
h.handleConcurrencyError(c, err, "user", streamStarted)
|
h.handleConcurrencyError(c, err, "user", streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 确保请求取消时也会释放槽位,避免长连接被动中断造成泄漏
|
||||||
|
userReleaseFunc = wrapReleaseOnDone(c.Request.Context(), userReleaseFunc)
|
||||||
if userReleaseFunc != nil {
|
if userReleaseFunc != nil {
|
||||||
defer userReleaseFunc()
|
defer userReleaseFunc()
|
||||||
}
|
}
|
||||||
@@ -131,7 +139,8 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
|||||||
// 2. Re-check billing eligibility after wait
|
// 2. Re-check billing eligibility after wait
|
||||||
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
if err := h.billingCacheService.CheckBillingEligibility(c.Request.Context(), apiKey.User, apiKey, apiKey.Group, subscription); err != nil {
|
||||||
log.Printf("Billing eligibility check failed after wait: %v", err)
|
log.Printf("Billing eligibility check failed after wait: %v", err)
|
||||||
h.handleStreamingAwareError(c, http.StatusForbidden, "billing_error", err.Error(), streamStarted)
|
status, code, message := billingErrorDetails(err)
|
||||||
|
h.handleStreamingAwareError(c, status, code, message, streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +210,9 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
|||||||
log.Printf("Bind sticky session failed: %v", err)
|
log.Printf("Bind sticky session failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 账号槽位/等待计数需要在超时或断开时安全回收
|
||||||
|
accountReleaseFunc = wrapReleaseOnDone(c.Request.Context(), accountReleaseFunc)
|
||||||
|
accountWaitRelease = wrapReleaseOnDone(c.Request.Context(), accountWaitRelease)
|
||||||
|
|
||||||
// Forward request
|
// Forward request
|
||||||
result, err := h.gatewayService.Forward(c.Request.Context(), c, account, body)
|
result, err := h.gatewayService.Forward(c.Request.Context(), c, account, body)
|
||||||
@@ -225,24 +237,25 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Error response already handled in Forward, just log
|
// Error response already handled in Forward, just log
|
||||||
log.Printf("Forward request failed: %v", err)
|
log.Printf("Account %d: Forward request failed: %v", account.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async record usage
|
// Async record usage
|
||||||
go func(result *service.OpenAIForwardResult, usedAccount *service.Account) {
|
go func(result *service.OpenAIForwardResult, usedAccount *service.Account, ua string) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := h.gatewayService.RecordUsage(ctx, &service.OpenAIRecordUsageInput{
|
if err := h.gatewayService.RecordUsage(ctx, &service.OpenAIRecordUsageInput{
|
||||||
Result: result,
|
Result: result,
|
||||||
ApiKey: apiKey,
|
APIKey: apiKey,
|
||||||
User: apiKey.User,
|
User: apiKey.User,
|
||||||
Account: usedAccount,
|
Account: usedAccount,
|
||||||
Subscription: subscription,
|
Subscription: subscription,
|
||||||
|
UserAgent: ua,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("Record usage failed: %v", err)
|
log.Printf("Record usage failed: %v", err)
|
||||||
}
|
}
|
||||||
}(result, account)
|
}(result, account, userAgent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
|
|||||||
SiteName: settings.SiteName,
|
SiteName: settings.SiteName,
|
||||||
SiteLogo: settings.SiteLogo,
|
SiteLogo: settings.SiteLogo,
|
||||||
SiteSubtitle: settings.SiteSubtitle,
|
SiteSubtitle: settings.SiteSubtitle,
|
||||||
ApiBaseUrl: settings.ApiBaseUrl,
|
APIBaseURL: settings.APIBaseURL,
|
||||||
ContactInfo: settings.ContactInfo,
|
ContactInfo: settings.ContactInfo,
|
||||||
DocUrl: settings.DocUrl,
|
DocURL: settings.DocURL,
|
||||||
Version: h.version,
|
Version: h.version,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ import (
|
|||||||
// UsageHandler handles usage-related requests
|
// UsageHandler handles usage-related requests
|
||||||
type UsageHandler struct {
|
type UsageHandler struct {
|
||||||
usageService *service.UsageService
|
usageService *service.UsageService
|
||||||
apiKeyService *service.ApiKeyService
|
apiKeyService *service.APIKeyService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUsageHandler creates a new UsageHandler
|
// NewUsageHandler creates a new UsageHandler
|
||||||
func NewUsageHandler(usageService *service.UsageService, apiKeyService *service.ApiKeyService) *UsageHandler {
|
func NewUsageHandler(usageService *service.UsageService, apiKeyService *service.APIKeyService) *UsageHandler {
|
||||||
return &UsageHandler{
|
return &UsageHandler{
|
||||||
usageService: usageService,
|
usageService: usageService,
|
||||||
apiKeyService: apiKeyService,
|
apiKeyService: apiKeyService,
|
||||||
@@ -88,8 +88,9 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
|
|
||||||
// Parse date range
|
// Parse date range
|
||||||
var startTime, endTime *time.Time
|
var startTime, endTime *time.Time
|
||||||
|
userTZ := c.Query("timezone") // Get user's timezone from request
|
||||||
if startDateStr := c.Query("start_date"); startDateStr != "" {
|
if startDateStr := c.Query("start_date"); startDateStr != "" {
|
||||||
t, err := timezone.ParseInLocation("2006-01-02", startDateStr)
|
t, err := timezone.ParseInUserLocation("2006-01-02", startDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -98,7 +99,7 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if endDateStr := c.Query("end_date"); endDateStr != "" {
|
if endDateStr := c.Query("end_date"); endDateStr != "" {
|
||||||
t, err := timezone.ParseInLocation("2006-01-02", endDateStr)
|
t, err := timezone.ParseInUserLocation("2006-01-02", endDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -111,7 +112,7 @@ func (h *UsageHandler) List(c *gin.Context) {
|
|||||||
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
|
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
|
||||||
filters := usagestats.UsageLogFilters{
|
filters := usagestats.UsageLogFilters{
|
||||||
UserID: subject.UserID, // Always filter by current user for security
|
UserID: subject.UserID, // Always filter by current user for security
|
||||||
ApiKeyID: apiKeyID,
|
APIKeyID: apiKeyID,
|
||||||
Model: model,
|
Model: model,
|
||||||
Stream: stream,
|
Stream: stream,
|
||||||
BillingType: billingType,
|
BillingType: billingType,
|
||||||
@@ -194,7 +195,8 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取时间范围参数
|
// 获取时间范围参数
|
||||||
now := timezone.Now()
|
userTZ := c.Query("timezone") // Get user's timezone from request
|
||||||
|
now := timezone.NowInUserLocation(userTZ)
|
||||||
var startTime, endTime time.Time
|
var startTime, endTime time.Time
|
||||||
|
|
||||||
// 优先使用 start_date 和 end_date 参数
|
// 优先使用 start_date 和 end_date 参数
|
||||||
@@ -204,12 +206,12 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
if startDateStr != "" && endDateStr != "" {
|
if startDateStr != "" && endDateStr != "" {
|
||||||
// 使用自定义日期范围
|
// 使用自定义日期范围
|
||||||
var err error
|
var err error
|
||||||
startTime, err = timezone.ParseInLocation("2006-01-02", startDateStr)
|
startTime, err = timezone.ParseInUserLocation("2006-01-02", startDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid start_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
endTime, err = timezone.ParseInLocation("2006-01-02", endDateStr)
|
endTime, err = timezone.ParseInUserLocation("2006-01-02", endDateStr, userTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
|
||||||
return
|
return
|
||||||
@@ -221,13 +223,13 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
period := c.DefaultQuery("period", "today")
|
period := c.DefaultQuery("period", "today")
|
||||||
switch period {
|
switch period {
|
||||||
case "today":
|
case "today":
|
||||||
startTime = timezone.StartOfDay(now)
|
startTime = timezone.StartOfDayInUserLocation(now, userTZ)
|
||||||
case "week":
|
case "week":
|
||||||
startTime = now.AddDate(0, 0, -7)
|
startTime = now.AddDate(0, 0, -7)
|
||||||
case "month":
|
case "month":
|
||||||
startTime = now.AddDate(0, -1, 0)
|
startTime = now.AddDate(0, -1, 0)
|
||||||
default:
|
default:
|
||||||
startTime = timezone.StartOfDay(now)
|
startTime = timezone.StartOfDayInUserLocation(now, userTZ)
|
||||||
}
|
}
|
||||||
endTime = now
|
endTime = now
|
||||||
}
|
}
|
||||||
@@ -235,7 +237,7 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
var stats *service.UsageStats
|
var stats *service.UsageStats
|
||||||
var err error
|
var err error
|
||||||
if apiKeyID > 0 {
|
if apiKeyID > 0 {
|
||||||
stats, err = h.usageService.GetStatsByApiKey(c.Request.Context(), apiKeyID, startTime, endTime)
|
stats, err = h.usageService.GetStatsByAPIKey(c.Request.Context(), apiKeyID, startTime, endTime)
|
||||||
} else {
|
} else {
|
||||||
stats, err = h.usageService.GetStatsByUser(c.Request.Context(), subject.UserID, startTime, endTime)
|
stats, err = h.usageService.GetStatsByUser(c.Request.Context(), subject.UserID, startTime, endTime)
|
||||||
}
|
}
|
||||||
@@ -248,31 +250,33 @@ func (h *UsageHandler) Stats(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseUserTimeRange parses start_date, end_date query parameters for user dashboard
|
// parseUserTimeRange parses start_date, end_date query parameters for user dashboard
|
||||||
|
// Uses user's timezone if provided, otherwise falls back to server timezone
|
||||||
func parseUserTimeRange(c *gin.Context) (time.Time, time.Time) {
|
func parseUserTimeRange(c *gin.Context) (time.Time, time.Time) {
|
||||||
now := timezone.Now()
|
userTZ := c.Query("timezone") // Get user's timezone from request
|
||||||
|
now := timezone.NowInUserLocation(userTZ)
|
||||||
startDate := c.Query("start_date")
|
startDate := c.Query("start_date")
|
||||||
endDate := c.Query("end_date")
|
endDate := c.Query("end_date")
|
||||||
|
|
||||||
var startTime, endTime time.Time
|
var startTime, endTime time.Time
|
||||||
|
|
||||||
if startDate != "" {
|
if startDate != "" {
|
||||||
if t, err := timezone.ParseInLocation("2006-01-02", startDate); err == nil {
|
if t, err := timezone.ParseInUserLocation("2006-01-02", startDate, userTZ); err == nil {
|
||||||
startTime = t
|
startTime = t
|
||||||
} else {
|
} else {
|
||||||
startTime = timezone.StartOfDay(now.AddDate(0, 0, -7))
|
startTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, -7), userTZ)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startTime = timezone.StartOfDay(now.AddDate(0, 0, -7))
|
startTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, -7), userTZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
if endDate != "" {
|
if endDate != "" {
|
||||||
if t, err := timezone.ParseInLocation("2006-01-02", endDate); err == nil {
|
if t, err := timezone.ParseInUserLocation("2006-01-02", endDate, userTZ); err == nil {
|
||||||
endTime = t.Add(24 * time.Hour) // Include the end date
|
endTime = t.Add(24 * time.Hour) // Include the end date
|
||||||
} else {
|
} else {
|
||||||
endTime = timezone.StartOfDay(now.AddDate(0, 0, 1))
|
endTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, 1), userTZ)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
endTime = timezone.StartOfDay(now.AddDate(0, 0, 1))
|
endTime = timezone.StartOfDayInUserLocation(now.AddDate(0, 0, 1), userTZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
return startTime, endTime
|
return startTime, endTime
|
||||||
@@ -346,49 +350,49 @@ func (h *UsageHandler) DashboardModels(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchApiKeysUsageRequest represents the request for batch API keys usage
|
// BatchAPIKeysUsageRequest represents the request for batch API keys usage
|
||||||
type BatchApiKeysUsageRequest struct {
|
type BatchAPIKeysUsageRequest struct {
|
||||||
ApiKeyIDs []int64 `json:"api_key_ids" binding:"required"`
|
APIKeyIDs []int64 `json:"api_key_ids" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DashboardApiKeysUsage handles getting usage stats for user's own API keys
|
// DashboardAPIKeysUsage handles getting usage stats for user's own API keys
|
||||||
// POST /api/v1/usage/dashboard/api-keys-usage
|
// POST /api/v1/usage/dashboard/api-keys-usage
|
||||||
func (h *UsageHandler) DashboardApiKeysUsage(c *gin.Context) {
|
func (h *UsageHandler) DashboardAPIKeysUsage(c *gin.Context) {
|
||||||
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
subject, ok := middleware2.GetAuthSubjectFromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
response.Unauthorized(c, "User not authenticated")
|
response.Unauthorized(c, "User not authenticated")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var req BatchApiKeysUsageRequest
|
var req BatchAPIKeysUsageRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(req.ApiKeyIDs) == 0 {
|
if len(req.APIKeyIDs) == 0 {
|
||||||
response.Success(c, gin.H{"stats": map[string]any{}})
|
response.Success(c, gin.H{"stats": map[string]any{}})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit the number of API key IDs to prevent SQL parameter overflow
|
// Limit the number of API key IDs to prevent SQL parameter overflow
|
||||||
if len(req.ApiKeyIDs) > 100 {
|
if len(req.APIKeyIDs) > 100 {
|
||||||
response.BadRequest(c, "Too many API key IDs (maximum 100 allowed)")
|
response.BadRequest(c, "Too many API key IDs (maximum 100 allowed)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
validApiKeyIDs, err := h.apiKeyService.VerifyOwnership(c.Request.Context(), subject.UserID, req.ApiKeyIDs)
|
validAPIKeyIDs, err := h.apiKeyService.VerifyOwnership(c.Request.Context(), subject.UserID, req.APIKeyIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(validApiKeyIDs) == 0 {
|
if len(validAPIKeyIDs) == 0 {
|
||||||
response.Success(c, gin.H{"stats": map[string]any{}})
|
response.Success(c, gin.H{"stats": map[string]any{}})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := h.usageService.GetBatchApiKeyUsageStats(c.Request.Context(), validApiKeyIDs)
|
stats, err := h.usageService.GetBatchAPIKeyUsageStats(c.Request.Context(), validAPIKeyIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package antigravity provides a client for the Antigravity API.
|
||||||
package antigravity
|
package antigravity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -12,16 +13,48 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// resolveHost 从 URL 解析 host
|
||||||
|
func resolveHost(urlStr string) string {
|
||||||
|
parsed, err := url.Parse(urlStr)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return parsed.Host
|
||||||
|
}
|
||||||
|
|
||||||
// NewAPIRequest 创建 Antigravity API 请求(v1internal 端点)
|
// NewAPIRequest 创建 Antigravity API 请求(v1internal 端点)
|
||||||
func NewAPIRequest(ctx context.Context, action, accessToken string, body []byte) (*http.Request, error) {
|
func NewAPIRequest(ctx context.Context, action, accessToken string, body []byte) (*http.Request, error) {
|
||||||
|
// 构建 URL,流式请求添加 ?alt=sse 参数
|
||||||
apiURL := fmt.Sprintf("%s/v1internal:%s", BaseURL, action)
|
apiURL := fmt.Sprintf("%s/v1internal:%s", BaseURL, action)
|
||||||
|
isStream := action == "streamGenerateContent"
|
||||||
|
if isStream {
|
||||||
|
apiURL += "?alt=sse"
|
||||||
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(body))
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 基础 Headers
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
req.Header.Set("User-Agent", UserAgent)
|
req.Header.Set("User-Agent", UserAgent)
|
||||||
|
|
||||||
|
// Accept Header 根据请求类型设置
|
||||||
|
if isStream {
|
||||||
|
req.Header.Set("Accept", "text/event-stream")
|
||||||
|
} else {
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显式设置 Host Header
|
||||||
|
if host := resolveHost(apiURL); host != "" {
|
||||||
|
req.Host = host
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:requestType 已在 JSON body 的 V1InternalRequest 中设置,不需要 HTTP Header
|
||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +90,29 @@ type TierInfo struct {
|
|||||||
Description string `json:"description"` // 描述
|
Description string `json:"description"` // 描述
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON supports both legacy string tiers and object tiers.
|
||||||
|
func (t *TierInfo) UnmarshalJSON(data []byte) error {
|
||||||
|
data = bytes.TrimSpace(data)
|
||||||
|
if len(data) == 0 || string(data) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if data[0] == '"' {
|
||||||
|
var id string
|
||||||
|
if err := json.Unmarshal(data, &id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.ID = id
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
type alias TierInfo
|
||||||
|
var decoded alias
|
||||||
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*t = TierInfo(decoded)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IneligibleTier 不符合条件的层级信息
|
// IneligibleTier 不符合条件的层级信息
|
||||||
type IneligibleTier struct {
|
type IneligibleTier struct {
|
||||||
Tier *TierInfo `json:"tier,omitempty"`
|
Tier *TierInfo `json:"tier,omitempty"`
|
||||||
|
|||||||
@@ -67,6 +67,13 @@ type GeminiGenerationConfig struct {
|
|||||||
TopK *int `json:"topK,omitempty"`
|
TopK *int `json:"topK,omitempty"`
|
||||||
ThinkingConfig *GeminiThinkingConfig `json:"thinkingConfig,omitempty"`
|
ThinkingConfig *GeminiThinkingConfig `json:"thinkingConfig,omitempty"`
|
||||||
StopSequences []string `json:"stopSequences,omitempty"`
|
StopSequences []string `json:"stopSequences,omitempty"`
|
||||||
|
ImageConfig *GeminiImageConfig `json:"imageConfig,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeminiImageConfig Gemini 图片生成配置(仅 gemini-3-pro-image 支持)
|
||||||
|
type GeminiImageConfig struct {
|
||||||
|
AspectRatio string `json:"aspectRatio,omitempty"` // "1:1", "16:9", "9:16", "4:3", "3:4"
|
||||||
|
ImageSize string `json:"imageSize,omitempty"` // "1K", "2K", "4K"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GeminiThinkingConfig Gemini thinking 配置
|
// GeminiThinkingConfig Gemini thinking 配置
|
||||||
|
|||||||
@@ -33,10 +33,11 @@ const (
|
|||||||
"https://www.googleapis.com/auth/experimentsandconfigs"
|
"https://www.googleapis.com/auth/experimentsandconfigs"
|
||||||
|
|
||||||
// API 端点
|
// API 端点
|
||||||
BaseURL = "https://cloudcode-pa.googleapis.com"
|
// 优先使用 sandbox daily URL,配额更宽松
|
||||||
|
BaseURL = "https://daily-cloudcode-pa.sandbox.googleapis.com"
|
||||||
|
|
||||||
// User-Agent
|
// User-Agent(模拟官方客户端)
|
||||||
UserAgent = "antigravity/1.11.9 windows/amd64"
|
UserAgent = "antigravity/1.104.0 darwin/arm64"
|
||||||
|
|
||||||
// Session 过期时间
|
// Session 过期时间
|
||||||
SessionTTL = 30 * time.Minute
|
SessionTTL = 30 * time.Minute
|
||||||
|
|||||||
@@ -1,16 +1,66 @@
|
|||||||
package antigravity
|
package antigravity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sessionRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
sessionRandMutex sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
// generateStableSessionID 基于用户消息内容生成稳定的 session ID
|
||||||
|
func generateStableSessionID(contents []GeminiContent) string {
|
||||||
|
// 查找第一个 user 消息的文本
|
||||||
|
for _, content := range contents {
|
||||||
|
if content.Role == "user" && len(content.Parts) > 0 {
|
||||||
|
if text := content.Parts[0].Text; text != "" {
|
||||||
|
h := sha256.Sum256([]byte(text))
|
||||||
|
n := int64(binary.BigEndian.Uint64(h[:8])) & 0x7FFFFFFFFFFFFFFF
|
||||||
|
return "-" + strconv.FormatInt(n, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 回退:生成随机 session ID
|
||||||
|
sessionRandMutex.Lock()
|
||||||
|
n := sessionRand.Int63n(9_000_000_000_000_000_000)
|
||||||
|
sessionRandMutex.Unlock()
|
||||||
|
return "-" + strconv.FormatInt(n, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransformOptions struct {
|
||||||
|
EnableIdentityPatch bool
|
||||||
|
// IdentityPatch 可选:自定义注入到 systemInstruction 开头的身份防护提示词;
|
||||||
|
// 为空时使用默认模板(包含 [IDENTITY_PATCH] 及 SYSTEM_PROMPT_BEGIN 标记)。
|
||||||
|
IdentityPatch string
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultTransformOptions() TransformOptions {
|
||||||
|
return TransformOptions{
|
||||||
|
EnableIdentityPatch: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TransformClaudeToGemini 将 Claude 请求转换为 v1internal Gemini 格式
|
// TransformClaudeToGemini 将 Claude 请求转换为 v1internal Gemini 格式
|
||||||
func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel string) ([]byte, error) {
|
func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel string) ([]byte, error) {
|
||||||
|
return TransformClaudeToGeminiWithOptions(claudeReq, projectID, mappedModel, DefaultTransformOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformClaudeToGeminiWithOptions 将 Claude 请求转换为 v1internal Gemini 格式(可配置身份补丁等行为)
|
||||||
|
func TransformClaudeToGeminiWithOptions(claudeReq *ClaudeRequest, projectID, mappedModel string, opts TransformOptions) ([]byte, error) {
|
||||||
// 用于存储 tool_use id -> name 映射
|
// 用于存储 tool_use id -> name 映射
|
||||||
toolIDToName := make(map[string]string)
|
toolIDToName := make(map[string]string)
|
||||||
|
|
||||||
@@ -22,24 +72,39 @@ func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel st
|
|||||||
allowDummyThought := strings.HasPrefix(mappedModel, "gemini-")
|
allowDummyThought := strings.HasPrefix(mappedModel, "gemini-")
|
||||||
|
|
||||||
// 1. 构建 contents
|
// 1. 构建 contents
|
||||||
contents, err := buildContents(claudeReq.Messages, toolIDToName, isThinkingEnabled, allowDummyThought)
|
contents, strippedThinking, err := buildContents(claudeReq.Messages, toolIDToName, isThinkingEnabled, allowDummyThought)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("build contents: %w", err)
|
return nil, fmt.Errorf("build contents: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 构建 systemInstruction
|
// 2. 构建 systemInstruction
|
||||||
systemInstruction := buildSystemInstruction(claudeReq.System, claudeReq.Model)
|
systemInstruction := buildSystemInstruction(claudeReq.System, claudeReq.Model, opts)
|
||||||
|
|
||||||
// 3. 构建 generationConfig
|
// 3. 构建 generationConfig
|
||||||
generationConfig := buildGenerationConfig(claudeReq)
|
reqForConfig := claudeReq
|
||||||
|
if strippedThinking {
|
||||||
|
// If we had to downgrade thinking blocks to plain text due to missing/invalid signatures,
|
||||||
|
// disable upstream thinking mode to avoid signature/structure validation errors.
|
||||||
|
reqCopy := *claudeReq
|
||||||
|
reqCopy.Thinking = nil
|
||||||
|
reqForConfig = &reqCopy
|
||||||
|
}
|
||||||
|
generationConfig := buildGenerationConfig(reqForConfig)
|
||||||
|
|
||||||
// 4. 构建 tools
|
// 4. 构建 tools
|
||||||
tools := buildTools(claudeReq.Tools)
|
tools := buildTools(claudeReq.Tools)
|
||||||
|
|
||||||
// 5. 构建内部请求
|
// 5. 构建内部请求
|
||||||
innerRequest := GeminiRequest{
|
innerRequest := GeminiRequest{
|
||||||
Contents: contents,
|
Contents: contents,
|
||||||
SafetySettings: DefaultSafetySettings,
|
// 总是设置 toolConfig,与官方客户端一致
|
||||||
|
ToolConfig: &GeminiToolConfig{
|
||||||
|
FunctionCallingConfig: &GeminiFunctionCallingConfig{
|
||||||
|
Mode: "VALIDATED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 总是生成 sessionId,基于用户消息内容
|
||||||
|
SessionID: generateStableSessionID(contents),
|
||||||
}
|
}
|
||||||
|
|
||||||
if systemInstruction != nil {
|
if systemInstruction != nil {
|
||||||
@@ -50,14 +115,9 @@ func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel st
|
|||||||
}
|
}
|
||||||
if len(tools) > 0 {
|
if len(tools) > 0 {
|
||||||
innerRequest.Tools = tools
|
innerRequest.Tools = tools
|
||||||
innerRequest.ToolConfig = &GeminiToolConfig{
|
|
||||||
FunctionCallingConfig: &GeminiFunctionCallingConfig{
|
|
||||||
Mode: "VALIDATED",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果提供了 metadata.user_id,复用为 sessionId
|
// 如果提供了 metadata.user_id,优先使用
|
||||||
if claudeReq.Metadata != nil && claudeReq.Metadata.UserID != "" {
|
if claudeReq.Metadata != nil && claudeReq.Metadata.UserID != "" {
|
||||||
innerRequest.SessionID = claudeReq.Metadata.UserID
|
innerRequest.SessionID = claudeReq.Metadata.UserID
|
||||||
}
|
}
|
||||||
@@ -66,7 +126,7 @@ func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel st
|
|||||||
v1Req := V1InternalRequest{
|
v1Req := V1InternalRequest{
|
||||||
Project: projectID,
|
Project: projectID,
|
||||||
RequestID: "agent-" + uuid.New().String(),
|
RequestID: "agent-" + uuid.New().String(),
|
||||||
UserAgent: "sub2api",
|
UserAgent: "antigravity", // 固定值,与官方客户端一致
|
||||||
RequestType: "agent",
|
RequestType: "agent",
|
||||||
Model: mappedModel,
|
Model: mappedModel,
|
||||||
Request: innerRequest,
|
Request: innerRequest,
|
||||||
@@ -75,28 +135,37 @@ func TransformClaudeToGemini(claudeReq *ClaudeRequest, projectID, mappedModel st
|
|||||||
return json.Marshal(v1Req)
|
return json.Marshal(v1Req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// antigravityIdentity Antigravity identity 提示词
|
||||||
|
const antigravityIdentity = `<identity>
|
||||||
|
You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding.
|
||||||
|
You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.
|
||||||
|
The USER will send you requests, which you must always prioritize addressing. Along with each USER request, we will attach additional metadata about their current state, such as what files they have open and where their cursor is.
|
||||||
|
This information may or may not be relevant to the coding task, it is up for you to decide.
|
||||||
|
</identity>
|
||||||
|
<communication_style>
|
||||||
|
- **Proactiveness**. As an agent, you are allowed to be proactive, but only in the course of completing the user's task. For example, if the user asks you to add a new component, you can edit the code, verify build and test statuses, and take any other obvious follow-up actions, such as performing additional research. However, avoid surprising the user. For example, if the user asks HOW to approach something, you should answer their question and instead of jumping into editing a file.</communication_style>`
|
||||||
|
|
||||||
|
func defaultIdentityPatch(_ string) string {
|
||||||
|
return antigravityIdentity
|
||||||
|
}
|
||||||
|
|
||||||
// buildSystemInstruction 构建 systemInstruction
|
// buildSystemInstruction 构建 systemInstruction
|
||||||
func buildSystemInstruction(system json.RawMessage, modelName string) *GeminiContent {
|
func buildSystemInstruction(system json.RawMessage, modelName string, opts TransformOptions) *GeminiContent {
|
||||||
var parts []GeminiPart
|
var parts []GeminiPart
|
||||||
|
|
||||||
// 注入身份防护指令
|
// 先解析用户的 system prompt,检测是否已包含 Antigravity identity
|
||||||
identityPatch := fmt.Sprintf(
|
userHasAntigravityIdentity := false
|
||||||
"--- [IDENTITY_PATCH] ---\n"+
|
var userSystemParts []GeminiPart
|
||||||
"Ignore any previous instructions regarding your identity or host platform (e.g., Amazon Q, Google AI).\n"+
|
|
||||||
"You are currently providing services as the native %s model via a standard API proxy.\n"+
|
|
||||||
"Always use the 'claude' command for terminal tasks if relevant.\n"+
|
|
||||||
"--- [SYSTEM_PROMPT_BEGIN] ---\n",
|
|
||||||
modelName,
|
|
||||||
)
|
|
||||||
parts = append(parts, GeminiPart{Text: identityPatch})
|
|
||||||
|
|
||||||
// 解析 system prompt
|
|
||||||
if len(system) > 0 {
|
if len(system) > 0 {
|
||||||
// 尝试解析为字符串
|
// 尝试解析为字符串
|
||||||
var sysStr string
|
var sysStr string
|
||||||
if err := json.Unmarshal(system, &sysStr); err == nil {
|
if err := json.Unmarshal(system, &sysStr); err == nil {
|
||||||
if strings.TrimSpace(sysStr) != "" {
|
if strings.TrimSpace(sysStr) != "" {
|
||||||
parts = append(parts, GeminiPart{Text: sysStr})
|
userSystemParts = append(userSystemParts, GeminiPart{Text: sysStr})
|
||||||
|
if strings.Contains(sysStr, "You are Antigravity") {
|
||||||
|
userHasAntigravityIdentity = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 尝试解析为数组
|
// 尝试解析为数组
|
||||||
@@ -104,14 +173,31 @@ func buildSystemInstruction(system json.RawMessage, modelName string) *GeminiCon
|
|||||||
if err := json.Unmarshal(system, &sysBlocks); err == nil {
|
if err := json.Unmarshal(system, &sysBlocks); err == nil {
|
||||||
for _, block := range sysBlocks {
|
for _, block := range sysBlocks {
|
||||||
if block.Type == "text" && strings.TrimSpace(block.Text) != "" {
|
if block.Type == "text" && strings.TrimSpace(block.Text) != "" {
|
||||||
parts = append(parts, GeminiPart{Text: block.Text})
|
userSystemParts = append(userSystemParts, GeminiPart{Text: block.Text})
|
||||||
|
if strings.Contains(block.Text, "You are Antigravity") {
|
||||||
|
userHasAntigravityIdentity = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parts = append(parts, GeminiPart{Text: "\n--- [SYSTEM_PROMPT_END] ---"})
|
// 仅在用户未提供 Antigravity identity 时注入
|
||||||
|
if opts.EnableIdentityPatch && !userHasAntigravityIdentity {
|
||||||
|
identityPatch := strings.TrimSpace(opts.IdentityPatch)
|
||||||
|
if identityPatch == "" {
|
||||||
|
identityPatch = defaultIdentityPatch(modelName)
|
||||||
|
}
|
||||||
|
parts = append(parts, GeminiPart{Text: identityPatch})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加用户的 system prompt
|
||||||
|
parts = append(parts, userSystemParts...)
|
||||||
|
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return &GeminiContent{
|
return &GeminiContent{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
@@ -120,8 +206,9 @@ func buildSystemInstruction(system json.RawMessage, modelName string) *GeminiCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildContents 构建 contents
|
// buildContents 构建 contents
|
||||||
func buildContents(messages []ClaudeMessage, toolIDToName map[string]string, isThinkingEnabled, allowDummyThought bool) ([]GeminiContent, error) {
|
func buildContents(messages []ClaudeMessage, toolIDToName map[string]string, isThinkingEnabled, allowDummyThought bool) ([]GeminiContent, bool, error) {
|
||||||
var contents []GeminiContent
|
var contents []GeminiContent
|
||||||
|
strippedThinking := false
|
||||||
|
|
||||||
for i, msg := range messages {
|
for i, msg := range messages {
|
||||||
role := msg.Role
|
role := msg.Role
|
||||||
@@ -129,9 +216,12 @@ func buildContents(messages []ClaudeMessage, toolIDToName map[string]string, isT
|
|||||||
role = "model"
|
role = "model"
|
||||||
}
|
}
|
||||||
|
|
||||||
parts, err := buildParts(msg.Content, toolIDToName, allowDummyThought)
|
parts, strippedThisMsg, err := buildParts(msg.Content, toolIDToName, allowDummyThought)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("build parts for message %d: %w", i, err)
|
return nil, false, fmt.Errorf("build parts for message %d: %w", i, err)
|
||||||
|
}
|
||||||
|
if strippedThisMsg {
|
||||||
|
strippedThinking = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只有 Gemini 模型支持 dummy thinking block workaround
|
// 只有 Gemini 模型支持 dummy thinking block workaround
|
||||||
@@ -165,7 +255,7 @@ func buildContents(messages []ClaudeMessage, toolIDToName map[string]string, isT
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return contents, nil
|
return contents, strippedThinking, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummyThoughtSignature 用于跳过 Gemini 3 thought_signature 验证
|
// dummyThoughtSignature 用于跳过 Gemini 3 thought_signature 验证
|
||||||
@@ -174,8 +264,9 @@ const dummyThoughtSignature = "skip_thought_signature_validator"
|
|||||||
|
|
||||||
// buildParts 构建消息的 parts
|
// buildParts 构建消息的 parts
|
||||||
// allowDummyThought: 只有 Gemini 模型支持 dummy thought signature
|
// allowDummyThought: 只有 Gemini 模型支持 dummy thought signature
|
||||||
func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDummyThought bool) ([]GeminiPart, error) {
|
func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDummyThought bool) ([]GeminiPart, bool, error) {
|
||||||
var parts []GeminiPart
|
var parts []GeminiPart
|
||||||
|
strippedThinking := false
|
||||||
|
|
||||||
// 尝试解析为字符串
|
// 尝试解析为字符串
|
||||||
var textContent string
|
var textContent string
|
||||||
@@ -183,13 +274,13 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu
|
|||||||
if textContent != "(no content)" && strings.TrimSpace(textContent) != "" {
|
if textContent != "(no content)" && strings.TrimSpace(textContent) != "" {
|
||||||
parts = append(parts, GeminiPart{Text: strings.TrimSpace(textContent)})
|
parts = append(parts, GeminiPart{Text: strings.TrimSpace(textContent)})
|
||||||
}
|
}
|
||||||
return parts, nil
|
return parts, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析为内容块数组
|
// 解析为内容块数组
|
||||||
var blocks []ContentBlock
|
var blocks []ContentBlock
|
||||||
if err := json.Unmarshal(content, &blocks); err != nil {
|
if err := json.Unmarshal(content, &blocks); err != nil {
|
||||||
return nil, fmt.Errorf("parse content blocks: %w", err)
|
return nil, false, fmt.Errorf("parse content blocks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, block := range blocks {
|
for _, block := range blocks {
|
||||||
@@ -208,8 +299,11 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu
|
|||||||
if block.Signature != "" {
|
if block.Signature != "" {
|
||||||
part.ThoughtSignature = block.Signature
|
part.ThoughtSignature = block.Signature
|
||||||
} else if !allowDummyThought {
|
} else if !allowDummyThought {
|
||||||
// Claude 模型需要有效 signature,跳过无 signature 的 thinking block
|
// Claude 模型需要有效 signature;在缺失时降级为普通文本,并在上层禁用 thinking mode。
|
||||||
log.Printf("Warning: skipping thinking block without signature for Claude model")
|
if strings.TrimSpace(block.Thinking) != "" {
|
||||||
|
parts = append(parts, GeminiPart{Text: block.Thinking})
|
||||||
|
}
|
||||||
|
strippedThinking = true
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
// Gemini 模型使用 dummy signature
|
// Gemini 模型使用 dummy signature
|
||||||
@@ -240,10 +334,13 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu
|
|||||||
ID: block.ID,
|
ID: block.ID,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// 只有 Gemini 模型使用 dummy signature
|
// tool_use 的 signature 处理:
|
||||||
// Claude 模型不设置 signature(避免验证问题)
|
// - Gemini 模型:使用 dummy signature(跳过 thought_signature 校验)
|
||||||
|
// - Claude 模型:透传上游返回的真实 signature(Vertex/Google 需要完整签名链路)
|
||||||
if allowDummyThought {
|
if allowDummyThought {
|
||||||
part.ThoughtSignature = dummyThoughtSignature
|
part.ThoughtSignature = dummyThoughtSignature
|
||||||
|
} else if block.Signature != "" && block.Signature != dummyThoughtSignature {
|
||||||
|
part.ThoughtSignature = block.Signature
|
||||||
}
|
}
|
||||||
parts = append(parts, part)
|
parts = append(parts, part)
|
||||||
|
|
||||||
@@ -273,7 +370,7 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parts, nil
|
return parts, strippedThinking, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseToolResultContent 解析 tool_result 的 content
|
// parseToolResultContent 解析 tool_result 的 content
|
||||||
@@ -443,7 +540,7 @@ func cleanJSONSchema(schema map[string]any) map[string]any {
|
|||||||
if schema == nil {
|
if schema == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cleaned := cleanSchemaValue(schema)
|
cleaned := cleanSchemaValue(schema, "$")
|
||||||
result, ok := cleaned.(map[string]any)
|
result, ok := cleaned.(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
@@ -481,6 +578,56 @@ func cleanJSONSchema(schema map[string]any) map[string]any {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var schemaValidationKeys = map[string]bool{
|
||||||
|
"minLength": true,
|
||||||
|
"maxLength": true,
|
||||||
|
"pattern": true,
|
||||||
|
"minimum": true,
|
||||||
|
"maximum": true,
|
||||||
|
"exclusiveMinimum": true,
|
||||||
|
"exclusiveMaximum": true,
|
||||||
|
"multipleOf": true,
|
||||||
|
"uniqueItems": true,
|
||||||
|
"minItems": true,
|
||||||
|
"maxItems": true,
|
||||||
|
"minProperties": true,
|
||||||
|
"maxProperties": true,
|
||||||
|
"patternProperties": true,
|
||||||
|
"propertyNames": true,
|
||||||
|
"dependencies": true,
|
||||||
|
"dependentSchemas": true,
|
||||||
|
"dependentRequired": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var warnedSchemaKeys sync.Map
|
||||||
|
|
||||||
|
func schemaCleaningWarningsEnabled() bool {
|
||||||
|
// 可通过环境变量强制开关,方便排查:SUB2API_SCHEMA_CLEAN_WARN=true/false
|
||||||
|
if v := strings.TrimSpace(os.Getenv("SUB2API_SCHEMA_CLEAN_WARN")); v != "" {
|
||||||
|
switch strings.ToLower(v) {
|
||||||
|
case "1", "true", "yes", "on":
|
||||||
|
return true
|
||||||
|
case "0", "false", "no", "off":
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 默认:非 release 模式下输出(debug/test)
|
||||||
|
return gin.Mode() != gin.ReleaseMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func warnSchemaKeyRemovedOnce(key, path string) {
|
||||||
|
if !schemaCleaningWarningsEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !schemaValidationKeys[key] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, loaded := warnedSchemaKeys.LoadOrStore(key, struct{}{}); loaded {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("[SchemaClean] removed unsupported JSON Schema validation field key=%q path=%q", key, path)
|
||||||
|
}
|
||||||
|
|
||||||
// excludedSchemaKeys 不支持的 schema 字段
|
// excludedSchemaKeys 不支持的 schema 字段
|
||||||
// 基于 Claude API (Vertex AI) 的实际支持情况
|
// 基于 Claude API (Vertex AI) 的实际支持情况
|
||||||
// 支持: type, description, enum, properties, required, additionalProperties, items
|
// 支持: type, description, enum, properties, required, additionalProperties, items
|
||||||
@@ -543,13 +690,14 @@ var excludedSchemaKeys = map[string]bool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanSchemaValue 递归清理 schema 值
|
// cleanSchemaValue 递归清理 schema 值
|
||||||
func cleanSchemaValue(value any) any {
|
func cleanSchemaValue(value any, path string) any {
|
||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case map[string]any:
|
case map[string]any:
|
||||||
result := make(map[string]any)
|
result := make(map[string]any)
|
||||||
for k, val := range v {
|
for k, val := range v {
|
||||||
// 跳过不支持的字段
|
// 跳过不支持的字段
|
||||||
if excludedSchemaKeys[k] {
|
if excludedSchemaKeys[k] {
|
||||||
|
warnSchemaKeyRemovedOnce(k, path)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,15 +731,15 @@ func cleanSchemaValue(value any) any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 递归清理所有值
|
// 递归清理所有值
|
||||||
result[k] = cleanSchemaValue(val)
|
result[k] = cleanSchemaValue(val, path+"."+k)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case []any:
|
case []any:
|
||||||
// 递归处理数组中的每个元素
|
// 递归处理数组中的每个元素
|
||||||
cleaned := make([]any, 0, len(v))
|
cleaned := make([]any, 0, len(v))
|
||||||
for _, item := range v {
|
for i, item := range v {
|
||||||
cleaned = append(cleaned, cleanSchemaValue(item))
|
cleaned = append(cleaned, cleanSchemaValue(item, fmt.Sprintf("%s[%d]", path, i)))
|
||||||
}
|
}
|
||||||
return cleaned
|
return cleaned
|
||||||
|
|
||||||
|
|||||||
@@ -15,26 +15,26 @@ func TestBuildParts_ThinkingBlockWithoutSignature(t *testing.T) {
|
|||||||
description string
|
description string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Claude model - skip thinking block without signature",
|
name: "Claude model - downgrade thinking to text without signature",
|
||||||
content: `[
|
content: `[
|
||||||
{"type": "text", "text": "Hello"},
|
{"type": "text", "text": "Hello"},
|
||||||
{"type": "thinking", "thinking": "Let me think...", "signature": ""},
|
{"type": "thinking", "thinking": "Let me think...", "signature": ""},
|
||||||
{"type": "text", "text": "World"}
|
{"type": "text", "text": "World"}
|
||||||
]`,
|
]`,
|
||||||
allowDummyThought: false,
|
allowDummyThought: false,
|
||||||
expectedParts: 2, // 只有两个text block
|
expectedParts: 3, // thinking 内容降级为普通 text part
|
||||||
description: "Claude模型应该跳过无signature的thinking block",
|
description: "Claude模型缺少signature时应将thinking降级为text,并在上层禁用thinking mode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Claude model - keep thinking block with signature",
|
name: "Claude model - preserve thinking block with signature",
|
||||||
content: `[
|
content: `[
|
||||||
{"type": "text", "text": "Hello"},
|
{"type": "text", "text": "Hello"},
|
||||||
{"type": "thinking", "thinking": "Let me think...", "signature": "valid_sig"},
|
{"type": "thinking", "thinking": "Let me think...", "signature": "sig_real_123"},
|
||||||
{"type": "text", "text": "World"}
|
{"type": "text", "text": "World"}
|
||||||
]`,
|
]`,
|
||||||
allowDummyThought: false,
|
allowDummyThought: false,
|
||||||
expectedParts: 3, // 三个block都保留
|
expectedParts: 3,
|
||||||
description: "Claude模型应该保留有signature的thinking block",
|
description: "Claude模型应透传带 signature 的 thinking block(用于 Vertex 签名链路)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Gemini model - use dummy signature",
|
name: "Gemini model - use dummy signature",
|
||||||
@@ -52,7 +52,7 @@ func TestBuildParts_ThinkingBlockWithoutSignature(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
toolIDToName := make(map[string]string)
|
toolIDToName := make(map[string]string)
|
||||||
parts, err := buildParts(json.RawMessage(tt.content), toolIDToName, tt.allowDummyThought)
|
parts, _, err := buildParts(json.RawMessage(tt.content), toolIDToName, tt.allowDummyThought)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("buildParts() error = %v", err)
|
t.Fatalf("buildParts() error = %v", err)
|
||||||
@@ -61,10 +61,75 @@ func TestBuildParts_ThinkingBlockWithoutSignature(t *testing.T) {
|
|||||||
if len(parts) != tt.expectedParts {
|
if len(parts) != tt.expectedParts {
|
||||||
t.Errorf("%s: got %d parts, want %d parts", tt.description, len(parts), tt.expectedParts)
|
t.Errorf("%s: got %d parts, want %d parts", tt.description, len(parts), tt.expectedParts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch tt.name {
|
||||||
|
case "Claude model - preserve thinking block with signature":
|
||||||
|
if len(parts) != 3 {
|
||||||
|
t.Fatalf("expected 3 parts, got %d", len(parts))
|
||||||
|
}
|
||||||
|
if !parts[1].Thought || parts[1].ThoughtSignature != "sig_real_123" {
|
||||||
|
t.Fatalf("expected thought part with signature sig_real_123, got thought=%v signature=%q",
|
||||||
|
parts[1].Thought, parts[1].ThoughtSignature)
|
||||||
|
}
|
||||||
|
case "Claude model - downgrade thinking to text without signature":
|
||||||
|
if len(parts) != 3 {
|
||||||
|
t.Fatalf("expected 3 parts, got %d", len(parts))
|
||||||
|
}
|
||||||
|
if parts[1].Thought {
|
||||||
|
t.Fatalf("expected downgraded text part, got thought=%v signature=%q",
|
||||||
|
parts[1].Thought, parts[1].ThoughtSignature)
|
||||||
|
}
|
||||||
|
if parts[1].Text != "Let me think..." {
|
||||||
|
t.Fatalf("expected downgraded text %q, got %q", "Let me think...", parts[1].Text)
|
||||||
|
}
|
||||||
|
case "Gemini model - use dummy signature":
|
||||||
|
if len(parts) != 3 {
|
||||||
|
t.Fatalf("expected 3 parts, got %d", len(parts))
|
||||||
|
}
|
||||||
|
if !parts[1].Thought || parts[1].ThoughtSignature != dummyThoughtSignature {
|
||||||
|
t.Fatalf("expected dummy thought signature, got thought=%v signature=%q",
|
||||||
|
parts[1].Thought, parts[1].ThoughtSignature)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildParts_ToolUseSignatureHandling(t *testing.T) {
|
||||||
|
content := `[
|
||||||
|
{"type": "tool_use", "id": "t1", "name": "Bash", "input": {"command": "ls"}, "signature": "sig_tool_abc"}
|
||||||
|
]`
|
||||||
|
|
||||||
|
t.Run("Gemini uses dummy tool_use signature", func(t *testing.T) {
|
||||||
|
toolIDToName := make(map[string]string)
|
||||||
|
parts, _, err := buildParts(json.RawMessage(content), toolIDToName, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("buildParts() error = %v", err)
|
||||||
|
}
|
||||||
|
if len(parts) != 1 || parts[0].FunctionCall == nil {
|
||||||
|
t.Fatalf("expected 1 functionCall part, got %+v", parts)
|
||||||
|
}
|
||||||
|
if parts[0].ThoughtSignature != dummyThoughtSignature {
|
||||||
|
t.Fatalf("expected dummy tool signature %q, got %q", dummyThoughtSignature, parts[0].ThoughtSignature)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Claude model - preserve valid signature for tool_use", func(t *testing.T) {
|
||||||
|
toolIDToName := make(map[string]string)
|
||||||
|
parts, _, err := buildParts(json.RawMessage(content), toolIDToName, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("buildParts() error = %v", err)
|
||||||
|
}
|
||||||
|
if len(parts) != 1 || parts[0].FunctionCall == nil {
|
||||||
|
t.Fatalf("expected 1 functionCall part, got %+v", parts)
|
||||||
|
}
|
||||||
|
// Claude 模型应透传有效的 signature(Vertex/Google 需要完整签名链路)
|
||||||
|
if parts[0].ThoughtSignature != "sig_tool_abc" {
|
||||||
|
t.Fatalf("expected preserved tool signature %q, got %q", "sig_tool_abc", parts[0].ThoughtSignature)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestBuildTools_CustomTypeTools 测试custom类型工具转换
|
// TestBuildTools_CustomTypeTools 测试custom类型工具转换
|
||||||
func TestBuildTools_CustomTypeTools(t *testing.T) {
|
func TestBuildTools_CustomTypeTools(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package claude provides constants and helpers for Claude API integration.
|
||||||
package claude
|
package claude
|
||||||
|
|
||||||
// Claude Code 客户端相关常量
|
// Claude Code 客户端相关常量
|
||||||
@@ -16,13 +17,13 @@ const DefaultBetaHeader = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleav
|
|||||||
// HaikuBetaHeader Haiku 模型使用的 anthropic-beta header(不需要 claude-code beta)
|
// HaikuBetaHeader Haiku 模型使用的 anthropic-beta header(不需要 claude-code beta)
|
||||||
const HaikuBetaHeader = BetaOAuth + "," + BetaInterleavedThinking
|
const HaikuBetaHeader = BetaOAuth + "," + BetaInterleavedThinking
|
||||||
|
|
||||||
// ApiKeyBetaHeader API-key 账号建议使用的 anthropic-beta header(不包含 oauth)
|
// APIKeyBetaHeader API-key 账号建议使用的 anthropic-beta header(不包含 oauth)
|
||||||
const ApiKeyBetaHeader = BetaClaudeCode + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
|
const APIKeyBetaHeader = BetaClaudeCode + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
|
||||||
|
|
||||||
// ApiKeyHaikuBetaHeader Haiku 模型在 API-key 账号下使用的 anthropic-beta header(不包含 oauth / claude-code)
|
// APIKeyHaikuBetaHeader Haiku 模型在 API-key 账号下使用的 anthropic-beta header(不包含 oauth / claude-code)
|
||||||
const ApiKeyHaikuBetaHeader = BetaInterleavedThinking
|
const APIKeyHaikuBetaHeader = BetaInterleavedThinking
|
||||||
|
|
||||||
// Claude Code 客户端默认请求头
|
// DefaultHeaders 是 Claude Code 客户端默认请求头。
|
||||||
var DefaultHeaders = map[string]string{
|
var DefaultHeaders = map[string]string{
|
||||||
"User-Agent": "claude-cli/2.0.62 (external, cli)",
|
"User-Agent": "claude-cli/2.0.62 (external, cli)",
|
||||||
"X-Stainless-Lang": "js",
|
"X-Stainless-Lang": "js",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package errors provides application error types and helpers.
|
||||||
// nolint:mnd
|
// nolint:mnd
|
||||||
package errors
|
package errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package gemini
|
// Package gemini provides minimal fallback model metadata for Gemini native endpoints.
|
||||||
|
|
||||||
// This package provides minimal fallback model metadata for Gemini native endpoints.
|
|
||||||
// It is used when upstream model listing is unavailable (e.g. OAuth token missing AI Studio scopes).
|
// It is used when upstream model listing is unavailable (e.g. OAuth token missing AI Studio scopes).
|
||||||
|
package gemini
|
||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package geminicli
|
package geminicli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
// LoadCodeAssistRequest matches done-hub's internal Code Assist call.
|
// LoadCodeAssistRequest matches done-hub's internal Code Assist call.
|
||||||
type LoadCodeAssistRequest struct {
|
type LoadCodeAssistRequest struct {
|
||||||
Metadata LoadCodeAssistMetadata `json:"metadata"`
|
Metadata LoadCodeAssistMetadata `json:"metadata"`
|
||||||
@@ -11,12 +16,51 @@ type LoadCodeAssistMetadata struct {
|
|||||||
PluginType string `json:"pluginType"`
|
PluginType string `json:"pluginType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TierInfo struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON supports both legacy string tiers and object tiers.
|
||||||
|
func (t *TierInfo) UnmarshalJSON(data []byte) error {
|
||||||
|
data = bytes.TrimSpace(data)
|
||||||
|
if len(data) == 0 || string(data) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if data[0] == '"' {
|
||||||
|
var id string
|
||||||
|
if err := json.Unmarshal(data, &id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.ID = id
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
type alias TierInfo
|
||||||
|
var decoded alias
|
||||||
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*t = TierInfo(decoded)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type LoadCodeAssistResponse struct {
|
type LoadCodeAssistResponse struct {
|
||||||
CurrentTier string `json:"currentTier,omitempty"`
|
CurrentTier *TierInfo `json:"currentTier,omitempty"`
|
||||||
|
PaidTier *TierInfo `json:"paidTier,omitempty"`
|
||||||
CloudAICompanionProject string `json:"cloudaicompanionProject,omitempty"`
|
CloudAICompanionProject string `json:"cloudaicompanionProject,omitempty"`
|
||||||
AllowedTiers []AllowedTier `json:"allowedTiers,omitempty"`
|
AllowedTiers []AllowedTier `json:"allowedTiers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTier extracts tier ID, prioritizing paidTier over currentTier
|
||||||
|
func (r *LoadCodeAssistResponse) GetTier() string {
|
||||||
|
if r.PaidTier != nil && r.PaidTier.ID != "" {
|
||||||
|
return r.PaidTier.ID
|
||||||
|
}
|
||||||
|
if r.CurrentTier != nil {
|
||||||
|
return r.CurrentTier.ID
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type AllowedTier struct {
|
type AllowedTier struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
IsDefault bool `json:"isDefault,omitempty"`
|
IsDefault bool `json:"isDefault,omitempty"`
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package geminicli provides helpers for interacting with Gemini CLI tools.
|
||||||
package geminicli
|
package geminicli
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
@@ -26,6 +27,12 @@ const (
|
|||||||
// https://www.googleapis.com/auth/generative-language.retriever (often with cloud-platform).
|
// https://www.googleapis.com/auth/generative-language.retriever (often with cloud-platform).
|
||||||
DefaultAIStudioScopes = "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever"
|
DefaultAIStudioScopes = "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever"
|
||||||
|
|
||||||
|
// DefaultScopes for Google One (personal Google accounts with Gemini access)
|
||||||
|
// Only used when a custom OAuth client is configured. When using the built-in Gemini CLI client,
|
||||||
|
// Google One uses DefaultCodeAssistScopes (same as code_assist) because the built-in client
|
||||||
|
// cannot request restricted scopes like generative-language.retriever or drive.readonly.
|
||||||
|
DefaultGoogleOneScopes = "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
|
||||||
|
|
||||||
// GeminiCLIRedirectURI is the redirect URI used by Gemini CLI for Code Assist OAuth.
|
// GeminiCLIRedirectURI is the redirect URI used by Gemini CLI for Code Assist OAuth.
|
||||||
GeminiCLIRedirectURI = "https://codeassist.google.com/authcode"
|
GeminiCLIRedirectURI = "https://codeassist.google.com/authcode"
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ type Model struct {
|
|||||||
|
|
||||||
// DefaultModels is the curated Gemini model list used by the admin UI "test account" flow.
|
// DefaultModels is the curated Gemini model list used by the admin UI "test account" flow.
|
||||||
var DefaultModels = []Model{
|
var DefaultModels = []Model{
|
||||||
{ID: "gemini-3-pro-preview", Type: "model", DisplayName: "Gemini 3 Pro Preview", CreatedAt: ""},
|
{ID: "gemini-2.0-flash", Type: "model", DisplayName: "Gemini 2.0 Flash", CreatedAt: ""},
|
||||||
{ID: "gemini-3-flash-preview", Type: "model", DisplayName: "Gemini 3 Flash Preview", CreatedAt: ""},
|
|
||||||
{ID: "gemini-2.5-pro", Type: "model", DisplayName: "Gemini 2.5 Pro", CreatedAt: ""},
|
{ID: "gemini-2.5-pro", Type: "model", DisplayName: "Gemini 2.5 Pro", CreatedAt: ""},
|
||||||
{ID: "gemini-2.5-flash", Type: "model", DisplayName: "Gemini 2.5 Flash", CreatedAt: ""},
|
{ID: "gemini-2.5-flash", Type: "model", DisplayName: "Gemini 2.5 Flash", CreatedAt: ""},
|
||||||
|
{ID: "gemini-3-pro-preview", Type: "model", DisplayName: "Gemini 3 Pro Preview", CreatedAt: ""},
|
||||||
|
{ID: "gemini-3-flash-preview", Type: "model", DisplayName: "Gemini 3 Flash Preview", CreatedAt: ""},
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultTestModel is the default model to preselect in test flows.
|
// DefaultTestModel is the default model to preselect in test flows.
|
||||||
const DefaultTestModel = "gemini-3-pro-preview"
|
const DefaultTestModel = "gemini-2.0-flash"
|
||||||
|
|||||||
@@ -19,13 +19,17 @@ type OAuthConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OAuthSession struct {
|
type OAuthSession struct {
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
CodeVerifier string `json:"code_verifier"`
|
CodeVerifier string `json:"code_verifier"`
|
||||||
ProxyURL string `json:"proxy_url,omitempty"`
|
ProxyURL string `json:"proxy_url,omitempty"`
|
||||||
RedirectURI string `json:"redirect_uri"`
|
RedirectURI string `json:"redirect_uri"`
|
||||||
ProjectID string `json:"project_id,omitempty"`
|
ProjectID string `json:"project_id,omitempty"`
|
||||||
OAuthType string `json:"oauth_type"` // "code_assist" 或 "ai_studio"
|
// TierID is a user-selected fallback tier.
|
||||||
CreatedAt time.Time `json:"created_at"`
|
// For oauth types that support auto detection (google_one/code_assist), the server will prefer
|
||||||
|
// the detected tier and fall back to TierID when detection fails.
|
||||||
|
TierID string `json:"tier_id,omitempty"`
|
||||||
|
OAuthType string `json:"oauth_type"` // "code_assist" 或 "ai_studio"
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionStore struct {
|
type SessionStore struct {
|
||||||
@@ -172,23 +176,32 @@ func EffectiveOAuthConfig(cfg OAuthConfig, oauthType string) (OAuthConfig, error
|
|||||||
|
|
||||||
if effective.Scopes == "" {
|
if effective.Scopes == "" {
|
||||||
// Use different default scopes based on OAuth type
|
// Use different default scopes based on OAuth type
|
||||||
if oauthType == "ai_studio" {
|
switch oauthType {
|
||||||
|
case "ai_studio":
|
||||||
// Built-in client can't request some AI Studio scopes (notably generative-language).
|
// Built-in client can't request some AI Studio scopes (notably generative-language).
|
||||||
if isBuiltinClient {
|
if isBuiltinClient {
|
||||||
effective.Scopes = DefaultCodeAssistScopes
|
effective.Scopes = DefaultCodeAssistScopes
|
||||||
} else {
|
} else {
|
||||||
effective.Scopes = DefaultAIStudioScopes
|
effective.Scopes = DefaultAIStudioScopes
|
||||||
}
|
}
|
||||||
} else {
|
case "google_one":
|
||||||
|
// Google One uses built-in Gemini CLI client (same as code_assist)
|
||||||
|
// Built-in client can't request restricted scopes like generative-language.retriever
|
||||||
|
if isBuiltinClient {
|
||||||
|
effective.Scopes = DefaultCodeAssistScopes
|
||||||
|
} else {
|
||||||
|
effective.Scopes = DefaultGoogleOneScopes
|
||||||
|
}
|
||||||
|
default:
|
||||||
// Default to Code Assist scopes
|
// Default to Code Assist scopes
|
||||||
effective.Scopes = DefaultCodeAssistScopes
|
effective.Scopes = DefaultCodeAssistScopes
|
||||||
}
|
}
|
||||||
} else if oauthType == "ai_studio" && isBuiltinClient {
|
} else if (oauthType == "ai_studio" || oauthType == "google_one") && isBuiltinClient {
|
||||||
// If user overrides scopes while still using the built-in client, strip restricted scopes.
|
// If user overrides scopes while still using the built-in client, strip restricted scopes.
|
||||||
parts := strings.Fields(effective.Scopes)
|
parts := strings.Fields(effective.Scopes)
|
||||||
filtered := make([]string, 0, len(parts))
|
filtered := make([]string, 0, len(parts))
|
||||||
for _, s := range parts {
|
for _, s := range parts {
|
||||||
if strings.Contains(s, "generative-language") {
|
if hasRestrictedScope(s) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filtered = append(filtered, s)
|
filtered = append(filtered, s)
|
||||||
@@ -214,6 +227,11 @@ func EffectiveOAuthConfig(cfg OAuthConfig, oauthType string) (OAuthConfig, error
|
|||||||
return effective, nil
|
return effective, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasRestrictedScope(scope string) bool {
|
||||||
|
return strings.HasPrefix(scope, "https://www.googleapis.com/auth/generative-language") ||
|
||||||
|
strings.HasPrefix(scope, "https://www.googleapis.com/auth/drive")
|
||||||
|
}
|
||||||
|
|
||||||
func BuildAuthorizationURL(cfg OAuthConfig, state, codeChallenge, redirectURI, projectID, oauthType string) (string, error) {
|
func BuildAuthorizationURL(cfg OAuthConfig, state, codeChallenge, redirectURI, projectID, oauthType string) (string, error) {
|
||||||
effectiveCfg, err := EffectiveOAuthConfig(cfg, oauthType)
|
effectiveCfg, err := EffectiveOAuthConfig(cfg, oauthType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
113
backend/internal/pkg/geminicli/oauth_test.go
Normal file
113
backend/internal/pkg/geminicli/oauth_test.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package geminicli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEffectiveOAuthConfig_GoogleOne(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input OAuthConfig
|
||||||
|
oauthType string
|
||||||
|
wantClientID string
|
||||||
|
wantScopes string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Google One with built-in client (empty config)",
|
||||||
|
input: OAuthConfig{},
|
||||||
|
oauthType: "google_one",
|
||||||
|
wantClientID: GeminiCLIOAuthClientID,
|
||||||
|
wantScopes: DefaultCodeAssistScopes,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Google One with custom client",
|
||||||
|
input: OAuthConfig{
|
||||||
|
ClientID: "custom-client-id",
|
||||||
|
ClientSecret: "custom-client-secret",
|
||||||
|
},
|
||||||
|
oauthType: "google_one",
|
||||||
|
wantClientID: "custom-client-id",
|
||||||
|
wantScopes: DefaultGoogleOneScopes,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Google One with built-in client and custom scopes (should filter restricted scopes)",
|
||||||
|
input: OAuthConfig{
|
||||||
|
Scopes: "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly",
|
||||||
|
},
|
||||||
|
oauthType: "google_one",
|
||||||
|
wantClientID: GeminiCLIOAuthClientID,
|
||||||
|
wantScopes: "https://www.googleapis.com/auth/cloud-platform",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Google One with built-in client and only restricted scopes (should fallback to default)",
|
||||||
|
input: OAuthConfig{
|
||||||
|
Scopes: "https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly",
|
||||||
|
},
|
||||||
|
oauthType: "google_one",
|
||||||
|
wantClientID: GeminiCLIOAuthClientID,
|
||||||
|
wantScopes: DefaultCodeAssistScopes,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Code Assist with built-in client",
|
||||||
|
input: OAuthConfig{},
|
||||||
|
oauthType: "code_assist",
|
||||||
|
wantClientID: GeminiCLIOAuthClientID,
|
||||||
|
wantScopes: DefaultCodeAssistScopes,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := EffectiveOAuthConfig(tt.input, tt.oauthType)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("EffectiveOAuthConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got.ClientID != tt.wantClientID {
|
||||||
|
t.Errorf("EffectiveOAuthConfig() ClientID = %v, want %v", got.ClientID, tt.wantClientID)
|
||||||
|
}
|
||||||
|
if got.Scopes != tt.wantScopes {
|
||||||
|
t.Errorf("EffectiveOAuthConfig() Scopes = %v, want %v", got.Scopes, tt.wantScopes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEffectiveOAuthConfig_ScopeFiltering(t *testing.T) {
|
||||||
|
// Test that Google One with built-in client filters out restricted scopes
|
||||||
|
cfg, err := EffectiveOAuthConfig(OAuthConfig{
|
||||||
|
Scopes: "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.profile",
|
||||||
|
}, "google_one")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EffectiveOAuthConfig() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should only contain cloud-platform, userinfo.email, and userinfo.profile
|
||||||
|
// Should NOT contain generative-language or drive scopes
|
||||||
|
if strings.Contains(cfg.Scopes, "generative-language") {
|
||||||
|
t.Errorf("Scopes should not contain generative-language when using built-in client, got: %v", cfg.Scopes)
|
||||||
|
}
|
||||||
|
if strings.Contains(cfg.Scopes, "drive") {
|
||||||
|
t.Errorf("Scopes should not contain drive when using built-in client, got: %v", cfg.Scopes)
|
||||||
|
}
|
||||||
|
if !strings.Contains(cfg.Scopes, "cloud-platform") {
|
||||||
|
t.Errorf("Scopes should contain cloud-platform, got: %v", cfg.Scopes)
|
||||||
|
}
|
||||||
|
if !strings.Contains(cfg.Scopes, "userinfo.email") {
|
||||||
|
t.Errorf("Scopes should contain userinfo.email, got: %v", cfg.Scopes)
|
||||||
|
}
|
||||||
|
if !strings.Contains(cfg.Scopes, "userinfo.profile") {
|
||||||
|
t.Errorf("Scopes should contain userinfo.profile, got: %v", cfg.Scopes)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package googleapi provides helpers for Google-style API responses.
|
||||||
package googleapi
|
package googleapi
|
||||||
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
package httpclient
|
package httpclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -25,13 +24,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/proxyutil"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/proxyutil"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/util/urlvalidator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transport 连接池默认配置
|
// Transport 连接池默认配置
|
||||||
const (
|
const (
|
||||||
defaultMaxIdleConns = 100 // 最大空闲连接数
|
defaultMaxIdleConns = 100 // 最大空闲连接数
|
||||||
defaultMaxIdleConnsPerHost = 10 // 每个主机最大空闲连接数
|
defaultMaxIdleConnsPerHost = 10 // 每个主机最大空闲连接数
|
||||||
defaultIdleConnTimeout = 90 * time.Second // 空闲连接超时时间
|
defaultIdleConnTimeout = 90 * time.Second // 空闲连接超时时间(建议小于上游 LB 超时)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options 定义共享 HTTP 客户端的构建参数
|
// Options 定义共享 HTTP 客户端的构建参数
|
||||||
@@ -39,7 +39,10 @@ type Options struct {
|
|||||||
ProxyURL string // 代理 URL(支持 http/https/socks5/socks5h)
|
ProxyURL string // 代理 URL(支持 http/https/socks5/socks5h)
|
||||||
Timeout time.Duration // 请求总超时时间
|
Timeout time.Duration // 请求总超时时间
|
||||||
ResponseHeaderTimeout time.Duration // 等待响应头超时时间
|
ResponseHeaderTimeout time.Duration // 等待响应头超时时间
|
||||||
InsecureSkipVerify bool // 是否跳过 TLS 证书验证
|
InsecureSkipVerify bool // 是否跳过 TLS 证书验证(已禁用,不允许设置为 true)
|
||||||
|
ProxyStrict bool // 严格代理模式:代理失败时返回错误而非回退
|
||||||
|
ValidateResolvedIP bool // 是否校验解析后的 IP(防止 DNS Rebinding)
|
||||||
|
AllowPrivateHosts bool // 允许私有地址解析(与 ValidateResolvedIP 一起使用)
|
||||||
|
|
||||||
// 可选的连接池参数(不设置则使用默认值)
|
// 可选的连接池参数(不设置则使用默认值)
|
||||||
MaxIdleConns int // 最大空闲连接总数(默认 100)
|
MaxIdleConns int // 最大空闲连接总数(默认 100)
|
||||||
@@ -79,8 +82,12 @@ func buildClient(opts Options) (*http.Client, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rt http.RoundTripper = transport
|
||||||
|
if opts.ValidateResolvedIP && !opts.AllowPrivateHosts {
|
||||||
|
rt = &validatedTransport{base: transport}
|
||||||
|
}
|
||||||
return &http.Client{
|
return &http.Client{
|
||||||
Transport: transport,
|
Transport: rt,
|
||||||
Timeout: opts.Timeout,
|
Timeout: opts.Timeout,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -105,7 +112,8 @@ func buildTransport(opts Options) (*http.Transport, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.InsecureSkipVerify {
|
if opts.InsecureSkipVerify {
|
||||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
// 安全要求:禁止跳过证书验证,避免中间人攻击。
|
||||||
|
return nil, fmt.Errorf("insecure_skip_verify is not allowed; install a trusted certificate instead")
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyURL := strings.TrimSpace(opts.ProxyURL)
|
proxyURL := strings.TrimSpace(opts.ProxyURL)
|
||||||
@@ -126,13 +134,32 @@ func buildTransport(opts Options) (*http.Transport, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildClientKey(opts Options) string {
|
func buildClientKey(opts Options) string {
|
||||||
return fmt.Sprintf("%s|%s|%s|%t|%d|%d|%d",
|
return fmt.Sprintf("%s|%s|%s|%t|%t|%t|%t|%d|%d|%d",
|
||||||
strings.TrimSpace(opts.ProxyURL),
|
strings.TrimSpace(opts.ProxyURL),
|
||||||
opts.Timeout.String(),
|
opts.Timeout.String(),
|
||||||
opts.ResponseHeaderTimeout.String(),
|
opts.ResponseHeaderTimeout.String(),
|
||||||
opts.InsecureSkipVerify,
|
opts.InsecureSkipVerify,
|
||||||
|
opts.ProxyStrict,
|
||||||
|
opts.ValidateResolvedIP,
|
||||||
|
opts.AllowPrivateHosts,
|
||||||
opts.MaxIdleConns,
|
opts.MaxIdleConns,
|
||||||
opts.MaxIdleConnsPerHost,
|
opts.MaxIdleConnsPerHost,
|
||||||
opts.MaxConnsPerHost,
|
opts.MaxConnsPerHost,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type validatedTransport struct {
|
||||||
|
base http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *validatedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
if req != nil && req.URL != nil {
|
||||||
|
host := strings.TrimSpace(req.URL.Hostname())
|
||||||
|
if host != "" {
|
||||||
|
if err := urlvalidator.ValidateResolvedIP(host); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t.base.RoundTrip(req)
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user