Merge remote-tracking branch 'origin/main'
# Conflicts: # backend/go.mod # backend/go.sum # backend/internal/repository/migrations_runner.go
This commit is contained in:
commit
ff7eab0392
22
.github/workflows/backend-ci.yml
vendored
22
.github/workflows/backend-ci.yml
vendored
@ -28,6 +28,26 @@ jobs:
|
||||
working-directory: backend
|
||||
run: make test-integration
|
||||
|
||||
frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 9
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Install frontend dependencies
|
||||
working-directory: frontend
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Frontend typecheck and critical vitest
|
||||
run: make test-frontend
|
||||
|
||||
golangci-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -46,4 +66,4 @@ jobs:
|
||||
with:
|
||||
version: v2.9
|
||||
args: --timeout=30m
|
||||
working-directory: backend
|
||||
working-directory: backend
|
||||
|
||||
59
.github/workflows/cla.yml
vendored
Normal file
59
.github/workflows/cla.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: "CLA Assistant"
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types: [opened, reopened, closed, synchronize]
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
|
||||
jobs:
|
||||
cla-check:
|
||||
if: |
|
||||
github.event_name == 'issue_comment' ||
|
||||
(github.event_name == 'pull_request_target' && github.event.action != 'closed')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
if: |
|
||||
(github.event.comment.body == 'recheck' ||
|
||||
github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') ||
|
||||
github.event_name == 'pull_request_target'
|
||||
uses: contributor-assistant/github-action@v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: "cla.json"
|
||||
path-to-document: "https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md"
|
||||
branch: "cla-signatures"
|
||||
allowlist: "dependabot[bot],renovate[bot],bot*"
|
||||
lock-pullrequest-aftermerge: false
|
||||
custom-notsigned-prcomment: |
|
||||
Thank you for your contribution! Before we can merge this PR, we need $you to sign our [Contributor License Agreement (CLA)](https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md).
|
||||
|
||||
**To sign**, please reply with the following comment:
|
||||
|
||||
> I have read the CLA Document and I hereby sign the CLA
|
||||
|
||||
You only need to sign once — it will be valid for all your future contributions to this project.
|
||||
custom-pr-sign-comment: "I have read the CLA Document and I hereby sign the CLA"
|
||||
custom-allsigned-prcomment: "All contributors have signed the CLA. ✅"
|
||||
|
||||
cla-lock:
|
||||
if: github.event_name == 'pull_request_target' && github.event.action == 'closed' && github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Lock merged PR"
|
||||
uses: contributor-assistant/github-action@v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: "cla.json"
|
||||
path-to-document: "https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md"
|
||||
branch: "cla-signatures"
|
||||
lock-pullrequest-aftermerge: true
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -129,9 +129,9 @@ vite.config.js
|
||||
docs/*
|
||||
!docs/PAYMENT.md
|
||||
!docs/PAYMENT_CN.md
|
||||
!docs/ADMIN_PAYMENT_INTEGRATION_API.md
|
||||
.serena/
|
||||
.codex/
|
||||
frontend/coverage/
|
||||
aicodex
|
||||
output/
|
||||
|
||||
|
||||
73
CLA.md
Normal file
73
CLA.md
Normal file
@ -0,0 +1,73 @@
|
||||
# Sub2API Individual Contributor License Agreement (v1.0)
|
||||
|
||||
Thank you for your interest in contributing to Sub2API ("the Project"). This Contributor License Agreement ("Agreement") documents the rights granted by contributors to the Project.
|
||||
|
||||
By signing this Agreement, you accept and agree to the following terms and conditions for your present and future contributions submitted to the Project.
|
||||
|
||||
## 1. Definitions
|
||||
|
||||
- **"You" (or "Your")** means the copyright owner or legal entity authorized by the copyright owner that is making this Agreement.
|
||||
- **"Contribution"** means any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to the Project for inclusion in, or documentation of, any of the products owned or managed by the Project. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Project or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Project for the purpose of discussing and improving the Project, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
|
||||
- **"Project Owner"** means Wesley Liddick, or any individual or legal entity to whom Wesley Liddick has explicitly assigned or transferred ownership of the Project in writing, and their respective successors and assigns.
|
||||
|
||||
## 2. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this Agreement, You hereby grant to the Project Owner a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. This license includes, without limitation, the right to sublicense, assign, and transfer these rights to any third party, including without limitation any successor, assignee, or acquiring entity of the Project or the Project Owner, and to use Your Contributions under any license, including proprietary or commercial licenses.
|
||||
|
||||
## 3. Moral Rights
|
||||
|
||||
To the fullest extent permitted by applicable law, You irrevocably waive and agree not to assert any moral rights (including rights of attribution and integrity) that You may have in Your Contributions, and agree that the Project Owner and its licensees may use, modify, and distribute Your Contributions without attribution or other obligations arising from moral rights.
|
||||
|
||||
## 4. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this Agreement, You hereby grant to the Project Owner a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer Your Contributions, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Project to which such Contribution(s) was submitted.
|
||||
|
||||
## 5. Representations and Warranties
|
||||
|
||||
You represent and warrant that:
|
||||
|
||||
(a) You are legally entitled to grant the above licenses.
|
||||
|
||||
(b) If Your employer(s) has rights to intellectual property that You create that includes Your Contributions, You have received permission to make Contributions on behalf of that employer, or that Your employer has waived such rights for Your Contributions to the Project.
|
||||
|
||||
(c) Each of Your Contributions is Your original creation, or You have sufficient rights to submit it under the terms of this Agreement. You agree to provide, upon request, reasonable documentation or explanation of any third-party materials included in Your Contributions.
|
||||
|
||||
## 6. No Warranty
|
||||
|
||||
Your Contributions are provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support.
|
||||
|
||||
## 7. No Obligation
|
||||
|
||||
You understand that the decision to include Your Contribution in any product or project is entirely at the discretion of the Project Owner, and this Agreement does not obligate the Project Owner to use Your Contribution.
|
||||
|
||||
## 8. Retention of Rights
|
||||
|
||||
You retain ownership of the copyright in Your Contributions. This Agreement does not transfer any copyright or other intellectual property rights from You to the Project Owner. This Agreement only grants the licenses described above.
|
||||
|
||||
## 9. Term and Termination
|
||||
|
||||
This Agreement shall remain in effect indefinitely. You may terminate this Agreement prospectively by providing written notice to the Project Owner, but such termination shall not affect the licenses granted for Contributions submitted prior to the effective date of termination. The licenses granted herein for Contributions submitted prior to termination are perpetual and irrevocable.
|
||||
|
||||
## 10. Electronic Signature
|
||||
|
||||
You agree that Your electronic signature (including but not limited to typing a specific phrase in a pull request, issue, or other electronic communication) is legally binding and has the same force and effect as a handwritten signature. You consent to the use of electronic means to enter into this Agreement and acknowledge that this Agreement is enforceable as if executed in a traditional written format.
|
||||
|
||||
## 11. General Provisions
|
||||
|
||||
**Entire Agreement.** This Agreement constitutes the entire agreement between You and the Project Owner with respect to Your Contributions and supersedes all prior or contemporaneous understandings regarding such subject matter.
|
||||
|
||||
**Severability.** If any provision of this Agreement is held to be unenforceable or invalid, that provision will be enforced to the maximum extent possible and the remaining provisions will remain in full force and effect.
|
||||
|
||||
**No Waiver.** The failure of the Project Owner to enforce any provision of this Agreement shall not constitute a waiver of that provision or any other provision.
|
||||
|
||||
**Amendment.** This Agreement may only be modified by a written instrument signed by both parties. Modifications to this Agreement apply only to Contributions submitted after the modified Agreement is published and accepted by You. Prior Contributions remain governed by the version of the Agreement in effect at the time of submission.
|
||||
|
||||
**Notification.** Notices under this Agreement shall be sent to the Project Owner via a GitHub issue on the Project repository. Notices are effective upon receipt.
|
||||
|
||||
---
|
||||
|
||||
**By signing this CLA, you acknowledge that you have read and understood this Agreement and agree to be bound by its terms.**
|
||||
|
||||
To sign, reply in the pull request with:
|
||||
|
||||
> I have read the CLA Document and I hereby sign the CLA
|
||||
178
LICENSE
178
LICENSE
@ -1,21 +1,165 @@
|
||||
MIT License
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (c) 2025 Wesley Liddick
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
14
Makefile
14
Makefile
@ -1,4 +1,12 @@
|
||||
.PHONY: build build-backend build-frontend build-datamanagementd test test-backend test-frontend test-datamanagementd secret-scan
|
||||
.PHONY: build build-backend build-frontend build-datamanagementd test test-backend test-frontend test-frontend-critical test-datamanagementd secret-scan
|
||||
|
||||
FRONTEND_CRITICAL_VITEST := \
|
||||
src/views/auth/__tests__/LinuxDoCallbackView.spec.ts \
|
||||
src/views/auth/__tests__/WechatCallbackView.spec.ts \
|
||||
src/views/user/__tests__/PaymentView.spec.ts \
|
||||
src/views/user/__tests__/PaymentResultView.spec.ts \
|
||||
src/components/user/profile/__tests__/ProfileInfoCard.spec.ts \
|
||||
src/views/admin/__tests__/SettingsView.spec.ts
|
||||
|
||||
# 一键编译前后端
|
||||
build: build-backend build-frontend
|
||||
@ -24,6 +32,10 @@ test-backend:
|
||||
test-frontend:
|
||||
@pnpm --dir frontend run lint:check
|
||||
@pnpm --dir frontend run typecheck
|
||||
@$(MAKE) test-frontend-critical
|
||||
|
||||
test-frontend-critical:
|
||||
@pnpm --dir frontend exec vitest run $(FRONTEND_CRITICAL_VITEST)
|
||||
|
||||
test-datamanagementd:
|
||||
@cd datamanagement && go test ./...
|
||||
|
||||
@ -96,6 +96,11 @@ Sub2API is an AI API gateway platform designed to distribute and manage API quot
|
||||
<td>Huge thanks to BmoPlus for sponsoring this project! BmoPlus is a highly reliable AI account provider built strictly for heavy AI users and developers. They offer rock-solid, ready-to-use accounts and official top-up services for ChatGPT Plus / ChatGPT Pro (Full Warranty) / Claude Pro / Super Grok / Gemini Pro. By registering and ordering through <a href="https://shop.bmoplus.com/?utm_source=github">BmoPlus - Premium AI Accounts & Top-ups</a>, users can unlock the mind-blowing rate of 10% of the official GPT subscription price (90% OFF)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="180"><a href="https://bestproxy.com/?keyword=a2e8iuol"><img src="assets/partners/logos/bestproxy.png" alt="bestproxy" width="150"></a></td>
|
||||
<td>Thanks to Bestproxy for sponsoring this project! <a href="https://bestproxy.com/?keyword=a2e8iuol">Bestproxy</a> provides high-purity residential IPs with dedicated one-IP-per-account support. By combining real home networks with fingerprint isolation, it enables link environment isolation and reduces the probability of association-based risk control.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
## Ecosystem
|
||||
@ -618,7 +623,9 @@ sub2api/
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
This project is licensed under the [GNU Lesser General Public License v3.0](LICENSE) (or later).
|
||||
|
||||
Copyright (c) 2026 Wesley Liddick
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -95,6 +95,11 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅的
|
||||
<td>感谢 BmoPlus 赞助了本项目!BmoPlus 是一家专为AI订阅重度用户打造的可靠 AI 账号代充服务商,提供稳定的 ChatGPT Plus / ChatGPT Pro(全程质保) / Claude Pro / Super Grok / Gemini Pro 的官方代充&成品账号。 通过<a href="https://shop.bmoplus.com/?utm_source=github">BmoPlus AI成品号专卖/代充</a>注册下单的用户,可享GPT 官网订阅一折 的震撼价格!</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="180"><a href="https://bestproxy.com/?keyword=a2e8iuol"><img src="assets/partners/logos/bestproxy.png" alt="bestproxy" width="150"></a></td>
|
||||
<td>感谢 Bestproxy 赞助了本项目!<a href="https://bestproxy.com/?keyword=a2e8iuol">Bestproxy</a> 是一家提供高纯度住宅IP,支持一号一IP独享,结合真实家庭网络与指纹隔离,可实现链路环境隔离,降低关联风控概率。</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
## 生态项目
|
||||
@ -679,7 +684,9 @@ sub2api/
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
本项目基于 [GNU 宽通用公共许可证 v3.0](LICENSE)(或更高版本)授权。
|
||||
|
||||
Copyright (c) 2026 Wesley Liddick
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -95,6 +95,11 @@ Sub2API は、AI 製品のサブスクリプションから API クォータを
|
||||
<td>本プロジェクトにご支援いただいた BmoPlus に感謝いたします!BmoPlusは、AIサブスクリプションのヘビーユーザー向けに特化した信頼性の高いAIアカウントサービスプロバイダーであり、安定した ChatGPT Plus / ChatGPT Pro (完全保証) / Claude Pro / Super Grok / Gemini Pro の公式代行チャージおよび即納アカウントを提供しています。こちらの<a href="https://shop.bmoplus.com/?utm_source=github">BmoPlus AIアカウント専門店/代行チャージ</a>経由でご登録・ご注文いただいたユーザー様は、GPTを 公式サイト価格の約1割(90% OFF) という驚異的な価格でご利用いただけます!</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="180"><a href="https://bestproxy.com/?keyword=a2e8iuol"><img src="assets/partners/logos/bestproxy.png" alt="bestproxy" width="150"></a></td>
|
||||
<td>Bestproxy のご支援に感謝します!<a href="https://bestproxy.com/?keyword=a2e8iuol">Bestproxy</a> は高純度の住宅IPを提供し、1アカウント1IP専有をサポートしています。実際の家庭ネットワークとフィンガープリント分離を組み合わせることで、リンク環境の分離を実現し、関連付けによるリスク管理の確率を低減します。</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
## エコシステム
|
||||
@ -617,7 +622,9 @@ sub2api/
|
||||
|
||||
## ライセンス
|
||||
|
||||
MIT License
|
||||
本プロジェクトは [GNU Lesser General Public License v3.0](LICENSE)(またはそれ以降のバージョン)の下でライセンスされています。
|
||||
|
||||
Copyright (c) 2026 Wesley Liddick
|
||||
|
||||
---
|
||||
|
||||
|
||||
BIN
assets/partners/logos/bestproxy.png
Normal file
BIN
assets/partners/logos/bestproxy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
@ -1 +1 @@
|
||||
0.1.114
|
||||
0.1.115
|
||||
|
||||
@ -79,7 +79,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
totpCache := repository.NewTotpCache(redisClient)
|
||||
totpService := service.NewTotpService(userRepository, secretEncryptor, totpCache, settingService, emailService, emailQueueService)
|
||||
authHandler := handler.NewAuthHandler(configConfig, authService, userService, settingService, promoService, redeemService, totpService)
|
||||
userHandler := handler.NewUserHandler(userService, emailService, emailCache)
|
||||
userHandler := handler.NewUserHandler(userService, authService, emailService, emailCache)
|
||||
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
|
||||
usageLogRepository := repository.NewUsageLogRepository(client, db)
|
||||
usageService := service.NewUsageService(usageLogRepository, userRepository, client, apiKeyAuthCacheInvalidator)
|
||||
|
||||
266
backend/ent/authidentity.go
Normal file
266
backend/ent/authidentity.go
Normal file
@ -0,0 +1,266 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AuthIdentity is the model entity for the AuthIdentity schema.
|
||||
type AuthIdentity struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// UserID holds the value of the "user_id" field.
|
||||
UserID int64 `json:"user_id,omitempty"`
|
||||
// ProviderType holds the value of the "provider_type" field.
|
||||
ProviderType string `json:"provider_type,omitempty"`
|
||||
// ProviderKey holds the value of the "provider_key" field.
|
||||
ProviderKey string `json:"provider_key,omitempty"`
|
||||
// ProviderSubject holds the value of the "provider_subject" field.
|
||||
ProviderSubject string `json:"provider_subject,omitempty"`
|
||||
// VerifiedAt holds the value of the "verified_at" field.
|
||||
VerifiedAt *time.Time `json:"verified_at,omitempty"`
|
||||
// Issuer holds the value of the "issuer" field.
|
||||
Issuer *string `json:"issuer,omitempty"`
|
||||
// Metadata holds the value of the "metadata" field.
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AuthIdentityQuery when eager-loading is set.
|
||||
Edges AuthIdentityEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// AuthIdentityEdges holds the relations/edges for other nodes in the graph.
|
||||
type AuthIdentityEdges struct {
|
||||
// User holds the value of the user edge.
|
||||
User *User `json:"user,omitempty"`
|
||||
// Channels holds the value of the channels edge.
|
||||
Channels []*AuthIdentityChannel `json:"channels,omitempty"`
|
||||
// AdoptionDecisions holds the value of the adoption_decisions edge.
|
||||
AdoptionDecisions []*IdentityAdoptionDecision `json:"adoption_decisions,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [3]bool
|
||||
}
|
||||
|
||||
// UserOrErr returns the User value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e AuthIdentityEdges) UserOrErr() (*User, error) {
|
||||
if e.User != nil {
|
||||
return e.User, nil
|
||||
} else if e.loadedTypes[0] {
|
||||
return nil, &NotFoundError{label: user.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "user"}
|
||||
}
|
||||
|
||||
// ChannelsOrErr returns the Channels value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e AuthIdentityEdges) ChannelsOrErr() ([]*AuthIdentityChannel, error) {
|
||||
if e.loadedTypes[1] {
|
||||
return e.Channels, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "channels"}
|
||||
}
|
||||
|
||||
// AdoptionDecisionsOrErr returns the AdoptionDecisions value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e AuthIdentityEdges) AdoptionDecisionsOrErr() ([]*IdentityAdoptionDecision, error) {
|
||||
if e.loadedTypes[2] {
|
||||
return e.AdoptionDecisions, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "adoption_decisions"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*AuthIdentity) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case authidentity.FieldMetadata:
|
||||
values[i] = new([]byte)
|
||||
case authidentity.FieldID, authidentity.FieldUserID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case authidentity.FieldProviderType, authidentity.FieldProviderKey, authidentity.FieldProviderSubject, authidentity.FieldIssuer:
|
||||
values[i] = new(sql.NullString)
|
||||
case authidentity.FieldCreatedAt, authidentity.FieldUpdatedAt, authidentity.FieldVerifiedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the AuthIdentity fields.
|
||||
func (_m *AuthIdentity) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case authidentity.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case authidentity.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case authidentity.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
case authidentity.FieldUserID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field user_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UserID = value.Int64
|
||||
}
|
||||
case authidentity.FieldProviderType:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_type", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderType = value.String
|
||||
}
|
||||
case authidentity.FieldProviderKey:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_key", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderKey = value.String
|
||||
}
|
||||
case authidentity.FieldProviderSubject:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_subject", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderSubject = value.String
|
||||
}
|
||||
case authidentity.FieldVerifiedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field verified_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.VerifiedAt = new(time.Time)
|
||||
*_m.VerifiedAt = value.Time
|
||||
}
|
||||
case authidentity.FieldIssuer:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field issuer", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Issuer = new(string)
|
||||
*_m.Issuer = value.String
|
||||
}
|
||||
case authidentity.FieldMetadata:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field metadata", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.Metadata); err != nil {
|
||||
return fmt.Errorf("unmarshal field metadata: %w", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the AuthIdentity.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *AuthIdentity) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryUser queries the "user" edge of the AuthIdentity entity.
|
||||
func (_m *AuthIdentity) QueryUser() *UserQuery {
|
||||
return NewAuthIdentityClient(_m.config).QueryUser(_m)
|
||||
}
|
||||
|
||||
// QueryChannels queries the "channels" edge of the AuthIdentity entity.
|
||||
func (_m *AuthIdentity) QueryChannels() *AuthIdentityChannelQuery {
|
||||
return NewAuthIdentityClient(_m.config).QueryChannels(_m)
|
||||
}
|
||||
|
||||
// QueryAdoptionDecisions queries the "adoption_decisions" edge of the AuthIdentity entity.
|
||||
func (_m *AuthIdentity) QueryAdoptionDecisions() *IdentityAdoptionDecisionQuery {
|
||||
return NewAuthIdentityClient(_m.config).QueryAdoptionDecisions(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this AuthIdentity.
|
||||
// Note that you need to call AuthIdentity.Unwrap() before calling this method if this AuthIdentity
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *AuthIdentity) Update() *AuthIdentityUpdateOne {
|
||||
return NewAuthIdentityClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the AuthIdentity entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *AuthIdentity) Unwrap() *AuthIdentity {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: AuthIdentity is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *AuthIdentity) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("AuthIdentity(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("user_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.UserID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_type=")
|
||||
builder.WriteString(_m.ProviderType)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_key=")
|
||||
builder.WriteString(_m.ProviderKey)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_subject=")
|
||||
builder.WriteString(_m.ProviderSubject)
|
||||
builder.WriteString(", ")
|
||||
if v := _m.VerifiedAt; v != nil {
|
||||
builder.WriteString("verified_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.Issuer; v != nil {
|
||||
builder.WriteString("issuer=")
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("metadata=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Metadata))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// AuthIdentities is a parsable slice of AuthIdentity.
|
||||
type AuthIdentities []*AuthIdentity
|
||||
209
backend/ent/authidentity/authidentity.go
Normal file
209
backend/ent/authidentity/authidentity.go
Normal file
@ -0,0 +1,209 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package authidentity
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the authidentity type in the database.
|
||||
Label = "auth_identity"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldUserID holds the string denoting the user_id field in the database.
|
||||
FieldUserID = "user_id"
|
||||
// FieldProviderType holds the string denoting the provider_type field in the database.
|
||||
FieldProviderType = "provider_type"
|
||||
// FieldProviderKey holds the string denoting the provider_key field in the database.
|
||||
FieldProviderKey = "provider_key"
|
||||
// FieldProviderSubject holds the string denoting the provider_subject field in the database.
|
||||
FieldProviderSubject = "provider_subject"
|
||||
// FieldVerifiedAt holds the string denoting the verified_at field in the database.
|
||||
FieldVerifiedAt = "verified_at"
|
||||
// FieldIssuer holds the string denoting the issuer field in the database.
|
||||
FieldIssuer = "issuer"
|
||||
// FieldMetadata holds the string denoting the metadata field in the database.
|
||||
FieldMetadata = "metadata"
|
||||
// EdgeUser holds the string denoting the user edge name in mutations.
|
||||
EdgeUser = "user"
|
||||
// EdgeChannels holds the string denoting the channels edge name in mutations.
|
||||
EdgeChannels = "channels"
|
||||
// EdgeAdoptionDecisions holds the string denoting the adoption_decisions edge name in mutations.
|
||||
EdgeAdoptionDecisions = "adoption_decisions"
|
||||
// Table holds the table name of the authidentity in the database.
|
||||
Table = "auth_identities"
|
||||
// UserTable is the table that holds the user relation/edge.
|
||||
UserTable = "auth_identities"
|
||||
// UserInverseTable is the table name for the User entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "user" package.
|
||||
UserInverseTable = "users"
|
||||
// UserColumn is the table column denoting the user relation/edge.
|
||||
UserColumn = "user_id"
|
||||
// ChannelsTable is the table that holds the channels relation/edge.
|
||||
ChannelsTable = "auth_identity_channels"
|
||||
// ChannelsInverseTable is the table name for the AuthIdentityChannel entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "authidentitychannel" package.
|
||||
ChannelsInverseTable = "auth_identity_channels"
|
||||
// ChannelsColumn is the table column denoting the channels relation/edge.
|
||||
ChannelsColumn = "identity_id"
|
||||
// AdoptionDecisionsTable is the table that holds the adoption_decisions relation/edge.
|
||||
AdoptionDecisionsTable = "identity_adoption_decisions"
|
||||
// AdoptionDecisionsInverseTable is the table name for the IdentityAdoptionDecision entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "identityadoptiondecision" package.
|
||||
AdoptionDecisionsInverseTable = "identity_adoption_decisions"
|
||||
// AdoptionDecisionsColumn is the table column denoting the adoption_decisions relation/edge.
|
||||
AdoptionDecisionsColumn = "identity_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for authidentity fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldUserID,
|
||||
FieldProviderType,
|
||||
FieldProviderKey,
|
||||
FieldProviderSubject,
|
||||
FieldVerifiedAt,
|
||||
FieldIssuer,
|
||||
FieldMetadata,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
// ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
ProviderTypeValidator func(string) error
|
||||
// ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
ProviderKeyValidator func(string) error
|
||||
// ProviderSubjectValidator is a validator for the "provider_subject" field. It is called by the builders before save.
|
||||
ProviderSubjectValidator func(string) error
|
||||
// DefaultMetadata holds the default value on creation for the "metadata" field.
|
||||
DefaultMetadata func() map[string]interface{}
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the AuthIdentity queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUserID orders the results by the user_id field.
|
||||
func ByUserID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUserID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderType orders the results by the provider_type field.
|
||||
func ByProviderType(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderType, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderKey orders the results by the provider_key field.
|
||||
func ByProviderKey(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderKey, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderSubject orders the results by the provider_subject field.
|
||||
func ByProviderSubject(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderSubject, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByVerifiedAt orders the results by the verified_at field.
|
||||
func ByVerifiedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldVerifiedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByIssuer orders the results by the issuer field.
|
||||
func ByIssuer(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldIssuer, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUserField orders the results by user field.
|
||||
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
|
||||
// ByChannelsCount orders the results by channels count.
|
||||
func ByChannelsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newChannelsStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByChannels orders the results by channels terms.
|
||||
func ByChannels(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newChannelsStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByAdoptionDecisionsCount orders the results by adoption_decisions count.
|
||||
func ByAdoptionDecisionsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newAdoptionDecisionsStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByAdoptionDecisions orders the results by adoption_decisions terms.
|
||||
func ByAdoptionDecisions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newAdoptionDecisionsStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
func newUserStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(UserInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
||||
)
|
||||
}
|
||||
func newChannelsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(ChannelsInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, ChannelsTable, ChannelsColumn),
|
||||
)
|
||||
}
|
||||
func newAdoptionDecisionsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(AdoptionDecisionsInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AdoptionDecisionsTable, AdoptionDecisionsColumn),
|
||||
)
|
||||
}
|
||||
600
backend/ent/authidentity/where.go
Normal file
600
backend/ent/authidentity/where.go
Normal file
@ -0,0 +1,600 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package authidentity
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
|
||||
func UserID(v int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// ProviderType applies equality check predicate on the "provider_type" field. It's identical to ProviderTypeEQ.
|
||||
func ProviderType(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderKey applies equality check predicate on the "provider_key" field. It's identical to ProviderKeyEQ.
|
||||
func ProviderKey(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderSubject applies equality check predicate on the "provider_subject" field. It's identical to ProviderSubjectEQ.
|
||||
func ProviderSubject(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// VerifiedAt applies equality check predicate on the "verified_at" field. It's identical to VerifiedAtEQ.
|
||||
func VerifiedAt(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// Issuer applies equality check predicate on the "issuer" field. It's identical to IssuerEQ.
|
||||
func Issuer(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UserIDEQ applies the EQ predicate on the "user_id" field.
|
||||
func UserIDEQ(v int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
|
||||
func UserIDNEQ(v int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldUserID, v))
|
||||
}
|
||||
|
||||
// UserIDIn applies the In predicate on the "user_id" field.
|
||||
func UserIDIn(vs ...int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldUserID, vs...))
|
||||
}
|
||||
|
||||
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
|
||||
func UserIDNotIn(vs ...int64) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldUserID, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeEQ applies the EQ predicate on the "provider_type" field.
|
||||
func ProviderTypeEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeNEQ applies the NEQ predicate on the "provider_type" field.
|
||||
func ProviderTypeNEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeIn applies the In predicate on the "provider_type" field.
|
||||
func ProviderTypeIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldProviderType, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeNotIn applies the NotIn predicate on the "provider_type" field.
|
||||
func ProviderTypeNotIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldProviderType, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeGT applies the GT predicate on the "provider_type" field.
|
||||
func ProviderTypeGT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeGTE applies the GTE predicate on the "provider_type" field.
|
||||
func ProviderTypeGTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeLT applies the LT predicate on the "provider_type" field.
|
||||
func ProviderTypeLT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeLTE applies the LTE predicate on the "provider_type" field.
|
||||
func ProviderTypeLTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeContains applies the Contains predicate on the "provider_type" field.
|
||||
func ProviderTypeContains(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContains(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeHasPrefix applies the HasPrefix predicate on the "provider_type" field.
|
||||
func ProviderTypeHasPrefix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasPrefix(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeHasSuffix applies the HasSuffix predicate on the "provider_type" field.
|
||||
func ProviderTypeHasSuffix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasSuffix(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeEqualFold applies the EqualFold predicate on the "provider_type" field.
|
||||
func ProviderTypeEqualFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEqualFold(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeContainsFold applies the ContainsFold predicate on the "provider_type" field.
|
||||
func ProviderTypeContainsFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContainsFold(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderKeyEQ applies the EQ predicate on the "provider_key" field.
|
||||
func ProviderKeyEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyNEQ applies the NEQ predicate on the "provider_key" field.
|
||||
func ProviderKeyNEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyIn applies the In predicate on the "provider_key" field.
|
||||
func ProviderKeyIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyNotIn applies the NotIn predicate on the "provider_key" field.
|
||||
func ProviderKeyNotIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyGT applies the GT predicate on the "provider_key" field.
|
||||
func ProviderKeyGT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyGTE applies the GTE predicate on the "provider_key" field.
|
||||
func ProviderKeyGTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLT applies the LT predicate on the "provider_key" field.
|
||||
func ProviderKeyLT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLTE applies the LTE predicate on the "provider_key" field.
|
||||
func ProviderKeyLTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContains applies the Contains predicate on the "provider_key" field.
|
||||
func ProviderKeyContains(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContains(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasPrefix applies the HasPrefix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasPrefix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasPrefix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasSuffix applies the HasSuffix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasSuffix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasSuffix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyEqualFold applies the EqualFold predicate on the "provider_key" field.
|
||||
func ProviderKeyEqualFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEqualFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContainsFold applies the ContainsFold predicate on the "provider_key" field.
|
||||
func ProviderKeyContainsFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContainsFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectEQ applies the EQ predicate on the "provider_subject" field.
|
||||
func ProviderSubjectEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectNEQ applies the NEQ predicate on the "provider_subject" field.
|
||||
func ProviderSubjectNEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectIn applies the In predicate on the "provider_subject" field.
|
||||
func ProviderSubjectIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldProviderSubject, vs...))
|
||||
}
|
||||
|
||||
// ProviderSubjectNotIn applies the NotIn predicate on the "provider_subject" field.
|
||||
func ProviderSubjectNotIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldProviderSubject, vs...))
|
||||
}
|
||||
|
||||
// ProviderSubjectGT applies the GT predicate on the "provider_subject" field.
|
||||
func ProviderSubjectGT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectGTE applies the GTE predicate on the "provider_subject" field.
|
||||
func ProviderSubjectGTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectLT applies the LT predicate on the "provider_subject" field.
|
||||
func ProviderSubjectLT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectLTE applies the LTE predicate on the "provider_subject" field.
|
||||
func ProviderSubjectLTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectContains applies the Contains predicate on the "provider_subject" field.
|
||||
func ProviderSubjectContains(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContains(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectHasPrefix applies the HasPrefix predicate on the "provider_subject" field.
|
||||
func ProviderSubjectHasPrefix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasPrefix(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectHasSuffix applies the HasSuffix predicate on the "provider_subject" field.
|
||||
func ProviderSubjectHasSuffix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasSuffix(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectEqualFold applies the EqualFold predicate on the "provider_subject" field.
|
||||
func ProviderSubjectEqualFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEqualFold(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// ProviderSubjectContainsFold applies the ContainsFold predicate on the "provider_subject" field.
|
||||
func ProviderSubjectContainsFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContainsFold(FieldProviderSubject, v))
|
||||
}
|
||||
|
||||
// VerifiedAtEQ applies the EQ predicate on the "verified_at" field.
|
||||
func VerifiedAtEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtNEQ applies the NEQ predicate on the "verified_at" field.
|
||||
func VerifiedAtNEQ(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtIn applies the In predicate on the "verified_at" field.
|
||||
func VerifiedAtIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldVerifiedAt, vs...))
|
||||
}
|
||||
|
||||
// VerifiedAtNotIn applies the NotIn predicate on the "verified_at" field.
|
||||
func VerifiedAtNotIn(vs ...time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldVerifiedAt, vs...))
|
||||
}
|
||||
|
||||
// VerifiedAtGT applies the GT predicate on the "verified_at" field.
|
||||
func VerifiedAtGT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtGTE applies the GTE predicate on the "verified_at" field.
|
||||
func VerifiedAtGTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtLT applies the LT predicate on the "verified_at" field.
|
||||
func VerifiedAtLT(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtLTE applies the LTE predicate on the "verified_at" field.
|
||||
func VerifiedAtLTE(v time.Time) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldVerifiedAt, v))
|
||||
}
|
||||
|
||||
// VerifiedAtIsNil applies the IsNil predicate on the "verified_at" field.
|
||||
func VerifiedAtIsNil() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIsNull(FieldVerifiedAt))
|
||||
}
|
||||
|
||||
// VerifiedAtNotNil applies the NotNil predicate on the "verified_at" field.
|
||||
func VerifiedAtNotNil() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotNull(FieldVerifiedAt))
|
||||
}
|
||||
|
||||
// IssuerEQ applies the EQ predicate on the "issuer" field.
|
||||
func IssuerEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEQ(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerNEQ applies the NEQ predicate on the "issuer" field.
|
||||
func IssuerNEQ(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNEQ(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerIn applies the In predicate on the "issuer" field.
|
||||
func IssuerIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIn(FieldIssuer, vs...))
|
||||
}
|
||||
|
||||
// IssuerNotIn applies the NotIn predicate on the "issuer" field.
|
||||
func IssuerNotIn(vs ...string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotIn(FieldIssuer, vs...))
|
||||
}
|
||||
|
||||
// IssuerGT applies the GT predicate on the "issuer" field.
|
||||
func IssuerGT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGT(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerGTE applies the GTE predicate on the "issuer" field.
|
||||
func IssuerGTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldGTE(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerLT applies the LT predicate on the "issuer" field.
|
||||
func IssuerLT(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLT(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerLTE applies the LTE predicate on the "issuer" field.
|
||||
func IssuerLTE(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldLTE(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerContains applies the Contains predicate on the "issuer" field.
|
||||
func IssuerContains(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContains(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerHasPrefix applies the HasPrefix predicate on the "issuer" field.
|
||||
func IssuerHasPrefix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasPrefix(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerHasSuffix applies the HasSuffix predicate on the "issuer" field.
|
||||
func IssuerHasSuffix(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldHasSuffix(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerIsNil applies the IsNil predicate on the "issuer" field.
|
||||
func IssuerIsNil() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldIsNull(FieldIssuer))
|
||||
}
|
||||
|
||||
// IssuerNotNil applies the NotNil predicate on the "issuer" field.
|
||||
func IssuerNotNil() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldNotNull(FieldIssuer))
|
||||
}
|
||||
|
||||
// IssuerEqualFold applies the EqualFold predicate on the "issuer" field.
|
||||
func IssuerEqualFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldEqualFold(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// IssuerContainsFold applies the ContainsFold predicate on the "issuer" field.
|
||||
func IssuerContainsFold(v string) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.FieldContainsFold(FieldIssuer, v))
|
||||
}
|
||||
|
||||
// HasUser applies the HasEdge predicate on the "user" edge.
|
||||
func HasUser() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
|
||||
func HasUserWith(preds ...predicate.User) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := newUserStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasChannels applies the HasEdge predicate on the "channels" edge.
|
||||
func HasChannels() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, ChannelsTable, ChannelsColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasChannelsWith applies the HasEdge predicate on the "channels" edge with a given conditions (other predicates).
|
||||
func HasChannelsWith(preds ...predicate.AuthIdentityChannel) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := newChannelsStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasAdoptionDecisions applies the HasEdge predicate on the "adoption_decisions" edge.
|
||||
func HasAdoptionDecisions() predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AdoptionDecisionsTable, AdoptionDecisionsColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasAdoptionDecisionsWith applies the HasEdge predicate on the "adoption_decisions" edge with a given conditions (other predicates).
|
||||
func HasAdoptionDecisionsWith(preds ...predicate.IdentityAdoptionDecision) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
step := newAdoptionDecisionsStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.AuthIdentity) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.AuthIdentity) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.AuthIdentity) predicate.AuthIdentity {
|
||||
return predicate.AuthIdentity(sql.NotPredicates(p))
|
||||
}
|
||||
1036
backend/ent/authidentity_create.go
Normal file
1036
backend/ent/authidentity_create.go
Normal file
File diff suppressed because it is too large
Load Diff
88
backend/ent/authidentity_delete.go
Normal file
88
backend/ent/authidentity_delete.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AuthIdentityDelete is the builder for deleting a AuthIdentity entity.
|
||||
type AuthIdentityDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityDelete builder.
|
||||
func (_d *AuthIdentityDelete) Where(ps ...predicate.AuthIdentity) *AuthIdentityDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *AuthIdentityDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AuthIdentityDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *AuthIdentityDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(authidentity.Table, sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// AuthIdentityDeleteOne is the builder for deleting a single AuthIdentity entity.
|
||||
type AuthIdentityDeleteOne struct {
|
||||
_d *AuthIdentityDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityDelete builder.
|
||||
func (_d *AuthIdentityDeleteOne) Where(ps ...predicate.AuthIdentity) *AuthIdentityDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *AuthIdentityDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{authidentity.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AuthIdentityDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
797
backend/ent/authidentity_query.go
Normal file
797
backend/ent/authidentity_query.go
Normal file
@ -0,0 +1,797 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AuthIdentityQuery is the builder for querying AuthIdentity entities.
|
||||
type AuthIdentityQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []authidentity.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.AuthIdentity
|
||||
withUser *UserQuery
|
||||
withChannels *AuthIdentityChannelQuery
|
||||
withAdoptionDecisions *IdentityAdoptionDecisionQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the AuthIdentityQuery builder.
|
||||
func (_q *AuthIdentityQuery) Where(ps ...predicate.AuthIdentity) *AuthIdentityQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *AuthIdentityQuery) Limit(limit int) *AuthIdentityQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *AuthIdentityQuery) Offset(offset int) *AuthIdentityQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *AuthIdentityQuery) Unique(unique bool) *AuthIdentityQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *AuthIdentityQuery) Order(o ...authidentity.OrderOption) *AuthIdentityQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryUser chains the current query on the "user" edge.
|
||||
func (_q *AuthIdentityQuery) QueryUser() *UserQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, selector),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, authidentity.UserTable, authidentity.UserColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryChannels chains the current query on the "channels" edge.
|
||||
func (_q *AuthIdentityQuery) QueryChannels() *AuthIdentityChannelQuery {
|
||||
query := (&AuthIdentityChannelClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, selector),
|
||||
sqlgraph.To(authidentitychannel.Table, authidentitychannel.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, authidentity.ChannelsTable, authidentity.ChannelsColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAdoptionDecisions chains the current query on the "adoption_decisions" edge.
|
||||
func (_q *AuthIdentityQuery) QueryAdoptionDecisions() *IdentityAdoptionDecisionQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, selector),
|
||||
sqlgraph.To(identityadoptiondecision.Table, identityadoptiondecision.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, authidentity.AdoptionDecisionsTable, authidentity.AdoptionDecisionsColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first AuthIdentity entity from the query.
|
||||
// Returns a *NotFoundError when no AuthIdentity was found.
|
||||
func (_q *AuthIdentityQuery) First(ctx context.Context) (*AuthIdentity, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{authidentity.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) FirstX(ctx context.Context) *AuthIdentity {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first AuthIdentity ID from the query.
|
||||
// Returns a *NotFoundError when no AuthIdentity ID was found.
|
||||
func (_q *AuthIdentityQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{authidentity.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single AuthIdentity entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one AuthIdentity entity is found.
|
||||
// Returns a *NotFoundError when no AuthIdentity entities are found.
|
||||
func (_q *AuthIdentityQuery) Only(ctx context.Context) (*AuthIdentity, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{authidentity.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{authidentity.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) OnlyX(ctx context.Context) *AuthIdentity {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only AuthIdentity ID in the query.
|
||||
// Returns a *NotSingularError when more than one AuthIdentity ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *AuthIdentityQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{authidentity.Label}
|
||||
default:
|
||||
err = &NotSingularError{authidentity.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of AuthIdentities.
|
||||
func (_q *AuthIdentityQuery) All(ctx context.Context) ([]*AuthIdentity, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*AuthIdentity, *AuthIdentityQuery]()
|
||||
return withInterceptors[[]*AuthIdentity](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) AllX(ctx context.Context) []*AuthIdentity {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of AuthIdentity IDs.
|
||||
func (_q *AuthIdentityQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(authidentity.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *AuthIdentityQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*AuthIdentityQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *AuthIdentityQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *AuthIdentityQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the AuthIdentityQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *AuthIdentityQuery) Clone() *AuthIdentityQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &AuthIdentityQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]authidentity.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.AuthIdentity{}, _q.predicates...),
|
||||
withUser: _q.withUser.Clone(),
|
||||
withChannels: _q.withChannels.Clone(),
|
||||
withAdoptionDecisions: _q.withAdoptionDecisions.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithUser tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AuthIdentityQuery) WithUser(opts ...func(*UserQuery)) *AuthIdentityQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withUser = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithChannels tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "channels" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AuthIdentityQuery) WithChannels(opts ...func(*AuthIdentityChannelQuery)) *AuthIdentityQuery {
|
||||
query := (&AuthIdentityChannelClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withChannels = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithAdoptionDecisions tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "adoption_decisions" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AuthIdentityQuery) WithAdoptionDecisions(opts ...func(*IdentityAdoptionDecisionQuery)) *AuthIdentityQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withAdoptionDecisions = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AuthIdentity.Query().
|
||||
// GroupBy(authidentity.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AuthIdentityQuery) GroupBy(field string, fields ...string) *AuthIdentityGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &AuthIdentityGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = authidentity.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AuthIdentity.Query().
|
||||
// Select(authidentity.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AuthIdentityQuery) Select(fields ...string) *AuthIdentitySelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &AuthIdentitySelect{AuthIdentityQuery: _q}
|
||||
sbuild.label = authidentity.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a AuthIdentitySelect configured with the given aggregations.
|
||||
func (_q *AuthIdentityQuery) Aggregate(fns ...AggregateFunc) *AuthIdentitySelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !authidentity.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AuthIdentity, error) {
|
||||
var (
|
||||
nodes = []*AuthIdentity{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [3]bool{
|
||||
_q.withUser != nil,
|
||||
_q.withChannels != nil,
|
||||
_q.withAdoptionDecisions != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*AuthIdentity).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &AuthIdentity{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withUser; query != nil {
|
||||
if err := _q.loadUser(ctx, query, nodes, nil,
|
||||
func(n *AuthIdentity, e *User) { n.Edges.User = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withChannels; query != nil {
|
||||
if err := _q.loadChannels(ctx, query, nodes,
|
||||
func(n *AuthIdentity) { n.Edges.Channels = []*AuthIdentityChannel{} },
|
||||
func(n *AuthIdentity, e *AuthIdentityChannel) { n.Edges.Channels = append(n.Edges.Channels, e) }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withAdoptionDecisions; query != nil {
|
||||
if err := _q.loadAdoptionDecisions(ctx, query, nodes,
|
||||
func(n *AuthIdentity) { n.Edges.AdoptionDecisions = []*IdentityAdoptionDecision{} },
|
||||
func(n *AuthIdentity, e *IdentityAdoptionDecision) {
|
||||
n.Edges.AdoptionDecisions = append(n.Edges.AdoptionDecisions, e)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*AuthIdentity, init func(*AuthIdentity), assign func(*AuthIdentity, *User)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*AuthIdentity)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].UserID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(user.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "user_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *AuthIdentityQuery) loadChannels(ctx context.Context, query *AuthIdentityChannelQuery, nodes []*AuthIdentity, init func(*AuthIdentity), assign func(*AuthIdentity, *AuthIdentityChannel)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*AuthIdentity)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(authidentitychannel.FieldIdentityID)
|
||||
}
|
||||
query.Where(predicate.AuthIdentityChannel(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(authidentity.ChannelsColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.IdentityID
|
||||
node, ok := nodeids[fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "identity_id" returned %v for node %v`, fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *AuthIdentityQuery) loadAdoptionDecisions(ctx context.Context, query *IdentityAdoptionDecisionQuery, nodes []*AuthIdentity, init func(*AuthIdentity), assign func(*AuthIdentity, *IdentityAdoptionDecision)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*AuthIdentity)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(identityadoptiondecision.FieldIdentityID)
|
||||
}
|
||||
query.Where(predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(authidentity.AdoptionDecisionsColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.IdentityID
|
||||
if fk == nil {
|
||||
return fmt.Errorf(`foreign-key "identity_id" is nil for node %v`, n.ID)
|
||||
}
|
||||
node, ok := nodeids[*fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "identity_id" returned %v for node %v`, *fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(authidentity.Table, authidentity.Columns, sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, authidentity.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != authidentity.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if _q.withUser != nil {
|
||||
_spec.Node.AddColumnOnce(authidentity.FieldUserID)
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(authidentity.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = authidentity.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *AuthIdentityQuery) ForUpdate(opts ...sql.LockOption) *AuthIdentityQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *AuthIdentityQuery) ForShare(opts ...sql.LockOption) *AuthIdentityQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// AuthIdentityGroupBy is the group-by builder for AuthIdentity entities.
|
||||
type AuthIdentityGroupBy struct {
|
||||
selector
|
||||
build *AuthIdentityQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *AuthIdentityGroupBy) Aggregate(fns ...AggregateFunc) *AuthIdentityGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *AuthIdentityGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AuthIdentityQuery, *AuthIdentityGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *AuthIdentityGroupBy) sqlScan(ctx context.Context, root *AuthIdentityQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// AuthIdentitySelect is the builder for selecting fields of AuthIdentity entities.
|
||||
type AuthIdentitySelect struct {
|
||||
*AuthIdentityQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *AuthIdentitySelect) Aggregate(fns ...AggregateFunc) *AuthIdentitySelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *AuthIdentitySelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AuthIdentityQuery, *AuthIdentitySelect](ctx, _s.AuthIdentityQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *AuthIdentitySelect) sqlScan(ctx context.Context, root *AuthIdentityQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
923
backend/ent/authidentity_update.go
Normal file
923
backend/ent/authidentity_update.go
Normal file
@ -0,0 +1,923 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// AuthIdentityUpdate is the builder for updating AuthIdentity entities.
|
||||
type AuthIdentityUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityUpdate builder.
|
||||
func (_u *AuthIdentityUpdate) Where(ps ...predicate.AuthIdentity) *AuthIdentityUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AuthIdentityUpdate) SetUpdatedAt(v time.Time) *AuthIdentityUpdate {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (_u *AuthIdentityUpdate) SetUserID(v int64) *AuthIdentityUpdate {
|
||||
_u.mutation.SetUserID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableUserID(v *int64) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetUserID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (_u *AuthIdentityUpdate) SetProviderType(v string) *AuthIdentityUpdate {
|
||||
_u.mutation.SetProviderType(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderType sets the "provider_type" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableProviderType(v *string) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderType(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *AuthIdentityUpdate) SetProviderKey(v string) *AuthIdentityUpdate {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableProviderKey(v *string) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderSubject sets the "provider_subject" field.
|
||||
func (_u *AuthIdentityUpdate) SetProviderSubject(v string) *AuthIdentityUpdate {
|
||||
_u.mutation.SetProviderSubject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderSubject sets the "provider_subject" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableProviderSubject(v *string) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderSubject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetVerifiedAt sets the "verified_at" field.
|
||||
func (_u *AuthIdentityUpdate) SetVerifiedAt(v time.Time) *AuthIdentityUpdate {
|
||||
_u.mutation.SetVerifiedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableVerifiedAt sets the "verified_at" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableVerifiedAt(v *time.Time) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetVerifiedAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearVerifiedAt clears the value of the "verified_at" field.
|
||||
func (_u *AuthIdentityUpdate) ClearVerifiedAt() *AuthIdentityUpdate {
|
||||
_u.mutation.ClearVerifiedAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIssuer sets the "issuer" field.
|
||||
func (_u *AuthIdentityUpdate) SetIssuer(v string) *AuthIdentityUpdate {
|
||||
_u.mutation.SetIssuer(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIssuer sets the "issuer" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdate) SetNillableIssuer(v *string) *AuthIdentityUpdate {
|
||||
if v != nil {
|
||||
_u.SetIssuer(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIssuer clears the value of the "issuer" field.
|
||||
func (_u *AuthIdentityUpdate) ClearIssuer() *AuthIdentityUpdate {
|
||||
_u.mutation.ClearIssuer()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (_u *AuthIdentityUpdate) SetMetadata(v map[string]interface{}) *AuthIdentityUpdate {
|
||||
_u.mutation.SetMetadata(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *AuthIdentityUpdate) SetUser(v *User) *AuthIdentityUpdate {
|
||||
return _u.SetUserID(v.ID)
|
||||
}
|
||||
|
||||
// AddChannelIDs adds the "channels" edge to the AuthIdentityChannel entity by IDs.
|
||||
func (_u *AuthIdentityUpdate) AddChannelIDs(ids ...int64) *AuthIdentityUpdate {
|
||||
_u.mutation.AddChannelIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddChannels adds the "channels" edges to the AuthIdentityChannel entity.
|
||||
func (_u *AuthIdentityUpdate) AddChannels(v ...*AuthIdentityChannel) *AuthIdentityUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddChannelIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAdoptionDecisionIDs adds the "adoption_decisions" edge to the IdentityAdoptionDecision entity by IDs.
|
||||
func (_u *AuthIdentityUpdate) AddAdoptionDecisionIDs(ids ...int64) *AuthIdentityUpdate {
|
||||
_u.mutation.AddAdoptionDecisionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAdoptionDecisions adds the "adoption_decisions" edges to the IdentityAdoptionDecision entity.
|
||||
func (_u *AuthIdentityUpdate) AddAdoptionDecisions(v ...*IdentityAdoptionDecision) *AuthIdentityUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAdoptionDecisionIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the AuthIdentityMutation object of the builder.
|
||||
func (_u *AuthIdentityUpdate) Mutation() *AuthIdentityMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearUser clears the "user" edge to the User entity.
|
||||
func (_u *AuthIdentityUpdate) ClearUser() *AuthIdentityUpdate {
|
||||
_u.mutation.ClearUser()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearChannels clears all "channels" edges to the AuthIdentityChannel entity.
|
||||
func (_u *AuthIdentityUpdate) ClearChannels() *AuthIdentityUpdate {
|
||||
_u.mutation.ClearChannels()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveChannelIDs removes the "channels" edge to AuthIdentityChannel entities by IDs.
|
||||
func (_u *AuthIdentityUpdate) RemoveChannelIDs(ids ...int64) *AuthIdentityUpdate {
|
||||
_u.mutation.RemoveChannelIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveChannels removes "channels" edges to AuthIdentityChannel entities.
|
||||
func (_u *AuthIdentityUpdate) RemoveChannels(v ...*AuthIdentityChannel) *AuthIdentityUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveChannelIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAdoptionDecisions clears all "adoption_decisions" edges to the IdentityAdoptionDecision entity.
|
||||
func (_u *AuthIdentityUpdate) ClearAdoptionDecisions() *AuthIdentityUpdate {
|
||||
_u.mutation.ClearAdoptionDecisions()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAdoptionDecisionIDs removes the "adoption_decisions" edge to IdentityAdoptionDecision entities by IDs.
|
||||
func (_u *AuthIdentityUpdate) RemoveAdoptionDecisionIDs(ids ...int64) *AuthIdentityUpdate {
|
||||
_u.mutation.RemoveAdoptionDecisionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAdoptionDecisions removes "adoption_decisions" edges to IdentityAdoptionDecision entities.
|
||||
func (_u *AuthIdentityUpdate) RemoveAdoptionDecisions(v ...*IdentityAdoptionDecision) *AuthIdentityUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAdoptionDecisionIDs(ids...)
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *AuthIdentityUpdate) Save(ctx context.Context) (int, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AuthIdentityUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *AuthIdentityUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AuthIdentityUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AuthIdentityUpdate) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := authidentity.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AuthIdentityUpdate) check() error {
|
||||
if v, ok := _u.mutation.ProviderType(); ok {
|
||||
if err := authidentity.ProviderTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_type", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := authidentity.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderSubject(); ok {
|
||||
if err := authidentity.ProviderSubjectValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_subject", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_subject": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AuthIdentity.user"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AuthIdentityUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(authidentity.Table, authidentity.Columns, sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(authidentity.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderType(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderType, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderSubject(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderSubject, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.VerifiedAt(); ok {
|
||||
_spec.SetField(authidentity.FieldVerifiedAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.VerifiedAtCleared() {
|
||||
_spec.ClearField(authidentity.FieldVerifiedAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.Issuer(); ok {
|
||||
_spec.SetField(authidentity.FieldIssuer, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.IssuerCleared() {
|
||||
_spec.ClearField(authidentity.FieldIssuer, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.Metadata(); ok {
|
||||
_spec.SetField(authidentity.FieldMetadata, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentity.UserTable,
|
||||
Columns: []string{authidentity.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentity.UserTable,
|
||||
Columns: []string{authidentity.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.ChannelsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedChannelsIDs(); len(nodes) > 0 && !_u.mutation.ChannelsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.ChannelsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AdoptionDecisionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAdoptionDecisionsIDs(); len(nodes) > 0 && !_u.mutation.AdoptionDecisionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AdoptionDecisionsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{authidentity.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// AuthIdentityUpdateOne is the builder for updating a single AuthIdentity entity.
|
||||
type AuthIdentityUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityMutation
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetUpdatedAt(v time.Time) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUserID sets the "user_id" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetUserID(v int64) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetUserID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableUserID sets the "user_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableUserID(v *int64) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetUserID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetProviderType(v string) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetProviderType(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderType sets the "provider_type" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableProviderType(v *string) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderType(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetProviderKey(v string) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableProviderKey(v *string) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderSubject sets the "provider_subject" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetProviderSubject(v string) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetProviderSubject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderSubject sets the "provider_subject" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableProviderSubject(v *string) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderSubject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetVerifiedAt sets the "verified_at" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetVerifiedAt(v time.Time) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetVerifiedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableVerifiedAt sets the "verified_at" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableVerifiedAt(v *time.Time) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetVerifiedAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearVerifiedAt clears the value of the "verified_at" field.
|
||||
func (_u *AuthIdentityUpdateOne) ClearVerifiedAt() *AuthIdentityUpdateOne {
|
||||
_u.mutation.ClearVerifiedAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIssuer sets the "issuer" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetIssuer(v string) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetIssuer(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIssuer sets the "issuer" field if the given value is not nil.
|
||||
func (_u *AuthIdentityUpdateOne) SetNillableIssuer(v *string) *AuthIdentityUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetIssuer(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIssuer clears the value of the "issuer" field.
|
||||
func (_u *AuthIdentityUpdateOne) ClearIssuer() *AuthIdentityUpdateOne {
|
||||
_u.mutation.ClearIssuer()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (_u *AuthIdentityUpdateOne) SetMetadata(v map[string]interface{}) *AuthIdentityUpdateOne {
|
||||
_u.mutation.SetMetadata(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUser sets the "user" edge to the User entity.
|
||||
func (_u *AuthIdentityUpdateOne) SetUser(v *User) *AuthIdentityUpdateOne {
|
||||
return _u.SetUserID(v.ID)
|
||||
}
|
||||
|
||||
// AddChannelIDs adds the "channels" edge to the AuthIdentityChannel entity by IDs.
|
||||
func (_u *AuthIdentityUpdateOne) AddChannelIDs(ids ...int64) *AuthIdentityUpdateOne {
|
||||
_u.mutation.AddChannelIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddChannels adds the "channels" edges to the AuthIdentityChannel entity.
|
||||
func (_u *AuthIdentityUpdateOne) AddChannels(v ...*AuthIdentityChannel) *AuthIdentityUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddChannelIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAdoptionDecisionIDs adds the "adoption_decisions" edge to the IdentityAdoptionDecision entity by IDs.
|
||||
func (_u *AuthIdentityUpdateOne) AddAdoptionDecisionIDs(ids ...int64) *AuthIdentityUpdateOne {
|
||||
_u.mutation.AddAdoptionDecisionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAdoptionDecisions adds the "adoption_decisions" edges to the IdentityAdoptionDecision entity.
|
||||
func (_u *AuthIdentityUpdateOne) AddAdoptionDecisions(v ...*IdentityAdoptionDecision) *AuthIdentityUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAdoptionDecisionIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the AuthIdentityMutation object of the builder.
|
||||
func (_u *AuthIdentityUpdateOne) Mutation() *AuthIdentityMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearUser clears the "user" edge to the User entity.
|
||||
func (_u *AuthIdentityUpdateOne) ClearUser() *AuthIdentityUpdateOne {
|
||||
_u.mutation.ClearUser()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearChannels clears all "channels" edges to the AuthIdentityChannel entity.
|
||||
func (_u *AuthIdentityUpdateOne) ClearChannels() *AuthIdentityUpdateOne {
|
||||
_u.mutation.ClearChannels()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveChannelIDs removes the "channels" edge to AuthIdentityChannel entities by IDs.
|
||||
func (_u *AuthIdentityUpdateOne) RemoveChannelIDs(ids ...int64) *AuthIdentityUpdateOne {
|
||||
_u.mutation.RemoveChannelIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveChannels removes "channels" edges to AuthIdentityChannel entities.
|
||||
func (_u *AuthIdentityUpdateOne) RemoveChannels(v ...*AuthIdentityChannel) *AuthIdentityUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveChannelIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAdoptionDecisions clears all "adoption_decisions" edges to the IdentityAdoptionDecision entity.
|
||||
func (_u *AuthIdentityUpdateOne) ClearAdoptionDecisions() *AuthIdentityUpdateOne {
|
||||
_u.mutation.ClearAdoptionDecisions()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAdoptionDecisionIDs removes the "adoption_decisions" edge to IdentityAdoptionDecision entities by IDs.
|
||||
func (_u *AuthIdentityUpdateOne) RemoveAdoptionDecisionIDs(ids ...int64) *AuthIdentityUpdateOne {
|
||||
_u.mutation.RemoveAdoptionDecisionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAdoptionDecisions removes "adoption_decisions" edges to IdentityAdoptionDecision entities.
|
||||
func (_u *AuthIdentityUpdateOne) RemoveAdoptionDecisions(v ...*IdentityAdoptionDecision) *AuthIdentityUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAdoptionDecisionIDs(ids...)
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityUpdate builder.
|
||||
func (_u *AuthIdentityUpdateOne) Where(ps ...predicate.AuthIdentity) *AuthIdentityUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *AuthIdentityUpdateOne) Select(field string, fields ...string) *AuthIdentityUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated AuthIdentity entity.
|
||||
func (_u *AuthIdentityUpdateOne) Save(ctx context.Context) (*AuthIdentity, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AuthIdentityUpdateOne) SaveX(ctx context.Context) *AuthIdentity {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *AuthIdentityUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AuthIdentityUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AuthIdentityUpdateOne) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := authidentity.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AuthIdentityUpdateOne) check() error {
|
||||
if v, ok := _u.mutation.ProviderType(); ok {
|
||||
if err := authidentity.ProviderTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_type", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := authidentity.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderSubject(); ok {
|
||||
if err := authidentity.ProviderSubjectValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_subject", err: fmt.Errorf(`ent: validator failed for field "AuthIdentity.provider_subject": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AuthIdentity.user"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AuthIdentityUpdateOne) sqlSave(ctx context.Context) (_node *AuthIdentity, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(authidentity.Table, authidentity.Columns, sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AuthIdentity.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, authidentity.FieldID)
|
||||
for _, f := range fields {
|
||||
if !authidentity.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != authidentity.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(authidentity.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderType(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderType, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderSubject(); ok {
|
||||
_spec.SetField(authidentity.FieldProviderSubject, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.VerifiedAt(); ok {
|
||||
_spec.SetField(authidentity.FieldVerifiedAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.VerifiedAtCleared() {
|
||||
_spec.ClearField(authidentity.FieldVerifiedAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.Issuer(); ok {
|
||||
_spec.SetField(authidentity.FieldIssuer, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.IssuerCleared() {
|
||||
_spec.ClearField(authidentity.FieldIssuer, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.Metadata(); ok {
|
||||
_spec.SetField(authidentity.FieldMetadata, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.UserCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentity.UserTable,
|
||||
Columns: []string{authidentity.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.UserIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentity.UserTable,
|
||||
Columns: []string{authidentity.UserColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.ChannelsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedChannelsIDs(); len(nodes) > 0 && !_u.mutation.ChannelsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.ChannelsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.ChannelsTable,
|
||||
Columns: []string{authidentity.ChannelsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AdoptionDecisionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAdoptionDecisionsIDs(); len(nodes) > 0 && !_u.mutation.AdoptionDecisionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AdoptionDecisionsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: authidentity.AdoptionDecisionsTable,
|
||||
Columns: []string{authidentity.AdoptionDecisionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &AuthIdentity{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{authidentity.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
228
backend/ent/authidentitychannel.go
Normal file
228
backend/ent/authidentitychannel.go
Normal file
@ -0,0 +1,228 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
)
|
||||
|
||||
// AuthIdentityChannel is the model entity for the AuthIdentityChannel schema.
|
||||
type AuthIdentityChannel struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// IdentityID holds the value of the "identity_id" field.
|
||||
IdentityID int64 `json:"identity_id,omitempty"`
|
||||
// ProviderType holds the value of the "provider_type" field.
|
||||
ProviderType string `json:"provider_type,omitempty"`
|
||||
// ProviderKey holds the value of the "provider_key" field.
|
||||
ProviderKey string `json:"provider_key,omitempty"`
|
||||
// Channel holds the value of the "channel" field.
|
||||
Channel string `json:"channel,omitempty"`
|
||||
// ChannelAppID holds the value of the "channel_app_id" field.
|
||||
ChannelAppID string `json:"channel_app_id,omitempty"`
|
||||
// ChannelSubject holds the value of the "channel_subject" field.
|
||||
ChannelSubject string `json:"channel_subject,omitempty"`
|
||||
// Metadata holds the value of the "metadata" field.
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AuthIdentityChannelQuery when eager-loading is set.
|
||||
Edges AuthIdentityChannelEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// AuthIdentityChannelEdges holds the relations/edges for other nodes in the graph.
|
||||
type AuthIdentityChannelEdges struct {
|
||||
// Identity holds the value of the identity edge.
|
||||
Identity *AuthIdentity `json:"identity,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [1]bool
|
||||
}
|
||||
|
||||
// IdentityOrErr returns the Identity value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e AuthIdentityChannelEdges) IdentityOrErr() (*AuthIdentity, error) {
|
||||
if e.Identity != nil {
|
||||
return e.Identity, nil
|
||||
} else if e.loadedTypes[0] {
|
||||
return nil, &NotFoundError{label: authidentity.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "identity"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*AuthIdentityChannel) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case authidentitychannel.FieldMetadata:
|
||||
values[i] = new([]byte)
|
||||
case authidentitychannel.FieldID, authidentitychannel.FieldIdentityID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case authidentitychannel.FieldProviderType, authidentitychannel.FieldProviderKey, authidentitychannel.FieldChannel, authidentitychannel.FieldChannelAppID, authidentitychannel.FieldChannelSubject:
|
||||
values[i] = new(sql.NullString)
|
||||
case authidentitychannel.FieldCreatedAt, authidentitychannel.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the AuthIdentityChannel fields.
|
||||
func (_m *AuthIdentityChannel) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case authidentitychannel.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case authidentitychannel.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case authidentitychannel.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
case authidentitychannel.FieldIdentityID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field identity_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.IdentityID = value.Int64
|
||||
}
|
||||
case authidentitychannel.FieldProviderType:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_type", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderType = value.String
|
||||
}
|
||||
case authidentitychannel.FieldProviderKey:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_key", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderKey = value.String
|
||||
}
|
||||
case authidentitychannel.FieldChannel:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field channel", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Channel = value.String
|
||||
}
|
||||
case authidentitychannel.FieldChannelAppID:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field channel_app_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ChannelAppID = value.String
|
||||
}
|
||||
case authidentitychannel.FieldChannelSubject:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field channel_subject", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ChannelSubject = value.String
|
||||
}
|
||||
case authidentitychannel.FieldMetadata:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field metadata", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.Metadata); err != nil {
|
||||
return fmt.Errorf("unmarshal field metadata: %w", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the AuthIdentityChannel.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *AuthIdentityChannel) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryIdentity queries the "identity" edge of the AuthIdentityChannel entity.
|
||||
func (_m *AuthIdentityChannel) QueryIdentity() *AuthIdentityQuery {
|
||||
return NewAuthIdentityChannelClient(_m.config).QueryIdentity(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this AuthIdentityChannel.
|
||||
// Note that you need to call AuthIdentityChannel.Unwrap() before calling this method if this AuthIdentityChannel
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *AuthIdentityChannel) Update() *AuthIdentityChannelUpdateOne {
|
||||
return NewAuthIdentityChannelClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the AuthIdentityChannel entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *AuthIdentityChannel) Unwrap() *AuthIdentityChannel {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: AuthIdentityChannel is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *AuthIdentityChannel) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("AuthIdentityChannel(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("identity_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.IdentityID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_type=")
|
||||
builder.WriteString(_m.ProviderType)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_key=")
|
||||
builder.WriteString(_m.ProviderKey)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("channel=")
|
||||
builder.WriteString(_m.Channel)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("channel_app_id=")
|
||||
builder.WriteString(_m.ChannelAppID)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("channel_subject=")
|
||||
builder.WriteString(_m.ChannelSubject)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("metadata=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.Metadata))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// AuthIdentityChannels is a parsable slice of AuthIdentityChannel.
|
||||
type AuthIdentityChannels []*AuthIdentityChannel
|
||||
153
backend/ent/authidentitychannel/authidentitychannel.go
Normal file
153
backend/ent/authidentitychannel/authidentitychannel.go
Normal file
@ -0,0 +1,153 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package authidentitychannel
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the authidentitychannel type in the database.
|
||||
Label = "auth_identity_channel"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldIdentityID holds the string denoting the identity_id field in the database.
|
||||
FieldIdentityID = "identity_id"
|
||||
// FieldProviderType holds the string denoting the provider_type field in the database.
|
||||
FieldProviderType = "provider_type"
|
||||
// FieldProviderKey holds the string denoting the provider_key field in the database.
|
||||
FieldProviderKey = "provider_key"
|
||||
// FieldChannel holds the string denoting the channel field in the database.
|
||||
FieldChannel = "channel"
|
||||
// FieldChannelAppID holds the string denoting the channel_app_id field in the database.
|
||||
FieldChannelAppID = "channel_app_id"
|
||||
// FieldChannelSubject holds the string denoting the channel_subject field in the database.
|
||||
FieldChannelSubject = "channel_subject"
|
||||
// FieldMetadata holds the string denoting the metadata field in the database.
|
||||
FieldMetadata = "metadata"
|
||||
// EdgeIdentity holds the string denoting the identity edge name in mutations.
|
||||
EdgeIdentity = "identity"
|
||||
// Table holds the table name of the authidentitychannel in the database.
|
||||
Table = "auth_identity_channels"
|
||||
// IdentityTable is the table that holds the identity relation/edge.
|
||||
IdentityTable = "auth_identity_channels"
|
||||
// IdentityInverseTable is the table name for the AuthIdentity entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "authidentity" package.
|
||||
IdentityInverseTable = "auth_identities"
|
||||
// IdentityColumn is the table column denoting the identity relation/edge.
|
||||
IdentityColumn = "identity_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for authidentitychannel fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldIdentityID,
|
||||
FieldProviderType,
|
||||
FieldProviderKey,
|
||||
FieldChannel,
|
||||
FieldChannelAppID,
|
||||
FieldChannelSubject,
|
||||
FieldMetadata,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
// ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
ProviderTypeValidator func(string) error
|
||||
// ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
ProviderKeyValidator func(string) error
|
||||
// ChannelValidator is a validator for the "channel" field. It is called by the builders before save.
|
||||
ChannelValidator func(string) error
|
||||
// ChannelAppIDValidator is a validator for the "channel_app_id" field. It is called by the builders before save.
|
||||
ChannelAppIDValidator func(string) error
|
||||
// ChannelSubjectValidator is a validator for the "channel_subject" field. It is called by the builders before save.
|
||||
ChannelSubjectValidator func(string) error
|
||||
// DefaultMetadata holds the default value on creation for the "metadata" field.
|
||||
DefaultMetadata func() map[string]interface{}
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the AuthIdentityChannel queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByIdentityID orders the results by the identity_id field.
|
||||
func ByIdentityID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldIdentityID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderType orders the results by the provider_type field.
|
||||
func ByProviderType(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderType, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderKey orders the results by the provider_key field.
|
||||
func ByProviderKey(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderKey, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByChannel orders the results by the channel field.
|
||||
func ByChannel(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldChannel, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByChannelAppID orders the results by the channel_app_id field.
|
||||
func ByChannelAppID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldChannelAppID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByChannelSubject orders the results by the channel_subject field.
|
||||
func ByChannelSubject(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldChannelSubject, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByIdentityField orders the results by identity field.
|
||||
func ByIdentityField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newIdentityStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
func newIdentityStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(IdentityInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, IdentityTable, IdentityColumn),
|
||||
)
|
||||
}
|
||||
559
backend/ent/authidentitychannel/where.go
Normal file
559
backend/ent/authidentitychannel/where.go
Normal file
@ -0,0 +1,559 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package authidentitychannel
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// IdentityID applies equality check predicate on the "identity_id" field. It's identical to IdentityIDEQ.
|
||||
func IdentityID(v int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// ProviderType applies equality check predicate on the "provider_type" field. It's identical to ProviderTypeEQ.
|
||||
func ProviderType(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderKey applies equality check predicate on the "provider_key" field. It's identical to ProviderKeyEQ.
|
||||
func ProviderKey(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// Channel applies equality check predicate on the "channel" field. It's identical to ChannelEQ.
|
||||
func Channel(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelAppID applies equality check predicate on the "channel_app_id" field. It's identical to ChannelAppIDEQ.
|
||||
func ChannelAppID(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelSubject applies equality check predicate on the "channel_subject" field. It's identical to ChannelSubjectEQ.
|
||||
func ChannelSubject(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// IdentityIDEQ applies the EQ predicate on the "identity_id" field.
|
||||
func IdentityIDEQ(v int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// IdentityIDNEQ applies the NEQ predicate on the "identity_id" field.
|
||||
func IdentityIDNEQ(v int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// IdentityIDIn applies the In predicate on the "identity_id" field.
|
||||
func IdentityIDIn(vs ...int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldIdentityID, vs...))
|
||||
}
|
||||
|
||||
// IdentityIDNotIn applies the NotIn predicate on the "identity_id" field.
|
||||
func IdentityIDNotIn(vs ...int64) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldIdentityID, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeEQ applies the EQ predicate on the "provider_type" field.
|
||||
func ProviderTypeEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeNEQ applies the NEQ predicate on the "provider_type" field.
|
||||
func ProviderTypeNEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeIn applies the In predicate on the "provider_type" field.
|
||||
func ProviderTypeIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldProviderType, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeNotIn applies the NotIn predicate on the "provider_type" field.
|
||||
func ProviderTypeNotIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldProviderType, vs...))
|
||||
}
|
||||
|
||||
// ProviderTypeGT applies the GT predicate on the "provider_type" field.
|
||||
func ProviderTypeGT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeGTE applies the GTE predicate on the "provider_type" field.
|
||||
func ProviderTypeGTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeLT applies the LT predicate on the "provider_type" field.
|
||||
func ProviderTypeLT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeLTE applies the LTE predicate on the "provider_type" field.
|
||||
func ProviderTypeLTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeContains applies the Contains predicate on the "provider_type" field.
|
||||
func ProviderTypeContains(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContains(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeHasPrefix applies the HasPrefix predicate on the "provider_type" field.
|
||||
func ProviderTypeHasPrefix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasPrefix(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeHasSuffix applies the HasSuffix predicate on the "provider_type" field.
|
||||
func ProviderTypeHasSuffix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasSuffix(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeEqualFold applies the EqualFold predicate on the "provider_type" field.
|
||||
func ProviderTypeEqualFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEqualFold(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderTypeContainsFold applies the ContainsFold predicate on the "provider_type" field.
|
||||
func ProviderTypeContainsFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContainsFold(FieldProviderType, v))
|
||||
}
|
||||
|
||||
// ProviderKeyEQ applies the EQ predicate on the "provider_key" field.
|
||||
func ProviderKeyEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyNEQ applies the NEQ predicate on the "provider_key" field.
|
||||
func ProviderKeyNEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyIn applies the In predicate on the "provider_key" field.
|
||||
func ProviderKeyIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyNotIn applies the NotIn predicate on the "provider_key" field.
|
||||
func ProviderKeyNotIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyGT applies the GT predicate on the "provider_key" field.
|
||||
func ProviderKeyGT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyGTE applies the GTE predicate on the "provider_key" field.
|
||||
func ProviderKeyGTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLT applies the LT predicate on the "provider_key" field.
|
||||
func ProviderKeyLT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLTE applies the LTE predicate on the "provider_key" field.
|
||||
func ProviderKeyLTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContains applies the Contains predicate on the "provider_key" field.
|
||||
func ProviderKeyContains(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContains(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasPrefix applies the HasPrefix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasPrefix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasPrefix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasSuffix applies the HasSuffix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasSuffix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasSuffix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyEqualFold applies the EqualFold predicate on the "provider_key" field.
|
||||
func ProviderKeyEqualFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEqualFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContainsFold applies the ContainsFold predicate on the "provider_key" field.
|
||||
func ProviderKeyContainsFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContainsFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ChannelEQ applies the EQ predicate on the "channel" field.
|
||||
func ChannelEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelNEQ applies the NEQ predicate on the "channel" field.
|
||||
func ChannelNEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelIn applies the In predicate on the "channel" field.
|
||||
func ChannelIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldChannel, vs...))
|
||||
}
|
||||
|
||||
// ChannelNotIn applies the NotIn predicate on the "channel" field.
|
||||
func ChannelNotIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldChannel, vs...))
|
||||
}
|
||||
|
||||
// ChannelGT applies the GT predicate on the "channel" field.
|
||||
func ChannelGT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelGTE applies the GTE predicate on the "channel" field.
|
||||
func ChannelGTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelLT applies the LT predicate on the "channel" field.
|
||||
func ChannelLT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelLTE applies the LTE predicate on the "channel" field.
|
||||
func ChannelLTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelContains applies the Contains predicate on the "channel" field.
|
||||
func ChannelContains(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContains(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelHasPrefix applies the HasPrefix predicate on the "channel" field.
|
||||
func ChannelHasPrefix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasPrefix(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelHasSuffix applies the HasSuffix predicate on the "channel" field.
|
||||
func ChannelHasSuffix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasSuffix(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelEqualFold applies the EqualFold predicate on the "channel" field.
|
||||
func ChannelEqualFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEqualFold(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelContainsFold applies the ContainsFold predicate on the "channel" field.
|
||||
func ChannelContainsFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContainsFold(FieldChannel, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDEQ applies the EQ predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDNEQ applies the NEQ predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDNEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDIn applies the In predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldChannelAppID, vs...))
|
||||
}
|
||||
|
||||
// ChannelAppIDNotIn applies the NotIn predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDNotIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldChannelAppID, vs...))
|
||||
}
|
||||
|
||||
// ChannelAppIDGT applies the GT predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDGT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDGTE applies the GTE predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDGTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDLT applies the LT predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDLT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDLTE applies the LTE predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDLTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDContains applies the Contains predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDContains(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContains(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDHasPrefix applies the HasPrefix predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDHasPrefix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasPrefix(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDHasSuffix applies the HasSuffix predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDHasSuffix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasSuffix(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDEqualFold applies the EqualFold predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDEqualFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEqualFold(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelAppIDContainsFold applies the ContainsFold predicate on the "channel_app_id" field.
|
||||
func ChannelAppIDContainsFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContainsFold(FieldChannelAppID, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectEQ applies the EQ predicate on the "channel_subject" field.
|
||||
func ChannelSubjectEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEQ(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectNEQ applies the NEQ predicate on the "channel_subject" field.
|
||||
func ChannelSubjectNEQ(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNEQ(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectIn applies the In predicate on the "channel_subject" field.
|
||||
func ChannelSubjectIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldIn(FieldChannelSubject, vs...))
|
||||
}
|
||||
|
||||
// ChannelSubjectNotIn applies the NotIn predicate on the "channel_subject" field.
|
||||
func ChannelSubjectNotIn(vs ...string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldNotIn(FieldChannelSubject, vs...))
|
||||
}
|
||||
|
||||
// ChannelSubjectGT applies the GT predicate on the "channel_subject" field.
|
||||
func ChannelSubjectGT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGT(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectGTE applies the GTE predicate on the "channel_subject" field.
|
||||
func ChannelSubjectGTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldGTE(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectLT applies the LT predicate on the "channel_subject" field.
|
||||
func ChannelSubjectLT(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLT(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectLTE applies the LTE predicate on the "channel_subject" field.
|
||||
func ChannelSubjectLTE(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldLTE(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectContains applies the Contains predicate on the "channel_subject" field.
|
||||
func ChannelSubjectContains(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContains(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectHasPrefix applies the HasPrefix predicate on the "channel_subject" field.
|
||||
func ChannelSubjectHasPrefix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasPrefix(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectHasSuffix applies the HasSuffix predicate on the "channel_subject" field.
|
||||
func ChannelSubjectHasSuffix(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldHasSuffix(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectEqualFold applies the EqualFold predicate on the "channel_subject" field.
|
||||
func ChannelSubjectEqualFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldEqualFold(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// ChannelSubjectContainsFold applies the ContainsFold predicate on the "channel_subject" field.
|
||||
func ChannelSubjectContainsFold(v string) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.FieldContainsFold(FieldChannelSubject, v))
|
||||
}
|
||||
|
||||
// HasIdentity applies the HasEdge predicate on the "identity" edge.
|
||||
func HasIdentity() predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, IdentityTable, IdentityColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasIdentityWith applies the HasEdge predicate on the "identity" edge with a given conditions (other predicates).
|
||||
func HasIdentityWith(preds ...predicate.AuthIdentity) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(func(s *sql.Selector) {
|
||||
step := newIdentityStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.AuthIdentityChannel) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.AuthIdentityChannel) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.AuthIdentityChannel) predicate.AuthIdentityChannel {
|
||||
return predicate.AuthIdentityChannel(sql.NotPredicates(p))
|
||||
}
|
||||
932
backend/ent/authidentitychannel_create.go
Normal file
932
backend/ent/authidentitychannel_create.go
Normal file
@ -0,0 +1,932 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
)
|
||||
|
||||
// AuthIdentityChannelCreate is the builder for creating a AuthIdentityChannel entity.
|
||||
type AuthIdentityChannelCreate struct {
|
||||
config
|
||||
mutation *AuthIdentityChannelMutation
|
||||
hooks []Hook
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetCreatedAt(v time.Time) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (_c *AuthIdentityChannelCreate) SetNillableCreatedAt(v *time.Time) *AuthIdentityChannelCreate {
|
||||
if v != nil {
|
||||
_c.SetCreatedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetUpdatedAt(v time.Time) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetUpdatedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||
func (_c *AuthIdentityChannelCreate) SetNillableUpdatedAt(v *time.Time) *AuthIdentityChannelCreate {
|
||||
if v != nil {
|
||||
_c.SetUpdatedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetIdentityID(v int64) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetIdentityID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetProviderType(v string) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetProviderType(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetProviderKey(v string) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetProviderKey(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetChannel(v string) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetChannel(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetChannelAppID(v string) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetChannelAppID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetChannelSubject(v string) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetChannelSubject(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (_c *AuthIdentityChannelCreate) SetMetadata(v map[string]interface{}) *AuthIdentityChannelCreate {
|
||||
_c.mutation.SetMetadata(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_c *AuthIdentityChannelCreate) SetIdentity(v *AuthIdentity) *AuthIdentityChannelCreate {
|
||||
return _c.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AuthIdentityChannelMutation object of the builder.
|
||||
func (_c *AuthIdentityChannelCreate) Mutation() *AuthIdentityChannelMutation {
|
||||
return _c.mutation
|
||||
}
|
||||
|
||||
// Save creates the AuthIdentityChannel in the database.
|
||||
func (_c *AuthIdentityChannelCreate) Save(ctx context.Context) (*AuthIdentityChannel, error) {
|
||||
_c.defaults()
|
||||
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (_c *AuthIdentityChannelCreate) SaveX(ctx context.Context) *AuthIdentityChannel {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *AuthIdentityChannelCreate) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *AuthIdentityChannelCreate) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_c *AuthIdentityChannelCreate) defaults() {
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
v := authidentitychannel.DefaultCreatedAt()
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
||||
v := authidentitychannel.DefaultUpdatedAt()
|
||||
_c.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
if _, ok := _c.mutation.Metadata(); !ok {
|
||||
v := authidentitychannel.DefaultMetadata()
|
||||
_c.mutation.SetMetadata(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_c *AuthIdentityChannelCreate) check() error {
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "AuthIdentityChannel.created_at"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
||||
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "AuthIdentityChannel.updated_at"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.IdentityID(); !ok {
|
||||
return &ValidationError{Name: "identity_id", err: errors.New(`ent: missing required field "AuthIdentityChannel.identity_id"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.ProviderType(); !ok {
|
||||
return &ValidationError{Name: "provider_type", err: errors.New(`ent: missing required field "AuthIdentityChannel.provider_type"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.ProviderType(); ok {
|
||||
if err := authidentitychannel.ProviderTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_type", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.ProviderKey(); !ok {
|
||||
return &ValidationError{Name: "provider_key", err: errors.New(`ent: missing required field "AuthIdentityChannel.provider_key"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.ProviderKey(); ok {
|
||||
if err := authidentitychannel.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.Channel(); !ok {
|
||||
return &ValidationError{Name: "channel", err: errors.New(`ent: missing required field "AuthIdentityChannel.channel"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.Channel(); ok {
|
||||
if err := authidentitychannel.ChannelValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.ChannelAppID(); !ok {
|
||||
return &ValidationError{Name: "channel_app_id", err: errors.New(`ent: missing required field "AuthIdentityChannel.channel_app_id"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.ChannelAppID(); ok {
|
||||
if err := authidentitychannel.ChannelAppIDValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_app_id", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_app_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.ChannelSubject(); !ok {
|
||||
return &ValidationError{Name: "channel_subject", err: errors.New(`ent: missing required field "AuthIdentityChannel.channel_subject"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.ChannelSubject(); ok {
|
||||
if err := authidentitychannel.ChannelSubjectValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_subject", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_subject": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.Metadata(); !ok {
|
||||
return &ValidationError{Name: "metadata", err: errors.New(`ent: missing required field "AuthIdentityChannel.metadata"`)}
|
||||
}
|
||||
if len(_c.mutation.IdentityIDs()) == 0 {
|
||||
return &ValidationError{Name: "identity", err: errors.New(`ent: missing required edge "AuthIdentityChannel.identity"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_c *AuthIdentityChannelCreate) sqlSave(ctx context.Context) (*AuthIdentityChannel, error) {
|
||||
if err := _c.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_node, _spec := _c.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
id := _spec.ID.Value.(int64)
|
||||
_node.ID = int64(id)
|
||||
_c.mutation.id = &_node.ID
|
||||
_c.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (_c *AuthIdentityChannelCreate) createSpec() (*AuthIdentityChannel, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &AuthIdentityChannel{config: _c.config}
|
||||
_spec = sqlgraph.NewCreateSpec(authidentitychannel.Table, sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64))
|
||||
)
|
||||
_spec.OnConflict = _c.conflict
|
||||
if value, ok := _c.mutation.CreatedAt(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldCreatedAt, field.TypeTime, value)
|
||||
_node.CreatedAt = value
|
||||
}
|
||||
if value, ok := _c.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldUpdatedAt, field.TypeTime, value)
|
||||
_node.UpdatedAt = value
|
||||
}
|
||||
if value, ok := _c.mutation.ProviderType(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderType, field.TypeString, value)
|
||||
_node.ProviderType = value
|
||||
}
|
||||
if value, ok := _c.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderKey, field.TypeString, value)
|
||||
_node.ProviderKey = value
|
||||
}
|
||||
if value, ok := _c.mutation.Channel(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannel, field.TypeString, value)
|
||||
_node.Channel = value
|
||||
}
|
||||
if value, ok := _c.mutation.ChannelAppID(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelAppID, field.TypeString, value)
|
||||
_node.ChannelAppID = value
|
||||
}
|
||||
if value, ok := _c.mutation.ChannelSubject(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelSubject, field.TypeString, value)
|
||||
_node.ChannelSubject = value
|
||||
}
|
||||
if value, ok := _c.mutation.Metadata(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldMetadata, field.TypeJSON, value)
|
||||
_node.Metadata = value
|
||||
}
|
||||
if nodes := _c.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentitychannel.IdentityTable,
|
||||
Columns: []string{authidentitychannel.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.IdentityID = nodes[0]
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// SetCreatedAt(v).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.AuthIdentityChannelUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *AuthIdentityChannelCreate) OnConflict(opts ...sql.ConflictOption) *AuthIdentityChannelUpsertOne {
|
||||
_c.conflict = opts
|
||||
return &AuthIdentityChannelUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *AuthIdentityChannelCreate) OnConflictColumns(columns ...string) *AuthIdentityChannelUpsertOne {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &AuthIdentityChannelUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// AuthIdentityChannelUpsertOne is the builder for "upsert"-ing
|
||||
// one AuthIdentityChannel node.
|
||||
AuthIdentityChannelUpsertOne struct {
|
||||
create *AuthIdentityChannelCreate
|
||||
}
|
||||
|
||||
// AuthIdentityChannelUpsert is the "OnConflict" setter.
|
||||
AuthIdentityChannelUpsert struct {
|
||||
*sql.UpdateSet
|
||||
}
|
||||
)
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetUpdatedAt(v time.Time) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldUpdatedAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateUpdatedAt() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldUpdatedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetIdentityID(v int64) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldIdentityID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateIdentityID() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldIdentityID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetProviderType(v string) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldProviderType, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateProviderType sets the "provider_type" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateProviderType() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldProviderType)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetProviderKey(v string) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldProviderKey, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateProviderKey() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldProviderKey)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetChannel(v string) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldChannel, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateChannel sets the "channel" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateChannel() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldChannel)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetChannelAppID(v string) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldChannelAppID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateChannelAppID sets the "channel_app_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateChannelAppID() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldChannelAppID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetChannelSubject(v string) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldChannelSubject, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateChannelSubject sets the "channel_subject" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateChannelSubject() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldChannelSubject)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (u *AuthIdentityChannelUpsert) SetMetadata(v map[string]interface{}) *AuthIdentityChannelUpsert {
|
||||
u.Set(authidentitychannel.FieldMetadata, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateMetadata sets the "metadata" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsert) UpdateMetadata() *AuthIdentityChannelUpsert {
|
||||
u.SetExcluded(authidentitychannel.FieldMetadata)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateNewValues() *AuthIdentityChannelUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(authidentitychannel.FieldCreatedAt)
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AuthIdentityChannelUpsertOne) Ignore() *AuthIdentityChannelUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *AuthIdentityChannelUpsertOne) DoNothing() *AuthIdentityChannelUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AuthIdentityChannelCreate.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AuthIdentityChannelUpsertOne) Update(set func(*AuthIdentityChannelUpsert)) *AuthIdentityChannelUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AuthIdentityChannelUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetUpdatedAt(v time.Time) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateUpdatedAt() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetIdentityID(v int64) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetIdentityID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateIdentityID() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetProviderType(v string) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetProviderType(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderType sets the "provider_type" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateProviderType() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateProviderType()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetProviderKey(v string) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetProviderKey(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateProviderKey() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetChannel(v string) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannel(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannel sets the "channel" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateChannel() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannel()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetChannelAppID(v string) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannelAppID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannelAppID sets the "channel_app_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateChannelAppID() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannelAppID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetChannelSubject(v string) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannelSubject(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannelSubject sets the "channel_subject" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateChannelSubject() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannelSubject()
|
||||
})
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (u *AuthIdentityChannelUpsertOne) SetMetadata(v map[string]interface{}) *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetMetadata(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateMetadata sets the "metadata" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertOne) UpdateMetadata() *AuthIdentityChannelUpsertOne {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateMetadata()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AuthIdentityChannelUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AuthIdentityChannelCreate.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AuthIdentityChannelUpsertOne) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
||||
func (u *AuthIdentityChannelUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
||||
node, err := u.create.Save(ctx)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return node.ID, nil
|
||||
}
|
||||
|
||||
// IDX is like ID, but panics if an error occurs.
|
||||
func (u *AuthIdentityChannelUpsertOne) IDX(ctx context.Context) int64 {
|
||||
id, err := u.ID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// AuthIdentityChannelCreateBulk is the builder for creating many AuthIdentityChannel entities in bulk.
|
||||
type AuthIdentityChannelCreateBulk struct {
|
||||
config
|
||||
err error
|
||||
builders []*AuthIdentityChannelCreate
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// Save creates the AuthIdentityChannel entities in the database.
|
||||
func (_c *AuthIdentityChannelCreateBulk) Save(ctx context.Context) ([]*AuthIdentityChannel, error) {
|
||||
if _c.err != nil {
|
||||
return nil, _c.err
|
||||
}
|
||||
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
|
||||
nodes := make([]*AuthIdentityChannel, len(_c.builders))
|
||||
mutators := make([]Mutator, len(_c.builders))
|
||||
for i := range _c.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := _c.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*AuthIdentityChannelMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err := builder.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.mutation = mutation
|
||||
var err error
|
||||
nodes[i], specs[i] = builder.createSpec()
|
||||
if i < len(mutators)-1 {
|
||||
_, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
spec.OnConflict = _c.conflict
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &nodes[i].ID
|
||||
if specs[i].ID.Value != nil {
|
||||
id := specs[i].ID.Value.(int64)
|
||||
nodes[i].ID = int64(id)
|
||||
}
|
||||
mutation.done = true
|
||||
return nodes[i], nil
|
||||
})
|
||||
for i := len(builder.hooks) - 1; i >= 0; i-- {
|
||||
mut = builder.hooks[i](mut)
|
||||
}
|
||||
mutators[i] = mut
|
||||
}(i, ctx)
|
||||
}
|
||||
if len(mutators) > 0 {
|
||||
if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_c *AuthIdentityChannelCreateBulk) SaveX(ctx context.Context) []*AuthIdentityChannel {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *AuthIdentityChannelCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *AuthIdentityChannelCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.AuthIdentityChannel.CreateBulk(builders...).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.AuthIdentityChannelUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *AuthIdentityChannelCreateBulk) OnConflict(opts ...sql.ConflictOption) *AuthIdentityChannelUpsertBulk {
|
||||
_c.conflict = opts
|
||||
return &AuthIdentityChannelUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *AuthIdentityChannelCreateBulk) OnConflictColumns(columns ...string) *AuthIdentityChannelUpsertBulk {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &AuthIdentityChannelUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// AuthIdentityChannelUpsertBulk is the builder for "upsert"-ing
|
||||
// a bulk of AuthIdentityChannel nodes.
|
||||
type AuthIdentityChannelUpsertBulk struct {
|
||||
create *AuthIdentityChannelCreateBulk
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that
|
||||
// were set on create. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateNewValues() *AuthIdentityChannelUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
for _, b := range u.create.builders {
|
||||
if _, exists := b.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(authidentitychannel.FieldCreatedAt)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AuthIdentityChannel.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AuthIdentityChannelUpsertBulk) Ignore() *AuthIdentityChannelUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *AuthIdentityChannelUpsertBulk) DoNothing() *AuthIdentityChannelUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AuthIdentityChannelCreateBulk.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AuthIdentityChannelUpsertBulk) Update(set func(*AuthIdentityChannelUpsert)) *AuthIdentityChannelUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AuthIdentityChannelUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetUpdatedAt(v time.Time) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateUpdatedAt() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetIdentityID(v int64) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetIdentityID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateIdentityID() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetProviderType(v string) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetProviderType(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderType sets the "provider_type" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateProviderType() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateProviderType()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetProviderKey(v string) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetProviderKey(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateProviderKey() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetChannel(v string) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannel(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannel sets the "channel" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateChannel() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannel()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetChannelAppID(v string) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannelAppID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannelAppID sets the "channel_app_id" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateChannelAppID() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannelAppID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetChannelSubject(v string) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetChannelSubject(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateChannelSubject sets the "channel_subject" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateChannelSubject() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateChannelSubject()
|
||||
})
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (u *AuthIdentityChannelUpsertBulk) SetMetadata(v map[string]interface{}) *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.SetMetadata(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateMetadata sets the "metadata" field to the value that was provided on create.
|
||||
func (u *AuthIdentityChannelUpsertBulk) UpdateMetadata() *AuthIdentityChannelUpsertBulk {
|
||||
return u.Update(func(s *AuthIdentityChannelUpsert) {
|
||||
s.UpdateMetadata()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AuthIdentityChannelUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
return u.create.err
|
||||
}
|
||||
for i, b := range u.create.builders {
|
||||
if len(b.conflict) != 0 {
|
||||
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the AuthIdentityChannelCreateBulk instead", i)
|
||||
}
|
||||
}
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AuthIdentityChannelCreateBulk.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AuthIdentityChannelUpsertBulk) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
88
backend/ent/authidentitychannel_delete.go
Normal file
88
backend/ent/authidentitychannel_delete.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AuthIdentityChannelDelete is the builder for deleting a AuthIdentityChannel entity.
|
||||
type AuthIdentityChannelDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityChannelMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityChannelDelete builder.
|
||||
func (_d *AuthIdentityChannelDelete) Where(ps ...predicate.AuthIdentityChannel) *AuthIdentityChannelDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *AuthIdentityChannelDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AuthIdentityChannelDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *AuthIdentityChannelDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(authidentitychannel.Table, sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// AuthIdentityChannelDeleteOne is the builder for deleting a single AuthIdentityChannel entity.
|
||||
type AuthIdentityChannelDeleteOne struct {
|
||||
_d *AuthIdentityChannelDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityChannelDelete builder.
|
||||
func (_d *AuthIdentityChannelDeleteOne) Where(ps ...predicate.AuthIdentityChannel) *AuthIdentityChannelDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *AuthIdentityChannelDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{authidentitychannel.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *AuthIdentityChannelDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
643
backend/ent/authidentitychannel_query.go
Normal file
643
backend/ent/authidentitychannel_query.go
Normal file
@ -0,0 +1,643 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AuthIdentityChannelQuery is the builder for querying AuthIdentityChannel entities.
|
||||
type AuthIdentityChannelQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []authidentitychannel.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.AuthIdentityChannel
|
||||
withIdentity *AuthIdentityQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the AuthIdentityChannelQuery builder.
|
||||
func (_q *AuthIdentityChannelQuery) Where(ps ...predicate.AuthIdentityChannel) *AuthIdentityChannelQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *AuthIdentityChannelQuery) Limit(limit int) *AuthIdentityChannelQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *AuthIdentityChannelQuery) Offset(offset int) *AuthIdentityChannelQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *AuthIdentityChannelQuery) Unique(unique bool) *AuthIdentityChannelQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *AuthIdentityChannelQuery) Order(o ...authidentitychannel.OrderOption) *AuthIdentityChannelQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryIdentity chains the current query on the "identity" edge.
|
||||
func (_q *AuthIdentityChannelQuery) QueryIdentity() *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentitychannel.Table, authidentitychannel.FieldID, selector),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, authidentitychannel.IdentityTable, authidentitychannel.IdentityColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first AuthIdentityChannel entity from the query.
|
||||
// Returns a *NotFoundError when no AuthIdentityChannel was found.
|
||||
func (_q *AuthIdentityChannelQuery) First(ctx context.Context) (*AuthIdentityChannel, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{authidentitychannel.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) FirstX(ctx context.Context) *AuthIdentityChannel {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first AuthIdentityChannel ID from the query.
|
||||
// Returns a *NotFoundError when no AuthIdentityChannel ID was found.
|
||||
func (_q *AuthIdentityChannelQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{authidentitychannel.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single AuthIdentityChannel entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one AuthIdentityChannel entity is found.
|
||||
// Returns a *NotFoundError when no AuthIdentityChannel entities are found.
|
||||
func (_q *AuthIdentityChannelQuery) Only(ctx context.Context) (*AuthIdentityChannel, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{authidentitychannel.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{authidentitychannel.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) OnlyX(ctx context.Context) *AuthIdentityChannel {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only AuthIdentityChannel ID in the query.
|
||||
// Returns a *NotSingularError when more than one AuthIdentityChannel ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *AuthIdentityChannelQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{authidentitychannel.Label}
|
||||
default:
|
||||
err = &NotSingularError{authidentitychannel.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of AuthIdentityChannels.
|
||||
func (_q *AuthIdentityChannelQuery) All(ctx context.Context) ([]*AuthIdentityChannel, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*AuthIdentityChannel, *AuthIdentityChannelQuery]()
|
||||
return withInterceptors[[]*AuthIdentityChannel](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) AllX(ctx context.Context) []*AuthIdentityChannel {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of AuthIdentityChannel IDs.
|
||||
func (_q *AuthIdentityChannelQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(authidentitychannel.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *AuthIdentityChannelQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*AuthIdentityChannelQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *AuthIdentityChannelQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *AuthIdentityChannelQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the AuthIdentityChannelQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *AuthIdentityChannelQuery) Clone() *AuthIdentityChannelQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &AuthIdentityChannelQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]authidentitychannel.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.AuthIdentityChannel{}, _q.predicates...),
|
||||
withIdentity: _q.withIdentity.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithIdentity tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "identity" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *AuthIdentityChannelQuery) WithIdentity(opts ...func(*AuthIdentityQuery)) *AuthIdentityChannelQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withIdentity = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AuthIdentityChannel.Query().
|
||||
// GroupBy(authidentitychannel.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AuthIdentityChannelQuery) GroupBy(field string, fields ...string) *AuthIdentityChannelGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &AuthIdentityChannelGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = authidentitychannel.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AuthIdentityChannel.Query().
|
||||
// Select(authidentitychannel.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *AuthIdentityChannelQuery) Select(fields ...string) *AuthIdentityChannelSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &AuthIdentityChannelSelect{AuthIdentityChannelQuery: _q}
|
||||
sbuild.label = authidentitychannel.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a AuthIdentityChannelSelect configured with the given aggregations.
|
||||
func (_q *AuthIdentityChannelQuery) Aggregate(fns ...AggregateFunc) *AuthIdentityChannelSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !authidentitychannel.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AuthIdentityChannel, error) {
|
||||
var (
|
||||
nodes = []*AuthIdentityChannel{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [1]bool{
|
||||
_q.withIdentity != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*AuthIdentityChannel).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &AuthIdentityChannel{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withIdentity; query != nil {
|
||||
if err := _q.loadIdentity(ctx, query, nodes, nil,
|
||||
func(n *AuthIdentityChannel, e *AuthIdentity) { n.Edges.Identity = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) loadIdentity(ctx context.Context, query *AuthIdentityQuery, nodes []*AuthIdentityChannel, init func(*AuthIdentityChannel), assign func(*AuthIdentityChannel, *AuthIdentity)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*AuthIdentityChannel)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].IdentityID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(authidentity.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "identity_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(authidentitychannel.Table, authidentitychannel.Columns, sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, authidentitychannel.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != authidentitychannel.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if _q.withIdentity != nil {
|
||||
_spec.Node.AddColumnOnce(authidentitychannel.FieldIdentityID)
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *AuthIdentityChannelQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(authidentitychannel.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = authidentitychannel.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *AuthIdentityChannelQuery) ForUpdate(opts ...sql.LockOption) *AuthIdentityChannelQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *AuthIdentityChannelQuery) ForShare(opts ...sql.LockOption) *AuthIdentityChannelQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// AuthIdentityChannelGroupBy is the group-by builder for AuthIdentityChannel entities.
|
||||
type AuthIdentityChannelGroupBy struct {
|
||||
selector
|
||||
build *AuthIdentityChannelQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *AuthIdentityChannelGroupBy) Aggregate(fns ...AggregateFunc) *AuthIdentityChannelGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *AuthIdentityChannelGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AuthIdentityChannelQuery, *AuthIdentityChannelGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *AuthIdentityChannelGroupBy) sqlScan(ctx context.Context, root *AuthIdentityChannelQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// AuthIdentityChannelSelect is the builder for selecting fields of AuthIdentityChannel entities.
|
||||
type AuthIdentityChannelSelect struct {
|
||||
*AuthIdentityChannelQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *AuthIdentityChannelSelect) Aggregate(fns ...AggregateFunc) *AuthIdentityChannelSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *AuthIdentityChannelSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AuthIdentityChannelQuery, *AuthIdentityChannelSelect](ctx, _s.AuthIdentityChannelQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *AuthIdentityChannelSelect) sqlScan(ctx context.Context, root *AuthIdentityChannelQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
581
backend/ent/authidentitychannel_update.go
Normal file
581
backend/ent/authidentitychannel_update.go
Normal file
@ -0,0 +1,581 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// AuthIdentityChannelUpdate is the builder for updating AuthIdentityChannel entities.
|
||||
type AuthIdentityChannelUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityChannelMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityChannelUpdate builder.
|
||||
func (_u *AuthIdentityChannelUpdate) Where(ps ...predicate.AuthIdentityChannel) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetUpdatedAt(v time.Time) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetIdentityID(v int64) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetIdentityID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIdentityID sets the "identity_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableIdentityID(v *int64) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetIdentityID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetProviderType(v string) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetProviderType(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderType sets the "provider_type" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableProviderType(v *string) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderType(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetProviderKey(v string) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableProviderKey(v *string) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetChannel(v string) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetChannel(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannel sets the "channel" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableChannel(v *string) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetChannel(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetChannelAppID(v string) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetChannelAppID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannelAppID sets the "channel_app_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableChannelAppID(v *string) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetChannelAppID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetChannelSubject(v string) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetChannelSubject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannelSubject sets the "channel_subject" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdate) SetNillableChannelSubject(v *string) *AuthIdentityChannelUpdate {
|
||||
if v != nil {
|
||||
_u.SetChannelSubject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (_u *AuthIdentityChannelUpdate) SetMetadata(v map[string]interface{}) *AuthIdentityChannelUpdate {
|
||||
_u.mutation.SetMetadata(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *AuthIdentityChannelUpdate) SetIdentity(v *AuthIdentity) *AuthIdentityChannelUpdate {
|
||||
return _u.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AuthIdentityChannelMutation object of the builder.
|
||||
func (_u *AuthIdentityChannelUpdate) Mutation() *AuthIdentityChannelMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearIdentity clears the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *AuthIdentityChannelUpdate) ClearIdentity() *AuthIdentityChannelUpdate {
|
||||
_u.mutation.ClearIdentity()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *AuthIdentityChannelUpdate) Save(ctx context.Context) (int, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AuthIdentityChannelUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *AuthIdentityChannelUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AuthIdentityChannelUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AuthIdentityChannelUpdate) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := authidentitychannel.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AuthIdentityChannelUpdate) check() error {
|
||||
if v, ok := _u.mutation.ProviderType(); ok {
|
||||
if err := authidentitychannel.ProviderTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_type", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := authidentitychannel.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Channel(); ok {
|
||||
if err := authidentitychannel.ChannelValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ChannelAppID(); ok {
|
||||
if err := authidentitychannel.ChannelAppIDValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_app_id", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_app_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ChannelSubject(); ok {
|
||||
if err := authidentitychannel.ChannelSubjectValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_subject", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_subject": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _u.mutation.IdentityCleared() && len(_u.mutation.IdentityIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AuthIdentityChannel.identity"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AuthIdentityChannelUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(authidentitychannel.Table, authidentitychannel.Columns, sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderType(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderType, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Channel(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannel, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ChannelAppID(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelAppID, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ChannelSubject(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelSubject, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Metadata(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldMetadata, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.IdentityCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentitychannel.IdentityTable,
|
||||
Columns: []string{authidentitychannel.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentitychannel.IdentityTable,
|
||||
Columns: []string{authidentitychannel.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{authidentitychannel.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// AuthIdentityChannelUpdateOne is the builder for updating a single AuthIdentityChannel entity.
|
||||
type AuthIdentityChannelUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *AuthIdentityChannelMutation
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetUpdatedAt(v time.Time) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetIdentityID(v int64) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetIdentityID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIdentityID sets the "identity_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableIdentityID(v *int64) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetIdentityID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderType sets the "provider_type" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetProviderType(v string) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetProviderType(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderType sets the "provider_type" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableProviderType(v *string) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderType(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetProviderKey(v string) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableProviderKey(v *string) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannel sets the "channel" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetChannel(v string) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetChannel(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannel sets the "channel" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableChannel(v *string) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetChannel(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannelAppID sets the "channel_app_id" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetChannelAppID(v string) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetChannelAppID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannelAppID sets the "channel_app_id" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableChannelAppID(v *string) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetChannelAppID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetChannelSubject sets the "channel_subject" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetChannelSubject(v string) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetChannelSubject(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableChannelSubject sets the "channel_subject" field if the given value is not nil.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetNillableChannelSubject(v *string) *AuthIdentityChannelUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetChannelSubject(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetMetadata sets the "metadata" field.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetMetadata(v map[string]interface{}) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.SetMetadata(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SetIdentity(v *AuthIdentity) *AuthIdentityChannelUpdateOne {
|
||||
return _u.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AuthIdentityChannelMutation object of the builder.
|
||||
func (_u *AuthIdentityChannelUpdateOne) Mutation() *AuthIdentityChannelMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearIdentity clears the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *AuthIdentityChannelUpdateOne) ClearIdentity() *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.ClearIdentity()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AuthIdentityChannelUpdate builder.
|
||||
func (_u *AuthIdentityChannelUpdateOne) Where(ps ...predicate.AuthIdentityChannel) *AuthIdentityChannelUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *AuthIdentityChannelUpdateOne) Select(field string, fields ...string) *AuthIdentityChannelUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated AuthIdentityChannel entity.
|
||||
func (_u *AuthIdentityChannelUpdateOne) Save(ctx context.Context) (*AuthIdentityChannel, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *AuthIdentityChannelUpdateOne) SaveX(ctx context.Context) *AuthIdentityChannel {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *AuthIdentityChannelUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *AuthIdentityChannelUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *AuthIdentityChannelUpdateOne) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := authidentitychannel.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *AuthIdentityChannelUpdateOne) check() error {
|
||||
if v, ok := _u.mutation.ProviderType(); ok {
|
||||
if err := authidentitychannel.ProviderTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_type", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := authidentitychannel.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Channel(); ok {
|
||||
if err := authidentitychannel.ChannelValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ChannelAppID(); ok {
|
||||
if err := authidentitychannel.ChannelAppIDValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_app_id", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_app_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ChannelSubject(); ok {
|
||||
if err := authidentitychannel.ChannelSubjectValidator(v); err != nil {
|
||||
return &ValidationError{Name: "channel_subject", err: fmt.Errorf(`ent: validator failed for field "AuthIdentityChannel.channel_subject": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _u.mutation.IdentityCleared() && len(_u.mutation.IdentityIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "AuthIdentityChannel.identity"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *AuthIdentityChannelUpdateOne) sqlSave(ctx context.Context) (_node *AuthIdentityChannel, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(authidentitychannel.Table, authidentitychannel.Columns, sqlgraph.NewFieldSpec(authidentitychannel.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AuthIdentityChannel.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, authidentitychannel.FieldID)
|
||||
for _, f := range fields {
|
||||
if !authidentitychannel.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != authidentitychannel.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderType(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderType, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Channel(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannel, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ChannelAppID(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelAppID, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.ChannelSubject(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldChannelSubject, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.Metadata(); ok {
|
||||
_spec.SetField(authidentitychannel.FieldMetadata, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.IdentityCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentitychannel.IdentityTable,
|
||||
Columns: []string{authidentitychannel.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: authidentitychannel.IdentityTable,
|
||||
Columns: []string{authidentitychannel.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &AuthIdentityChannel{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{authidentitychannel.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
@ -20,12 +20,16 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/proxy"
|
||||
@ -60,18 +64,26 @@ type Client struct {
|
||||
Announcement *AnnouncementClient
|
||||
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
|
||||
AnnouncementRead *AnnouncementReadClient
|
||||
// AuthIdentity is the client for interacting with the AuthIdentity builders.
|
||||
AuthIdentity *AuthIdentityClient
|
||||
// AuthIdentityChannel is the client for interacting with the AuthIdentityChannel builders.
|
||||
AuthIdentityChannel *AuthIdentityChannelClient
|
||||
// ErrorPassthroughRule is the client for interacting with the ErrorPassthroughRule builders.
|
||||
ErrorPassthroughRule *ErrorPassthroughRuleClient
|
||||
// Group is the client for interacting with the Group builders.
|
||||
Group *GroupClient
|
||||
// IdempotencyRecord is the client for interacting with the IdempotencyRecord builders.
|
||||
IdempotencyRecord *IdempotencyRecordClient
|
||||
// IdentityAdoptionDecision is the client for interacting with the IdentityAdoptionDecision builders.
|
||||
IdentityAdoptionDecision *IdentityAdoptionDecisionClient
|
||||
// PaymentAuditLog is the client for interacting with the PaymentAuditLog builders.
|
||||
PaymentAuditLog *PaymentAuditLogClient
|
||||
// PaymentOrder is the client for interacting with the PaymentOrder builders.
|
||||
PaymentOrder *PaymentOrderClient
|
||||
// PaymentProviderInstance is the client for interacting with the PaymentProviderInstance builders.
|
||||
PaymentProviderInstance *PaymentProviderInstanceClient
|
||||
// PendingAuthSession is the client for interacting with the PendingAuthSession builders.
|
||||
PendingAuthSession *PendingAuthSessionClient
|
||||
// PromoCode is the client for interacting with the PromoCode builders.
|
||||
PromoCode *PromoCodeClient
|
||||
// PromoCodeUsage is the client for interacting with the PromoCodeUsage builders.
|
||||
@ -118,12 +130,16 @@ func (c *Client) init() {
|
||||
c.AccountGroup = NewAccountGroupClient(c.config)
|
||||
c.Announcement = NewAnnouncementClient(c.config)
|
||||
c.AnnouncementRead = NewAnnouncementReadClient(c.config)
|
||||
c.AuthIdentity = NewAuthIdentityClient(c.config)
|
||||
c.AuthIdentityChannel = NewAuthIdentityChannelClient(c.config)
|
||||
c.ErrorPassthroughRule = NewErrorPassthroughRuleClient(c.config)
|
||||
c.Group = NewGroupClient(c.config)
|
||||
c.IdempotencyRecord = NewIdempotencyRecordClient(c.config)
|
||||
c.IdentityAdoptionDecision = NewIdentityAdoptionDecisionClient(c.config)
|
||||
c.PaymentAuditLog = NewPaymentAuditLogClient(c.config)
|
||||
c.PaymentOrder = NewPaymentOrderClient(c.config)
|
||||
c.PaymentProviderInstance = NewPaymentProviderInstanceClient(c.config)
|
||||
c.PendingAuthSession = NewPendingAuthSessionClient(c.config)
|
||||
c.PromoCode = NewPromoCodeClient(c.config)
|
||||
c.PromoCodeUsage = NewPromoCodeUsageClient(c.config)
|
||||
c.Proxy = NewProxyClient(c.config)
|
||||
@ -229,34 +245,38 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
||||
cfg := c.config
|
||||
cfg.driver = tx
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
|
||||
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
|
||||
PaymentOrder: NewPaymentOrderClient(cfg),
|
||||
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
Proxy: NewProxyClient(cfg),
|
||||
RedeemCode: NewRedeemCodeClient(cfg),
|
||||
SecuritySecret: NewSecuritySecretClient(cfg),
|
||||
Setting: NewSettingClient(cfg),
|
||||
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
|
||||
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
|
||||
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
|
||||
UsageLog: NewUsageLogClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserAllowedGroup: NewUserAllowedGroupClient(cfg),
|
||||
UserAttributeDefinition: NewUserAttributeDefinitionClient(cfg),
|
||||
UserAttributeValue: NewUserAttributeValueClient(cfg),
|
||||
UserSubscription: NewUserSubscriptionClient(cfg),
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
AuthIdentity: NewAuthIdentityClient(cfg),
|
||||
AuthIdentityChannel: NewAuthIdentityChannelClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
|
||||
IdentityAdoptionDecision: NewIdentityAdoptionDecisionClient(cfg),
|
||||
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
|
||||
PaymentOrder: NewPaymentOrderClient(cfg),
|
||||
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
|
||||
PendingAuthSession: NewPendingAuthSessionClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
Proxy: NewProxyClient(cfg),
|
||||
RedeemCode: NewRedeemCodeClient(cfg),
|
||||
SecuritySecret: NewSecuritySecretClient(cfg),
|
||||
Setting: NewSettingClient(cfg),
|
||||
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
|
||||
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
|
||||
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
|
||||
UsageLog: NewUsageLogClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserAllowedGroup: NewUserAllowedGroupClient(cfg),
|
||||
UserAttributeDefinition: NewUserAttributeDefinitionClient(cfg),
|
||||
UserAttributeValue: NewUserAttributeValueClient(cfg),
|
||||
UserSubscription: NewUserSubscriptionClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -274,34 +294,38 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
|
||||
cfg := c.config
|
||||
cfg.driver = &txDriver{tx: tx, drv: c.driver}
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
|
||||
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
|
||||
PaymentOrder: NewPaymentOrderClient(cfg),
|
||||
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
Proxy: NewProxyClient(cfg),
|
||||
RedeemCode: NewRedeemCodeClient(cfg),
|
||||
SecuritySecret: NewSecuritySecretClient(cfg),
|
||||
Setting: NewSettingClient(cfg),
|
||||
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
|
||||
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
|
||||
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
|
||||
UsageLog: NewUsageLogClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserAllowedGroup: NewUserAllowedGroupClient(cfg),
|
||||
UserAttributeDefinition: NewUserAttributeDefinitionClient(cfg),
|
||||
UserAttributeValue: NewUserAttributeValueClient(cfg),
|
||||
UserSubscription: NewUserSubscriptionClient(cfg),
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
APIKey: NewAPIKeyClient(cfg),
|
||||
Account: NewAccountClient(cfg),
|
||||
AccountGroup: NewAccountGroupClient(cfg),
|
||||
Announcement: NewAnnouncementClient(cfg),
|
||||
AnnouncementRead: NewAnnouncementReadClient(cfg),
|
||||
AuthIdentity: NewAuthIdentityClient(cfg),
|
||||
AuthIdentityChannel: NewAuthIdentityChannelClient(cfg),
|
||||
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
|
||||
Group: NewGroupClient(cfg),
|
||||
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
|
||||
IdentityAdoptionDecision: NewIdentityAdoptionDecisionClient(cfg),
|
||||
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
|
||||
PaymentOrder: NewPaymentOrderClient(cfg),
|
||||
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
|
||||
PendingAuthSession: NewPendingAuthSessionClient(cfg),
|
||||
PromoCode: NewPromoCodeClient(cfg),
|
||||
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
|
||||
Proxy: NewProxyClient(cfg),
|
||||
RedeemCode: NewRedeemCodeClient(cfg),
|
||||
SecuritySecret: NewSecuritySecretClient(cfg),
|
||||
Setting: NewSettingClient(cfg),
|
||||
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
|
||||
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
|
||||
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
|
||||
UsageLog: NewUsageLogClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserAllowedGroup: NewUserAllowedGroupClient(cfg),
|
||||
UserAttributeDefinition: NewUserAttributeDefinitionClient(cfg),
|
||||
UserAttributeValue: NewUserAttributeValueClient(cfg),
|
||||
UserSubscription: NewUserSubscriptionClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -332,11 +356,12 @@ func (c *Client) Close() error {
|
||||
func (c *Client) Use(hooks ...Hook) {
|
||||
for _, n := range []interface{ Use(...Hook) }{
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
|
||||
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PaymentAuditLog,
|
||||
c.PaymentOrder, c.PaymentProviderInstance, c.PromoCode, c.PromoCodeUsage,
|
||||
c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, c.SubscriptionPlan,
|
||||
c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.AuthIdentity, c.AuthIdentityChannel, c.ErrorPassthroughRule, c.Group,
|
||||
c.IdempotencyRecord, c.IdentityAdoptionDecision, c.PaymentAuditLog,
|
||||
c.PaymentOrder, c.PaymentProviderInstance, c.PendingAuthSession, c.PromoCode,
|
||||
c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting,
|
||||
c.SubscriptionPlan, c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog,
|
||||
c.User, c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.UserSubscription,
|
||||
} {
|
||||
n.Use(hooks...)
|
||||
@ -348,11 +373,12 @@ func (c *Client) Use(hooks ...Hook) {
|
||||
func (c *Client) Intercept(interceptors ...Interceptor) {
|
||||
for _, n := range []interface{ Intercept(...Interceptor) }{
|
||||
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
|
||||
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PaymentAuditLog,
|
||||
c.PaymentOrder, c.PaymentProviderInstance, c.PromoCode, c.PromoCodeUsage,
|
||||
c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, c.SubscriptionPlan,
|
||||
c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog, c.User,
|
||||
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.AuthIdentity, c.AuthIdentityChannel, c.ErrorPassthroughRule, c.Group,
|
||||
c.IdempotencyRecord, c.IdentityAdoptionDecision, c.PaymentAuditLog,
|
||||
c.PaymentOrder, c.PaymentProviderInstance, c.PendingAuthSession, c.PromoCode,
|
||||
c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting,
|
||||
c.SubscriptionPlan, c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog,
|
||||
c.User, c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
|
||||
c.UserSubscription,
|
||||
} {
|
||||
n.Intercept(interceptors...)
|
||||
@ -372,18 +398,26 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
||||
return c.Announcement.mutate(ctx, m)
|
||||
case *AnnouncementReadMutation:
|
||||
return c.AnnouncementRead.mutate(ctx, m)
|
||||
case *AuthIdentityMutation:
|
||||
return c.AuthIdentity.mutate(ctx, m)
|
||||
case *AuthIdentityChannelMutation:
|
||||
return c.AuthIdentityChannel.mutate(ctx, m)
|
||||
case *ErrorPassthroughRuleMutation:
|
||||
return c.ErrorPassthroughRule.mutate(ctx, m)
|
||||
case *GroupMutation:
|
||||
return c.Group.mutate(ctx, m)
|
||||
case *IdempotencyRecordMutation:
|
||||
return c.IdempotencyRecord.mutate(ctx, m)
|
||||
case *IdentityAdoptionDecisionMutation:
|
||||
return c.IdentityAdoptionDecision.mutate(ctx, m)
|
||||
case *PaymentAuditLogMutation:
|
||||
return c.PaymentAuditLog.mutate(ctx, m)
|
||||
case *PaymentOrderMutation:
|
||||
return c.PaymentOrder.mutate(ctx, m)
|
||||
case *PaymentProviderInstanceMutation:
|
||||
return c.PaymentProviderInstance.mutate(ctx, m)
|
||||
case *PendingAuthSessionMutation:
|
||||
return c.PendingAuthSession.mutate(ctx, m)
|
||||
case *PromoCodeMutation:
|
||||
return c.PromoCode.mutate(ctx, m)
|
||||
case *PromoCodeUsageMutation:
|
||||
@ -1231,6 +1265,336 @@ func (c *AnnouncementReadClient) mutate(ctx context.Context, m *AnnouncementRead
|
||||
}
|
||||
}
|
||||
|
||||
// AuthIdentityClient is a client for the AuthIdentity schema.
|
||||
type AuthIdentityClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewAuthIdentityClient returns a client for the AuthIdentity from the given config.
|
||||
func NewAuthIdentityClient(c config) *AuthIdentityClient {
|
||||
return &AuthIdentityClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `authidentity.Hooks(f(g(h())))`.
|
||||
func (c *AuthIdentityClient) Use(hooks ...Hook) {
|
||||
c.hooks.AuthIdentity = append(c.hooks.AuthIdentity, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `authidentity.Intercept(f(g(h())))`.
|
||||
func (c *AuthIdentityClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.AuthIdentity = append(c.inters.AuthIdentity, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a AuthIdentity entity.
|
||||
func (c *AuthIdentityClient) Create() *AuthIdentityCreate {
|
||||
mutation := newAuthIdentityMutation(c.config, OpCreate)
|
||||
return &AuthIdentityCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of AuthIdentity entities.
|
||||
func (c *AuthIdentityClient) CreateBulk(builders ...*AuthIdentityCreate) *AuthIdentityCreateBulk {
|
||||
return &AuthIdentityCreateBulk{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 *AuthIdentityClient) MapCreateBulk(slice any, setFunc func(*AuthIdentityCreate, int)) *AuthIdentityCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &AuthIdentityCreateBulk{err: fmt.Errorf("calling to AuthIdentityClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*AuthIdentityCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &AuthIdentityCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for AuthIdentity.
|
||||
func (c *AuthIdentityClient) Update() *AuthIdentityUpdate {
|
||||
mutation := newAuthIdentityMutation(c.config, OpUpdate)
|
||||
return &AuthIdentityUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *AuthIdentityClient) UpdateOne(_m *AuthIdentity) *AuthIdentityUpdateOne {
|
||||
mutation := newAuthIdentityMutation(c.config, OpUpdateOne, withAuthIdentity(_m))
|
||||
return &AuthIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *AuthIdentityClient) UpdateOneID(id int64) *AuthIdentityUpdateOne {
|
||||
mutation := newAuthIdentityMutation(c.config, OpUpdateOne, withAuthIdentityID(id))
|
||||
return &AuthIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for AuthIdentity.
|
||||
func (c *AuthIdentityClient) Delete() *AuthIdentityDelete {
|
||||
mutation := newAuthIdentityMutation(c.config, OpDelete)
|
||||
return &AuthIdentityDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *AuthIdentityClient) DeleteOne(_m *AuthIdentity) *AuthIdentityDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *AuthIdentityClient) DeleteOneID(id int64) *AuthIdentityDeleteOne {
|
||||
builder := c.Delete().Where(authidentity.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &AuthIdentityDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for AuthIdentity.
|
||||
func (c *AuthIdentityClient) Query() *AuthIdentityQuery {
|
||||
return &AuthIdentityQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeAuthIdentity},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a AuthIdentity entity by its id.
|
||||
func (c *AuthIdentityClient) Get(ctx context.Context, id int64) (*AuthIdentity, error) {
|
||||
return c.Query().Where(authidentity.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *AuthIdentityClient) GetX(ctx context.Context, id int64) *AuthIdentity {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryUser queries the user edge of a AuthIdentity.
|
||||
func (c *AuthIdentityClient) QueryUser(_m *AuthIdentity) *UserQuery {
|
||||
query := (&UserClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, id),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, authidentity.UserTable, authidentity.UserColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryChannels queries the channels edge of a AuthIdentity.
|
||||
func (c *AuthIdentityClient) QueryChannels(_m *AuthIdentity) *AuthIdentityChannelQuery {
|
||||
query := (&AuthIdentityChannelClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, id),
|
||||
sqlgraph.To(authidentitychannel.Table, authidentitychannel.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, authidentity.ChannelsTable, authidentity.ChannelsColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAdoptionDecisions queries the adoption_decisions edge of a AuthIdentity.
|
||||
func (c *AuthIdentityClient) QueryAdoptionDecisions(_m *AuthIdentity) *IdentityAdoptionDecisionQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentity.Table, authidentity.FieldID, id),
|
||||
sqlgraph.To(identityadoptiondecision.Table, identityadoptiondecision.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, authidentity.AdoptionDecisionsTable, authidentity.AdoptionDecisionsColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *AuthIdentityClient) Hooks() []Hook {
|
||||
return c.hooks.AuthIdentity
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *AuthIdentityClient) Interceptors() []Interceptor {
|
||||
return c.inters.AuthIdentity
|
||||
}
|
||||
|
||||
func (c *AuthIdentityClient) mutate(ctx context.Context, m *AuthIdentityMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&AuthIdentityCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&AuthIdentityUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&AuthIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&AuthIdentityDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown AuthIdentity mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// AuthIdentityChannelClient is a client for the AuthIdentityChannel schema.
|
||||
type AuthIdentityChannelClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewAuthIdentityChannelClient returns a client for the AuthIdentityChannel from the given config.
|
||||
func NewAuthIdentityChannelClient(c config) *AuthIdentityChannelClient {
|
||||
return &AuthIdentityChannelClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `authidentitychannel.Hooks(f(g(h())))`.
|
||||
func (c *AuthIdentityChannelClient) Use(hooks ...Hook) {
|
||||
c.hooks.AuthIdentityChannel = append(c.hooks.AuthIdentityChannel, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `authidentitychannel.Intercept(f(g(h())))`.
|
||||
func (c *AuthIdentityChannelClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.AuthIdentityChannel = append(c.inters.AuthIdentityChannel, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a AuthIdentityChannel entity.
|
||||
func (c *AuthIdentityChannelClient) Create() *AuthIdentityChannelCreate {
|
||||
mutation := newAuthIdentityChannelMutation(c.config, OpCreate)
|
||||
return &AuthIdentityChannelCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of AuthIdentityChannel entities.
|
||||
func (c *AuthIdentityChannelClient) CreateBulk(builders ...*AuthIdentityChannelCreate) *AuthIdentityChannelCreateBulk {
|
||||
return &AuthIdentityChannelCreateBulk{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 *AuthIdentityChannelClient) MapCreateBulk(slice any, setFunc func(*AuthIdentityChannelCreate, int)) *AuthIdentityChannelCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &AuthIdentityChannelCreateBulk{err: fmt.Errorf("calling to AuthIdentityChannelClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*AuthIdentityChannelCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &AuthIdentityChannelCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for AuthIdentityChannel.
|
||||
func (c *AuthIdentityChannelClient) Update() *AuthIdentityChannelUpdate {
|
||||
mutation := newAuthIdentityChannelMutation(c.config, OpUpdate)
|
||||
return &AuthIdentityChannelUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *AuthIdentityChannelClient) UpdateOne(_m *AuthIdentityChannel) *AuthIdentityChannelUpdateOne {
|
||||
mutation := newAuthIdentityChannelMutation(c.config, OpUpdateOne, withAuthIdentityChannel(_m))
|
||||
return &AuthIdentityChannelUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *AuthIdentityChannelClient) UpdateOneID(id int64) *AuthIdentityChannelUpdateOne {
|
||||
mutation := newAuthIdentityChannelMutation(c.config, OpUpdateOne, withAuthIdentityChannelID(id))
|
||||
return &AuthIdentityChannelUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for AuthIdentityChannel.
|
||||
func (c *AuthIdentityChannelClient) Delete() *AuthIdentityChannelDelete {
|
||||
mutation := newAuthIdentityChannelMutation(c.config, OpDelete)
|
||||
return &AuthIdentityChannelDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *AuthIdentityChannelClient) DeleteOne(_m *AuthIdentityChannel) *AuthIdentityChannelDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *AuthIdentityChannelClient) DeleteOneID(id int64) *AuthIdentityChannelDeleteOne {
|
||||
builder := c.Delete().Where(authidentitychannel.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &AuthIdentityChannelDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for AuthIdentityChannel.
|
||||
func (c *AuthIdentityChannelClient) Query() *AuthIdentityChannelQuery {
|
||||
return &AuthIdentityChannelQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeAuthIdentityChannel},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a AuthIdentityChannel entity by its id.
|
||||
func (c *AuthIdentityChannelClient) Get(ctx context.Context, id int64) (*AuthIdentityChannel, error) {
|
||||
return c.Query().Where(authidentitychannel.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *AuthIdentityChannelClient) GetX(ctx context.Context, id int64) *AuthIdentityChannel {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryIdentity queries the identity edge of a AuthIdentityChannel.
|
||||
func (c *AuthIdentityChannelClient) QueryIdentity(_m *AuthIdentityChannel) *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(authidentitychannel.Table, authidentitychannel.FieldID, id),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, authidentitychannel.IdentityTable, authidentitychannel.IdentityColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *AuthIdentityChannelClient) Hooks() []Hook {
|
||||
return c.hooks.AuthIdentityChannel
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *AuthIdentityChannelClient) Interceptors() []Interceptor {
|
||||
return c.inters.AuthIdentityChannel
|
||||
}
|
||||
|
||||
func (c *AuthIdentityChannelClient) mutate(ctx context.Context, m *AuthIdentityChannelMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&AuthIdentityChannelCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&AuthIdentityChannelUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&AuthIdentityChannelUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&AuthIdentityChannelDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown AuthIdentityChannel mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorPassthroughRuleClient is a client for the ErrorPassthroughRule schema.
|
||||
type ErrorPassthroughRuleClient struct {
|
||||
config
|
||||
@ -1760,6 +2124,171 @@ func (c *IdempotencyRecordClient) mutate(ctx context.Context, m *IdempotencyReco
|
||||
}
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionClient is a client for the IdentityAdoptionDecision schema.
|
||||
type IdentityAdoptionDecisionClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewIdentityAdoptionDecisionClient returns a client for the IdentityAdoptionDecision from the given config.
|
||||
func NewIdentityAdoptionDecisionClient(c config) *IdentityAdoptionDecisionClient {
|
||||
return &IdentityAdoptionDecisionClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `identityadoptiondecision.Hooks(f(g(h())))`.
|
||||
func (c *IdentityAdoptionDecisionClient) Use(hooks ...Hook) {
|
||||
c.hooks.IdentityAdoptionDecision = append(c.hooks.IdentityAdoptionDecision, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `identityadoptiondecision.Intercept(f(g(h())))`.
|
||||
func (c *IdentityAdoptionDecisionClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.IdentityAdoptionDecision = append(c.inters.IdentityAdoptionDecision, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a IdentityAdoptionDecision entity.
|
||||
func (c *IdentityAdoptionDecisionClient) Create() *IdentityAdoptionDecisionCreate {
|
||||
mutation := newIdentityAdoptionDecisionMutation(c.config, OpCreate)
|
||||
return &IdentityAdoptionDecisionCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of IdentityAdoptionDecision entities.
|
||||
func (c *IdentityAdoptionDecisionClient) CreateBulk(builders ...*IdentityAdoptionDecisionCreate) *IdentityAdoptionDecisionCreateBulk {
|
||||
return &IdentityAdoptionDecisionCreateBulk{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 *IdentityAdoptionDecisionClient) MapCreateBulk(slice any, setFunc func(*IdentityAdoptionDecisionCreate, int)) *IdentityAdoptionDecisionCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &IdentityAdoptionDecisionCreateBulk{err: fmt.Errorf("calling to IdentityAdoptionDecisionClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*IdentityAdoptionDecisionCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &IdentityAdoptionDecisionCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for IdentityAdoptionDecision.
|
||||
func (c *IdentityAdoptionDecisionClient) Update() *IdentityAdoptionDecisionUpdate {
|
||||
mutation := newIdentityAdoptionDecisionMutation(c.config, OpUpdate)
|
||||
return &IdentityAdoptionDecisionUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *IdentityAdoptionDecisionClient) UpdateOne(_m *IdentityAdoptionDecision) *IdentityAdoptionDecisionUpdateOne {
|
||||
mutation := newIdentityAdoptionDecisionMutation(c.config, OpUpdateOne, withIdentityAdoptionDecision(_m))
|
||||
return &IdentityAdoptionDecisionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *IdentityAdoptionDecisionClient) UpdateOneID(id int64) *IdentityAdoptionDecisionUpdateOne {
|
||||
mutation := newIdentityAdoptionDecisionMutation(c.config, OpUpdateOne, withIdentityAdoptionDecisionID(id))
|
||||
return &IdentityAdoptionDecisionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for IdentityAdoptionDecision.
|
||||
func (c *IdentityAdoptionDecisionClient) Delete() *IdentityAdoptionDecisionDelete {
|
||||
mutation := newIdentityAdoptionDecisionMutation(c.config, OpDelete)
|
||||
return &IdentityAdoptionDecisionDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *IdentityAdoptionDecisionClient) DeleteOne(_m *IdentityAdoptionDecision) *IdentityAdoptionDecisionDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *IdentityAdoptionDecisionClient) DeleteOneID(id int64) *IdentityAdoptionDecisionDeleteOne {
|
||||
builder := c.Delete().Where(identityadoptiondecision.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &IdentityAdoptionDecisionDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for IdentityAdoptionDecision.
|
||||
func (c *IdentityAdoptionDecisionClient) Query() *IdentityAdoptionDecisionQuery {
|
||||
return &IdentityAdoptionDecisionQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeIdentityAdoptionDecision},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a IdentityAdoptionDecision entity by its id.
|
||||
func (c *IdentityAdoptionDecisionClient) Get(ctx context.Context, id int64) (*IdentityAdoptionDecision, error) {
|
||||
return c.Query().Where(identityadoptiondecision.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *IdentityAdoptionDecisionClient) GetX(ctx context.Context, id int64) *IdentityAdoptionDecision {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryPendingAuthSession queries the pending_auth_session edge of a IdentityAdoptionDecision.
|
||||
func (c *IdentityAdoptionDecisionClient) QueryPendingAuthSession(_m *IdentityAdoptionDecision) *PendingAuthSessionQuery {
|
||||
query := (&PendingAuthSessionClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(identityadoptiondecision.Table, identityadoptiondecision.FieldID, id),
|
||||
sqlgraph.To(pendingauthsession.Table, pendingauthsession.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, true, identityadoptiondecision.PendingAuthSessionTable, identityadoptiondecision.PendingAuthSessionColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryIdentity queries the identity edge of a IdentityAdoptionDecision.
|
||||
func (c *IdentityAdoptionDecisionClient) QueryIdentity(_m *IdentityAdoptionDecision) *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(identityadoptiondecision.Table, identityadoptiondecision.FieldID, id),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, identityadoptiondecision.IdentityTable, identityadoptiondecision.IdentityColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *IdentityAdoptionDecisionClient) Hooks() []Hook {
|
||||
return c.hooks.IdentityAdoptionDecision
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *IdentityAdoptionDecisionClient) Interceptors() []Interceptor {
|
||||
return c.inters.IdentityAdoptionDecision
|
||||
}
|
||||
|
||||
func (c *IdentityAdoptionDecisionClient) mutate(ctx context.Context, m *IdentityAdoptionDecisionMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&IdentityAdoptionDecisionCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&IdentityAdoptionDecisionUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&IdentityAdoptionDecisionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&IdentityAdoptionDecisionDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown IdentityAdoptionDecision mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// PaymentAuditLogClient is a client for the PaymentAuditLog schema.
|
||||
type PaymentAuditLogClient struct {
|
||||
config
|
||||
@ -2175,6 +2704,171 @@ func (c *PaymentProviderInstanceClient) mutate(ctx context.Context, m *PaymentPr
|
||||
}
|
||||
}
|
||||
|
||||
// PendingAuthSessionClient is a client for the PendingAuthSession schema.
|
||||
type PendingAuthSessionClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewPendingAuthSessionClient returns a client for the PendingAuthSession from the given config.
|
||||
func NewPendingAuthSessionClient(c config) *PendingAuthSessionClient {
|
||||
return &PendingAuthSessionClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `pendingauthsession.Hooks(f(g(h())))`.
|
||||
func (c *PendingAuthSessionClient) Use(hooks ...Hook) {
|
||||
c.hooks.PendingAuthSession = append(c.hooks.PendingAuthSession, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `pendingauthsession.Intercept(f(g(h())))`.
|
||||
func (c *PendingAuthSessionClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.PendingAuthSession = append(c.inters.PendingAuthSession, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a PendingAuthSession entity.
|
||||
func (c *PendingAuthSessionClient) Create() *PendingAuthSessionCreate {
|
||||
mutation := newPendingAuthSessionMutation(c.config, OpCreate)
|
||||
return &PendingAuthSessionCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of PendingAuthSession entities.
|
||||
func (c *PendingAuthSessionClient) CreateBulk(builders ...*PendingAuthSessionCreate) *PendingAuthSessionCreateBulk {
|
||||
return &PendingAuthSessionCreateBulk{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 *PendingAuthSessionClient) MapCreateBulk(slice any, setFunc func(*PendingAuthSessionCreate, int)) *PendingAuthSessionCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &PendingAuthSessionCreateBulk{err: fmt.Errorf("calling to PendingAuthSessionClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*PendingAuthSessionCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &PendingAuthSessionCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for PendingAuthSession.
|
||||
func (c *PendingAuthSessionClient) Update() *PendingAuthSessionUpdate {
|
||||
mutation := newPendingAuthSessionMutation(c.config, OpUpdate)
|
||||
return &PendingAuthSessionUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *PendingAuthSessionClient) UpdateOne(_m *PendingAuthSession) *PendingAuthSessionUpdateOne {
|
||||
mutation := newPendingAuthSessionMutation(c.config, OpUpdateOne, withPendingAuthSession(_m))
|
||||
return &PendingAuthSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *PendingAuthSessionClient) UpdateOneID(id int64) *PendingAuthSessionUpdateOne {
|
||||
mutation := newPendingAuthSessionMutation(c.config, OpUpdateOne, withPendingAuthSessionID(id))
|
||||
return &PendingAuthSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for PendingAuthSession.
|
||||
func (c *PendingAuthSessionClient) Delete() *PendingAuthSessionDelete {
|
||||
mutation := newPendingAuthSessionMutation(c.config, OpDelete)
|
||||
return &PendingAuthSessionDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *PendingAuthSessionClient) DeleteOne(_m *PendingAuthSession) *PendingAuthSessionDeleteOne {
|
||||
return c.DeleteOneID(_m.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *PendingAuthSessionClient) DeleteOneID(id int64) *PendingAuthSessionDeleteOne {
|
||||
builder := c.Delete().Where(pendingauthsession.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &PendingAuthSessionDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for PendingAuthSession.
|
||||
func (c *PendingAuthSessionClient) Query() *PendingAuthSessionQuery {
|
||||
return &PendingAuthSessionQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypePendingAuthSession},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a PendingAuthSession entity by its id.
|
||||
func (c *PendingAuthSessionClient) Get(ctx context.Context, id int64) (*PendingAuthSession, error) {
|
||||
return c.Query().Where(pendingauthsession.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *PendingAuthSessionClient) GetX(ctx context.Context, id int64) *PendingAuthSession {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryTargetUser queries the target_user edge of a PendingAuthSession.
|
||||
func (c *PendingAuthSessionClient) QueryTargetUser(_m *PendingAuthSession) *UserQuery {
|
||||
query := (&UserClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(pendingauthsession.Table, pendingauthsession.FieldID, id),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, pendingauthsession.TargetUserTable, pendingauthsession.TargetUserColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAdoptionDecision queries the adoption_decision edge of a PendingAuthSession.
|
||||
func (c *PendingAuthSessionClient) QueryAdoptionDecision(_m *PendingAuthSession) *IdentityAdoptionDecisionQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(pendingauthsession.Table, pendingauthsession.FieldID, id),
|
||||
sqlgraph.To(identityadoptiondecision.Table, identityadoptiondecision.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, false, pendingauthsession.AdoptionDecisionTable, pendingauthsession.AdoptionDecisionColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *PendingAuthSessionClient) Hooks() []Hook {
|
||||
return c.hooks.PendingAuthSession
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *PendingAuthSessionClient) Interceptors() []Interceptor {
|
||||
return c.inters.PendingAuthSession
|
||||
}
|
||||
|
||||
func (c *PendingAuthSessionClient) mutate(ctx context.Context, m *PendingAuthSessionMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&PendingAuthSessionCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&PendingAuthSessionUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&PendingAuthSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&PendingAuthSessionDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown PendingAuthSession mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// PromoCodeClient is a client for the PromoCode schema.
|
||||
type PromoCodeClient struct {
|
||||
config
|
||||
@ -3951,6 +4645,38 @@ func (c *UserClient) QueryPaymentOrders(_m *User) *PaymentOrderQuery {
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAuthIdentities queries the auth_identities edge of a User.
|
||||
func (c *UserClient) QueryAuthIdentities(_m *User) *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, id),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.AuthIdentitiesTable, user.AuthIdentitiesColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryPendingAuthSessions queries the pending_auth_sessions edge of a User.
|
||||
func (c *UserClient) QueryPendingAuthSessions(_m *User) *PendingAuthSessionQuery {
|
||||
query := (&PendingAuthSessionClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := _m.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, id),
|
||||
sqlgraph.To(pendingauthsession.Table, pendingauthsession.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.PendingAuthSessionsTable, user.PendingAuthSessionsColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryUserAllowedGroups queries the user_allowed_groups edge of a User.
|
||||
func (c *UserClient) QueryUserAllowedGroups(_m *User) *UserAllowedGroupQuery {
|
||||
query := (&UserAllowedGroupClient{config: c.config}).Query()
|
||||
@ -4628,18 +5354,20 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription
|
||||
// hooks and interceptors per client, for fast access.
|
||||
type (
|
||||
hooks struct {
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
|
||||
ErrorPassthroughRule, Group, IdempotencyRecord, PaymentAuditLog, PaymentOrder,
|
||||
PaymentProviderInstance, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
|
||||
SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead, AuthIdentity,
|
||||
AuthIdentityChannel, ErrorPassthroughRule, Group, IdempotencyRecord,
|
||||
IdentityAdoptionDecision, PaymentAuditLog, PaymentOrder,
|
||||
PaymentProviderInstance, PendingAuthSession, PromoCode, PromoCodeUsage, Proxy,
|
||||
RedeemCode, SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
|
||||
UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition,
|
||||
UserAttributeValue, UserSubscription []ent.Hook
|
||||
}
|
||||
inters struct {
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
|
||||
ErrorPassthroughRule, Group, IdempotencyRecord, PaymentAuditLog, PaymentOrder,
|
||||
PaymentProviderInstance, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
|
||||
SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
|
||||
APIKey, Account, AccountGroup, Announcement, AnnouncementRead, AuthIdentity,
|
||||
AuthIdentityChannel, ErrorPassthroughRule, Group, IdempotencyRecord,
|
||||
IdentityAdoptionDecision, PaymentAuditLog, PaymentOrder,
|
||||
PaymentProviderInstance, PendingAuthSession, PromoCode, PromoCodeUsage, Proxy,
|
||||
RedeemCode, SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
|
||||
UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition,
|
||||
UserAttributeValue, UserSubscription []ent.Interceptor
|
||||
}
|
||||
|
||||
@ -17,12 +17,16 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/proxy"
|
||||
@ -98,32 +102,36 @@ var (
|
||||
func checkColumn(t, c string) error {
|
||||
initCheck.Do(func() {
|
||||
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
|
||||
apikey.Table: apikey.ValidColumn,
|
||||
account.Table: account.ValidColumn,
|
||||
accountgroup.Table: accountgroup.ValidColumn,
|
||||
announcement.Table: announcement.ValidColumn,
|
||||
announcementread.Table: announcementread.ValidColumn,
|
||||
errorpassthroughrule.Table: errorpassthroughrule.ValidColumn,
|
||||
group.Table: group.ValidColumn,
|
||||
idempotencyrecord.Table: idempotencyrecord.ValidColumn,
|
||||
paymentauditlog.Table: paymentauditlog.ValidColumn,
|
||||
paymentorder.Table: paymentorder.ValidColumn,
|
||||
paymentproviderinstance.Table: paymentproviderinstance.ValidColumn,
|
||||
promocode.Table: promocode.ValidColumn,
|
||||
promocodeusage.Table: promocodeusage.ValidColumn,
|
||||
proxy.Table: proxy.ValidColumn,
|
||||
redeemcode.Table: redeemcode.ValidColumn,
|
||||
securitysecret.Table: securitysecret.ValidColumn,
|
||||
setting.Table: setting.ValidColumn,
|
||||
subscriptionplan.Table: subscriptionplan.ValidColumn,
|
||||
tlsfingerprintprofile.Table: tlsfingerprintprofile.ValidColumn,
|
||||
usagecleanuptask.Table: usagecleanuptask.ValidColumn,
|
||||
usagelog.Table: usagelog.ValidColumn,
|
||||
user.Table: user.ValidColumn,
|
||||
userallowedgroup.Table: userallowedgroup.ValidColumn,
|
||||
userattributedefinition.Table: userattributedefinition.ValidColumn,
|
||||
userattributevalue.Table: userattributevalue.ValidColumn,
|
||||
usersubscription.Table: usersubscription.ValidColumn,
|
||||
apikey.Table: apikey.ValidColumn,
|
||||
account.Table: account.ValidColumn,
|
||||
accountgroup.Table: accountgroup.ValidColumn,
|
||||
announcement.Table: announcement.ValidColumn,
|
||||
announcementread.Table: announcementread.ValidColumn,
|
||||
authidentity.Table: authidentity.ValidColumn,
|
||||
authidentitychannel.Table: authidentitychannel.ValidColumn,
|
||||
errorpassthroughrule.Table: errorpassthroughrule.ValidColumn,
|
||||
group.Table: group.ValidColumn,
|
||||
idempotencyrecord.Table: idempotencyrecord.ValidColumn,
|
||||
identityadoptiondecision.Table: identityadoptiondecision.ValidColumn,
|
||||
paymentauditlog.Table: paymentauditlog.ValidColumn,
|
||||
paymentorder.Table: paymentorder.ValidColumn,
|
||||
paymentproviderinstance.Table: paymentproviderinstance.ValidColumn,
|
||||
pendingauthsession.Table: pendingauthsession.ValidColumn,
|
||||
promocode.Table: promocode.ValidColumn,
|
||||
promocodeusage.Table: promocodeusage.ValidColumn,
|
||||
proxy.Table: proxy.ValidColumn,
|
||||
redeemcode.Table: redeemcode.ValidColumn,
|
||||
securitysecret.Table: securitysecret.ValidColumn,
|
||||
setting.Table: setting.ValidColumn,
|
||||
subscriptionplan.Table: subscriptionplan.ValidColumn,
|
||||
tlsfingerprintprofile.Table: tlsfingerprintprofile.ValidColumn,
|
||||
usagecleanuptask.Table: usagecleanuptask.ValidColumn,
|
||||
usagelog.Table: usagelog.ValidColumn,
|
||||
user.Table: user.ValidColumn,
|
||||
userallowedgroup.Table: userallowedgroup.ValidColumn,
|
||||
userattributedefinition.Table: userattributedefinition.ValidColumn,
|
||||
userattributevalue.Table: userattributevalue.ValidColumn,
|
||||
usersubscription.Table: usersubscription.ValidColumn,
|
||||
})
|
||||
})
|
||||
return columnCheck(t, c)
|
||||
|
||||
@ -69,6 +69,30 @@ func (f AnnouncementReadFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.V
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AnnouncementReadMutation", m)
|
||||
}
|
||||
|
||||
// The AuthIdentityFunc type is an adapter to allow the use of ordinary
|
||||
// function as AuthIdentity mutator.
|
||||
type AuthIdentityFunc func(context.Context, *ent.AuthIdentityMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f AuthIdentityFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.AuthIdentityMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AuthIdentityMutation", m)
|
||||
}
|
||||
|
||||
// The AuthIdentityChannelFunc type is an adapter to allow the use of ordinary
|
||||
// function as AuthIdentityChannel mutator.
|
||||
type AuthIdentityChannelFunc func(context.Context, *ent.AuthIdentityChannelMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f AuthIdentityChannelFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.AuthIdentityChannelMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AuthIdentityChannelMutation", m)
|
||||
}
|
||||
|
||||
// The ErrorPassthroughRuleFunc type is an adapter to allow the use of ordinary
|
||||
// function as ErrorPassthroughRule mutator.
|
||||
type ErrorPassthroughRuleFunc func(context.Context, *ent.ErrorPassthroughRuleMutation) (ent.Value, error)
|
||||
@ -105,6 +129,18 @@ func (f IdempotencyRecordFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IdempotencyRecordMutation", m)
|
||||
}
|
||||
|
||||
// The IdentityAdoptionDecisionFunc type is an adapter to allow the use of ordinary
|
||||
// function as IdentityAdoptionDecision mutator.
|
||||
type IdentityAdoptionDecisionFunc func(context.Context, *ent.IdentityAdoptionDecisionMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f IdentityAdoptionDecisionFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.IdentityAdoptionDecisionMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IdentityAdoptionDecisionMutation", m)
|
||||
}
|
||||
|
||||
// The PaymentAuditLogFunc type is an adapter to allow the use of ordinary
|
||||
// function as PaymentAuditLog mutator.
|
||||
type PaymentAuditLogFunc func(context.Context, *ent.PaymentAuditLogMutation) (ent.Value, error)
|
||||
@ -141,6 +177,18 @@ func (f PaymentProviderInstanceFunc) Mutate(ctx context.Context, m ent.Mutation)
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PaymentProviderInstanceMutation", m)
|
||||
}
|
||||
|
||||
// The PendingAuthSessionFunc type is an adapter to allow the use of ordinary
|
||||
// function as PendingAuthSession mutator.
|
||||
type PendingAuthSessionFunc func(context.Context, *ent.PendingAuthSessionMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f PendingAuthSessionFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.PendingAuthSessionMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PendingAuthSessionMutation", m)
|
||||
}
|
||||
|
||||
// The PromoCodeFunc type is an adapter to allow the use of ordinary
|
||||
// function as PromoCode mutator.
|
||||
type PromoCodeFunc func(context.Context, *ent.PromoCodeMutation) (ent.Value, error)
|
||||
|
||||
223
backend/ent/identityadoptiondecision.go
Normal file
223
backend/ent/identityadoptiondecision.go
Normal file
@ -0,0 +1,223 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecision is the model entity for the IdentityAdoptionDecision schema.
|
||||
type IdentityAdoptionDecision struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// PendingAuthSessionID holds the value of the "pending_auth_session_id" field.
|
||||
PendingAuthSessionID int64 `json:"pending_auth_session_id,omitempty"`
|
||||
// IdentityID holds the value of the "identity_id" field.
|
||||
IdentityID *int64 `json:"identity_id,omitempty"`
|
||||
// AdoptDisplayName holds the value of the "adopt_display_name" field.
|
||||
AdoptDisplayName bool `json:"adopt_display_name,omitempty"`
|
||||
// AdoptAvatar holds the value of the "adopt_avatar" field.
|
||||
AdoptAvatar bool `json:"adopt_avatar,omitempty"`
|
||||
// DecidedAt holds the value of the "decided_at" field.
|
||||
DecidedAt time.Time `json:"decided_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the IdentityAdoptionDecisionQuery when eager-loading is set.
|
||||
Edges IdentityAdoptionDecisionEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionEdges holds the relations/edges for other nodes in the graph.
|
||||
type IdentityAdoptionDecisionEdges struct {
|
||||
// PendingAuthSession holds the value of the pending_auth_session edge.
|
||||
PendingAuthSession *PendingAuthSession `json:"pending_auth_session,omitempty"`
|
||||
// Identity holds the value of the identity edge.
|
||||
Identity *AuthIdentity `json:"identity,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [2]bool
|
||||
}
|
||||
|
||||
// PendingAuthSessionOrErr returns the PendingAuthSession value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e IdentityAdoptionDecisionEdges) PendingAuthSessionOrErr() (*PendingAuthSession, error) {
|
||||
if e.PendingAuthSession != nil {
|
||||
return e.PendingAuthSession, nil
|
||||
} else if e.loadedTypes[0] {
|
||||
return nil, &NotFoundError{label: pendingauthsession.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "pending_auth_session"}
|
||||
}
|
||||
|
||||
// IdentityOrErr returns the Identity value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e IdentityAdoptionDecisionEdges) IdentityOrErr() (*AuthIdentity, error) {
|
||||
if e.Identity != nil {
|
||||
return e.Identity, nil
|
||||
} else if e.loadedTypes[1] {
|
||||
return nil, &NotFoundError{label: authidentity.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "identity"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*IdentityAdoptionDecision) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case identityadoptiondecision.FieldAdoptDisplayName, identityadoptiondecision.FieldAdoptAvatar:
|
||||
values[i] = new(sql.NullBool)
|
||||
case identityadoptiondecision.FieldID, identityadoptiondecision.FieldPendingAuthSessionID, identityadoptiondecision.FieldIdentityID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case identityadoptiondecision.FieldCreatedAt, identityadoptiondecision.FieldUpdatedAt, identityadoptiondecision.FieldDecidedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the IdentityAdoptionDecision fields.
|
||||
func (_m *IdentityAdoptionDecision) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case identityadoptiondecision.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case identityadoptiondecision.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case identityadoptiondecision.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
case identityadoptiondecision.FieldPendingAuthSessionID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field pending_auth_session_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.PendingAuthSessionID = value.Int64
|
||||
}
|
||||
case identityadoptiondecision.FieldIdentityID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field identity_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.IdentityID = new(int64)
|
||||
*_m.IdentityID = value.Int64
|
||||
}
|
||||
case identityadoptiondecision.FieldAdoptDisplayName:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field adopt_display_name", values[i])
|
||||
} else if value.Valid {
|
||||
_m.AdoptDisplayName = value.Bool
|
||||
}
|
||||
case identityadoptiondecision.FieldAdoptAvatar:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field adopt_avatar", values[i])
|
||||
} else if value.Valid {
|
||||
_m.AdoptAvatar = value.Bool
|
||||
}
|
||||
case identityadoptiondecision.FieldDecidedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field decided_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.DecidedAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the IdentityAdoptionDecision.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *IdentityAdoptionDecision) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryPendingAuthSession queries the "pending_auth_session" edge of the IdentityAdoptionDecision entity.
|
||||
func (_m *IdentityAdoptionDecision) QueryPendingAuthSession() *PendingAuthSessionQuery {
|
||||
return NewIdentityAdoptionDecisionClient(_m.config).QueryPendingAuthSession(_m)
|
||||
}
|
||||
|
||||
// QueryIdentity queries the "identity" edge of the IdentityAdoptionDecision entity.
|
||||
func (_m *IdentityAdoptionDecision) QueryIdentity() *AuthIdentityQuery {
|
||||
return NewIdentityAdoptionDecisionClient(_m.config).QueryIdentity(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this IdentityAdoptionDecision.
|
||||
// Note that you need to call IdentityAdoptionDecision.Unwrap() before calling this method if this IdentityAdoptionDecision
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *IdentityAdoptionDecision) Update() *IdentityAdoptionDecisionUpdateOne {
|
||||
return NewIdentityAdoptionDecisionClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the IdentityAdoptionDecision entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *IdentityAdoptionDecision) Unwrap() *IdentityAdoptionDecision {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: IdentityAdoptionDecision is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *IdentityAdoptionDecision) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("IdentityAdoptionDecision(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("pending_auth_session_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.PendingAuthSessionID))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.IdentityID; v != nil {
|
||||
builder.WriteString("identity_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("adopt_display_name=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.AdoptDisplayName))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("adopt_avatar=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.AdoptAvatar))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("decided_at=")
|
||||
builder.WriteString(_m.DecidedAt.Format(time.ANSIC))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisions is a parsable slice of IdentityAdoptionDecision.
|
||||
type IdentityAdoptionDecisions []*IdentityAdoptionDecision
|
||||
159
backend/ent/identityadoptiondecision/identityadoptiondecision.go
Normal file
159
backend/ent/identityadoptiondecision/identityadoptiondecision.go
Normal file
@ -0,0 +1,159 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package identityadoptiondecision
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the identityadoptiondecision type in the database.
|
||||
Label = "identity_adoption_decision"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldPendingAuthSessionID holds the string denoting the pending_auth_session_id field in the database.
|
||||
FieldPendingAuthSessionID = "pending_auth_session_id"
|
||||
// FieldIdentityID holds the string denoting the identity_id field in the database.
|
||||
FieldIdentityID = "identity_id"
|
||||
// FieldAdoptDisplayName holds the string denoting the adopt_display_name field in the database.
|
||||
FieldAdoptDisplayName = "adopt_display_name"
|
||||
// FieldAdoptAvatar holds the string denoting the adopt_avatar field in the database.
|
||||
FieldAdoptAvatar = "adopt_avatar"
|
||||
// FieldDecidedAt holds the string denoting the decided_at field in the database.
|
||||
FieldDecidedAt = "decided_at"
|
||||
// EdgePendingAuthSession holds the string denoting the pending_auth_session edge name in mutations.
|
||||
EdgePendingAuthSession = "pending_auth_session"
|
||||
// EdgeIdentity holds the string denoting the identity edge name in mutations.
|
||||
EdgeIdentity = "identity"
|
||||
// Table holds the table name of the identityadoptiondecision in the database.
|
||||
Table = "identity_adoption_decisions"
|
||||
// PendingAuthSessionTable is the table that holds the pending_auth_session relation/edge.
|
||||
PendingAuthSessionTable = "identity_adoption_decisions"
|
||||
// PendingAuthSessionInverseTable is the table name for the PendingAuthSession entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "pendingauthsession" package.
|
||||
PendingAuthSessionInverseTable = "pending_auth_sessions"
|
||||
// PendingAuthSessionColumn is the table column denoting the pending_auth_session relation/edge.
|
||||
PendingAuthSessionColumn = "pending_auth_session_id"
|
||||
// IdentityTable is the table that holds the identity relation/edge.
|
||||
IdentityTable = "identity_adoption_decisions"
|
||||
// IdentityInverseTable is the table name for the AuthIdentity entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "authidentity" package.
|
||||
IdentityInverseTable = "auth_identities"
|
||||
// IdentityColumn is the table column denoting the identity relation/edge.
|
||||
IdentityColumn = "identity_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for identityadoptiondecision fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldPendingAuthSessionID,
|
||||
FieldIdentityID,
|
||||
FieldAdoptDisplayName,
|
||||
FieldAdoptAvatar,
|
||||
FieldDecidedAt,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
// DefaultAdoptDisplayName holds the default value on creation for the "adopt_display_name" field.
|
||||
DefaultAdoptDisplayName bool
|
||||
// DefaultAdoptAvatar holds the default value on creation for the "adopt_avatar" field.
|
||||
DefaultAdoptAvatar bool
|
||||
// DefaultDecidedAt holds the default value on creation for the "decided_at" field.
|
||||
DefaultDecidedAt func() time.Time
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the IdentityAdoptionDecision queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPendingAuthSessionID orders the results by the pending_auth_session_id field.
|
||||
func ByPendingAuthSessionID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldPendingAuthSessionID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByIdentityID orders the results by the identity_id field.
|
||||
func ByIdentityID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldIdentityID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAdoptDisplayName orders the results by the adopt_display_name field.
|
||||
func ByAdoptDisplayName(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldAdoptDisplayName, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByAdoptAvatar orders the results by the adopt_avatar field.
|
||||
func ByAdoptAvatar(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldAdoptAvatar, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByDecidedAt orders the results by the decided_at field.
|
||||
func ByDecidedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldDecidedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPendingAuthSessionField orders the results by pending_auth_session field.
|
||||
func ByPendingAuthSessionField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newPendingAuthSessionStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
|
||||
// ByIdentityField orders the results by identity field.
|
||||
func ByIdentityField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newIdentityStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
func newPendingAuthSessionStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(PendingAuthSessionInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, true, PendingAuthSessionTable, PendingAuthSessionColumn),
|
||||
)
|
||||
}
|
||||
func newIdentityStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(IdentityInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, IdentityTable, IdentityColumn),
|
||||
)
|
||||
}
|
||||
342
backend/ent/identityadoptiondecision/where.go
Normal file
342
backend/ent/identityadoptiondecision/where.go
Normal file
@ -0,0 +1,342 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package identityadoptiondecision
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// PendingAuthSessionID applies equality check predicate on the "pending_auth_session_id" field. It's identical to PendingAuthSessionIDEQ.
|
||||
func PendingAuthSessionID(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldPendingAuthSessionID, v))
|
||||
}
|
||||
|
||||
// IdentityID applies equality check predicate on the "identity_id" field. It's identical to IdentityIDEQ.
|
||||
func IdentityID(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// AdoptDisplayName applies equality check predicate on the "adopt_display_name" field. It's identical to AdoptDisplayNameEQ.
|
||||
func AdoptDisplayName(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldAdoptDisplayName, v))
|
||||
}
|
||||
|
||||
// AdoptAvatar applies equality check predicate on the "adopt_avatar" field. It's identical to AdoptAvatarEQ.
|
||||
func AdoptAvatar(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldAdoptAvatar, v))
|
||||
}
|
||||
|
||||
// DecidedAt applies equality check predicate on the "decided_at" field. It's identical to DecidedAtEQ.
|
||||
func DecidedAt(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// PendingAuthSessionIDEQ applies the EQ predicate on the "pending_auth_session_id" field.
|
||||
func PendingAuthSessionIDEQ(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldPendingAuthSessionID, v))
|
||||
}
|
||||
|
||||
// PendingAuthSessionIDNEQ applies the NEQ predicate on the "pending_auth_session_id" field.
|
||||
func PendingAuthSessionIDNEQ(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldPendingAuthSessionID, v))
|
||||
}
|
||||
|
||||
// PendingAuthSessionIDIn applies the In predicate on the "pending_auth_session_id" field.
|
||||
func PendingAuthSessionIDIn(vs ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldPendingAuthSessionID, vs...))
|
||||
}
|
||||
|
||||
// PendingAuthSessionIDNotIn applies the NotIn predicate on the "pending_auth_session_id" field.
|
||||
func PendingAuthSessionIDNotIn(vs ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldPendingAuthSessionID, vs...))
|
||||
}
|
||||
|
||||
// IdentityIDEQ applies the EQ predicate on the "identity_id" field.
|
||||
func IdentityIDEQ(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// IdentityIDNEQ applies the NEQ predicate on the "identity_id" field.
|
||||
func IdentityIDNEQ(v int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldIdentityID, v))
|
||||
}
|
||||
|
||||
// IdentityIDIn applies the In predicate on the "identity_id" field.
|
||||
func IdentityIDIn(vs ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldIdentityID, vs...))
|
||||
}
|
||||
|
||||
// IdentityIDNotIn applies the NotIn predicate on the "identity_id" field.
|
||||
func IdentityIDNotIn(vs ...int64) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldIdentityID, vs...))
|
||||
}
|
||||
|
||||
// IdentityIDIsNil applies the IsNil predicate on the "identity_id" field.
|
||||
func IdentityIDIsNil() predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIsNull(FieldIdentityID))
|
||||
}
|
||||
|
||||
// IdentityIDNotNil applies the NotNil predicate on the "identity_id" field.
|
||||
func IdentityIDNotNil() predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotNull(FieldIdentityID))
|
||||
}
|
||||
|
||||
// AdoptDisplayNameEQ applies the EQ predicate on the "adopt_display_name" field.
|
||||
func AdoptDisplayNameEQ(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldAdoptDisplayName, v))
|
||||
}
|
||||
|
||||
// AdoptDisplayNameNEQ applies the NEQ predicate on the "adopt_display_name" field.
|
||||
func AdoptDisplayNameNEQ(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldAdoptDisplayName, v))
|
||||
}
|
||||
|
||||
// AdoptAvatarEQ applies the EQ predicate on the "adopt_avatar" field.
|
||||
func AdoptAvatarEQ(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldAdoptAvatar, v))
|
||||
}
|
||||
|
||||
// AdoptAvatarNEQ applies the NEQ predicate on the "adopt_avatar" field.
|
||||
func AdoptAvatarNEQ(v bool) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldAdoptAvatar, v))
|
||||
}
|
||||
|
||||
// DecidedAtEQ applies the EQ predicate on the "decided_at" field.
|
||||
func DecidedAtEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldEQ(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// DecidedAtNEQ applies the NEQ predicate on the "decided_at" field.
|
||||
func DecidedAtNEQ(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNEQ(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// DecidedAtIn applies the In predicate on the "decided_at" field.
|
||||
func DecidedAtIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldIn(FieldDecidedAt, vs...))
|
||||
}
|
||||
|
||||
// DecidedAtNotIn applies the NotIn predicate on the "decided_at" field.
|
||||
func DecidedAtNotIn(vs ...time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldNotIn(FieldDecidedAt, vs...))
|
||||
}
|
||||
|
||||
// DecidedAtGT applies the GT predicate on the "decided_at" field.
|
||||
func DecidedAtGT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGT(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// DecidedAtGTE applies the GTE predicate on the "decided_at" field.
|
||||
func DecidedAtGTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldGTE(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// DecidedAtLT applies the LT predicate on the "decided_at" field.
|
||||
func DecidedAtLT(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLT(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// DecidedAtLTE applies the LTE predicate on the "decided_at" field.
|
||||
func DecidedAtLTE(v time.Time) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.FieldLTE(FieldDecidedAt, v))
|
||||
}
|
||||
|
||||
// HasPendingAuthSession applies the HasEdge predicate on the "pending_auth_session" edge.
|
||||
func HasPendingAuthSession() predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, true, PendingAuthSessionTable, PendingAuthSessionColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasPendingAuthSessionWith applies the HasEdge predicate on the "pending_auth_session" edge with a given conditions (other predicates).
|
||||
func HasPendingAuthSessionWith(preds ...predicate.PendingAuthSession) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
step := newPendingAuthSessionStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasIdentity applies the HasEdge predicate on the "identity" edge.
|
||||
func HasIdentity() predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, IdentityTable, IdentityColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasIdentityWith applies the HasEdge predicate on the "identity" edge with a given conditions (other predicates).
|
||||
func HasIdentityWith(preds ...predicate.AuthIdentity) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
step := newIdentityStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.IdentityAdoptionDecision) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.IdentityAdoptionDecision) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.IdentityAdoptionDecision) predicate.IdentityAdoptionDecision {
|
||||
return predicate.IdentityAdoptionDecision(sql.NotPredicates(p))
|
||||
}
|
||||
843
backend/ent/identityadoptiondecision_create.go
Normal file
843
backend/ent/identityadoptiondecision_create.go
Normal file
@ -0,0 +1,843 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecisionCreate is the builder for creating a IdentityAdoptionDecision entity.
|
||||
type IdentityAdoptionDecisionCreate struct {
|
||||
config
|
||||
mutation *IdentityAdoptionDecisionMutation
|
||||
hooks []Hook
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetCreatedAt(v time.Time) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableCreatedAt(v *time.Time) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetCreatedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetUpdatedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableUpdatedAt(v *time.Time) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetUpdatedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetPendingAuthSessionID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetIdentityID(v int64) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetIdentityID(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableIdentityID sets the "identity_id" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableIdentityID(v *int64) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetIdentityID(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetAdoptDisplayName(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableAdoptDisplayName sets the "adopt_display_name" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableAdoptDisplayName(v *bool) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetAdoptDisplayName(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetAdoptAvatar(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableAdoptAvatar sets the "adopt_avatar" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableAdoptAvatar(v *bool) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetAdoptAvatar(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetDecidedAt sets the "decided_at" field.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetDecidedAt(v time.Time) *IdentityAdoptionDecisionCreate {
|
||||
_c.mutation.SetDecidedAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableDecidedAt sets the "decided_at" field if the given value is not nil.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetNillableDecidedAt(v *time.Time) *IdentityAdoptionDecisionCreate {
|
||||
if v != nil {
|
||||
_c.SetDecidedAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetPendingAuthSession sets the "pending_auth_session" edge to the PendingAuthSession entity.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetPendingAuthSession(v *PendingAuthSession) *IdentityAdoptionDecisionCreate {
|
||||
return _c.SetPendingAuthSessionID(v.ID)
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SetIdentity(v *AuthIdentity) *IdentityAdoptionDecisionCreate {
|
||||
return _c.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the IdentityAdoptionDecisionMutation object of the builder.
|
||||
func (_c *IdentityAdoptionDecisionCreate) Mutation() *IdentityAdoptionDecisionMutation {
|
||||
return _c.mutation
|
||||
}
|
||||
|
||||
// Save creates the IdentityAdoptionDecision in the database.
|
||||
func (_c *IdentityAdoptionDecisionCreate) Save(ctx context.Context) (*IdentityAdoptionDecision, error) {
|
||||
_c.defaults()
|
||||
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (_c *IdentityAdoptionDecisionCreate) SaveX(ctx context.Context) *IdentityAdoptionDecision {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *IdentityAdoptionDecisionCreate) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *IdentityAdoptionDecisionCreate) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_c *IdentityAdoptionDecisionCreate) defaults() {
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
v := identityadoptiondecision.DefaultCreatedAt()
|
||||
_c.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
||||
v := identityadoptiondecision.DefaultUpdatedAt()
|
||||
_c.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
if _, ok := _c.mutation.AdoptDisplayName(); !ok {
|
||||
v := identityadoptiondecision.DefaultAdoptDisplayName
|
||||
_c.mutation.SetAdoptDisplayName(v)
|
||||
}
|
||||
if _, ok := _c.mutation.AdoptAvatar(); !ok {
|
||||
v := identityadoptiondecision.DefaultAdoptAvatar
|
||||
_c.mutation.SetAdoptAvatar(v)
|
||||
}
|
||||
if _, ok := _c.mutation.DecidedAt(); !ok {
|
||||
v := identityadoptiondecision.DefaultDecidedAt()
|
||||
_c.mutation.SetDecidedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_c *IdentityAdoptionDecisionCreate) check() error {
|
||||
if _, ok := _c.mutation.CreatedAt(); !ok {
|
||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.created_at"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.UpdatedAt(); !ok {
|
||||
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.updated_at"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.PendingAuthSessionID(); !ok {
|
||||
return &ValidationError{Name: "pending_auth_session_id", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.pending_auth_session_id"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.AdoptDisplayName(); !ok {
|
||||
return &ValidationError{Name: "adopt_display_name", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.adopt_display_name"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.AdoptAvatar(); !ok {
|
||||
return &ValidationError{Name: "adopt_avatar", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.adopt_avatar"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.DecidedAt(); !ok {
|
||||
return &ValidationError{Name: "decided_at", err: errors.New(`ent: missing required field "IdentityAdoptionDecision.decided_at"`)}
|
||||
}
|
||||
if len(_c.mutation.PendingAuthSessionIDs()) == 0 {
|
||||
return &ValidationError{Name: "pending_auth_session", err: errors.New(`ent: missing required edge "IdentityAdoptionDecision.pending_auth_session"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_c *IdentityAdoptionDecisionCreate) sqlSave(ctx context.Context) (*IdentityAdoptionDecision, error) {
|
||||
if err := _c.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_node, _spec := _c.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
id := _spec.ID.Value.(int64)
|
||||
_node.ID = int64(id)
|
||||
_c.mutation.id = &_node.ID
|
||||
_c.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (_c *IdentityAdoptionDecisionCreate) createSpec() (*IdentityAdoptionDecision, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &IdentityAdoptionDecision{config: _c.config}
|
||||
_spec = sqlgraph.NewCreateSpec(identityadoptiondecision.Table, sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64))
|
||||
)
|
||||
_spec.OnConflict = _c.conflict
|
||||
if value, ok := _c.mutation.CreatedAt(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldCreatedAt, field.TypeTime, value)
|
||||
_node.CreatedAt = value
|
||||
}
|
||||
if value, ok := _c.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldUpdatedAt, field.TypeTime, value)
|
||||
_node.UpdatedAt = value
|
||||
}
|
||||
if value, ok := _c.mutation.AdoptDisplayName(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptDisplayName, field.TypeBool, value)
|
||||
_node.AdoptDisplayName = value
|
||||
}
|
||||
if value, ok := _c.mutation.AdoptAvatar(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptAvatar, field.TypeBool, value)
|
||||
_node.AdoptAvatar = value
|
||||
}
|
||||
if value, ok := _c.mutation.DecidedAt(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldDecidedAt, field.TypeTime, value)
|
||||
_node.DecidedAt = value
|
||||
}
|
||||
if nodes := _c.mutation.PendingAuthSessionIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.PendingAuthSessionTable,
|
||||
Columns: []string{identityadoptiondecision.PendingAuthSessionColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.PendingAuthSessionID = nodes[0]
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.IdentityTable,
|
||||
Columns: []string{identityadoptiondecision.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.IdentityID = &nodes[0]
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// SetCreatedAt(v).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.IdentityAdoptionDecisionUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *IdentityAdoptionDecisionCreate) OnConflict(opts ...sql.ConflictOption) *IdentityAdoptionDecisionUpsertOne {
|
||||
_c.conflict = opts
|
||||
return &IdentityAdoptionDecisionUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *IdentityAdoptionDecisionCreate) OnConflictColumns(columns ...string) *IdentityAdoptionDecisionUpsertOne {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &IdentityAdoptionDecisionUpsertOne{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// IdentityAdoptionDecisionUpsertOne is the builder for "upsert"-ing
|
||||
// one IdentityAdoptionDecision node.
|
||||
IdentityAdoptionDecisionUpsertOne struct {
|
||||
create *IdentityAdoptionDecisionCreate
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionUpsert is the "OnConflict" setter.
|
||||
IdentityAdoptionDecisionUpsert struct {
|
||||
*sql.UpdateSet
|
||||
}
|
||||
)
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionUpsert {
|
||||
u.Set(identityadoptiondecision.FieldUpdatedAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsert) UpdateUpdatedAt() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetExcluded(identityadoptiondecision.FieldUpdatedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionUpsert {
|
||||
u.Set(identityadoptiondecision.FieldPendingAuthSessionID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdatePendingAuthSessionID sets the "pending_auth_session_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsert) UpdatePendingAuthSessionID() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetExcluded(identityadoptiondecision.FieldPendingAuthSessionID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) SetIdentityID(v int64) *IdentityAdoptionDecisionUpsert {
|
||||
u.Set(identityadoptiondecision.FieldIdentityID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsert) UpdateIdentityID() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetExcluded(identityadoptiondecision.FieldIdentityID)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearIdentityID clears the value of the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) ClearIdentityID() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetNull(identityadoptiondecision.FieldIdentityID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionUpsert {
|
||||
u.Set(identityadoptiondecision.FieldAdoptDisplayName, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateAdoptDisplayName sets the "adopt_display_name" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsert) UpdateAdoptDisplayName() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetExcluded(identityadoptiondecision.FieldAdoptDisplayName)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (u *IdentityAdoptionDecisionUpsert) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionUpsert {
|
||||
u.Set(identityadoptiondecision.FieldAdoptAvatar, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateAdoptAvatar sets the "adopt_avatar" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsert) UpdateAdoptAvatar() *IdentityAdoptionDecisionUpsert {
|
||||
u.SetExcluded(identityadoptiondecision.FieldAdoptAvatar)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdateNewValues() *IdentityAdoptionDecisionUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(identityadoptiondecision.FieldCreatedAt)
|
||||
}
|
||||
if _, exists := u.create.mutation.DecidedAt(); exists {
|
||||
s.SetIgnore(identityadoptiondecision.FieldDecidedAt)
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) Ignore() *IdentityAdoptionDecisionUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) DoNothing() *IdentityAdoptionDecisionUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the IdentityAdoptionDecisionCreate.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) Update(set func(*IdentityAdoptionDecisionUpsert)) *IdentityAdoptionDecisionUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&IdentityAdoptionDecisionUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdateUpdatedAt() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetPendingAuthSessionID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatePendingAuthSessionID sets the "pending_auth_session_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdatePendingAuthSessionID() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdatePendingAuthSessionID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) SetIdentityID(v int64) *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetIdentityID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdateIdentityID() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearIdentityID clears the value of the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) ClearIdentityID() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.ClearIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetAdoptDisplayName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAdoptDisplayName sets the "adopt_display_name" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdateAdoptDisplayName() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateAdoptDisplayName()
|
||||
})
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetAdoptAvatar(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAdoptAvatar sets the "adopt_avatar" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) UpdateAdoptAvatar() *IdentityAdoptionDecisionUpsertOne {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateAdoptAvatar()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for IdentityAdoptionDecisionCreate.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) ID(ctx context.Context) (id int64, err error) {
|
||||
node, err := u.create.Save(ctx)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return node.ID, nil
|
||||
}
|
||||
|
||||
// IDX is like ID, but panics if an error occurs.
|
||||
func (u *IdentityAdoptionDecisionUpsertOne) IDX(ctx context.Context) int64 {
|
||||
id, err := u.ID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionCreateBulk is the builder for creating many IdentityAdoptionDecision entities in bulk.
|
||||
type IdentityAdoptionDecisionCreateBulk struct {
|
||||
config
|
||||
err error
|
||||
builders []*IdentityAdoptionDecisionCreate
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// Save creates the IdentityAdoptionDecision entities in the database.
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) Save(ctx context.Context) ([]*IdentityAdoptionDecision, error) {
|
||||
if _c.err != nil {
|
||||
return nil, _c.err
|
||||
}
|
||||
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
|
||||
nodes := make([]*IdentityAdoptionDecision, len(_c.builders))
|
||||
mutators := make([]Mutator, len(_c.builders))
|
||||
for i := range _c.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := _c.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*IdentityAdoptionDecisionMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err := builder.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.mutation = mutation
|
||||
var err error
|
||||
nodes[i], specs[i] = builder.createSpec()
|
||||
if i < len(mutators)-1 {
|
||||
_, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
spec.OnConflict = _c.conflict
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &nodes[i].ID
|
||||
if specs[i].ID.Value != nil {
|
||||
id := specs[i].ID.Value.(int64)
|
||||
nodes[i].ID = int64(id)
|
||||
}
|
||||
mutation.done = true
|
||||
return nodes[i], nil
|
||||
})
|
||||
for i := len(builder.hooks) - 1; i >= 0; i-- {
|
||||
mut = builder.hooks[i](mut)
|
||||
}
|
||||
mutators[i] = mut
|
||||
}(i, ctx)
|
||||
}
|
||||
if len(mutators) > 0 {
|
||||
if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) SaveX(ctx context.Context) []*IdentityAdoptionDecision {
|
||||
v, err := _c.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := _c.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := _c.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.CreateBulk(builders...).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.IdentityAdoptionDecisionUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) OnConflict(opts ...sql.ConflictOption) *IdentityAdoptionDecisionUpsertBulk {
|
||||
_c.conflict = opts
|
||||
return &IdentityAdoptionDecisionUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (_c *IdentityAdoptionDecisionCreateBulk) OnConflictColumns(columns ...string) *IdentityAdoptionDecisionUpsertBulk {
|
||||
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
|
||||
return &IdentityAdoptionDecisionUpsertBulk{
|
||||
create: _c,
|
||||
}
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionUpsertBulk is the builder for "upsert"-ing
|
||||
// a bulk of IdentityAdoptionDecision nodes.
|
||||
type IdentityAdoptionDecisionUpsertBulk struct {
|
||||
create *IdentityAdoptionDecisionCreateBulk
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that
|
||||
// were set on create. Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdateNewValues() *IdentityAdoptionDecisionUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
for _, b := range u.create.builders {
|
||||
if _, exists := b.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(identityadoptiondecision.FieldCreatedAt)
|
||||
}
|
||||
if _, exists := b.mutation.DecidedAt(); exists {
|
||||
s.SetIgnore(identityadoptiondecision.FieldDecidedAt)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) Ignore() *IdentityAdoptionDecisionUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) DoNothing() *IdentityAdoptionDecisionUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the IdentityAdoptionDecisionCreateBulk.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) Update(set func(*IdentityAdoptionDecisionUpsert)) *IdentityAdoptionDecisionUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&IdentityAdoptionDecisionUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdateUpdatedAt() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetPendingAuthSessionID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatePendingAuthSessionID sets the "pending_auth_session_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdatePendingAuthSessionID() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdatePendingAuthSessionID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) SetIdentityID(v int64) *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetIdentityID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateIdentityID sets the "identity_id" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdateIdentityID() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearIdentityID clears the value of the "identity_id" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) ClearIdentityID() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.ClearIdentityID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetAdoptDisplayName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAdoptDisplayName sets the "adopt_display_name" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdateAdoptDisplayName() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateAdoptDisplayName()
|
||||
})
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.SetAdoptAvatar(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAdoptAvatar sets the "adopt_avatar" field to the value that was provided on create.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) UpdateAdoptAvatar() *IdentityAdoptionDecisionUpsertBulk {
|
||||
return u.Update(func(s *IdentityAdoptionDecisionUpsert) {
|
||||
s.UpdateAdoptAvatar()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
return u.create.err
|
||||
}
|
||||
for i, b := range u.create.builders {
|
||||
if len(b.conflict) != 0 {
|
||||
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the IdentityAdoptionDecisionCreateBulk instead", i)
|
||||
}
|
||||
}
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for IdentityAdoptionDecisionCreateBulk.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *IdentityAdoptionDecisionUpsertBulk) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
88
backend/ent/identityadoptiondecision_delete.go
Normal file
88
backend/ent/identityadoptiondecision_delete.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecisionDelete is the builder for deleting a IdentityAdoptionDecision entity.
|
||||
type IdentityAdoptionDecisionDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *IdentityAdoptionDecisionMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the IdentityAdoptionDecisionDelete builder.
|
||||
func (_d *IdentityAdoptionDecisionDelete) Where(ps ...predicate.IdentityAdoptionDecision) *IdentityAdoptionDecisionDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *IdentityAdoptionDecisionDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *IdentityAdoptionDecisionDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *IdentityAdoptionDecisionDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(identityadoptiondecision.Table, sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionDeleteOne is the builder for deleting a single IdentityAdoptionDecision entity.
|
||||
type IdentityAdoptionDecisionDeleteOne struct {
|
||||
_d *IdentityAdoptionDecisionDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the IdentityAdoptionDecisionDelete builder.
|
||||
func (_d *IdentityAdoptionDecisionDeleteOne) Where(ps ...predicate.IdentityAdoptionDecision) *IdentityAdoptionDecisionDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *IdentityAdoptionDecisionDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{identityadoptiondecision.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *IdentityAdoptionDecisionDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
721
backend/ent/identityadoptiondecision_query.go
Normal file
721
backend/ent/identityadoptiondecision_query.go
Normal file
@ -0,0 +1,721 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecisionQuery is the builder for querying IdentityAdoptionDecision entities.
|
||||
type IdentityAdoptionDecisionQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []identityadoptiondecision.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.IdentityAdoptionDecision
|
||||
withPendingAuthSession *PendingAuthSessionQuery
|
||||
withIdentity *AuthIdentityQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the IdentityAdoptionDecisionQuery builder.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Where(ps ...predicate.IdentityAdoptionDecision) *IdentityAdoptionDecisionQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Limit(limit int) *IdentityAdoptionDecisionQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Offset(offset int) *IdentityAdoptionDecisionQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Unique(unique bool) *IdentityAdoptionDecisionQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Order(o ...identityadoptiondecision.OrderOption) *IdentityAdoptionDecisionQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryPendingAuthSession chains the current query on the "pending_auth_session" edge.
|
||||
func (_q *IdentityAdoptionDecisionQuery) QueryPendingAuthSession() *PendingAuthSessionQuery {
|
||||
query := (&PendingAuthSessionClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(identityadoptiondecision.Table, identityadoptiondecision.FieldID, selector),
|
||||
sqlgraph.To(pendingauthsession.Table, pendingauthsession.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, true, identityadoptiondecision.PendingAuthSessionTable, identityadoptiondecision.PendingAuthSessionColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryIdentity chains the current query on the "identity" edge.
|
||||
func (_q *IdentityAdoptionDecisionQuery) QueryIdentity() *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(identityadoptiondecision.Table, identityadoptiondecision.FieldID, selector),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, identityadoptiondecision.IdentityTable, identityadoptiondecision.IdentityColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first IdentityAdoptionDecision entity from the query.
|
||||
// Returns a *NotFoundError when no IdentityAdoptionDecision was found.
|
||||
func (_q *IdentityAdoptionDecisionQuery) First(ctx context.Context) (*IdentityAdoptionDecision, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{identityadoptiondecision.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) FirstX(ctx context.Context) *IdentityAdoptionDecision {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first IdentityAdoptionDecision ID from the query.
|
||||
// Returns a *NotFoundError when no IdentityAdoptionDecision ID was found.
|
||||
func (_q *IdentityAdoptionDecisionQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{identityadoptiondecision.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single IdentityAdoptionDecision entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one IdentityAdoptionDecision entity is found.
|
||||
// Returns a *NotFoundError when no IdentityAdoptionDecision entities are found.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Only(ctx context.Context) (*IdentityAdoptionDecision, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{identityadoptiondecision.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{identityadoptiondecision.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) OnlyX(ctx context.Context) *IdentityAdoptionDecision {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only IdentityAdoptionDecision ID in the query.
|
||||
// Returns a *NotSingularError when more than one IdentityAdoptionDecision ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *IdentityAdoptionDecisionQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{identityadoptiondecision.Label}
|
||||
default:
|
||||
err = &NotSingularError{identityadoptiondecision.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of IdentityAdoptionDecisions.
|
||||
func (_q *IdentityAdoptionDecisionQuery) All(ctx context.Context) ([]*IdentityAdoptionDecision, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*IdentityAdoptionDecision, *IdentityAdoptionDecisionQuery]()
|
||||
return withInterceptors[[]*IdentityAdoptionDecision](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) AllX(ctx context.Context) []*IdentityAdoptionDecision {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of IdentityAdoptionDecision IDs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(identityadoptiondecision.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*IdentityAdoptionDecisionQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *IdentityAdoptionDecisionQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the IdentityAdoptionDecisionQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Clone() *IdentityAdoptionDecisionQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &IdentityAdoptionDecisionQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]identityadoptiondecision.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.IdentityAdoptionDecision{}, _q.predicates...),
|
||||
withPendingAuthSession: _q.withPendingAuthSession.Clone(),
|
||||
withIdentity: _q.withIdentity.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithPendingAuthSession tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "pending_auth_session" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *IdentityAdoptionDecisionQuery) WithPendingAuthSession(opts ...func(*PendingAuthSessionQuery)) *IdentityAdoptionDecisionQuery {
|
||||
query := (&PendingAuthSessionClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withPendingAuthSession = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithIdentity tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "identity" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *IdentityAdoptionDecisionQuery) WithIdentity(opts ...func(*AuthIdentityQuery)) *IdentityAdoptionDecisionQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withIdentity = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Query().
|
||||
// GroupBy(identityadoptiondecision.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *IdentityAdoptionDecisionQuery) GroupBy(field string, fields ...string) *IdentityAdoptionDecisionGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &IdentityAdoptionDecisionGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = identityadoptiondecision.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.IdentityAdoptionDecision.Query().
|
||||
// Select(identityadoptiondecision.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *IdentityAdoptionDecisionQuery) Select(fields ...string) *IdentityAdoptionDecisionSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &IdentityAdoptionDecisionSelect{IdentityAdoptionDecisionQuery: _q}
|
||||
sbuild.label = identityadoptiondecision.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a IdentityAdoptionDecisionSelect configured with the given aggregations.
|
||||
func (_q *IdentityAdoptionDecisionQuery) Aggregate(fns ...AggregateFunc) *IdentityAdoptionDecisionSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !identityadoptiondecision.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*IdentityAdoptionDecision, error) {
|
||||
var (
|
||||
nodes = []*IdentityAdoptionDecision{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [2]bool{
|
||||
_q.withPendingAuthSession != nil,
|
||||
_q.withIdentity != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*IdentityAdoptionDecision).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &IdentityAdoptionDecision{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withPendingAuthSession; query != nil {
|
||||
if err := _q.loadPendingAuthSession(ctx, query, nodes, nil,
|
||||
func(n *IdentityAdoptionDecision, e *PendingAuthSession) { n.Edges.PendingAuthSession = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withIdentity; query != nil {
|
||||
if err := _q.loadIdentity(ctx, query, nodes, nil,
|
||||
func(n *IdentityAdoptionDecision, e *AuthIdentity) { n.Edges.Identity = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) loadPendingAuthSession(ctx context.Context, query *PendingAuthSessionQuery, nodes []*IdentityAdoptionDecision, init func(*IdentityAdoptionDecision), assign func(*IdentityAdoptionDecision, *PendingAuthSession)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*IdentityAdoptionDecision)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].PendingAuthSessionID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(pendingauthsession.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "pending_auth_session_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *IdentityAdoptionDecisionQuery) loadIdentity(ctx context.Context, query *AuthIdentityQuery, nodes []*IdentityAdoptionDecision, init func(*IdentityAdoptionDecision), assign func(*IdentityAdoptionDecision, *AuthIdentity)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*IdentityAdoptionDecision)
|
||||
for i := range nodes {
|
||||
if nodes[i].IdentityID == nil {
|
||||
continue
|
||||
}
|
||||
fk := *nodes[i].IdentityID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(authidentity.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "identity_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(identityadoptiondecision.Table, identityadoptiondecision.Columns, sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, identityadoptiondecision.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != identityadoptiondecision.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if _q.withPendingAuthSession != nil {
|
||||
_spec.Node.AddColumnOnce(identityadoptiondecision.FieldPendingAuthSessionID)
|
||||
}
|
||||
if _q.withIdentity != nil {
|
||||
_spec.Node.AddColumnOnce(identityadoptiondecision.FieldIdentityID)
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *IdentityAdoptionDecisionQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(identityadoptiondecision.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = identityadoptiondecision.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *IdentityAdoptionDecisionQuery) ForUpdate(opts ...sql.LockOption) *IdentityAdoptionDecisionQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *IdentityAdoptionDecisionQuery) ForShare(opts ...sql.LockOption) *IdentityAdoptionDecisionQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionGroupBy is the group-by builder for IdentityAdoptionDecision entities.
|
||||
type IdentityAdoptionDecisionGroupBy struct {
|
||||
selector
|
||||
build *IdentityAdoptionDecisionQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *IdentityAdoptionDecisionGroupBy) Aggregate(fns ...AggregateFunc) *IdentityAdoptionDecisionGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *IdentityAdoptionDecisionGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*IdentityAdoptionDecisionQuery, *IdentityAdoptionDecisionGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *IdentityAdoptionDecisionGroupBy) sqlScan(ctx context.Context, root *IdentityAdoptionDecisionQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionSelect is the builder for selecting fields of IdentityAdoptionDecision entities.
|
||||
type IdentityAdoptionDecisionSelect struct {
|
||||
*IdentityAdoptionDecisionQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *IdentityAdoptionDecisionSelect) Aggregate(fns ...AggregateFunc) *IdentityAdoptionDecisionSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *IdentityAdoptionDecisionSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*IdentityAdoptionDecisionQuery, *IdentityAdoptionDecisionSelect](ctx, _s.IdentityAdoptionDecisionQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *IdentityAdoptionDecisionSelect) sqlScan(ctx context.Context, root *IdentityAdoptionDecisionQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
532
backend/ent/identityadoptiondecision_update.go
Normal file
532
backend/ent/identityadoptiondecision_update.go
Normal file
@ -0,0 +1,532 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecisionUpdate is the builder for updating IdentityAdoptionDecision entities.
|
||||
type IdentityAdoptionDecisionUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *IdentityAdoptionDecisionMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the IdentityAdoptionDecisionUpdate builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) Where(ps ...predicate.IdentityAdoptionDecision) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.SetPendingAuthSessionID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePendingAuthSessionID sets the "pending_auth_session_id" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetNillablePendingAuthSessionID(v *int64) *IdentityAdoptionDecisionUpdate {
|
||||
if v != nil {
|
||||
_u.SetPendingAuthSessionID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetIdentityID(v int64) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.SetIdentityID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIdentityID sets the "identity_id" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetNillableIdentityID(v *int64) *IdentityAdoptionDecisionUpdate {
|
||||
if v != nil {
|
||||
_u.SetIdentityID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIdentityID clears the value of the "identity_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) ClearIdentityID() *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.ClearIdentityID()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.SetAdoptDisplayName(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAdoptDisplayName sets the "adopt_display_name" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetNillableAdoptDisplayName(v *bool) *IdentityAdoptionDecisionUpdate {
|
||||
if v != nil {
|
||||
_u.SetAdoptDisplayName(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.SetAdoptAvatar(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAdoptAvatar sets the "adopt_avatar" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetNillableAdoptAvatar(v *bool) *IdentityAdoptionDecisionUpdate {
|
||||
if v != nil {
|
||||
_u.SetAdoptAvatar(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPendingAuthSession sets the "pending_auth_session" edge to the PendingAuthSession entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetPendingAuthSession(v *PendingAuthSession) *IdentityAdoptionDecisionUpdate {
|
||||
return _u.SetPendingAuthSessionID(v.ID)
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SetIdentity(v *AuthIdentity) *IdentityAdoptionDecisionUpdate {
|
||||
return _u.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the IdentityAdoptionDecisionMutation object of the builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) Mutation() *IdentityAdoptionDecisionMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearPendingAuthSession clears the "pending_auth_session" edge to the PendingAuthSession entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) ClearPendingAuthSession() *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.ClearPendingAuthSession()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIdentity clears the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) ClearIdentity() *IdentityAdoptionDecisionUpdate {
|
||||
_u.mutation.ClearIdentity()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) Save(ctx context.Context) (int, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := identityadoptiondecision.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdate) check() error {
|
||||
if _u.mutation.PendingAuthSessionCleared() && len(_u.mutation.PendingAuthSessionIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "IdentityAdoptionDecision.pending_auth_session"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *IdentityAdoptionDecisionUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(identityadoptiondecision.Table, identityadoptiondecision.Columns, sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64))
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AdoptDisplayName(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptDisplayName, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AdoptAvatar(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptAvatar, field.TypeBool, value)
|
||||
}
|
||||
if _u.mutation.PendingAuthSessionCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.PendingAuthSessionTable,
|
||||
Columns: []string{identityadoptiondecision.PendingAuthSessionColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.PendingAuthSessionIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.PendingAuthSessionTable,
|
||||
Columns: []string{identityadoptiondecision.PendingAuthSessionColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.IdentityCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.IdentityTable,
|
||||
Columns: []string{identityadoptiondecision.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.IdentityTable,
|
||||
Columns: []string{identityadoptiondecision.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{identityadoptiondecision.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
// IdentityAdoptionDecisionUpdateOne is the builder for updating a single IdentityAdoptionDecision entity.
|
||||
type IdentityAdoptionDecisionUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *IdentityAdoptionDecisionMutation
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetUpdatedAt(v time.Time) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPendingAuthSessionID sets the "pending_auth_session_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetPendingAuthSessionID(v int64) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.SetPendingAuthSessionID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillablePendingAuthSessionID sets the "pending_auth_session_id" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetNillablePendingAuthSessionID(v *int64) *IdentityAdoptionDecisionUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetPendingAuthSessionID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetIdentityID sets the "identity_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetIdentityID(v int64) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.SetIdentityID(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableIdentityID sets the "identity_id" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetNillableIdentityID(v *int64) *IdentityAdoptionDecisionUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetIdentityID(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIdentityID clears the value of the "identity_id" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) ClearIdentityID() *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.ClearIdentityID()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAdoptDisplayName sets the "adopt_display_name" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetAdoptDisplayName(v bool) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.SetAdoptDisplayName(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAdoptDisplayName sets the "adopt_display_name" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetNillableAdoptDisplayName(v *bool) *IdentityAdoptionDecisionUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetAdoptDisplayName(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetAdoptAvatar sets the "adopt_avatar" field.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetAdoptAvatar(v bool) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.SetAdoptAvatar(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableAdoptAvatar sets the "adopt_avatar" field if the given value is not nil.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetNillableAdoptAvatar(v *bool) *IdentityAdoptionDecisionUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetAdoptAvatar(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetPendingAuthSession sets the "pending_auth_session" edge to the PendingAuthSession entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetPendingAuthSession(v *PendingAuthSession) *IdentityAdoptionDecisionUpdateOne {
|
||||
return _u.SetPendingAuthSessionID(v.ID)
|
||||
}
|
||||
|
||||
// SetIdentity sets the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SetIdentity(v *AuthIdentity) *IdentityAdoptionDecisionUpdateOne {
|
||||
return _u.SetIdentityID(v.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the IdentityAdoptionDecisionMutation object of the builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) Mutation() *IdentityAdoptionDecisionMutation {
|
||||
return _u.mutation
|
||||
}
|
||||
|
||||
// ClearPendingAuthSession clears the "pending_auth_session" edge to the PendingAuthSession entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) ClearPendingAuthSession() *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.ClearPendingAuthSession()
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearIdentity clears the "identity" edge to the AuthIdentity entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) ClearIdentity() *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.ClearIdentity()
|
||||
return _u
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the IdentityAdoptionDecisionUpdate builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) Where(ps ...predicate.IdentityAdoptionDecision) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) Select(field string, fields ...string) *IdentityAdoptionDecisionUpdateOne {
|
||||
_u.fields = append([]string{field}, fields...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated IdentityAdoptionDecision entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) Save(ctx context.Context) (*IdentityAdoptionDecision, error) {
|
||||
_u.defaults()
|
||||
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) SaveX(ctx context.Context) *IdentityAdoptionDecision {
|
||||
node, err := _u.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := _u.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := _u.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) defaults() {
|
||||
if _, ok := _u.mutation.UpdatedAt(); !ok {
|
||||
v := identityadoptiondecision.UpdateDefaultUpdatedAt()
|
||||
_u.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) check() error {
|
||||
if _u.mutation.PendingAuthSessionCleared() && len(_u.mutation.PendingAuthSessionIDs()) > 0 {
|
||||
return errors.New(`ent: clearing a required unique edge "IdentityAdoptionDecision.pending_auth_session"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_u *IdentityAdoptionDecisionUpdateOne) sqlSave(ctx context.Context) (_node *IdentityAdoptionDecision, err error) {
|
||||
if err := _u.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(identityadoptiondecision.Table, identityadoptiondecision.Columns, sqlgraph.NewFieldSpec(identityadoptiondecision.FieldID, field.TypeInt64))
|
||||
id, ok := _u.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "IdentityAdoptionDecision.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := _u.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, identityadoptiondecision.FieldID)
|
||||
for _, f := range fields {
|
||||
if !identityadoptiondecision.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != identityadoptiondecision.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := _u.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := _u.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AdoptDisplayName(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptDisplayName, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := _u.mutation.AdoptAvatar(); ok {
|
||||
_spec.SetField(identityadoptiondecision.FieldAdoptAvatar, field.TypeBool, value)
|
||||
}
|
||||
if _u.mutation.PendingAuthSessionCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.PendingAuthSessionTable,
|
||||
Columns: []string{identityadoptiondecision.PendingAuthSessionColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.PendingAuthSessionIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.PendingAuthSessionTable,
|
||||
Columns: []string{identityadoptiondecision.PendingAuthSessionColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.IdentityCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.IdentityTable,
|
||||
Columns: []string{identityadoptiondecision.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.IdentityIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: identityadoptiondecision.IdentityTable,
|
||||
Columns: []string{identityadoptiondecision.IdentityColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &IdentityAdoptionDecision{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{identityadoptiondecision.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
_u.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
@ -13,12 +13,16 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
@ -228,6 +232,60 @@ func (f TraverseAnnouncementRead) Traverse(ctx context.Context, q ent.Query) err
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AnnouncementReadQuery", q)
|
||||
}
|
||||
|
||||
// The AuthIdentityFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type AuthIdentityFunc func(context.Context, *ent.AuthIdentityQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f AuthIdentityFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.AuthIdentityQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.AuthIdentityQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseAuthIdentity type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseAuthIdentity func(context.Context, *ent.AuthIdentityQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseAuthIdentity) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseAuthIdentity) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.AuthIdentityQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AuthIdentityQuery", q)
|
||||
}
|
||||
|
||||
// The AuthIdentityChannelFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type AuthIdentityChannelFunc func(context.Context, *ent.AuthIdentityChannelQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f AuthIdentityChannelFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.AuthIdentityChannelQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.AuthIdentityChannelQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseAuthIdentityChannel type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseAuthIdentityChannel func(context.Context, *ent.AuthIdentityChannelQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseAuthIdentityChannel) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseAuthIdentityChannel) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.AuthIdentityChannelQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.AuthIdentityChannelQuery", q)
|
||||
}
|
||||
|
||||
// The ErrorPassthroughRuleFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type ErrorPassthroughRuleFunc func(context.Context, *ent.ErrorPassthroughRuleQuery) (ent.Value, error)
|
||||
|
||||
@ -309,6 +367,33 @@ func (f TraverseIdempotencyRecord) Traverse(ctx context.Context, q ent.Query) er
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.IdempotencyRecordQuery", q)
|
||||
}
|
||||
|
||||
// The IdentityAdoptionDecisionFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type IdentityAdoptionDecisionFunc func(context.Context, *ent.IdentityAdoptionDecisionQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f IdentityAdoptionDecisionFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.IdentityAdoptionDecisionQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.IdentityAdoptionDecisionQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseIdentityAdoptionDecision type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseIdentityAdoptionDecision func(context.Context, *ent.IdentityAdoptionDecisionQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseIdentityAdoptionDecision) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseIdentityAdoptionDecision) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.IdentityAdoptionDecisionQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.IdentityAdoptionDecisionQuery", q)
|
||||
}
|
||||
|
||||
// The PaymentAuditLogFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type PaymentAuditLogFunc func(context.Context, *ent.PaymentAuditLogQuery) (ent.Value, error)
|
||||
|
||||
@ -390,6 +475,33 @@ func (f TraversePaymentProviderInstance) Traverse(ctx context.Context, q ent.Que
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.PaymentProviderInstanceQuery", q)
|
||||
}
|
||||
|
||||
// The PendingAuthSessionFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type PendingAuthSessionFunc func(context.Context, *ent.PendingAuthSessionQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f PendingAuthSessionFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.PendingAuthSessionQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.PendingAuthSessionQuery", q)
|
||||
}
|
||||
|
||||
// The TraversePendingAuthSession type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraversePendingAuthSession func(context.Context, *ent.PendingAuthSessionQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraversePendingAuthSession) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraversePendingAuthSession) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.PendingAuthSessionQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.PendingAuthSessionQuery", q)
|
||||
}
|
||||
|
||||
// The PromoCodeFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type PromoCodeFunc func(context.Context, *ent.PromoCodeQuery) (ent.Value, error)
|
||||
|
||||
@ -808,18 +920,26 @@ func NewQuery(q ent.Query) (Query, error) {
|
||||
return &query[*ent.AnnouncementQuery, predicate.Announcement, announcement.OrderOption]{typ: ent.TypeAnnouncement, tq: q}, nil
|
||||
case *ent.AnnouncementReadQuery:
|
||||
return &query[*ent.AnnouncementReadQuery, predicate.AnnouncementRead, announcementread.OrderOption]{typ: ent.TypeAnnouncementRead, tq: q}, nil
|
||||
case *ent.AuthIdentityQuery:
|
||||
return &query[*ent.AuthIdentityQuery, predicate.AuthIdentity, authidentity.OrderOption]{typ: ent.TypeAuthIdentity, tq: q}, nil
|
||||
case *ent.AuthIdentityChannelQuery:
|
||||
return &query[*ent.AuthIdentityChannelQuery, predicate.AuthIdentityChannel, authidentitychannel.OrderOption]{typ: ent.TypeAuthIdentityChannel, tq: q}, nil
|
||||
case *ent.ErrorPassthroughRuleQuery:
|
||||
return &query[*ent.ErrorPassthroughRuleQuery, predicate.ErrorPassthroughRule, errorpassthroughrule.OrderOption]{typ: ent.TypeErrorPassthroughRule, tq: q}, nil
|
||||
case *ent.GroupQuery:
|
||||
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
|
||||
case *ent.IdempotencyRecordQuery:
|
||||
return &query[*ent.IdempotencyRecordQuery, predicate.IdempotencyRecord, idempotencyrecord.OrderOption]{typ: ent.TypeIdempotencyRecord, tq: q}, nil
|
||||
case *ent.IdentityAdoptionDecisionQuery:
|
||||
return &query[*ent.IdentityAdoptionDecisionQuery, predicate.IdentityAdoptionDecision, identityadoptiondecision.OrderOption]{typ: ent.TypeIdentityAdoptionDecision, tq: q}, nil
|
||||
case *ent.PaymentAuditLogQuery:
|
||||
return &query[*ent.PaymentAuditLogQuery, predicate.PaymentAuditLog, paymentauditlog.OrderOption]{typ: ent.TypePaymentAuditLog, tq: q}, nil
|
||||
case *ent.PaymentOrderQuery:
|
||||
return &query[*ent.PaymentOrderQuery, predicate.PaymentOrder, paymentorder.OrderOption]{typ: ent.TypePaymentOrder, tq: q}, nil
|
||||
case *ent.PaymentProviderInstanceQuery:
|
||||
return &query[*ent.PaymentProviderInstanceQuery, predicate.PaymentProviderInstance, paymentproviderinstance.OrderOption]{typ: ent.TypePaymentProviderInstance, tq: q}, nil
|
||||
case *ent.PendingAuthSessionQuery:
|
||||
return &query[*ent.PendingAuthSessionQuery, predicate.PendingAuthSession, pendingauthsession.OrderOption]{typ: ent.TypePendingAuthSession, tq: q}, nil
|
||||
case *ent.PromoCodeQuery:
|
||||
return &query[*ent.PromoCodeQuery, predicate.PromoCode, promocode.OrderOption]{typ: ent.TypePromoCode, tq: q}, nil
|
||||
case *ent.PromoCodeUsageQuery:
|
||||
|
||||
73
backend/ent/migrate/auth_identity_fk_ondelete_test.go
Normal file
73
backend/ent/migrate/auth_identity_fk_ondelete_test.go
Normal file
@ -0,0 +1,73 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
entschema "entgo.io/ent/dialect/sql/schema"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthIdentityFoundationForeignKeyOnDeleteActions(t *testing.T) {
|
||||
require.Equal(
|
||||
t,
|
||||
entschema.Cascade,
|
||||
findForeignKeyBySymbol(t, AuthIdentitiesTable, "auth_identities_users_auth_identities").OnDelete,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
entschema.Cascade,
|
||||
findForeignKeyBySymbol(t, AuthIdentityChannelsTable, "auth_identity_channels_auth_identities_channels").OnDelete,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
entschema.Cascade,
|
||||
findForeignKeyBySymbol(t, IdentityAdoptionDecisionsTable, "identity_adoption_decisions_pending_auth_sessions_adoption_decision").OnDelete,
|
||||
)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
entschema.SetNull,
|
||||
findForeignKeyBySymbol(t, PendingAuthSessionsTable, "pending_auth_sessions_users_pending_auth_sessions").OnDelete,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
entschema.SetNull,
|
||||
findForeignKeyBySymbol(t, IdentityAdoptionDecisionsTable, "identity_adoption_decisions_auth_identities_adoption_decisions").OnDelete,
|
||||
)
|
||||
}
|
||||
|
||||
func TestPaymentOrdersOutTradeNoPartialUniqueIndex(t *testing.T) {
|
||||
idx := findIndexByName(t, PaymentOrdersTable, "paymentorder_out_trade_no")
|
||||
require.True(t, idx.Unique)
|
||||
require.Len(t, idx.Columns, 1)
|
||||
require.Equal(t, "out_trade_no", idx.Columns[0].Name)
|
||||
require.NotNil(t, idx.Annotation)
|
||||
require.Equal(t, (&entsql.IndexAnnotation{Where: "out_trade_no <> ''"}).Where, idx.Annotation.Where)
|
||||
}
|
||||
|
||||
func findForeignKeyBySymbol(t *testing.T, table *entschema.Table, symbol string) *entschema.ForeignKey {
|
||||
t.Helper()
|
||||
|
||||
for _, fk := range table.ForeignKeys {
|
||||
if fk.Symbol == symbol {
|
||||
return fk
|
||||
}
|
||||
}
|
||||
|
||||
require.Failf(t, "missing foreign key", "table %s should include foreign key %s", table.Name, symbol)
|
||||
return nil
|
||||
}
|
||||
|
||||
func findIndexByName(t *testing.T, table *entschema.Table, name string) *entschema.Index {
|
||||
t.Helper()
|
||||
|
||||
for _, idx := range table.Indexes {
|
||||
if idx.Name == name {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
|
||||
require.Failf(t, "missing index", "table %s should include index %s", table.Name, name)
|
||||
return nil
|
||||
}
|
||||
@ -338,6 +338,89 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
// AuthIdentitiesColumns holds the columns for the "auth_identities" table.
|
||||
AuthIdentitiesColumns = []*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: "provider_type", Type: field.TypeString, Size: 20},
|
||||
{Name: "provider_key", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "provider_subject", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "verified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "issuer", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "metadata", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "user_id", Type: field.TypeInt64},
|
||||
}
|
||||
// AuthIdentitiesTable holds the schema information for the "auth_identities" table.
|
||||
AuthIdentitiesTable = &schema.Table{
|
||||
Name: "auth_identities",
|
||||
Columns: AuthIdentitiesColumns,
|
||||
PrimaryKey: []*schema.Column{AuthIdentitiesColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "auth_identities_users_auth_identities",
|
||||
Columns: []*schema.Column{AuthIdentitiesColumns[9]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "authidentity_provider_type_provider_key_provider_subject",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{AuthIdentitiesColumns[3], AuthIdentitiesColumns[4], AuthIdentitiesColumns[5]},
|
||||
},
|
||||
{
|
||||
Name: "authidentity_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AuthIdentitiesColumns[9]},
|
||||
},
|
||||
{
|
||||
Name: "authidentity_user_id_provider_type",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AuthIdentitiesColumns[9], AuthIdentitiesColumns[3]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// AuthIdentityChannelsColumns holds the columns for the "auth_identity_channels" table.
|
||||
AuthIdentityChannelsColumns = []*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: "provider_type", Type: field.TypeString, Size: 20},
|
||||
{Name: "provider_key", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "channel", Type: field.TypeString, Size: 20},
|
||||
{Name: "channel_app_id", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "channel_subject", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "metadata", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "identity_id", Type: field.TypeInt64},
|
||||
}
|
||||
// AuthIdentityChannelsTable holds the schema information for the "auth_identity_channels" table.
|
||||
AuthIdentityChannelsTable = &schema.Table{
|
||||
Name: "auth_identity_channels",
|
||||
Columns: AuthIdentityChannelsColumns,
|
||||
PrimaryKey: []*schema.Column{AuthIdentityChannelsColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "auth_identity_channels_auth_identities_channels",
|
||||
Columns: []*schema.Column{AuthIdentityChannelsColumns[9]},
|
||||
RefColumns: []*schema.Column{AuthIdentitiesColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "authidentitychannel_provider_type_provider_key_channel_channel_app_id_channel_subject",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{AuthIdentityChannelsColumns[3], AuthIdentityChannelsColumns[4], AuthIdentityChannelsColumns[5], AuthIdentityChannelsColumns[6], AuthIdentityChannelsColumns[7]},
|
||||
},
|
||||
{
|
||||
Name: "authidentitychannel_identity_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{AuthIdentityChannelsColumns[9]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// ErrorPassthroughRulesColumns holds the columns for the "error_passthrough_rules" table.
|
||||
ErrorPassthroughRulesColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
@ -485,6 +568,49 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
// IdentityAdoptionDecisionsColumns holds the columns for the "identity_adoption_decisions" table.
|
||||
IdentityAdoptionDecisionsColumns = []*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: "adopt_display_name", Type: field.TypeBool, Default: false},
|
||||
{Name: "adopt_avatar", Type: field.TypeBool, Default: false},
|
||||
{Name: "decided_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "identity_id", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "pending_auth_session_id", Type: field.TypeInt64, Unique: true},
|
||||
}
|
||||
// IdentityAdoptionDecisionsTable holds the schema information for the "identity_adoption_decisions" table.
|
||||
IdentityAdoptionDecisionsTable = &schema.Table{
|
||||
Name: "identity_adoption_decisions",
|
||||
Columns: IdentityAdoptionDecisionsColumns,
|
||||
PrimaryKey: []*schema.Column{IdentityAdoptionDecisionsColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "identity_adoption_decisions_auth_identities_adoption_decisions",
|
||||
Columns: []*schema.Column{IdentityAdoptionDecisionsColumns[6]},
|
||||
RefColumns: []*schema.Column{AuthIdentitiesColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
{
|
||||
Symbol: "identity_adoption_decisions_pending_auth_sessions_adoption_decision",
|
||||
Columns: []*schema.Column{IdentityAdoptionDecisionsColumns[7]},
|
||||
RefColumns: []*schema.Column{PendingAuthSessionsColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "identityadoptiondecision_pending_auth_session_id",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{IdentityAdoptionDecisionsColumns[7]},
|
||||
},
|
||||
{
|
||||
Name: "identityadoptiondecision_identity_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{IdentityAdoptionDecisionsColumns[6]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// PaymentAuditLogsColumns holds the columns for the "payment_audit_logs" table.
|
||||
PaymentAuditLogsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
@ -528,6 +654,8 @@ var (
|
||||
{Name: "subscription_group_id", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "subscription_days", Type: field.TypeInt, Nullable: true},
|
||||
{Name: "provider_instance_id", Type: field.TypeString, Nullable: true, Size: 64},
|
||||
{Name: "provider_key", Type: field.TypeString, Nullable: true, Size: 30},
|
||||
{Name: "provider_snapshot", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "status", Type: field.TypeString, Size: 30, Default: "PENDING"},
|
||||
{Name: "refund_amount", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
|
||||
{Name: "refund_reason", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||
@ -556,7 +684,7 @@ var (
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "payment_orders_users_payment_orders",
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[37]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[39]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
},
|
||||
@ -564,38 +692,41 @@ var (
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "paymentorder_out_trade_no",
|
||||
Unique: false,
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[8]},
|
||||
Annotation: &entsql.IndexAnnotation{
|
||||
Where: "out_trade_no <> ''",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[37]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[39]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_status",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[19]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[21]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_expires_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[27]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[29]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_created_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[35]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[37]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_paid_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[28]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[30]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_payment_type_paid_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[9], PaymentOrdersColumns[28]},
|
||||
Columns: []*schema.Column{PaymentOrdersColumns[9], PaymentOrdersColumns[30]},
|
||||
},
|
||||
{
|
||||
Name: "paymentorder_order_type",
|
||||
@ -638,6 +769,72 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
// PendingAuthSessionsColumns holds the columns for the "pending_auth_sessions" table.
|
||||
PendingAuthSessionsColumns = []*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: "session_token", Type: field.TypeString, Size: 255},
|
||||
{Name: "intent", Type: field.TypeString, Size: 40},
|
||||
{Name: "provider_type", Type: field.TypeString, Size: 20},
|
||||
{Name: "provider_key", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "provider_subject", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "redirect_to", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "resolved_email", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "registration_password_hash", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "upstream_identity_claims", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "local_flow_state", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||
{Name: "browser_session_key", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "completion_code_hash", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "completion_code_expires_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "email_verified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "password_verified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "totp_verified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "expires_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "consumed_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "target_user_id", Type: field.TypeInt64, Nullable: true},
|
||||
}
|
||||
// PendingAuthSessionsTable holds the schema information for the "pending_auth_sessions" table.
|
||||
PendingAuthSessionsTable = &schema.Table{
|
||||
Name: "pending_auth_sessions",
|
||||
Columns: PendingAuthSessionsColumns,
|
||||
PrimaryKey: []*schema.Column{PendingAuthSessionsColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "pending_auth_sessions_users_pending_auth_sessions",
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[21]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "pendingauthsession_session_token",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "pendingauthsession_target_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[21]},
|
||||
},
|
||||
{
|
||||
Name: "pendingauthsession_expires_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[19]},
|
||||
},
|
||||
{
|
||||
Name: "pendingauthsession_provider_type_provider_key_provider_subject",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[5], PendingAuthSessionsColumns[6], PendingAuthSessionsColumns[7]},
|
||||
},
|
||||
{
|
||||
Name: "pendingauthsession_completion_code_hash",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{PendingAuthSessionsColumns[14]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// PromoCodesColumns holds the columns for the "promo_codes" table.
|
||||
PromoCodesColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||
@ -1079,6 +1276,9 @@ var (
|
||||
{Name: "totp_secret_encrypted", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
|
||||
{Name: "totp_enabled", Type: field.TypeBool, Default: false},
|
||||
{Name: "totp_enabled_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "signup_source", Type: field.TypeString, Size: 20, Default: "email"},
|
||||
{Name: "last_login_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "last_active_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
|
||||
{Name: "balance_notify_enabled", Type: field.TypeBool, Default: true},
|
||||
{Name: "balance_notify_threshold_type", Type: field.TypeString, Default: "fixed"},
|
||||
{Name: "balance_notify_threshold", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
@ -1318,12 +1518,16 @@ var (
|
||||
AccountGroupsTable,
|
||||
AnnouncementsTable,
|
||||
AnnouncementReadsTable,
|
||||
AuthIdentitiesTable,
|
||||
AuthIdentityChannelsTable,
|
||||
ErrorPassthroughRulesTable,
|
||||
GroupsTable,
|
||||
IdempotencyRecordsTable,
|
||||
IdentityAdoptionDecisionsTable,
|
||||
PaymentAuditLogsTable,
|
||||
PaymentOrdersTable,
|
||||
PaymentProviderInstancesTable,
|
||||
PendingAuthSessionsTable,
|
||||
PromoCodesTable,
|
||||
PromoCodeUsagesTable,
|
||||
ProxiesTable,
|
||||
@ -1365,6 +1569,14 @@ func init() {
|
||||
AnnouncementReadsTable.Annotation = &entsql.Annotation{
|
||||
Table: "announcement_reads",
|
||||
}
|
||||
AuthIdentitiesTable.ForeignKeys[0].RefTable = UsersTable
|
||||
AuthIdentitiesTable.Annotation = &entsql.Annotation{
|
||||
Table: "auth_identities",
|
||||
}
|
||||
AuthIdentityChannelsTable.ForeignKeys[0].RefTable = AuthIdentitiesTable
|
||||
AuthIdentityChannelsTable.Annotation = &entsql.Annotation{
|
||||
Table: "auth_identity_channels",
|
||||
}
|
||||
ErrorPassthroughRulesTable.Annotation = &entsql.Annotation{
|
||||
Table: "error_passthrough_rules",
|
||||
}
|
||||
@ -1374,6 +1586,11 @@ func init() {
|
||||
IdempotencyRecordsTable.Annotation = &entsql.Annotation{
|
||||
Table: "idempotency_records",
|
||||
}
|
||||
IdentityAdoptionDecisionsTable.ForeignKeys[0].RefTable = AuthIdentitiesTable
|
||||
IdentityAdoptionDecisionsTable.ForeignKeys[1].RefTable = PendingAuthSessionsTable
|
||||
IdentityAdoptionDecisionsTable.Annotation = &entsql.Annotation{
|
||||
Table: "identity_adoption_decisions",
|
||||
}
|
||||
PaymentAuditLogsTable.Annotation = &entsql.Annotation{
|
||||
Table: "payment_audit_logs",
|
||||
}
|
||||
@ -1384,6 +1601,10 @@ func init() {
|
||||
PaymentProviderInstancesTable.Annotation = &entsql.Annotation{
|
||||
Table: "payment_provider_instances",
|
||||
}
|
||||
PendingAuthSessionsTable.ForeignKeys[0].RefTable = UsersTable
|
||||
PendingAuthSessionsTable.Annotation = &entsql.Annotation{
|
||||
Table: "pending_auth_sessions",
|
||||
}
|
||||
PromoCodesTable.Annotation = &entsql.Annotation{
|
||||
Table: "promo_codes",
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -56,6 +57,10 @@ type PaymentOrder struct {
|
||||
SubscriptionDays *int `json:"subscription_days,omitempty"`
|
||||
// ProviderInstanceID holds the value of the "provider_instance_id" field.
|
||||
ProviderInstanceID *string `json:"provider_instance_id,omitempty"`
|
||||
// ProviderKey holds the value of the "provider_key" field.
|
||||
ProviderKey *string `json:"provider_key,omitempty"`
|
||||
// ProviderSnapshot holds the value of the "provider_snapshot" field.
|
||||
ProviderSnapshot map[string]interface{} `json:"provider_snapshot,omitempty"`
|
||||
// Status holds the value of the "status" field.
|
||||
Status string `json:"status,omitempty"`
|
||||
// RefundAmount holds the value of the "refund_amount" field.
|
||||
@ -123,13 +128,15 @@ func (*PaymentOrder) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case paymentorder.FieldProviderSnapshot:
|
||||
values[i] = new([]byte)
|
||||
case paymentorder.FieldForceRefund:
|
||||
values[i] = new(sql.NullBool)
|
||||
case paymentorder.FieldAmount, paymentorder.FieldPayAmount, paymentorder.FieldFeeRate, paymentorder.FieldRefundAmount:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
case paymentorder.FieldID, paymentorder.FieldUserID, paymentorder.FieldPlanID, paymentorder.FieldSubscriptionGroupID, paymentorder.FieldSubscriptionDays:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case paymentorder.FieldUserEmail, paymentorder.FieldUserName, paymentorder.FieldUserNotes, paymentorder.FieldRechargeCode, paymentorder.FieldOutTradeNo, paymentorder.FieldPaymentType, paymentorder.FieldPaymentTradeNo, paymentorder.FieldPayURL, paymentorder.FieldQrCode, paymentorder.FieldQrCodeImg, paymentorder.FieldOrderType, paymentorder.FieldProviderInstanceID, paymentorder.FieldStatus, paymentorder.FieldRefundReason, paymentorder.FieldRefundRequestReason, paymentorder.FieldRefundRequestedBy, paymentorder.FieldFailedReason, paymentorder.FieldClientIP, paymentorder.FieldSrcHost, paymentorder.FieldSrcURL:
|
||||
case paymentorder.FieldUserEmail, paymentorder.FieldUserName, paymentorder.FieldUserNotes, paymentorder.FieldRechargeCode, paymentorder.FieldOutTradeNo, paymentorder.FieldPaymentType, paymentorder.FieldPaymentTradeNo, paymentorder.FieldPayURL, paymentorder.FieldQrCode, paymentorder.FieldQrCodeImg, paymentorder.FieldOrderType, paymentorder.FieldProviderInstanceID, paymentorder.FieldProviderKey, paymentorder.FieldStatus, paymentorder.FieldRefundReason, paymentorder.FieldRefundRequestReason, paymentorder.FieldRefundRequestedBy, paymentorder.FieldFailedReason, paymentorder.FieldClientIP, paymentorder.FieldSrcHost, paymentorder.FieldSrcURL:
|
||||
values[i] = new(sql.NullString)
|
||||
case paymentorder.FieldRefundAt, paymentorder.FieldRefundRequestedAt, paymentorder.FieldExpiresAt, paymentorder.FieldPaidAt, paymentorder.FieldCompletedAt, paymentorder.FieldFailedAt, paymentorder.FieldCreatedAt, paymentorder.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
@ -276,6 +283,21 @@ func (_m *PaymentOrder) assignValues(columns []string, values []any) error {
|
||||
_m.ProviderInstanceID = new(string)
|
||||
*_m.ProviderInstanceID = value.String
|
||||
}
|
||||
case paymentorder.FieldProviderKey:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_key", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderKey = new(string)
|
||||
*_m.ProviderKey = value.String
|
||||
}
|
||||
case paymentorder.FieldProviderSnapshot:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_snapshot", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.ProviderSnapshot); err != nil {
|
||||
return fmt.Errorf("unmarshal field provider_snapshot: %w", err)
|
||||
}
|
||||
}
|
||||
case paymentorder.FieldStatus:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field status", values[i])
|
||||
@ -508,6 +530,14 @@ func (_m *PaymentOrder) String() string {
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.ProviderKey; v != nil {
|
||||
builder.WriteString("provider_key=")
|
||||
builder.WriteString(*v)
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_snapshot=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.ProviderSnapshot))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("status=")
|
||||
builder.WriteString(_m.Status)
|
||||
builder.WriteString(", ")
|
||||
|
||||
@ -52,6 +52,10 @@ const (
|
||||
FieldSubscriptionDays = "subscription_days"
|
||||
// FieldProviderInstanceID holds the string denoting the provider_instance_id field in the database.
|
||||
FieldProviderInstanceID = "provider_instance_id"
|
||||
// FieldProviderKey holds the string denoting the provider_key field in the database.
|
||||
FieldProviderKey = "provider_key"
|
||||
// FieldProviderSnapshot holds the string denoting the provider_snapshot field in the database.
|
||||
FieldProviderSnapshot = "provider_snapshot"
|
||||
// FieldStatus holds the string denoting the status field in the database.
|
||||
FieldStatus = "status"
|
||||
// FieldRefundAmount holds the string denoting the refund_amount field in the database.
|
||||
@ -123,6 +127,8 @@ var Columns = []string{
|
||||
FieldSubscriptionGroupID,
|
||||
FieldSubscriptionDays,
|
||||
FieldProviderInstanceID,
|
||||
FieldProviderKey,
|
||||
FieldProviderSnapshot,
|
||||
FieldStatus,
|
||||
FieldRefundAmount,
|
||||
FieldRefundReason,
|
||||
@ -176,6 +182,8 @@ var (
|
||||
OrderTypeValidator func(string) error
|
||||
// ProviderInstanceIDValidator is a validator for the "provider_instance_id" field. It is called by the builders before save.
|
||||
ProviderInstanceIDValidator func(string) error
|
||||
// ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
ProviderKeyValidator func(string) error
|
||||
// DefaultStatus holds the default value on creation for the "status" field.
|
||||
DefaultStatus string
|
||||
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
@ -301,6 +309,11 @@ func ByProviderInstanceID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderInstanceID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderKey orders the results by the provider_key field.
|
||||
func ByProviderKey(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderKey, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByStatus orders the results by the status field.
|
||||
func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
||||
|
||||
@ -150,6 +150,11 @@ func ProviderInstanceID(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEQ(FieldProviderInstanceID, v))
|
||||
}
|
||||
|
||||
// ProviderKey applies equality check predicate on the "provider_key" field. It's identical to ProviderKeyEQ.
|
||||
func ProviderKey(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
|
||||
func Status(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEQ(FieldStatus, v))
|
||||
@ -1360,6 +1365,91 @@ func ProviderInstanceIDContainsFold(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldContainsFold(FieldProviderInstanceID, v))
|
||||
}
|
||||
|
||||
// ProviderKeyEQ applies the EQ predicate on the "provider_key" field.
|
||||
func ProviderKeyEQ(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyNEQ applies the NEQ predicate on the "provider_key" field.
|
||||
func ProviderKeyNEQ(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldNEQ(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyIn applies the In predicate on the "provider_key" field.
|
||||
func ProviderKeyIn(vs ...string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyNotIn applies the NotIn predicate on the "provider_key" field.
|
||||
func ProviderKeyNotIn(vs ...string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldNotIn(FieldProviderKey, vs...))
|
||||
}
|
||||
|
||||
// ProviderKeyGT applies the GT predicate on the "provider_key" field.
|
||||
func ProviderKeyGT(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldGT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyGTE applies the GTE predicate on the "provider_key" field.
|
||||
func ProviderKeyGTE(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldGTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLT applies the LT predicate on the "provider_key" field.
|
||||
func ProviderKeyLT(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldLT(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyLTE applies the LTE predicate on the "provider_key" field.
|
||||
func ProviderKeyLTE(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldLTE(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContains applies the Contains predicate on the "provider_key" field.
|
||||
func ProviderKeyContains(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldContains(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasPrefix applies the HasPrefix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasPrefix(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldHasPrefix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyHasSuffix applies the HasSuffix predicate on the "provider_key" field.
|
||||
func ProviderKeyHasSuffix(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldHasSuffix(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyIsNil applies the IsNil predicate on the "provider_key" field.
|
||||
func ProviderKeyIsNil() predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldIsNull(FieldProviderKey))
|
||||
}
|
||||
|
||||
// ProviderKeyNotNil applies the NotNil predicate on the "provider_key" field.
|
||||
func ProviderKeyNotNil() predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldNotNull(FieldProviderKey))
|
||||
}
|
||||
|
||||
// ProviderKeyEqualFold applies the EqualFold predicate on the "provider_key" field.
|
||||
func ProviderKeyEqualFold(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEqualFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderKeyContainsFold applies the ContainsFold predicate on the "provider_key" field.
|
||||
func ProviderKeyContainsFold(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldContainsFold(FieldProviderKey, v))
|
||||
}
|
||||
|
||||
// ProviderSnapshotIsNil applies the IsNil predicate on the "provider_snapshot" field.
|
||||
func ProviderSnapshotIsNil() predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldIsNull(FieldProviderSnapshot))
|
||||
}
|
||||
|
||||
// ProviderSnapshotNotNil applies the NotNil predicate on the "provider_snapshot" field.
|
||||
func ProviderSnapshotNotNil() predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldNotNull(FieldProviderSnapshot))
|
||||
}
|
||||
|
||||
// StatusEQ applies the EQ predicate on the "status" field.
|
||||
func StatusEQ(v string) predicate.PaymentOrder {
|
||||
return predicate.PaymentOrder(sql.FieldEQ(FieldStatus, v))
|
||||
|
||||
@ -225,6 +225,26 @@ func (_c *PaymentOrderCreate) SetNillableProviderInstanceID(v *string) *PaymentO
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_c *PaymentOrderCreate) SetProviderKey(v string) *PaymentOrderCreate {
|
||||
_c.mutation.SetProviderKey(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_c *PaymentOrderCreate) SetNillableProviderKey(v *string) *PaymentOrderCreate {
|
||||
if v != nil {
|
||||
_c.SetProviderKey(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (_c *PaymentOrderCreate) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderCreate {
|
||||
_c.mutation.SetProviderSnapshot(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (_c *PaymentOrderCreate) SetStatus(v string) *PaymentOrderCreate {
|
||||
_c.mutation.SetStatus(v)
|
||||
@ -602,6 +622,11 @@ func (_c *PaymentOrderCreate) check() error {
|
||||
return &ValidationError{Name: "provider_instance_id", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_instance_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _c.mutation.ProviderKey(); ok {
|
||||
if err := paymentorder.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.Status(); !ok {
|
||||
return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "PaymentOrder.status"`)}
|
||||
}
|
||||
@ -748,6 +773,14 @@ func (_c *PaymentOrderCreate) createSpec() (*PaymentOrder, *sqlgraph.CreateSpec)
|
||||
_spec.SetField(paymentorder.FieldProviderInstanceID, field.TypeString, value)
|
||||
_node.ProviderInstanceID = &value
|
||||
}
|
||||
if value, ok := _c.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderKey, field.TypeString, value)
|
||||
_node.ProviderKey = &value
|
||||
}
|
||||
if value, ok := _c.mutation.ProviderSnapshot(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderSnapshot, field.TypeJSON, value)
|
||||
_node.ProviderSnapshot = value
|
||||
}
|
||||
if value, ok := _c.mutation.Status(); ok {
|
||||
_spec.SetField(paymentorder.FieldStatus, field.TypeString, value)
|
||||
_node.Status = value
|
||||
@ -1201,6 +1234,42 @@ func (u *PaymentOrderUpsert) ClearProviderInstanceID() *PaymentOrderUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *PaymentOrderUpsert) SetProviderKey(v string) *PaymentOrderUpsert {
|
||||
u.Set(paymentorder.FieldProviderKey, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsert) UpdateProviderKey() *PaymentOrderUpsert {
|
||||
u.SetExcluded(paymentorder.FieldProviderKey)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearProviderKey clears the value of the "provider_key" field.
|
||||
func (u *PaymentOrderUpsert) ClearProviderKey() *PaymentOrderUpsert {
|
||||
u.SetNull(paymentorder.FieldProviderKey)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsert) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderUpsert {
|
||||
u.Set(paymentorder.FieldProviderSnapshot, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateProviderSnapshot sets the "provider_snapshot" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsert) UpdateProviderSnapshot() *PaymentOrderUpsert {
|
||||
u.SetExcluded(paymentorder.FieldProviderSnapshot)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearProviderSnapshot clears the value of the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsert) ClearProviderSnapshot() *PaymentOrderUpsert {
|
||||
u.SetNull(paymentorder.FieldProviderSnapshot)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (u *PaymentOrderUpsert) SetStatus(v string) *PaymentOrderUpsert {
|
||||
u.Set(paymentorder.FieldStatus, v)
|
||||
@ -1880,6 +1949,48 @@ func (u *PaymentOrderUpsertOne) ClearProviderInstanceID() *PaymentOrderUpsertOne
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *PaymentOrderUpsertOne) SetProviderKey(v string) *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.SetProviderKey(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsertOne) UpdateProviderKey() *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.UpdateProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearProviderKey clears the value of the "provider_key" field.
|
||||
func (u *PaymentOrderUpsertOne) ClearProviderKey() *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.ClearProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsertOne) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.SetProviderSnapshot(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderSnapshot sets the "provider_snapshot" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsertOne) UpdateProviderSnapshot() *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.UpdateProviderSnapshot()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearProviderSnapshot clears the value of the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsertOne) ClearProviderSnapshot() *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.ClearProviderSnapshot()
|
||||
})
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (u *PaymentOrderUpsertOne) SetStatus(v string) *PaymentOrderUpsertOne {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
@ -2770,6 +2881,48 @@ func (u *PaymentOrderUpsertBulk) ClearProviderInstanceID() *PaymentOrderUpsertBu
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (u *PaymentOrderUpsertBulk) SetProviderKey(v string) *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.SetProviderKey(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderKey sets the "provider_key" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsertBulk) UpdateProviderKey() *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.UpdateProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearProviderKey clears the value of the "provider_key" field.
|
||||
func (u *PaymentOrderUpsertBulk) ClearProviderKey() *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.ClearProviderKey()
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsertBulk) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.SetProviderSnapshot(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateProviderSnapshot sets the "provider_snapshot" field to the value that was provided on create.
|
||||
func (u *PaymentOrderUpsertBulk) UpdateProviderSnapshot() *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.UpdateProviderSnapshot()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearProviderSnapshot clears the value of the "provider_snapshot" field.
|
||||
func (u *PaymentOrderUpsertBulk) ClearProviderSnapshot() *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
s.ClearProviderSnapshot()
|
||||
})
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (u *PaymentOrderUpsertBulk) SetStatus(v string) *PaymentOrderUpsertBulk {
|
||||
return u.Update(func(s *PaymentOrderUpsert) {
|
||||
|
||||
@ -385,6 +385,38 @@ func (_u *PaymentOrderUpdate) ClearProviderInstanceID() *PaymentOrderUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *PaymentOrderUpdate) SetProviderKey(v string) *PaymentOrderUpdate {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *PaymentOrderUpdate) SetNillableProviderKey(v *string) *PaymentOrderUpdate {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearProviderKey clears the value of the "provider_key" field.
|
||||
func (_u *PaymentOrderUpdate) ClearProviderKey() *PaymentOrderUpdate {
|
||||
_u.mutation.ClearProviderKey()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (_u *PaymentOrderUpdate) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderUpdate {
|
||||
_u.mutation.SetProviderSnapshot(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearProviderSnapshot clears the value of the "provider_snapshot" field.
|
||||
func (_u *PaymentOrderUpdate) ClearProviderSnapshot() *PaymentOrderUpdate {
|
||||
_u.mutation.ClearProviderSnapshot()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (_u *PaymentOrderUpdate) SetStatus(v string) *PaymentOrderUpdate {
|
||||
_u.mutation.SetStatus(v)
|
||||
@ -776,6 +808,11 @@ func (_u *PaymentOrderUpdate) check() error {
|
||||
return &ValidationError{Name: "provider_instance_id", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_instance_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := paymentorder.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Status(); ok {
|
||||
if err := paymentorder.StatusValidator(v); err != nil {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.status": %w`, err)}
|
||||
@ -910,6 +947,18 @@ func (_u *PaymentOrderUpdate) sqlSave(ctx context.Context) (_node int, err error
|
||||
if _u.mutation.ProviderInstanceIDCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderInstanceID, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.ProviderKeyCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderKey, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderSnapshot(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderSnapshot, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.ProviderSnapshotCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderSnapshot, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Status(); ok {
|
||||
_spec.SetField(paymentorder.FieldStatus, field.TypeString, value)
|
||||
}
|
||||
@ -1399,6 +1448,38 @@ func (_u *PaymentOrderUpdateOne) ClearProviderInstanceID() *PaymentOrderUpdateOn
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderKey sets the "provider_key" field.
|
||||
func (_u *PaymentOrderUpdateOne) SetProviderKey(v string) *PaymentOrderUpdateOne {
|
||||
_u.mutation.SetProviderKey(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
|
||||
func (_u *PaymentOrderUpdateOne) SetNillableProviderKey(v *string) *PaymentOrderUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetProviderKey(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearProviderKey clears the value of the "provider_key" field.
|
||||
func (_u *PaymentOrderUpdateOne) ClearProviderKey() *PaymentOrderUpdateOne {
|
||||
_u.mutation.ClearProviderKey()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetProviderSnapshot sets the "provider_snapshot" field.
|
||||
func (_u *PaymentOrderUpdateOne) SetProviderSnapshot(v map[string]interface{}) *PaymentOrderUpdateOne {
|
||||
_u.mutation.SetProviderSnapshot(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearProviderSnapshot clears the value of the "provider_snapshot" field.
|
||||
func (_u *PaymentOrderUpdateOne) ClearProviderSnapshot() *PaymentOrderUpdateOne {
|
||||
_u.mutation.ClearProviderSnapshot()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetStatus sets the "status" field.
|
||||
func (_u *PaymentOrderUpdateOne) SetStatus(v string) *PaymentOrderUpdateOne {
|
||||
_u.mutation.SetStatus(v)
|
||||
@ -1803,6 +1884,11 @@ func (_u *PaymentOrderUpdateOne) check() error {
|
||||
return &ValidationError{Name: "provider_instance_id", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_instance_id": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.ProviderKey(); ok {
|
||||
if err := paymentorder.ProviderKeyValidator(v); err != nil {
|
||||
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.provider_key": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.Status(); ok {
|
||||
if err := paymentorder.StatusValidator(v); err != nil {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "PaymentOrder.status": %w`, err)}
|
||||
@ -1954,6 +2040,18 @@ func (_u *PaymentOrderUpdateOne) sqlSave(ctx context.Context) (_node *PaymentOrd
|
||||
if _u.mutation.ProviderInstanceIDCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderInstanceID, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderKey(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderKey, field.TypeString, value)
|
||||
}
|
||||
if _u.mutation.ProviderKeyCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderKey, field.TypeString)
|
||||
}
|
||||
if value, ok := _u.mutation.ProviderSnapshot(); ok {
|
||||
_spec.SetField(paymentorder.FieldProviderSnapshot, field.TypeJSON, value)
|
||||
}
|
||||
if _u.mutation.ProviderSnapshotCleared() {
|
||||
_spec.ClearField(paymentorder.FieldProviderSnapshot, field.TypeJSON)
|
||||
}
|
||||
if value, ok := _u.mutation.Status(); ok {
|
||||
_spec.SetField(paymentorder.FieldStatus, field.TypeString, value)
|
||||
}
|
||||
|
||||
399
backend/ent/pendingauthsession.go
Normal file
399
backend/ent/pendingauthsession.go
Normal file
@ -0,0 +1,399 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// PendingAuthSession is the model entity for the PendingAuthSession schema.
|
||||
type PendingAuthSession struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// SessionToken holds the value of the "session_token" field.
|
||||
SessionToken string `json:"session_token,omitempty"`
|
||||
// Intent holds the value of the "intent" field.
|
||||
Intent string `json:"intent,omitempty"`
|
||||
// ProviderType holds the value of the "provider_type" field.
|
||||
ProviderType string `json:"provider_type,omitempty"`
|
||||
// ProviderKey holds the value of the "provider_key" field.
|
||||
ProviderKey string `json:"provider_key,omitempty"`
|
||||
// ProviderSubject holds the value of the "provider_subject" field.
|
||||
ProviderSubject string `json:"provider_subject,omitempty"`
|
||||
// TargetUserID holds the value of the "target_user_id" field.
|
||||
TargetUserID *int64 `json:"target_user_id,omitempty"`
|
||||
// RedirectTo holds the value of the "redirect_to" field.
|
||||
RedirectTo string `json:"redirect_to,omitempty"`
|
||||
// ResolvedEmail holds the value of the "resolved_email" field.
|
||||
ResolvedEmail string `json:"resolved_email,omitempty"`
|
||||
// RegistrationPasswordHash holds the value of the "registration_password_hash" field.
|
||||
RegistrationPasswordHash string `json:"registration_password_hash,omitempty"`
|
||||
// UpstreamIdentityClaims holds the value of the "upstream_identity_claims" field.
|
||||
UpstreamIdentityClaims map[string]interface{} `json:"upstream_identity_claims,omitempty"`
|
||||
// LocalFlowState holds the value of the "local_flow_state" field.
|
||||
LocalFlowState map[string]interface{} `json:"local_flow_state,omitempty"`
|
||||
// BrowserSessionKey holds the value of the "browser_session_key" field.
|
||||
BrowserSessionKey string `json:"browser_session_key,omitempty"`
|
||||
// CompletionCodeHash holds the value of the "completion_code_hash" field.
|
||||
CompletionCodeHash string `json:"completion_code_hash,omitempty"`
|
||||
// CompletionCodeExpiresAt holds the value of the "completion_code_expires_at" field.
|
||||
CompletionCodeExpiresAt *time.Time `json:"completion_code_expires_at,omitempty"`
|
||||
// EmailVerifiedAt holds the value of the "email_verified_at" field.
|
||||
EmailVerifiedAt *time.Time `json:"email_verified_at,omitempty"`
|
||||
// PasswordVerifiedAt holds the value of the "password_verified_at" field.
|
||||
PasswordVerifiedAt *time.Time `json:"password_verified_at,omitempty"`
|
||||
// TotpVerifiedAt holds the value of the "totp_verified_at" field.
|
||||
TotpVerifiedAt *time.Time `json:"totp_verified_at,omitempty"`
|
||||
// ExpiresAt holds the value of the "expires_at" field.
|
||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||
// ConsumedAt holds the value of the "consumed_at" field.
|
||||
ConsumedAt *time.Time `json:"consumed_at,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the PendingAuthSessionQuery when eager-loading is set.
|
||||
Edges PendingAuthSessionEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// PendingAuthSessionEdges holds the relations/edges for other nodes in the graph.
|
||||
type PendingAuthSessionEdges struct {
|
||||
// TargetUser holds the value of the target_user edge.
|
||||
TargetUser *User `json:"target_user,omitempty"`
|
||||
// AdoptionDecision holds the value of the adoption_decision edge.
|
||||
AdoptionDecision *IdentityAdoptionDecision `json:"adoption_decision,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [2]bool
|
||||
}
|
||||
|
||||
// TargetUserOrErr returns the TargetUser value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e PendingAuthSessionEdges) TargetUserOrErr() (*User, error) {
|
||||
if e.TargetUser != nil {
|
||||
return e.TargetUser, nil
|
||||
} else if e.loadedTypes[0] {
|
||||
return nil, &NotFoundError{label: user.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "target_user"}
|
||||
}
|
||||
|
||||
// AdoptionDecisionOrErr returns the AdoptionDecision value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e PendingAuthSessionEdges) AdoptionDecisionOrErr() (*IdentityAdoptionDecision, error) {
|
||||
if e.AdoptionDecision != nil {
|
||||
return e.AdoptionDecision, nil
|
||||
} else if e.loadedTypes[1] {
|
||||
return nil, &NotFoundError{label: identityadoptiondecision.Label}
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "adoption_decision"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*PendingAuthSession) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case pendingauthsession.FieldUpstreamIdentityClaims, pendingauthsession.FieldLocalFlowState:
|
||||
values[i] = new([]byte)
|
||||
case pendingauthsession.FieldID, pendingauthsession.FieldTargetUserID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case pendingauthsession.FieldSessionToken, pendingauthsession.FieldIntent, pendingauthsession.FieldProviderType, pendingauthsession.FieldProviderKey, pendingauthsession.FieldProviderSubject, pendingauthsession.FieldRedirectTo, pendingauthsession.FieldResolvedEmail, pendingauthsession.FieldRegistrationPasswordHash, pendingauthsession.FieldBrowserSessionKey, pendingauthsession.FieldCompletionCodeHash:
|
||||
values[i] = new(sql.NullString)
|
||||
case pendingauthsession.FieldCreatedAt, pendingauthsession.FieldUpdatedAt, pendingauthsession.FieldCompletionCodeExpiresAt, pendingauthsession.FieldEmailVerifiedAt, pendingauthsession.FieldPasswordVerifiedAt, pendingauthsession.FieldTotpVerifiedAt, pendingauthsession.FieldExpiresAt, pendingauthsession.FieldConsumedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the PendingAuthSession fields.
|
||||
func (_m *PendingAuthSession) assignValues(columns []string, values []any) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case pendingauthsession.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
_m.ID = int64(value.Int64)
|
||||
case pendingauthsession.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CreatedAt = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.UpdatedAt = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldSessionToken:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field session_token", values[i])
|
||||
} else if value.Valid {
|
||||
_m.SessionToken = value.String
|
||||
}
|
||||
case pendingauthsession.FieldIntent:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field intent", values[i])
|
||||
} else if value.Valid {
|
||||
_m.Intent = value.String
|
||||
}
|
||||
case pendingauthsession.FieldProviderType:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_type", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderType = value.String
|
||||
}
|
||||
case pendingauthsession.FieldProviderKey:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_key", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderKey = value.String
|
||||
}
|
||||
case pendingauthsession.FieldProviderSubject:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field provider_subject", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ProviderSubject = value.String
|
||||
}
|
||||
case pendingauthsession.FieldTargetUserID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field target_user_id", values[i])
|
||||
} else if value.Valid {
|
||||
_m.TargetUserID = new(int64)
|
||||
*_m.TargetUserID = value.Int64
|
||||
}
|
||||
case pendingauthsession.FieldRedirectTo:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field redirect_to", values[i])
|
||||
} else if value.Valid {
|
||||
_m.RedirectTo = value.String
|
||||
}
|
||||
case pendingauthsession.FieldResolvedEmail:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field resolved_email", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ResolvedEmail = value.String
|
||||
}
|
||||
case pendingauthsession.FieldRegistrationPasswordHash:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field registration_password_hash", values[i])
|
||||
} else if value.Valid {
|
||||
_m.RegistrationPasswordHash = value.String
|
||||
}
|
||||
case pendingauthsession.FieldUpstreamIdentityClaims:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field upstream_identity_claims", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.UpstreamIdentityClaims); err != nil {
|
||||
return fmt.Errorf("unmarshal field upstream_identity_claims: %w", err)
|
||||
}
|
||||
}
|
||||
case pendingauthsession.FieldLocalFlowState:
|
||||
if value, ok := values[i].(*[]byte); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field local_flow_state", values[i])
|
||||
} else if value != nil && len(*value) > 0 {
|
||||
if err := json.Unmarshal(*value, &_m.LocalFlowState); err != nil {
|
||||
return fmt.Errorf("unmarshal field local_flow_state: %w", err)
|
||||
}
|
||||
}
|
||||
case pendingauthsession.FieldBrowserSessionKey:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field browser_session_key", values[i])
|
||||
} else if value.Valid {
|
||||
_m.BrowserSessionKey = value.String
|
||||
}
|
||||
case pendingauthsession.FieldCompletionCodeHash:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field completion_code_hash", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CompletionCodeHash = value.String
|
||||
}
|
||||
case pendingauthsession.FieldCompletionCodeExpiresAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field completion_code_expires_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.CompletionCodeExpiresAt = new(time.Time)
|
||||
*_m.CompletionCodeExpiresAt = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldEmailVerifiedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field email_verified_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.EmailVerifiedAt = new(time.Time)
|
||||
*_m.EmailVerifiedAt = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldPasswordVerifiedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field password_verified_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.PasswordVerifiedAt = new(time.Time)
|
||||
*_m.PasswordVerifiedAt = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldTotpVerifiedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field totp_verified_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.TotpVerifiedAt = new(time.Time)
|
||||
*_m.TotpVerifiedAt = value.Time
|
||||
}
|
||||
case pendingauthsession.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 = value.Time
|
||||
}
|
||||
case pendingauthsession.FieldConsumedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field consumed_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.ConsumedAt = new(time.Time)
|
||||
*_m.ConsumedAt = value.Time
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the PendingAuthSession.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (_m *PendingAuthSession) Value(name string) (ent.Value, error) {
|
||||
return _m.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryTargetUser queries the "target_user" edge of the PendingAuthSession entity.
|
||||
func (_m *PendingAuthSession) QueryTargetUser() *UserQuery {
|
||||
return NewPendingAuthSessionClient(_m.config).QueryTargetUser(_m)
|
||||
}
|
||||
|
||||
// QueryAdoptionDecision queries the "adoption_decision" edge of the PendingAuthSession entity.
|
||||
func (_m *PendingAuthSession) QueryAdoptionDecision() *IdentityAdoptionDecisionQuery {
|
||||
return NewPendingAuthSessionClient(_m.config).QueryAdoptionDecision(_m)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this PendingAuthSession.
|
||||
// Note that you need to call PendingAuthSession.Unwrap() before calling this method if this PendingAuthSession
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (_m *PendingAuthSession) Update() *PendingAuthSessionUpdateOne {
|
||||
return NewPendingAuthSessionClient(_m.config).UpdateOne(_m)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the PendingAuthSession entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (_m *PendingAuthSession) Unwrap() *PendingAuthSession {
|
||||
_tx, ok := _m.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: PendingAuthSession is not a transactional entity")
|
||||
}
|
||||
_m.config.driver = _tx.drv
|
||||
return _m
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (_m *PendingAuthSession) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("PendingAuthSession(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("session_token=")
|
||||
builder.WriteString(_m.SessionToken)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("intent=")
|
||||
builder.WriteString(_m.Intent)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_type=")
|
||||
builder.WriteString(_m.ProviderType)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_key=")
|
||||
builder.WriteString(_m.ProviderKey)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("provider_subject=")
|
||||
builder.WriteString(_m.ProviderSubject)
|
||||
builder.WriteString(", ")
|
||||
if v := _m.TargetUserID; v != nil {
|
||||
builder.WriteString("target_user_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", *v))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("redirect_to=")
|
||||
builder.WriteString(_m.RedirectTo)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("resolved_email=")
|
||||
builder.WriteString(_m.ResolvedEmail)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("registration_password_hash=")
|
||||
builder.WriteString(_m.RegistrationPasswordHash)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("upstream_identity_claims=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.UpstreamIdentityClaims))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("local_flow_state=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.LocalFlowState))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("browser_session_key=")
|
||||
builder.WriteString(_m.BrowserSessionKey)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("completion_code_hash=")
|
||||
builder.WriteString(_m.CompletionCodeHash)
|
||||
builder.WriteString(", ")
|
||||
if v := _m.CompletionCodeExpiresAt; v != nil {
|
||||
builder.WriteString("completion_code_expires_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.EmailVerifiedAt; v != nil {
|
||||
builder.WriteString("email_verified_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.PasswordVerifiedAt; v != nil {
|
||||
builder.WriteString("password_verified_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.TotpVerifiedAt; v != nil {
|
||||
builder.WriteString("totp_verified_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("expires_at=")
|
||||
builder.WriteString(_m.ExpiresAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
if v := _m.ConsumedAt; v != nil {
|
||||
builder.WriteString("consumed_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// PendingAuthSessions is a parsable slice of PendingAuthSession.
|
||||
type PendingAuthSessions []*PendingAuthSession
|
||||
279
backend/ent/pendingauthsession/pendingauthsession.go
Normal file
279
backend/ent/pendingauthsession/pendingauthsession.go
Normal file
@ -0,0 +1,279 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package pendingauthsession
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the pendingauthsession type in the database.
|
||||
Label = "pending_auth_session"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldSessionToken holds the string denoting the session_token field in the database.
|
||||
FieldSessionToken = "session_token"
|
||||
// FieldIntent holds the string denoting the intent field in the database.
|
||||
FieldIntent = "intent"
|
||||
// FieldProviderType holds the string denoting the provider_type field in the database.
|
||||
FieldProviderType = "provider_type"
|
||||
// FieldProviderKey holds the string denoting the provider_key field in the database.
|
||||
FieldProviderKey = "provider_key"
|
||||
// FieldProviderSubject holds the string denoting the provider_subject field in the database.
|
||||
FieldProviderSubject = "provider_subject"
|
||||
// FieldTargetUserID holds the string denoting the target_user_id field in the database.
|
||||
FieldTargetUserID = "target_user_id"
|
||||
// FieldRedirectTo holds the string denoting the redirect_to field in the database.
|
||||
FieldRedirectTo = "redirect_to"
|
||||
// FieldResolvedEmail holds the string denoting the resolved_email field in the database.
|
||||
FieldResolvedEmail = "resolved_email"
|
||||
// FieldRegistrationPasswordHash holds the string denoting the registration_password_hash field in the database.
|
||||
FieldRegistrationPasswordHash = "registration_password_hash"
|
||||
// FieldUpstreamIdentityClaims holds the string denoting the upstream_identity_claims field in the database.
|
||||
FieldUpstreamIdentityClaims = "upstream_identity_claims"
|
||||
// FieldLocalFlowState holds the string denoting the local_flow_state field in the database.
|
||||
FieldLocalFlowState = "local_flow_state"
|
||||
// FieldBrowserSessionKey holds the string denoting the browser_session_key field in the database.
|
||||
FieldBrowserSessionKey = "browser_session_key"
|
||||
// FieldCompletionCodeHash holds the string denoting the completion_code_hash field in the database.
|
||||
FieldCompletionCodeHash = "completion_code_hash"
|
||||
// FieldCompletionCodeExpiresAt holds the string denoting the completion_code_expires_at field in the database.
|
||||
FieldCompletionCodeExpiresAt = "completion_code_expires_at"
|
||||
// FieldEmailVerifiedAt holds the string denoting the email_verified_at field in the database.
|
||||
FieldEmailVerifiedAt = "email_verified_at"
|
||||
// FieldPasswordVerifiedAt holds the string denoting the password_verified_at field in the database.
|
||||
FieldPasswordVerifiedAt = "password_verified_at"
|
||||
// FieldTotpVerifiedAt holds the string denoting the totp_verified_at field in the database.
|
||||
FieldTotpVerifiedAt = "totp_verified_at"
|
||||
// FieldExpiresAt holds the string denoting the expires_at field in the database.
|
||||
FieldExpiresAt = "expires_at"
|
||||
// FieldConsumedAt holds the string denoting the consumed_at field in the database.
|
||||
FieldConsumedAt = "consumed_at"
|
||||
// EdgeTargetUser holds the string denoting the target_user edge name in mutations.
|
||||
EdgeTargetUser = "target_user"
|
||||
// EdgeAdoptionDecision holds the string denoting the adoption_decision edge name in mutations.
|
||||
EdgeAdoptionDecision = "adoption_decision"
|
||||
// Table holds the table name of the pendingauthsession in the database.
|
||||
Table = "pending_auth_sessions"
|
||||
// TargetUserTable is the table that holds the target_user relation/edge.
|
||||
TargetUserTable = "pending_auth_sessions"
|
||||
// TargetUserInverseTable is the table name for the User entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "user" package.
|
||||
TargetUserInverseTable = "users"
|
||||
// TargetUserColumn is the table column denoting the target_user relation/edge.
|
||||
TargetUserColumn = "target_user_id"
|
||||
// AdoptionDecisionTable is the table that holds the adoption_decision relation/edge.
|
||||
AdoptionDecisionTable = "identity_adoption_decisions"
|
||||
// AdoptionDecisionInverseTable is the table name for the IdentityAdoptionDecision entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "identityadoptiondecision" package.
|
||||
AdoptionDecisionInverseTable = "identity_adoption_decisions"
|
||||
// AdoptionDecisionColumn is the table column denoting the adoption_decision relation/edge.
|
||||
AdoptionDecisionColumn = "pending_auth_session_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for pendingauthsession fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldSessionToken,
|
||||
FieldIntent,
|
||||
FieldProviderType,
|
||||
FieldProviderKey,
|
||||
FieldProviderSubject,
|
||||
FieldTargetUserID,
|
||||
FieldRedirectTo,
|
||||
FieldResolvedEmail,
|
||||
FieldRegistrationPasswordHash,
|
||||
FieldUpstreamIdentityClaims,
|
||||
FieldLocalFlowState,
|
||||
FieldBrowserSessionKey,
|
||||
FieldCompletionCodeHash,
|
||||
FieldCompletionCodeExpiresAt,
|
||||
FieldEmailVerifiedAt,
|
||||
FieldPasswordVerifiedAt,
|
||||
FieldTotpVerifiedAt,
|
||||
FieldExpiresAt,
|
||||
FieldConsumedAt,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
// SessionTokenValidator is a validator for the "session_token" field. It is called by the builders before save.
|
||||
SessionTokenValidator func(string) error
|
||||
// IntentValidator is a validator for the "intent" field. It is called by the builders before save.
|
||||
IntentValidator func(string) error
|
||||
// ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
ProviderTypeValidator func(string) error
|
||||
// ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
ProviderKeyValidator func(string) error
|
||||
// ProviderSubjectValidator is a validator for the "provider_subject" field. It is called by the builders before save.
|
||||
ProviderSubjectValidator func(string) error
|
||||
// DefaultRedirectTo holds the default value on creation for the "redirect_to" field.
|
||||
DefaultRedirectTo string
|
||||
// DefaultResolvedEmail holds the default value on creation for the "resolved_email" field.
|
||||
DefaultResolvedEmail string
|
||||
// DefaultRegistrationPasswordHash holds the default value on creation for the "registration_password_hash" field.
|
||||
DefaultRegistrationPasswordHash string
|
||||
// DefaultUpstreamIdentityClaims holds the default value on creation for the "upstream_identity_claims" field.
|
||||
DefaultUpstreamIdentityClaims func() map[string]interface{}
|
||||
// DefaultLocalFlowState holds the default value on creation for the "local_flow_state" field.
|
||||
DefaultLocalFlowState func() map[string]interface{}
|
||||
// DefaultBrowserSessionKey holds the default value on creation for the "browser_session_key" field.
|
||||
DefaultBrowserSessionKey string
|
||||
// DefaultCompletionCodeHash holds the default value on creation for the "completion_code_hash" field.
|
||||
DefaultCompletionCodeHash string
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the PendingAuthSession queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySessionToken orders the results by the session_token field.
|
||||
func BySessionToken(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSessionToken, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByIntent orders the results by the intent field.
|
||||
func ByIntent(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldIntent, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderType orders the results by the provider_type field.
|
||||
func ByProviderType(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderType, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderKey orders the results by the provider_key field.
|
||||
func ByProviderKey(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderKey, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByProviderSubject orders the results by the provider_subject field.
|
||||
func ByProviderSubject(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldProviderSubject, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTargetUserID orders the results by the target_user_id field.
|
||||
func ByTargetUserID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTargetUserID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByRedirectTo orders the results by the redirect_to field.
|
||||
func ByRedirectTo(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldRedirectTo, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByResolvedEmail orders the results by the resolved_email field.
|
||||
func ByResolvedEmail(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldResolvedEmail, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByRegistrationPasswordHash orders the results by the registration_password_hash field.
|
||||
func ByRegistrationPasswordHash(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldRegistrationPasswordHash, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByBrowserSessionKey orders the results by the browser_session_key field.
|
||||
func ByBrowserSessionKey(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldBrowserSessionKey, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCompletionCodeHash orders the results by the completion_code_hash field.
|
||||
func ByCompletionCodeHash(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCompletionCodeHash, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCompletionCodeExpiresAt orders the results by the completion_code_expires_at field.
|
||||
func ByCompletionCodeExpiresAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCompletionCodeExpiresAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByEmailVerifiedAt orders the results by the email_verified_at field.
|
||||
func ByEmailVerifiedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldEmailVerifiedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByPasswordVerifiedAt orders the results by the password_verified_at field.
|
||||
func ByPasswordVerifiedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldPasswordVerifiedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTotpVerifiedAt orders the results by the totp_verified_at field.
|
||||
func ByTotpVerifiedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTotpVerifiedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByExpiresAt orders the results by the expires_at field.
|
||||
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldExpiresAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByConsumedAt orders the results by the consumed_at field.
|
||||
func ByConsumedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldConsumedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByTargetUserField orders the results by target_user field.
|
||||
func ByTargetUserField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newTargetUserStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
|
||||
// ByAdoptionDecisionField orders the results by adoption_decision field.
|
||||
func ByAdoptionDecisionField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newAdoptionDecisionStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
func newTargetUserStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(TargetUserInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, TargetUserTable, TargetUserColumn),
|
||||
)
|
||||
}
|
||||
func newAdoptionDecisionStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(AdoptionDecisionInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, false, AdoptionDecisionTable, AdoptionDecisionColumn),
|
||||
)
|
||||
}
|
||||
1262
backend/ent/pendingauthsession/where.go
Normal file
1262
backend/ent/pendingauthsession/where.go
Normal file
File diff suppressed because it is too large
Load Diff
1815
backend/ent/pendingauthsession_create.go
Normal file
1815
backend/ent/pendingauthsession_create.go
Normal file
File diff suppressed because it is too large
Load Diff
88
backend/ent/pendingauthsession_delete.go
Normal file
88
backend/ent/pendingauthsession_delete.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
)
|
||||
|
||||
// PendingAuthSessionDelete is the builder for deleting a PendingAuthSession entity.
|
||||
type PendingAuthSessionDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *PendingAuthSessionMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the PendingAuthSessionDelete builder.
|
||||
func (_d *PendingAuthSessionDelete) Where(ps ...predicate.PendingAuthSession) *PendingAuthSessionDelete {
|
||||
_d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (_d *PendingAuthSessionDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *PendingAuthSessionDelete) ExecX(ctx context.Context) int {
|
||||
n, err := _d.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (_d *PendingAuthSessionDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(pendingauthsession.Table, sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64))
|
||||
if ps := _d.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
_d.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// PendingAuthSessionDeleteOne is the builder for deleting a single PendingAuthSession entity.
|
||||
type PendingAuthSessionDeleteOne struct {
|
||||
_d *PendingAuthSessionDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the PendingAuthSessionDelete builder.
|
||||
func (_d *PendingAuthSessionDeleteOne) Where(ps ...predicate.PendingAuthSession) *PendingAuthSessionDeleteOne {
|
||||
_d._d.mutation.Where(ps...)
|
||||
return _d
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (_d *PendingAuthSessionDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := _d._d.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{pendingauthsession.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (_d *PendingAuthSessionDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := _d.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
717
backend/ent/pendingauthsession_query.go
Normal file
717
backend/ent/pendingauthsession_query.go
Normal file
@ -0,0 +1,717 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/user"
|
||||
)
|
||||
|
||||
// PendingAuthSessionQuery is the builder for querying PendingAuthSession entities.
|
||||
type PendingAuthSessionQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []pendingauthsession.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.PendingAuthSession
|
||||
withTargetUser *UserQuery
|
||||
withAdoptionDecision *IdentityAdoptionDecisionQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the PendingAuthSessionQuery builder.
|
||||
func (_q *PendingAuthSessionQuery) Where(ps ...predicate.PendingAuthSession) *PendingAuthSessionQuery {
|
||||
_q.predicates = append(_q.predicates, ps...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (_q *PendingAuthSessionQuery) Limit(limit int) *PendingAuthSessionQuery {
|
||||
_q.ctx.Limit = &limit
|
||||
return _q
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (_q *PendingAuthSessionQuery) Offset(offset int) *PendingAuthSessionQuery {
|
||||
_q.ctx.Offset = &offset
|
||||
return _q
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (_q *PendingAuthSessionQuery) Unique(unique bool) *PendingAuthSessionQuery {
|
||||
_q.ctx.Unique = &unique
|
||||
return _q
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (_q *PendingAuthSessionQuery) Order(o ...pendingauthsession.OrderOption) *PendingAuthSessionQuery {
|
||||
_q.order = append(_q.order, o...)
|
||||
return _q
|
||||
}
|
||||
|
||||
// QueryTargetUser chains the current query on the "target_user" edge.
|
||||
func (_q *PendingAuthSessionQuery) QueryTargetUser() *UserQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(pendingauthsession.Table, pendingauthsession.FieldID, selector),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, pendingauthsession.TargetUserTable, pendingauthsession.TargetUserColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAdoptionDecision chains the current query on the "adoption_decision" edge.
|
||||
func (_q *PendingAuthSessionQuery) QueryAdoptionDecision() *IdentityAdoptionDecisionQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(pendingauthsession.Table, pendingauthsession.FieldID, selector),
|
||||
sqlgraph.To(identityadoptiondecision.Table, identityadoptiondecision.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2O, false, pendingauthsession.AdoptionDecisionTable, pendingauthsession.AdoptionDecisionColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first PendingAuthSession entity from the query.
|
||||
// Returns a *NotFoundError when no PendingAuthSession was found.
|
||||
func (_q *PendingAuthSessionQuery) First(ctx context.Context) (*PendingAuthSession, error) {
|
||||
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{pendingauthsession.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) FirstX(ctx context.Context) *PendingAuthSession {
|
||||
node, err := _q.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first PendingAuthSession ID from the query.
|
||||
// Returns a *NotFoundError when no PendingAuthSession ID was found.
|
||||
func (_q *PendingAuthSessionQuery) FirstID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{pendingauthsession.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) FirstIDX(ctx context.Context) int64 {
|
||||
id, err := _q.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single PendingAuthSession entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one PendingAuthSession entity is found.
|
||||
// Returns a *NotFoundError when no PendingAuthSession entities are found.
|
||||
func (_q *PendingAuthSessionQuery) Only(ctx context.Context) (*PendingAuthSession, error) {
|
||||
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{pendingauthsession.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{pendingauthsession.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) OnlyX(ctx context.Context) *PendingAuthSession {
|
||||
node, err := _q.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only PendingAuthSession ID in the query.
|
||||
// Returns a *NotSingularError when more than one PendingAuthSession ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (_q *PendingAuthSessionQuery) OnlyID(ctx context.Context) (id int64, err error) {
|
||||
var ids []int64
|
||||
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{pendingauthsession.Label}
|
||||
default:
|
||||
err = &NotSingularError{pendingauthsession.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) OnlyIDX(ctx context.Context) int64 {
|
||||
id, err := _q.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of PendingAuthSessions.
|
||||
func (_q *PendingAuthSessionQuery) All(ctx context.Context) ([]*PendingAuthSession, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*PendingAuthSession, *PendingAuthSessionQuery]()
|
||||
return withInterceptors[[]*PendingAuthSession](ctx, _q, qr, _q.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) AllX(ctx context.Context) []*PendingAuthSession {
|
||||
nodes, err := _q.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of PendingAuthSession IDs.
|
||||
func (_q *PendingAuthSessionQuery) IDs(ctx context.Context) (ids []int64, err error) {
|
||||
if _q.ctx.Unique == nil && _q.path != nil {
|
||||
_q.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
|
||||
if err = _q.Select(pendingauthsession.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) IDsX(ctx context.Context) []int64 {
|
||||
ids, err := _q.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (_q *PendingAuthSessionQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, _q, querierCount[*PendingAuthSessionQuery](), _q.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) CountX(ctx context.Context) int {
|
||||
count, err := _q.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (_q *PendingAuthSessionQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
|
||||
switch _, err := _q.FirstID(ctx); {
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (_q *PendingAuthSessionQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := _q.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the PendingAuthSessionQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (_q *PendingAuthSessionQuery) Clone() *PendingAuthSessionQuery {
|
||||
if _q == nil {
|
||||
return nil
|
||||
}
|
||||
return &PendingAuthSessionQuery{
|
||||
config: _q.config,
|
||||
ctx: _q.ctx.Clone(),
|
||||
order: append([]pendingauthsession.OrderOption{}, _q.order...),
|
||||
inters: append([]Interceptor{}, _q.inters...),
|
||||
predicates: append([]predicate.PendingAuthSession{}, _q.predicates...),
|
||||
withTargetUser: _q.withTargetUser.Clone(),
|
||||
withAdoptionDecision: _q.withAdoptionDecision.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
path: _q.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithTargetUser tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "target_user" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *PendingAuthSessionQuery) WithTargetUser(opts ...func(*UserQuery)) *PendingAuthSessionQuery {
|
||||
query := (&UserClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withTargetUser = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithAdoptionDecision tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "adoption_decision" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *PendingAuthSessionQuery) WithAdoptionDecision(opts ...func(*IdentityAdoptionDecisionQuery)) *PendingAuthSessionQuery {
|
||||
query := (&IdentityAdoptionDecisionClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withAdoptionDecision = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.PendingAuthSession.Query().
|
||||
// GroupBy(pendingauthsession.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *PendingAuthSessionQuery) GroupBy(field string, fields ...string) *PendingAuthSessionGroupBy {
|
||||
_q.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &PendingAuthSessionGroupBy{build: _q}
|
||||
grbuild.flds = &_q.ctx.Fields
|
||||
grbuild.label = pendingauthsession.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.PendingAuthSession.Query().
|
||||
// Select(pendingauthsession.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (_q *PendingAuthSessionQuery) Select(fields ...string) *PendingAuthSessionSelect {
|
||||
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
|
||||
sbuild := &PendingAuthSessionSelect{PendingAuthSessionQuery: _q}
|
||||
sbuild.label = pendingauthsession.Label
|
||||
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a PendingAuthSessionSelect configured with the given aggregations.
|
||||
func (_q *PendingAuthSessionQuery) Aggregate(fns ...AggregateFunc) *PendingAuthSessionSelect {
|
||||
return _q.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range _q.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, _q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range _q.ctx.Fields {
|
||||
if !pendingauthsession.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if _q.path != nil {
|
||||
prev, err := _q.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_q.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PendingAuthSession, error) {
|
||||
var (
|
||||
nodes = []*PendingAuthSession{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [2]bool{
|
||||
_q.withTargetUser != nil,
|
||||
_q.withAdoptionDecision != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*PendingAuthSession).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &PendingAuthSession{config: _q.config}
|
||||
nodes = append(nodes, node)
|
||||
node.Edges.loadedTypes = loadedTypes
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
for i := range hooks {
|
||||
hooks[i](ctx, _spec)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := _q.withTargetUser; query != nil {
|
||||
if err := _q.loadTargetUser(ctx, query, nodes, nil,
|
||||
func(n *PendingAuthSession, e *User) { n.Edges.TargetUser = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withAdoptionDecision; query != nil {
|
||||
if err := _q.loadAdoptionDecision(ctx, query, nodes, nil,
|
||||
func(n *PendingAuthSession, e *IdentityAdoptionDecision) { n.Edges.AdoptionDecision = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) loadTargetUser(ctx context.Context, query *UserQuery, nodes []*PendingAuthSession, init func(*PendingAuthSession), assign func(*PendingAuthSession, *User)) error {
|
||||
ids := make([]int64, 0, len(nodes))
|
||||
nodeids := make(map[int64][]*PendingAuthSession)
|
||||
for i := range nodes {
|
||||
if nodes[i].TargetUserID == nil {
|
||||
continue
|
||||
}
|
||||
fk := *nodes[i].TargetUserID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(user.IDIn(ids...))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
nodes, ok := nodeids[n.ID]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected foreign-key "target_user_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *PendingAuthSessionQuery) loadAdoptionDecision(ctx context.Context, query *IdentityAdoptionDecisionQuery, nodes []*PendingAuthSession, init func(*PendingAuthSession), assign func(*PendingAuthSession, *IdentityAdoptionDecision)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*PendingAuthSession)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(identityadoptiondecision.FieldPendingAuthSessionID)
|
||||
}
|
||||
query.Where(predicate.IdentityAdoptionDecision(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(pendingauthsession.AdoptionDecisionColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.PendingAuthSessionID
|
||||
node, ok := nodeids[fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "pending_auth_session_id" returned %v for node %v`, fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := _q.querySpec()
|
||||
if len(_q.modifiers) > 0 {
|
||||
_spec.Modifiers = _q.modifiers
|
||||
}
|
||||
_spec.Node.Columns = _q.ctx.Fields
|
||||
if len(_q.ctx.Fields) > 0 {
|
||||
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(pendingauthsession.Table, pendingauthsession.Columns, sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64))
|
||||
_spec.From = _q.sql
|
||||
if unique := _q.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if _q.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := _q.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, pendingauthsession.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != pendingauthsession.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if _q.withTargetUser != nil {
|
||||
_spec.Node.AddColumnOnce(pendingauthsession.FieldTargetUserID)
|
||||
}
|
||||
}
|
||||
if ps := _q.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := _q.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (_q *PendingAuthSessionQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(_q.driver.Dialect())
|
||||
t1 := builder.Table(pendingauthsession.Table)
|
||||
columns := _q.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = pendingauthsession.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if _q.sql != nil {
|
||||
selector = _q.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if _q.ctx.Unique != nil && *_q.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, m := range _q.modifiers {
|
||||
m(selector)
|
||||
}
|
||||
for _, p := range _q.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range _q.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := _q.ctx.Offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := _q.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
|
||||
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
|
||||
// either committed or rolled-back.
|
||||
func (_q *PendingAuthSessionQuery) ForUpdate(opts ...sql.LockOption) *PendingAuthSessionQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForUpdate(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
|
||||
// on any rows that are read. Other sessions can read the rows, but cannot modify them
|
||||
// until your transaction commits.
|
||||
func (_q *PendingAuthSessionQuery) ForShare(opts ...sql.LockOption) *PendingAuthSessionQuery {
|
||||
if _q.driver.Dialect() == dialect.Postgres {
|
||||
_q.Unique(false)
|
||||
}
|
||||
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
|
||||
s.ForShare(opts...)
|
||||
})
|
||||
return _q
|
||||
}
|
||||
|
||||
// PendingAuthSessionGroupBy is the group-by builder for PendingAuthSession entities.
|
||||
type PendingAuthSessionGroupBy struct {
|
||||
selector
|
||||
build *PendingAuthSessionQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (_g *PendingAuthSessionGroupBy) Aggregate(fns ...AggregateFunc) *PendingAuthSessionGroupBy {
|
||||
_g.fns = append(_g.fns, fns...)
|
||||
return _g
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_g *PendingAuthSessionGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := _g.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*PendingAuthSessionQuery, *PendingAuthSessionGroupBy](ctx, _g.build, _g, _g.build.inters, v)
|
||||
}
|
||||
|
||||
func (_g *PendingAuthSessionGroupBy) sqlScan(ctx context.Context, root *PendingAuthSessionQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(_g.fns))
|
||||
for _, fn := range _g.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
|
||||
for _, f := range *_g.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*_g.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// PendingAuthSessionSelect is the builder for selecting fields of PendingAuthSession entities.
|
||||
type PendingAuthSessionSelect struct {
|
||||
*PendingAuthSessionQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (_s *PendingAuthSessionSelect) Aggregate(fns ...AggregateFunc) *PendingAuthSessionSelect {
|
||||
_s.fns = append(_s.fns, fns...)
|
||||
return _s
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (_s *PendingAuthSessionSelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
|
||||
if err := _s.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*PendingAuthSessionQuery, *PendingAuthSessionSelect](ctx, _s.PendingAuthSessionQuery, _s, _s.inters, v)
|
||||
}
|
||||
|
||||
func (_s *PendingAuthSessionSelect) sqlScan(ctx context.Context, root *PendingAuthSessionQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(_s.fns))
|
||||
for _, fn := range _s.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*_s.selector.flds); {
|
||||
case n == 0 && len(aggregation) > 0:
|
||||
selector.Select(aggregation...)
|
||||
case n != 0 && len(aggregation) > 0:
|
||||
selector.AppendSelect(aggregation...)
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
1178
backend/ent/pendingauthsession_update.go
Normal file
1178
backend/ent/pendingauthsession_update.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,12 @@ type Announcement func(*sql.Selector)
|
||||
// AnnouncementRead is the predicate function for announcementread builders.
|
||||
type AnnouncementRead func(*sql.Selector)
|
||||
|
||||
// AuthIdentity is the predicate function for authidentity builders.
|
||||
type AuthIdentity func(*sql.Selector)
|
||||
|
||||
// AuthIdentityChannel is the predicate function for authidentitychannel builders.
|
||||
type AuthIdentityChannel func(*sql.Selector)
|
||||
|
||||
// ErrorPassthroughRule is the predicate function for errorpassthroughrule builders.
|
||||
type ErrorPassthroughRule func(*sql.Selector)
|
||||
|
||||
@ -30,6 +36,9 @@ type Group func(*sql.Selector)
|
||||
// IdempotencyRecord is the predicate function for idempotencyrecord builders.
|
||||
type IdempotencyRecord func(*sql.Selector)
|
||||
|
||||
// IdentityAdoptionDecision is the predicate function for identityadoptiondecision builders.
|
||||
type IdentityAdoptionDecision func(*sql.Selector)
|
||||
|
||||
// PaymentAuditLog is the predicate function for paymentauditlog builders.
|
||||
type PaymentAuditLog func(*sql.Selector)
|
||||
|
||||
@ -39,6 +48,9 @@ type PaymentOrder func(*sql.Selector)
|
||||
// PaymentProviderInstance is the predicate function for paymentproviderinstance builders.
|
||||
type PaymentProviderInstance func(*sql.Selector)
|
||||
|
||||
// PendingAuthSession is the predicate function for pendingauthsession builders.
|
||||
type PendingAuthSession func(*sql.Selector)
|
||||
|
||||
// PromoCode is the predicate function for promocode builders.
|
||||
type PromoCode func(*sql.Selector)
|
||||
|
||||
|
||||
@ -10,12 +10,16 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcement"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentitychannel"
|
||||
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/proxy"
|
||||
@ -309,6 +313,120 @@ func init() {
|
||||
announcementreadDescCreatedAt := announcementreadFields[3].Descriptor()
|
||||
// announcementread.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
announcementread.DefaultCreatedAt = announcementreadDescCreatedAt.Default.(func() time.Time)
|
||||
authidentityMixin := schema.AuthIdentity{}.Mixin()
|
||||
authidentityMixinFields0 := authidentityMixin[0].Fields()
|
||||
_ = authidentityMixinFields0
|
||||
authidentityFields := schema.AuthIdentity{}.Fields()
|
||||
_ = authidentityFields
|
||||
// authidentityDescCreatedAt is the schema descriptor for created_at field.
|
||||
authidentityDescCreatedAt := authidentityMixinFields0[0].Descriptor()
|
||||
// authidentity.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
authidentity.DefaultCreatedAt = authidentityDescCreatedAt.Default.(func() time.Time)
|
||||
// authidentityDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
authidentityDescUpdatedAt := authidentityMixinFields0[1].Descriptor()
|
||||
// authidentity.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
authidentity.DefaultUpdatedAt = authidentityDescUpdatedAt.Default.(func() time.Time)
|
||||
// authidentity.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
authidentity.UpdateDefaultUpdatedAt = authidentityDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
// authidentityDescProviderType is the schema descriptor for provider_type field.
|
||||
authidentityDescProviderType := authidentityFields[1].Descriptor()
|
||||
// authidentity.ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
authidentity.ProviderTypeValidator = func() func(string) error {
|
||||
validators := authidentityDescProviderType.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
validators[2].(func(string) error),
|
||||
}
|
||||
return func(provider_type string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(provider_type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// authidentityDescProviderKey is the schema descriptor for provider_key field.
|
||||
authidentityDescProviderKey := authidentityFields[2].Descriptor()
|
||||
// authidentity.ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
authidentity.ProviderKeyValidator = authidentityDescProviderKey.Validators[0].(func(string) error)
|
||||
// authidentityDescProviderSubject is the schema descriptor for provider_subject field.
|
||||
authidentityDescProviderSubject := authidentityFields[3].Descriptor()
|
||||
// authidentity.ProviderSubjectValidator is a validator for the "provider_subject" field. It is called by the builders before save.
|
||||
authidentity.ProviderSubjectValidator = authidentityDescProviderSubject.Validators[0].(func(string) error)
|
||||
// authidentityDescMetadata is the schema descriptor for metadata field.
|
||||
authidentityDescMetadata := authidentityFields[6].Descriptor()
|
||||
// authidentity.DefaultMetadata holds the default value on creation for the metadata field.
|
||||
authidentity.DefaultMetadata = authidentityDescMetadata.Default.(func() map[string]interface{})
|
||||
authidentitychannelMixin := schema.AuthIdentityChannel{}.Mixin()
|
||||
authidentitychannelMixinFields0 := authidentitychannelMixin[0].Fields()
|
||||
_ = authidentitychannelMixinFields0
|
||||
authidentitychannelFields := schema.AuthIdentityChannel{}.Fields()
|
||||
_ = authidentitychannelFields
|
||||
// authidentitychannelDescCreatedAt is the schema descriptor for created_at field.
|
||||
authidentitychannelDescCreatedAt := authidentitychannelMixinFields0[0].Descriptor()
|
||||
// authidentitychannel.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
authidentitychannel.DefaultCreatedAt = authidentitychannelDescCreatedAt.Default.(func() time.Time)
|
||||
// authidentitychannelDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
authidentitychannelDescUpdatedAt := authidentitychannelMixinFields0[1].Descriptor()
|
||||
// authidentitychannel.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
authidentitychannel.DefaultUpdatedAt = authidentitychannelDescUpdatedAt.Default.(func() time.Time)
|
||||
// authidentitychannel.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
authidentitychannel.UpdateDefaultUpdatedAt = authidentitychannelDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
// authidentitychannelDescProviderType is the schema descriptor for provider_type field.
|
||||
authidentitychannelDescProviderType := authidentitychannelFields[1].Descriptor()
|
||||
// authidentitychannel.ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
authidentitychannel.ProviderTypeValidator = func() func(string) error {
|
||||
validators := authidentitychannelDescProviderType.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
validators[2].(func(string) error),
|
||||
}
|
||||
return func(provider_type string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(provider_type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// authidentitychannelDescProviderKey is the schema descriptor for provider_key field.
|
||||
authidentitychannelDescProviderKey := authidentitychannelFields[2].Descriptor()
|
||||
// authidentitychannel.ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
authidentitychannel.ProviderKeyValidator = authidentitychannelDescProviderKey.Validators[0].(func(string) error)
|
||||
// authidentitychannelDescChannel is the schema descriptor for channel field.
|
||||
authidentitychannelDescChannel := authidentitychannelFields[3].Descriptor()
|
||||
// authidentitychannel.ChannelValidator is a validator for the "channel" field. It is called by the builders before save.
|
||||
authidentitychannel.ChannelValidator = func() func(string) error {
|
||||
validators := authidentitychannelDescChannel.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
}
|
||||
return func(channel string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(channel); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// authidentitychannelDescChannelAppID is the schema descriptor for channel_app_id field.
|
||||
authidentitychannelDescChannelAppID := authidentitychannelFields[4].Descriptor()
|
||||
// authidentitychannel.ChannelAppIDValidator is a validator for the "channel_app_id" field. It is called by the builders before save.
|
||||
authidentitychannel.ChannelAppIDValidator = authidentitychannelDescChannelAppID.Validators[0].(func(string) error)
|
||||
// authidentitychannelDescChannelSubject is the schema descriptor for channel_subject field.
|
||||
authidentitychannelDescChannelSubject := authidentitychannelFields[5].Descriptor()
|
||||
// authidentitychannel.ChannelSubjectValidator is a validator for the "channel_subject" field. It is called by the builders before save.
|
||||
authidentitychannel.ChannelSubjectValidator = authidentitychannelDescChannelSubject.Validators[0].(func(string) error)
|
||||
// authidentitychannelDescMetadata is the schema descriptor for metadata field.
|
||||
authidentitychannelDescMetadata := authidentitychannelFields[6].Descriptor()
|
||||
// authidentitychannel.DefaultMetadata holds the default value on creation for the metadata field.
|
||||
authidentitychannel.DefaultMetadata = authidentitychannelDescMetadata.Default.(func() map[string]interface{})
|
||||
errorpassthroughruleMixin := schema.ErrorPassthroughRule{}.Mixin()
|
||||
errorpassthroughruleMixinFields0 := errorpassthroughruleMixin[0].Fields()
|
||||
_ = errorpassthroughruleMixinFields0
|
||||
@ -512,6 +630,33 @@ func init() {
|
||||
idempotencyrecordDescErrorReason := idempotencyrecordFields[6].Descriptor()
|
||||
// idempotencyrecord.ErrorReasonValidator is a validator for the "error_reason" field. It is called by the builders before save.
|
||||
idempotencyrecord.ErrorReasonValidator = idempotencyrecordDescErrorReason.Validators[0].(func(string) error)
|
||||
identityadoptiondecisionMixin := schema.IdentityAdoptionDecision{}.Mixin()
|
||||
identityadoptiondecisionMixinFields0 := identityadoptiondecisionMixin[0].Fields()
|
||||
_ = identityadoptiondecisionMixinFields0
|
||||
identityadoptiondecisionFields := schema.IdentityAdoptionDecision{}.Fields()
|
||||
_ = identityadoptiondecisionFields
|
||||
// identityadoptiondecisionDescCreatedAt is the schema descriptor for created_at field.
|
||||
identityadoptiondecisionDescCreatedAt := identityadoptiondecisionMixinFields0[0].Descriptor()
|
||||
// identityadoptiondecision.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
identityadoptiondecision.DefaultCreatedAt = identityadoptiondecisionDescCreatedAt.Default.(func() time.Time)
|
||||
// identityadoptiondecisionDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
identityadoptiondecisionDescUpdatedAt := identityadoptiondecisionMixinFields0[1].Descriptor()
|
||||
// identityadoptiondecision.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
identityadoptiondecision.DefaultUpdatedAt = identityadoptiondecisionDescUpdatedAt.Default.(func() time.Time)
|
||||
// identityadoptiondecision.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
identityadoptiondecision.UpdateDefaultUpdatedAt = identityadoptiondecisionDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
// identityadoptiondecisionDescAdoptDisplayName is the schema descriptor for adopt_display_name field.
|
||||
identityadoptiondecisionDescAdoptDisplayName := identityadoptiondecisionFields[2].Descriptor()
|
||||
// identityadoptiondecision.DefaultAdoptDisplayName holds the default value on creation for the adopt_display_name field.
|
||||
identityadoptiondecision.DefaultAdoptDisplayName = identityadoptiondecisionDescAdoptDisplayName.Default.(bool)
|
||||
// identityadoptiondecisionDescAdoptAvatar is the schema descriptor for adopt_avatar field.
|
||||
identityadoptiondecisionDescAdoptAvatar := identityadoptiondecisionFields[3].Descriptor()
|
||||
// identityadoptiondecision.DefaultAdoptAvatar holds the default value on creation for the adopt_avatar field.
|
||||
identityadoptiondecision.DefaultAdoptAvatar = identityadoptiondecisionDescAdoptAvatar.Default.(bool)
|
||||
// identityadoptiondecisionDescDecidedAt is the schema descriptor for decided_at field.
|
||||
identityadoptiondecisionDescDecidedAt := identityadoptiondecisionFields[4].Descriptor()
|
||||
// identityadoptiondecision.DefaultDecidedAt holds the default value on creation for the decided_at field.
|
||||
identityadoptiondecision.DefaultDecidedAt = identityadoptiondecisionDescDecidedAt.Default.(func() time.Time)
|
||||
paymentauditlogFields := schema.PaymentAuditLog{}.Fields()
|
||||
_ = paymentauditlogFields
|
||||
// paymentauditlogDescOrderID is the schema descriptor for order_id field.
|
||||
@ -578,38 +723,42 @@ func init() {
|
||||
paymentorderDescProviderInstanceID := paymentorderFields[18].Descriptor()
|
||||
// paymentorder.ProviderInstanceIDValidator is a validator for the "provider_instance_id" field. It is called by the builders before save.
|
||||
paymentorder.ProviderInstanceIDValidator = paymentorderDescProviderInstanceID.Validators[0].(func(string) error)
|
||||
// paymentorderDescProviderKey is the schema descriptor for provider_key field.
|
||||
paymentorderDescProviderKey := paymentorderFields[19].Descriptor()
|
||||
// paymentorder.ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
paymentorder.ProviderKeyValidator = paymentorderDescProviderKey.Validators[0].(func(string) error)
|
||||
// paymentorderDescStatus is the schema descriptor for status field.
|
||||
paymentorderDescStatus := paymentorderFields[19].Descriptor()
|
||||
paymentorderDescStatus := paymentorderFields[21].Descriptor()
|
||||
// paymentorder.DefaultStatus holds the default value on creation for the status field.
|
||||
paymentorder.DefaultStatus = paymentorderDescStatus.Default.(string)
|
||||
// paymentorder.StatusValidator is a validator for the "status" field. It is called by the builders before save.
|
||||
paymentorder.StatusValidator = paymentorderDescStatus.Validators[0].(func(string) error)
|
||||
// paymentorderDescRefundAmount is the schema descriptor for refund_amount field.
|
||||
paymentorderDescRefundAmount := paymentorderFields[20].Descriptor()
|
||||
paymentorderDescRefundAmount := paymentorderFields[22].Descriptor()
|
||||
// paymentorder.DefaultRefundAmount holds the default value on creation for the refund_amount field.
|
||||
paymentorder.DefaultRefundAmount = paymentorderDescRefundAmount.Default.(float64)
|
||||
// paymentorderDescForceRefund is the schema descriptor for force_refund field.
|
||||
paymentorderDescForceRefund := paymentorderFields[23].Descriptor()
|
||||
paymentorderDescForceRefund := paymentorderFields[25].Descriptor()
|
||||
// paymentorder.DefaultForceRefund holds the default value on creation for the force_refund field.
|
||||
paymentorder.DefaultForceRefund = paymentorderDescForceRefund.Default.(bool)
|
||||
// paymentorderDescRefundRequestedBy is the schema descriptor for refund_requested_by field.
|
||||
paymentorderDescRefundRequestedBy := paymentorderFields[26].Descriptor()
|
||||
paymentorderDescRefundRequestedBy := paymentorderFields[28].Descriptor()
|
||||
// paymentorder.RefundRequestedByValidator is a validator for the "refund_requested_by" field. It is called by the builders before save.
|
||||
paymentorder.RefundRequestedByValidator = paymentorderDescRefundRequestedBy.Validators[0].(func(string) error)
|
||||
// paymentorderDescClientIP is the schema descriptor for client_ip field.
|
||||
paymentorderDescClientIP := paymentorderFields[32].Descriptor()
|
||||
paymentorderDescClientIP := paymentorderFields[34].Descriptor()
|
||||
// paymentorder.ClientIPValidator is a validator for the "client_ip" field. It is called by the builders before save.
|
||||
paymentorder.ClientIPValidator = paymentorderDescClientIP.Validators[0].(func(string) error)
|
||||
// paymentorderDescSrcHost is the schema descriptor for src_host field.
|
||||
paymentorderDescSrcHost := paymentorderFields[33].Descriptor()
|
||||
paymentorderDescSrcHost := paymentorderFields[35].Descriptor()
|
||||
// paymentorder.SrcHostValidator is a validator for the "src_host" field. It is called by the builders before save.
|
||||
paymentorder.SrcHostValidator = paymentorderDescSrcHost.Validators[0].(func(string) error)
|
||||
// paymentorderDescCreatedAt is the schema descriptor for created_at field.
|
||||
paymentorderDescCreatedAt := paymentorderFields[35].Descriptor()
|
||||
paymentorderDescCreatedAt := paymentorderFields[37].Descriptor()
|
||||
// paymentorder.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
paymentorder.DefaultCreatedAt = paymentorderDescCreatedAt.Default.(func() time.Time)
|
||||
// paymentorderDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
paymentorderDescUpdatedAt := paymentorderFields[36].Descriptor()
|
||||
paymentorderDescUpdatedAt := paymentorderFields[38].Descriptor()
|
||||
// paymentorder.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
paymentorder.DefaultUpdatedAt = paymentorderDescUpdatedAt.Default.(func() time.Time)
|
||||
// paymentorder.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
@ -682,6 +831,113 @@ func init() {
|
||||
paymentproviderinstance.DefaultUpdatedAt = paymentproviderinstanceDescUpdatedAt.Default.(func() time.Time)
|
||||
// paymentproviderinstance.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
paymentproviderinstance.UpdateDefaultUpdatedAt = paymentproviderinstanceDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
pendingauthsessionMixin := schema.PendingAuthSession{}.Mixin()
|
||||
pendingauthsessionMixinFields0 := pendingauthsessionMixin[0].Fields()
|
||||
_ = pendingauthsessionMixinFields0
|
||||
pendingauthsessionFields := schema.PendingAuthSession{}.Fields()
|
||||
_ = pendingauthsessionFields
|
||||
// pendingauthsessionDescCreatedAt is the schema descriptor for created_at field.
|
||||
pendingauthsessionDescCreatedAt := pendingauthsessionMixinFields0[0].Descriptor()
|
||||
// pendingauthsession.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
pendingauthsession.DefaultCreatedAt = pendingauthsessionDescCreatedAt.Default.(func() time.Time)
|
||||
// pendingauthsessionDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
pendingauthsessionDescUpdatedAt := pendingauthsessionMixinFields0[1].Descriptor()
|
||||
// pendingauthsession.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
pendingauthsession.DefaultUpdatedAt = pendingauthsessionDescUpdatedAt.Default.(func() time.Time)
|
||||
// pendingauthsession.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
pendingauthsession.UpdateDefaultUpdatedAt = pendingauthsessionDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
// pendingauthsessionDescSessionToken is the schema descriptor for session_token field.
|
||||
pendingauthsessionDescSessionToken := pendingauthsessionFields[0].Descriptor()
|
||||
// pendingauthsession.SessionTokenValidator is a validator for the "session_token" field. It is called by the builders before save.
|
||||
pendingauthsession.SessionTokenValidator = func() func(string) error {
|
||||
validators := pendingauthsessionDescSessionToken.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
}
|
||||
return func(session_token string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(session_token); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// pendingauthsessionDescIntent is the schema descriptor for intent field.
|
||||
pendingauthsessionDescIntent := pendingauthsessionFields[1].Descriptor()
|
||||
// pendingauthsession.IntentValidator is a validator for the "intent" field. It is called by the builders before save.
|
||||
pendingauthsession.IntentValidator = func() func(string) error {
|
||||
validators := pendingauthsessionDescIntent.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
validators[2].(func(string) error),
|
||||
}
|
||||
return func(intent string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(intent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// pendingauthsessionDescProviderType is the schema descriptor for provider_type field.
|
||||
pendingauthsessionDescProviderType := pendingauthsessionFields[2].Descriptor()
|
||||
// pendingauthsession.ProviderTypeValidator is a validator for the "provider_type" field. It is called by the builders before save.
|
||||
pendingauthsession.ProviderTypeValidator = func() func(string) error {
|
||||
validators := pendingauthsessionDescProviderType.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
validators[2].(func(string) error),
|
||||
}
|
||||
return func(provider_type string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(provider_type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// pendingauthsessionDescProviderKey is the schema descriptor for provider_key field.
|
||||
pendingauthsessionDescProviderKey := pendingauthsessionFields[3].Descriptor()
|
||||
// pendingauthsession.ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
|
||||
pendingauthsession.ProviderKeyValidator = pendingauthsessionDescProviderKey.Validators[0].(func(string) error)
|
||||
// pendingauthsessionDescProviderSubject is the schema descriptor for provider_subject field.
|
||||
pendingauthsessionDescProviderSubject := pendingauthsessionFields[4].Descriptor()
|
||||
// pendingauthsession.ProviderSubjectValidator is a validator for the "provider_subject" field. It is called by the builders before save.
|
||||
pendingauthsession.ProviderSubjectValidator = pendingauthsessionDescProviderSubject.Validators[0].(func(string) error)
|
||||
// pendingauthsessionDescRedirectTo is the schema descriptor for redirect_to field.
|
||||
pendingauthsessionDescRedirectTo := pendingauthsessionFields[6].Descriptor()
|
||||
// pendingauthsession.DefaultRedirectTo holds the default value on creation for the redirect_to field.
|
||||
pendingauthsession.DefaultRedirectTo = pendingauthsessionDescRedirectTo.Default.(string)
|
||||
// pendingauthsessionDescResolvedEmail is the schema descriptor for resolved_email field.
|
||||
pendingauthsessionDescResolvedEmail := pendingauthsessionFields[7].Descriptor()
|
||||
// pendingauthsession.DefaultResolvedEmail holds the default value on creation for the resolved_email field.
|
||||
pendingauthsession.DefaultResolvedEmail = pendingauthsessionDescResolvedEmail.Default.(string)
|
||||
// pendingauthsessionDescRegistrationPasswordHash is the schema descriptor for registration_password_hash field.
|
||||
pendingauthsessionDescRegistrationPasswordHash := pendingauthsessionFields[8].Descriptor()
|
||||
// pendingauthsession.DefaultRegistrationPasswordHash holds the default value on creation for the registration_password_hash field.
|
||||
pendingauthsession.DefaultRegistrationPasswordHash = pendingauthsessionDescRegistrationPasswordHash.Default.(string)
|
||||
// pendingauthsessionDescUpstreamIdentityClaims is the schema descriptor for upstream_identity_claims field.
|
||||
pendingauthsessionDescUpstreamIdentityClaims := pendingauthsessionFields[9].Descriptor()
|
||||
// pendingauthsession.DefaultUpstreamIdentityClaims holds the default value on creation for the upstream_identity_claims field.
|
||||
pendingauthsession.DefaultUpstreamIdentityClaims = pendingauthsessionDescUpstreamIdentityClaims.Default.(func() map[string]interface{})
|
||||
// pendingauthsessionDescLocalFlowState is the schema descriptor for local_flow_state field.
|
||||
pendingauthsessionDescLocalFlowState := pendingauthsessionFields[10].Descriptor()
|
||||
// pendingauthsession.DefaultLocalFlowState holds the default value on creation for the local_flow_state field.
|
||||
pendingauthsession.DefaultLocalFlowState = pendingauthsessionDescLocalFlowState.Default.(func() map[string]interface{})
|
||||
// pendingauthsessionDescBrowserSessionKey is the schema descriptor for browser_session_key field.
|
||||
pendingauthsessionDescBrowserSessionKey := pendingauthsessionFields[11].Descriptor()
|
||||
// pendingauthsession.DefaultBrowserSessionKey holds the default value on creation for the browser_session_key field.
|
||||
pendingauthsession.DefaultBrowserSessionKey = pendingauthsessionDescBrowserSessionKey.Default.(string)
|
||||
// pendingauthsessionDescCompletionCodeHash is the schema descriptor for completion_code_hash field.
|
||||
pendingauthsessionDescCompletionCodeHash := pendingauthsessionFields[12].Descriptor()
|
||||
// pendingauthsession.DefaultCompletionCodeHash holds the default value on creation for the completion_code_hash field.
|
||||
pendingauthsession.DefaultCompletionCodeHash = pendingauthsessionDescCompletionCodeHash.Default.(string)
|
||||
promocodeFields := schema.PromoCode{}.Fields()
|
||||
_ = promocodeFields
|
||||
// promocodeDescCode is the schema descriptor for code field.
|
||||
@ -1297,20 +1553,26 @@ func init() {
|
||||
userDescTotpEnabled := userFields[9].Descriptor()
|
||||
// user.DefaultTotpEnabled holds the default value on creation for the totp_enabled field.
|
||||
user.DefaultTotpEnabled = userDescTotpEnabled.Default.(bool)
|
||||
// userDescSignupSource is the schema descriptor for signup_source field.
|
||||
userDescSignupSource := userFields[11].Descriptor()
|
||||
// user.DefaultSignupSource holds the default value on creation for the signup_source field.
|
||||
user.DefaultSignupSource = userDescSignupSource.Default.(string)
|
||||
// user.SignupSourceValidator is a validator for the "signup_source" field. It is called by the builders before save.
|
||||
user.SignupSourceValidator = userDescSignupSource.Validators[0].(func(string) error)
|
||||
// userDescBalanceNotifyEnabled is the schema descriptor for balance_notify_enabled field.
|
||||
userDescBalanceNotifyEnabled := userFields[11].Descriptor()
|
||||
userDescBalanceNotifyEnabled := userFields[14].Descriptor()
|
||||
// user.DefaultBalanceNotifyEnabled holds the default value on creation for the balance_notify_enabled field.
|
||||
user.DefaultBalanceNotifyEnabled = userDescBalanceNotifyEnabled.Default.(bool)
|
||||
// userDescBalanceNotifyThresholdType is the schema descriptor for balance_notify_threshold_type field.
|
||||
userDescBalanceNotifyThresholdType := userFields[12].Descriptor()
|
||||
userDescBalanceNotifyThresholdType := userFields[15].Descriptor()
|
||||
// user.DefaultBalanceNotifyThresholdType holds the default value on creation for the balance_notify_threshold_type field.
|
||||
user.DefaultBalanceNotifyThresholdType = userDescBalanceNotifyThresholdType.Default.(string)
|
||||
// userDescBalanceNotifyExtraEmails is the schema descriptor for balance_notify_extra_emails field.
|
||||
userDescBalanceNotifyExtraEmails := userFields[14].Descriptor()
|
||||
userDescBalanceNotifyExtraEmails := userFields[17].Descriptor()
|
||||
// user.DefaultBalanceNotifyExtraEmails holds the default value on creation for the balance_notify_extra_emails field.
|
||||
user.DefaultBalanceNotifyExtraEmails = userDescBalanceNotifyExtraEmails.Default.(string)
|
||||
// userDescTotalRecharged is the schema descriptor for total_recharged field.
|
||||
userDescTotalRecharged := userFields[15].Descriptor()
|
||||
userDescTotalRecharged := userFields[18].Descriptor()
|
||||
// user.DefaultTotalRecharged holds the default value on creation for the total_recharged field.
|
||||
user.DefaultTotalRecharged = userDescTotalRecharged.Default.(float64)
|
||||
userallowedgroupFields := schema.UserAllowedGroup{}.Fields()
|
||||
|
||||
94
backend/ent/schema/auth_identity.go
Normal file
94
backend/ent/schema/auth_identity.go
Normal file
@ -0,0 +1,94 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
var authProviderTypes = map[string]struct{}{
|
||||
"email": {},
|
||||
"linuxdo": {},
|
||||
"oidc": {},
|
||||
"wechat": {},
|
||||
}
|
||||
|
||||
func validateAuthProviderType(value string) error {
|
||||
if _, ok := authProviderTypes[value]; ok {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid auth provider type %q", value)
|
||||
}
|
||||
|
||||
// AuthIdentity stores the canonical login identity for an account.
|
||||
type AuthIdentity struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (AuthIdentity) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "auth_identities"},
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentity) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
mixins.TimeMixin{},
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentity) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int64("user_id"),
|
||||
field.String("provider_type").
|
||||
MaxLen(20).
|
||||
NotEmpty().
|
||||
Validate(validateAuthProviderType),
|
||||
field.String("provider_key").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("provider_subject").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.Time("verified_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.String("issuer").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.JSON("metadata", map[string]any{}).
|
||||
Default(func() map[string]any { return map[string]any{} }).
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentity) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("user", User.Type).
|
||||
Ref("auth_identities").
|
||||
Field("user_id").
|
||||
Required().
|
||||
Unique(),
|
||||
edge.To("channels", AuthIdentityChannel.Type).
|
||||
Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
edge.To("adoption_decisions", IdentityAdoptionDecision.Type),
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentity) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("provider_type", "provider_key", "provider_subject").Unique(),
|
||||
index.Fields("user_id"),
|
||||
index.Fields("user_id", "provider_type"),
|
||||
}
|
||||
}
|
||||
72
backend/ent/schema/auth_identity_channel.go
Normal file
72
backend/ent/schema/auth_identity_channel.go
Normal file
@ -0,0 +1,72 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// AuthIdentityChannel stores channel-scoped identifiers for a canonical identity.
|
||||
type AuthIdentityChannel struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (AuthIdentityChannel) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "auth_identity_channels"},
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentityChannel) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
mixins.TimeMixin{},
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentityChannel) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int64("identity_id"),
|
||||
field.String("provider_type").
|
||||
MaxLen(20).
|
||||
NotEmpty().
|
||||
Validate(validateAuthProviderType),
|
||||
field.String("provider_key").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("channel").
|
||||
MaxLen(20).
|
||||
NotEmpty(),
|
||||
field.String("channel_app_id").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("channel_subject").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.JSON("metadata", map[string]any{}).
|
||||
Default(func() map[string]any { return map[string]any{} }).
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentityChannel) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("identity", AuthIdentity.Type).
|
||||
Ref("channels").
|
||||
Field("identity_id").
|
||||
Required().
|
||||
Unique(),
|
||||
}
|
||||
}
|
||||
|
||||
func (AuthIdentityChannel) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("provider_type", "provider_key", "channel", "channel_app_id", "channel_subject").Unique(),
|
||||
index.Fields("identity_id"),
|
||||
}
|
||||
}
|
||||
168
backend/ent/schema/auth_identity_schema_test.go
Normal file
168
backend/ent/schema/auth_identity_schema_test.go
Normal file
@ -0,0 +1,168 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/entc/load"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthIdentityFoundationSchemas(t *testing.T) {
|
||||
spec, err := (&load.Config{Path: "."}).Load()
|
||||
require.NoError(t, err)
|
||||
|
||||
schemas := map[string]*load.Schema{}
|
||||
for _, schema := range spec.Schemas {
|
||||
schemas[schema.Name] = schema
|
||||
}
|
||||
|
||||
authIdentity := requireSchema(t, schemas, "AuthIdentity")
|
||||
requireSchemaFields(t, authIdentity,
|
||||
"user_id",
|
||||
"provider_type",
|
||||
"provider_key",
|
||||
"provider_subject",
|
||||
"verified_at",
|
||||
"issuer",
|
||||
"metadata",
|
||||
)
|
||||
requireHasUniqueIndex(t, authIdentity, "provider_type", "provider_key", "provider_subject")
|
||||
|
||||
authIdentityChannel := requireSchema(t, schemas, "AuthIdentityChannel")
|
||||
requireSchemaFields(t, authIdentityChannel,
|
||||
"identity_id",
|
||||
"provider_type",
|
||||
"provider_key",
|
||||
"channel",
|
||||
"channel_app_id",
|
||||
"channel_subject",
|
||||
"metadata",
|
||||
)
|
||||
requireHasUniqueIndex(t, authIdentityChannel, "provider_type", "provider_key", "channel", "channel_app_id", "channel_subject")
|
||||
|
||||
pendingAuthSession := requireSchema(t, schemas, "PendingAuthSession")
|
||||
requireSchemaFields(t, pendingAuthSession,
|
||||
"intent",
|
||||
"provider_type",
|
||||
"provider_key",
|
||||
"provider_subject",
|
||||
"target_user_id",
|
||||
"redirect_to",
|
||||
"resolved_email",
|
||||
"registration_password_hash",
|
||||
"upstream_identity_claims",
|
||||
"local_flow_state",
|
||||
"browser_session_key",
|
||||
"completion_code_hash",
|
||||
"completion_code_expires_at",
|
||||
"email_verified_at",
|
||||
"password_verified_at",
|
||||
"totp_verified_at",
|
||||
"expires_at",
|
||||
"consumed_at",
|
||||
)
|
||||
|
||||
adoptionDecision := requireSchema(t, schemas, "IdentityAdoptionDecision")
|
||||
requireSchemaFields(t, adoptionDecision,
|
||||
"pending_auth_session_id",
|
||||
"identity_id",
|
||||
"adopt_display_name",
|
||||
"adopt_avatar",
|
||||
"decided_at",
|
||||
)
|
||||
requireHasUniqueIndex(t, adoptionDecision, "pending_auth_session_id")
|
||||
|
||||
userSchema := requireSchema(t, schemas, "User")
|
||||
requireSchemaFields(t, userSchema, "signup_source", "last_login_at", "last_active_at")
|
||||
signupSource := requireSchemaField(t, userSchema, "signup_source")
|
||||
require.Equal(t, field.TypeString, signupSource.Info.Type)
|
||||
require.True(t, signupSource.Default)
|
||||
require.Equal(t, "email", signupSource.DefaultValue)
|
||||
require.Equal(t, 1, signupSource.Validators)
|
||||
|
||||
validator := requireStringFieldValidator(t, User{}.Fields(), "signup_source")
|
||||
for _, value := range []string{"email", "linuxdo", "wechat", "oidc"} {
|
||||
require.NoError(t, validator(value))
|
||||
}
|
||||
require.Error(t, validator("github"))
|
||||
}
|
||||
|
||||
func requireSchema(t *testing.T, schemas map[string]*load.Schema, name string) *load.Schema {
|
||||
t.Helper()
|
||||
|
||||
schema, ok := schemas[name]
|
||||
require.True(t, ok, "schema %s should exist", name)
|
||||
return schema
|
||||
}
|
||||
|
||||
func requireSchemaFields(t *testing.T, schema *load.Schema, names ...string) {
|
||||
t.Helper()
|
||||
|
||||
fields := map[string]struct{}{}
|
||||
for _, field := range schema.Fields {
|
||||
fields[field.Name] = struct{}{}
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
_, ok := fields[name]
|
||||
require.True(t, ok, "schema %s should include field %s", schema.Name, name)
|
||||
}
|
||||
}
|
||||
|
||||
func requireSchemaField(t *testing.T, schema *load.Schema, name string) *load.Field {
|
||||
t.Helper()
|
||||
|
||||
for _, schemaField := range schema.Fields {
|
||||
if schemaField.Name == name {
|
||||
return schemaField
|
||||
}
|
||||
}
|
||||
|
||||
require.Failf(t, "missing schema field", "schema %s should include field %s", schema.Name, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func requireStringFieldValidator(t *testing.T, fields []ent.Field, name string) func(string) error {
|
||||
t.Helper()
|
||||
|
||||
for _, entField := range fields {
|
||||
descriptor := entField.Descriptor()
|
||||
if descriptor.Name != name {
|
||||
continue
|
||||
}
|
||||
require.NotEmpty(t, descriptor.Validators, "field %s should include a validator", name)
|
||||
validator, ok := descriptor.Validators[0].(func(string) error)
|
||||
require.True(t, ok, "field %s validator should be func(string) error", name)
|
||||
return validator
|
||||
}
|
||||
|
||||
require.Failf(t, "missing field validator", "schema should include field %s", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func requireHasUniqueIndex(t *testing.T, schema *load.Schema, fields ...string) {
|
||||
t.Helper()
|
||||
|
||||
for _, index := range schema.Indexes {
|
||||
if !index.Unique {
|
||||
continue
|
||||
}
|
||||
if len(index.Fields) != len(fields) {
|
||||
continue
|
||||
}
|
||||
match := true
|
||||
for i := range fields {
|
||||
if index.Fields[i] != fields[i] {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if match {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
require.Failf(t, "missing unique index", "schema %s should include unique index on %v", schema.Name, fields)
|
||||
}
|
||||
70
backend/ent/schema/identity_adoption_decision.go
Normal file
70
backend/ent/schema/identity_adoption_decision.go
Normal file
@ -0,0 +1,70 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// IdentityAdoptionDecision stores the one-time profile adoption choice captured during a pending auth flow.
|
||||
type IdentityAdoptionDecision struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (IdentityAdoptionDecision) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "identity_adoption_decisions"},
|
||||
}
|
||||
}
|
||||
|
||||
func (IdentityAdoptionDecision) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
mixins.TimeMixin{},
|
||||
}
|
||||
}
|
||||
|
||||
func (IdentityAdoptionDecision) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int64("pending_auth_session_id"),
|
||||
field.Int64("identity_id").
|
||||
Optional().
|
||||
Nillable(),
|
||||
field.Bool("adopt_display_name").
|
||||
Default(false),
|
||||
field.Bool("adopt_avatar").
|
||||
Default(false),
|
||||
field.Time("decided_at").
|
||||
Immutable().
|
||||
Default(time.Now).
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (IdentityAdoptionDecision) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("pending_auth_session", PendingAuthSession.Type).
|
||||
Ref("adoption_decision").
|
||||
Field("pending_auth_session_id").
|
||||
Required().
|
||||
Unique(),
|
||||
edge.From("identity", AuthIdentity.Type).
|
||||
Ref("adoption_decisions").
|
||||
Field("identity_id").
|
||||
Unique(),
|
||||
}
|
||||
}
|
||||
|
||||
func (IdentityAdoptionDecision) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("pending_auth_session_id").Unique(),
|
||||
index.Fields("identity_id"),
|
||||
}
|
||||
}
|
||||
@ -91,6 +91,13 @@ func (PaymentOrder) Fields() []ent.Field {
|
||||
Optional().
|
||||
Nillable().
|
||||
MaxLen(64),
|
||||
field.String("provider_key").
|
||||
Optional().
|
||||
Nillable().
|
||||
MaxLen(30),
|
||||
field.JSON("provider_snapshot", map[string]any{}).
|
||||
Optional().
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
|
||||
// 状态
|
||||
field.String("status").
|
||||
@ -178,7 +185,9 @@ func (PaymentOrder) Edges() []ent.Edge {
|
||||
|
||||
func (PaymentOrder) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("out_trade_no"),
|
||||
index.Fields("out_trade_no").
|
||||
Unique().
|
||||
Annotations(entsql.IndexWhere("out_trade_no <> ''")),
|
||||
index.Fields("user_id"),
|
||||
index.Fields("status"),
|
||||
index.Fields("expires_at"),
|
||||
|
||||
135
backend/ent/schema/pending_auth_session.go
Normal file
135
backend/ent/schema/pending_auth_session.go
Normal file
@ -0,0 +1,135 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
var pendingAuthIntents = map[string]struct{}{
|
||||
"login": {},
|
||||
"bind_current_user": {},
|
||||
"adopt_existing_user_by_email": {},
|
||||
}
|
||||
|
||||
func validatePendingAuthIntent(value string) error {
|
||||
if _, ok := pendingAuthIntents[value]; ok {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid pending auth intent %q", value)
|
||||
}
|
||||
|
||||
// PendingAuthSession stores a short-lived post-auth decision session.
|
||||
type PendingAuthSession struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (PendingAuthSession) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
entsql.Annotation{Table: "pending_auth_sessions"},
|
||||
}
|
||||
}
|
||||
|
||||
func (PendingAuthSession) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
mixins.TimeMixin{},
|
||||
}
|
||||
}
|
||||
|
||||
func (PendingAuthSession) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.String("session_token").
|
||||
MaxLen(255).
|
||||
NotEmpty(),
|
||||
field.String("intent").
|
||||
MaxLen(40).
|
||||
NotEmpty().
|
||||
Validate(validatePendingAuthIntent),
|
||||
field.String("provider_type").
|
||||
MaxLen(20).
|
||||
NotEmpty().
|
||||
Validate(validateAuthProviderType),
|
||||
field.String("provider_key").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("provider_subject").
|
||||
NotEmpty().
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.Int64("target_user_id").
|
||||
Optional().
|
||||
Nillable(),
|
||||
field.String("redirect_to").
|
||||
Default("").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("resolved_email").
|
||||
Default("").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("registration_password_hash").
|
||||
Default("").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.JSON("upstream_identity_claims", map[string]any{}).
|
||||
Default(func() map[string]any { return map[string]any{} }).
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
field.JSON("local_flow_state", map[string]any{}).
|
||||
Default(func() map[string]any { return map[string]any{} }).
|
||||
SchemaType(map[string]string{dialect.Postgres: "jsonb"}),
|
||||
field.String("browser_session_key").
|
||||
Default("").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.String("completion_code_hash").
|
||||
Default("").
|
||||
SchemaType(map[string]string{dialect.Postgres: "text"}),
|
||||
field.Time("completion_code_expires_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("email_verified_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("password_verified_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("totp_verified_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("expires_at").
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("consumed_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (PendingAuthSession) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("target_user", User.Type).
|
||||
Ref("pending_auth_sessions").
|
||||
Field("target_user_id").
|
||||
Unique(),
|
||||
edge.To("adoption_decision", IdentityAdoptionDecision.Type).
|
||||
Annotations(entsql.OnDelete(entsql.Cascade)).
|
||||
Unique(),
|
||||
}
|
||||
}
|
||||
|
||||
func (PendingAuthSession) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("session_token").Unique(),
|
||||
index.Fields("target_user_id"),
|
||||
index.Fields("expires_at"),
|
||||
index.Fields("provider_type", "provider_key", "provider_subject"),
|
||||
index.Fields("completion_code_hash"),
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
@ -72,6 +74,24 @@ func (User) Fields() []ent.Field {
|
||||
field.Time("totp_enabled_at").
|
||||
Optional().
|
||||
Nillable(),
|
||||
field.String("signup_source").
|
||||
Validate(func(value string) error {
|
||||
switch value {
|
||||
case "email", "linuxdo", "wechat", "oidc":
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("must be one of email, linuxdo, wechat, oidc")
|
||||
}
|
||||
}).
|
||||
Default("email"),
|
||||
field.Time("last_login_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
field.Time("last_active_at").
|
||||
Optional().
|
||||
Nillable().
|
||||
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
|
||||
|
||||
// 余额不足通知
|
||||
field.Bool("balance_notify_enabled").
|
||||
@ -104,6 +124,9 @@ func (User) Edges() []ent.Edge {
|
||||
edge.To("attribute_values", UserAttributeValue.Type),
|
||||
edge.To("promo_code_usages", PromoCodeUsage.Type),
|
||||
edge.To("payment_orders", PaymentOrder.Type),
|
||||
edge.To("auth_identities", AuthIdentity.Type).
|
||||
Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
edge.To("pending_auth_sessions", PendingAuthSession.Type),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -24,18 +24,26 @@ type Tx struct {
|
||||
Announcement *AnnouncementClient
|
||||
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
|
||||
AnnouncementRead *AnnouncementReadClient
|
||||
// AuthIdentity is the client for interacting with the AuthIdentity builders.
|
||||
AuthIdentity *AuthIdentityClient
|
||||
// AuthIdentityChannel is the client for interacting with the AuthIdentityChannel builders.
|
||||
AuthIdentityChannel *AuthIdentityChannelClient
|
||||
// ErrorPassthroughRule is the client for interacting with the ErrorPassthroughRule builders.
|
||||
ErrorPassthroughRule *ErrorPassthroughRuleClient
|
||||
// Group is the client for interacting with the Group builders.
|
||||
Group *GroupClient
|
||||
// IdempotencyRecord is the client for interacting with the IdempotencyRecord builders.
|
||||
IdempotencyRecord *IdempotencyRecordClient
|
||||
// IdentityAdoptionDecision is the client for interacting with the IdentityAdoptionDecision builders.
|
||||
IdentityAdoptionDecision *IdentityAdoptionDecisionClient
|
||||
// PaymentAuditLog is the client for interacting with the PaymentAuditLog builders.
|
||||
PaymentAuditLog *PaymentAuditLogClient
|
||||
// PaymentOrder is the client for interacting with the PaymentOrder builders.
|
||||
PaymentOrder *PaymentOrderClient
|
||||
// PaymentProviderInstance is the client for interacting with the PaymentProviderInstance builders.
|
||||
PaymentProviderInstance *PaymentProviderInstanceClient
|
||||
// PendingAuthSession is the client for interacting with the PendingAuthSession builders.
|
||||
PendingAuthSession *PendingAuthSessionClient
|
||||
// PromoCode is the client for interacting with the PromoCode builders.
|
||||
PromoCode *PromoCodeClient
|
||||
// PromoCodeUsage is the client for interacting with the PromoCodeUsage builders.
|
||||
@ -202,12 +210,16 @@ func (tx *Tx) init() {
|
||||
tx.AccountGroup = NewAccountGroupClient(tx.config)
|
||||
tx.Announcement = NewAnnouncementClient(tx.config)
|
||||
tx.AnnouncementRead = NewAnnouncementReadClient(tx.config)
|
||||
tx.AuthIdentity = NewAuthIdentityClient(tx.config)
|
||||
tx.AuthIdentityChannel = NewAuthIdentityChannelClient(tx.config)
|
||||
tx.ErrorPassthroughRule = NewErrorPassthroughRuleClient(tx.config)
|
||||
tx.Group = NewGroupClient(tx.config)
|
||||
tx.IdempotencyRecord = NewIdempotencyRecordClient(tx.config)
|
||||
tx.IdentityAdoptionDecision = NewIdentityAdoptionDecisionClient(tx.config)
|
||||
tx.PaymentAuditLog = NewPaymentAuditLogClient(tx.config)
|
||||
tx.PaymentOrder = NewPaymentOrderClient(tx.config)
|
||||
tx.PaymentProviderInstance = NewPaymentProviderInstanceClient(tx.config)
|
||||
tx.PendingAuthSession = NewPendingAuthSessionClient(tx.config)
|
||||
tx.PromoCode = NewPromoCodeClient(tx.config)
|
||||
tx.PromoCodeUsage = NewPromoCodeUsageClient(tx.config)
|
||||
tx.Proxy = NewProxyClient(tx.config)
|
||||
|
||||
@ -45,6 +45,12 @@ type User struct {
|
||||
TotpEnabled bool `json:"totp_enabled,omitempty"`
|
||||
// TotpEnabledAt holds the value of the "totp_enabled_at" field.
|
||||
TotpEnabledAt *time.Time `json:"totp_enabled_at,omitempty"`
|
||||
// SignupSource holds the value of the "signup_source" field.
|
||||
SignupSource string `json:"signup_source,omitempty"`
|
||||
// LastLoginAt holds the value of the "last_login_at" field.
|
||||
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
|
||||
// LastActiveAt holds the value of the "last_active_at" field.
|
||||
LastActiveAt *time.Time `json:"last_active_at,omitempty"`
|
||||
// BalanceNotifyEnabled holds the value of the "balance_notify_enabled" field.
|
||||
BalanceNotifyEnabled bool `json:"balance_notify_enabled,omitempty"`
|
||||
// BalanceNotifyThresholdType holds the value of the "balance_notify_threshold_type" field.
|
||||
@ -83,11 +89,15 @@ type UserEdges struct {
|
||||
PromoCodeUsages []*PromoCodeUsage `json:"promo_code_usages,omitempty"`
|
||||
// PaymentOrders holds the value of the payment_orders edge.
|
||||
PaymentOrders []*PaymentOrder `json:"payment_orders,omitempty"`
|
||||
// AuthIdentities holds the value of the auth_identities edge.
|
||||
AuthIdentities []*AuthIdentity `json:"auth_identities,omitempty"`
|
||||
// PendingAuthSessions holds the value of the pending_auth_sessions edge.
|
||||
PendingAuthSessions []*PendingAuthSession `json:"pending_auth_sessions,omitempty"`
|
||||
// UserAllowedGroups holds the value of the user_allowed_groups edge.
|
||||
UserAllowedGroups []*UserAllowedGroup `json:"user_allowed_groups,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [11]bool
|
||||
loadedTypes [13]bool
|
||||
}
|
||||
|
||||
// APIKeysOrErr returns the APIKeys value or an error if the edge
|
||||
@ -180,10 +190,28 @@ func (e UserEdges) PaymentOrdersOrErr() ([]*PaymentOrder, error) {
|
||||
return nil, &NotLoadedError{edge: "payment_orders"}
|
||||
}
|
||||
|
||||
// AuthIdentitiesOrErr returns the AuthIdentities value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) AuthIdentitiesOrErr() ([]*AuthIdentity, error) {
|
||||
if e.loadedTypes[10] {
|
||||
return e.AuthIdentities, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "auth_identities"}
|
||||
}
|
||||
|
||||
// PendingAuthSessionsOrErr returns the PendingAuthSessions value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) PendingAuthSessionsOrErr() ([]*PendingAuthSession, error) {
|
||||
if e.loadedTypes[11] {
|
||||
return e.PendingAuthSessions, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "pending_auth_sessions"}
|
||||
}
|
||||
|
||||
// UserAllowedGroupsOrErr returns the UserAllowedGroups value or an error if the edge
|
||||
// was not loaded in eager-loading.
|
||||
func (e UserEdges) UserAllowedGroupsOrErr() ([]*UserAllowedGroup, error) {
|
||||
if e.loadedTypes[10] {
|
||||
if e.loadedTypes[12] {
|
||||
return e.UserAllowedGroups, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "user_allowed_groups"}
|
||||
@ -200,9 +228,9 @@ func (*User) scanValues(columns []string) ([]any, error) {
|
||||
values[i] = new(sql.NullFloat64)
|
||||
case user.FieldID, user.FieldConcurrency:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case user.FieldEmail, user.FieldPasswordHash, user.FieldRole, user.FieldStatus, user.FieldUsername, user.FieldNotes, user.FieldTotpSecretEncrypted, user.FieldBalanceNotifyThresholdType, user.FieldBalanceNotifyExtraEmails:
|
||||
case user.FieldEmail, user.FieldPasswordHash, user.FieldRole, user.FieldStatus, user.FieldUsername, user.FieldNotes, user.FieldTotpSecretEncrypted, user.FieldSignupSource, user.FieldBalanceNotifyThresholdType, user.FieldBalanceNotifyExtraEmails:
|
||||
values[i] = new(sql.NullString)
|
||||
case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldDeletedAt, user.FieldTotpEnabledAt:
|
||||
case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldDeletedAt, user.FieldTotpEnabledAt, user.FieldLastLoginAt, user.FieldLastActiveAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
@ -312,6 +340,26 @@ func (_m *User) assignValues(columns []string, values []any) error {
|
||||
_m.TotpEnabledAt = new(time.Time)
|
||||
*_m.TotpEnabledAt = value.Time
|
||||
}
|
||||
case user.FieldSignupSource:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field signup_source", values[i])
|
||||
} else if value.Valid {
|
||||
_m.SignupSource = value.String
|
||||
}
|
||||
case user.FieldLastLoginAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field last_login_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.LastLoginAt = new(time.Time)
|
||||
*_m.LastLoginAt = value.Time
|
||||
}
|
||||
case user.FieldLastActiveAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field last_active_at", values[i])
|
||||
} else if value.Valid {
|
||||
_m.LastActiveAt = new(time.Time)
|
||||
*_m.LastActiveAt = value.Time
|
||||
}
|
||||
case user.FieldBalanceNotifyEnabled:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field balance_notify_enabled", values[i])
|
||||
@ -406,6 +454,16 @@ func (_m *User) QueryPaymentOrders() *PaymentOrderQuery {
|
||||
return NewUserClient(_m.config).QueryPaymentOrders(_m)
|
||||
}
|
||||
|
||||
// QueryAuthIdentities queries the "auth_identities" edge of the User entity.
|
||||
func (_m *User) QueryAuthIdentities() *AuthIdentityQuery {
|
||||
return NewUserClient(_m.config).QueryAuthIdentities(_m)
|
||||
}
|
||||
|
||||
// QueryPendingAuthSessions queries the "pending_auth_sessions" edge of the User entity.
|
||||
func (_m *User) QueryPendingAuthSessions() *PendingAuthSessionQuery {
|
||||
return NewUserClient(_m.config).QueryPendingAuthSessions(_m)
|
||||
}
|
||||
|
||||
// QueryUserAllowedGroups queries the "user_allowed_groups" edge of the User entity.
|
||||
func (_m *User) QueryUserAllowedGroups() *UserAllowedGroupQuery {
|
||||
return NewUserClient(_m.config).QueryUserAllowedGroups(_m)
|
||||
@ -482,6 +540,19 @@ func (_m *User) String() string {
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("signup_source=")
|
||||
builder.WriteString(_m.SignupSource)
|
||||
builder.WriteString(", ")
|
||||
if v := _m.LastLoginAt; v != nil {
|
||||
builder.WriteString("last_login_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
if v := _m.LastActiveAt; v != nil {
|
||||
builder.WriteString("last_active_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("balance_notify_enabled=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.BalanceNotifyEnabled))
|
||||
builder.WriteString(", ")
|
||||
|
||||
@ -43,6 +43,12 @@ const (
|
||||
FieldTotpEnabled = "totp_enabled"
|
||||
// FieldTotpEnabledAt holds the string denoting the totp_enabled_at field in the database.
|
||||
FieldTotpEnabledAt = "totp_enabled_at"
|
||||
// FieldSignupSource holds the string denoting the signup_source field in the database.
|
||||
FieldSignupSource = "signup_source"
|
||||
// FieldLastLoginAt holds the string denoting the last_login_at field in the database.
|
||||
FieldLastLoginAt = "last_login_at"
|
||||
// FieldLastActiveAt holds the string denoting the last_active_at field in the database.
|
||||
FieldLastActiveAt = "last_active_at"
|
||||
// FieldBalanceNotifyEnabled holds the string denoting the balance_notify_enabled field in the database.
|
||||
FieldBalanceNotifyEnabled = "balance_notify_enabled"
|
||||
// FieldBalanceNotifyThresholdType holds the string denoting the balance_notify_threshold_type field in the database.
|
||||
@ -73,6 +79,10 @@ const (
|
||||
EdgePromoCodeUsages = "promo_code_usages"
|
||||
// EdgePaymentOrders holds the string denoting the payment_orders edge name in mutations.
|
||||
EdgePaymentOrders = "payment_orders"
|
||||
// EdgeAuthIdentities holds the string denoting the auth_identities edge name in mutations.
|
||||
EdgeAuthIdentities = "auth_identities"
|
||||
// EdgePendingAuthSessions holds the string denoting the pending_auth_sessions edge name in mutations.
|
||||
EdgePendingAuthSessions = "pending_auth_sessions"
|
||||
// EdgeUserAllowedGroups holds the string denoting the user_allowed_groups edge name in mutations.
|
||||
EdgeUserAllowedGroups = "user_allowed_groups"
|
||||
// Table holds the table name of the user in the database.
|
||||
@ -145,6 +155,20 @@ const (
|
||||
PaymentOrdersInverseTable = "payment_orders"
|
||||
// PaymentOrdersColumn is the table column denoting the payment_orders relation/edge.
|
||||
PaymentOrdersColumn = "user_id"
|
||||
// AuthIdentitiesTable is the table that holds the auth_identities relation/edge.
|
||||
AuthIdentitiesTable = "auth_identities"
|
||||
// AuthIdentitiesInverseTable is the table name for the AuthIdentity entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "authidentity" package.
|
||||
AuthIdentitiesInverseTable = "auth_identities"
|
||||
// AuthIdentitiesColumn is the table column denoting the auth_identities relation/edge.
|
||||
AuthIdentitiesColumn = "user_id"
|
||||
// PendingAuthSessionsTable is the table that holds the pending_auth_sessions relation/edge.
|
||||
PendingAuthSessionsTable = "pending_auth_sessions"
|
||||
// PendingAuthSessionsInverseTable is the table name for the PendingAuthSession entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "pendingauthsession" package.
|
||||
PendingAuthSessionsInverseTable = "pending_auth_sessions"
|
||||
// PendingAuthSessionsColumn is the table column denoting the pending_auth_sessions relation/edge.
|
||||
PendingAuthSessionsColumn = "target_user_id"
|
||||
// UserAllowedGroupsTable is the table that holds the user_allowed_groups relation/edge.
|
||||
UserAllowedGroupsTable = "user_allowed_groups"
|
||||
// UserAllowedGroupsInverseTable is the table name for the UserAllowedGroup entity.
|
||||
@ -171,6 +195,9 @@ var Columns = []string{
|
||||
FieldTotpSecretEncrypted,
|
||||
FieldTotpEnabled,
|
||||
FieldTotpEnabledAt,
|
||||
FieldSignupSource,
|
||||
FieldLastLoginAt,
|
||||
FieldLastActiveAt,
|
||||
FieldBalanceNotifyEnabled,
|
||||
FieldBalanceNotifyThresholdType,
|
||||
FieldBalanceNotifyThreshold,
|
||||
@ -232,6 +259,10 @@ var (
|
||||
DefaultNotes string
|
||||
// DefaultTotpEnabled holds the default value on creation for the "totp_enabled" field.
|
||||
DefaultTotpEnabled bool
|
||||
// DefaultSignupSource holds the default value on creation for the "signup_source" field.
|
||||
DefaultSignupSource string
|
||||
// SignupSourceValidator is a validator for the "signup_source" field. It is called by the builders before save.
|
||||
SignupSourceValidator func(string) error
|
||||
// DefaultBalanceNotifyEnabled holds the default value on creation for the "balance_notify_enabled" field.
|
||||
DefaultBalanceNotifyEnabled bool
|
||||
// DefaultBalanceNotifyThresholdType holds the default value on creation for the "balance_notify_threshold_type" field.
|
||||
@ -320,6 +351,21 @@ func ByTotpEnabledAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldTotpEnabledAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySignupSource orders the results by the signup_source field.
|
||||
func BySignupSource(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSignupSource, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByLastLoginAt orders the results by the last_login_at field.
|
||||
func ByLastLoginAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldLastLoginAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByLastActiveAt orders the results by the last_active_at field.
|
||||
func ByLastActiveAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldLastActiveAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByBalanceNotifyEnabled orders the results by the balance_notify_enabled field.
|
||||
func ByBalanceNotifyEnabled(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldBalanceNotifyEnabled, opts...).ToFunc()
|
||||
@ -485,6 +531,34 @@ func ByPaymentOrders(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
}
|
||||
}
|
||||
|
||||
// ByAuthIdentitiesCount orders the results by auth_identities count.
|
||||
func ByAuthIdentitiesCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newAuthIdentitiesStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByAuthIdentities orders the results by auth_identities terms.
|
||||
func ByAuthIdentities(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newAuthIdentitiesStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByPendingAuthSessionsCount orders the results by pending_auth_sessions count.
|
||||
func ByPendingAuthSessionsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborsCount(s, newPendingAuthSessionsStep(), opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByPendingAuthSessions orders the results by pending_auth_sessions terms.
|
||||
func ByPendingAuthSessions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newPendingAuthSessionsStep(), append([]sql.OrderTerm{term}, terms...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// ByUserAllowedGroupsCount orders the results by user_allowed_groups count.
|
||||
func ByUserAllowedGroupsCount(opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
@ -568,6 +642,20 @@ func newPaymentOrdersStep() *sqlgraph.Step {
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, PaymentOrdersTable, PaymentOrdersColumn),
|
||||
)
|
||||
}
|
||||
func newAuthIdentitiesStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(AuthIdentitiesInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AuthIdentitiesTable, AuthIdentitiesColumn),
|
||||
)
|
||||
}
|
||||
func newPendingAuthSessionsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(PendingAuthSessionsInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, PendingAuthSessionsTable, PendingAuthSessionsColumn),
|
||||
)
|
||||
}
|
||||
func newUserAllowedGroupsStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
|
||||
@ -125,6 +125,21 @@ func TotpEnabledAt(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldTotpEnabledAt, v))
|
||||
}
|
||||
|
||||
// SignupSource applies equality check predicate on the "signup_source" field. It's identical to SignupSourceEQ.
|
||||
func SignupSource(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// LastLoginAt applies equality check predicate on the "last_login_at" field. It's identical to LastLoginAtEQ.
|
||||
func LastLoginAt(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAt applies equality check predicate on the "last_active_at" field. It's identical to LastActiveAtEQ.
|
||||
func LastActiveAt(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// BalanceNotifyEnabled applies equality check predicate on the "balance_notify_enabled" field. It's identical to BalanceNotifyEnabledEQ.
|
||||
func BalanceNotifyEnabled(v bool) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldBalanceNotifyEnabled, v))
|
||||
@ -885,6 +900,171 @@ func TotpEnabledAtNotNil() predicate.User {
|
||||
return predicate.User(sql.FieldNotNull(FieldTotpEnabledAt))
|
||||
}
|
||||
|
||||
// SignupSourceEQ applies the EQ predicate on the "signup_source" field.
|
||||
func SignupSourceEQ(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceNEQ applies the NEQ predicate on the "signup_source" field.
|
||||
func SignupSourceNEQ(v string) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceIn applies the In predicate on the "signup_source" field.
|
||||
func SignupSourceIn(vs ...string) predicate.User {
|
||||
return predicate.User(sql.FieldIn(FieldSignupSource, vs...))
|
||||
}
|
||||
|
||||
// SignupSourceNotIn applies the NotIn predicate on the "signup_source" field.
|
||||
func SignupSourceNotIn(vs ...string) predicate.User {
|
||||
return predicate.User(sql.FieldNotIn(FieldSignupSource, vs...))
|
||||
}
|
||||
|
||||
// SignupSourceGT applies the GT predicate on the "signup_source" field.
|
||||
func SignupSourceGT(v string) predicate.User {
|
||||
return predicate.User(sql.FieldGT(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceGTE applies the GTE predicate on the "signup_source" field.
|
||||
func SignupSourceGTE(v string) predicate.User {
|
||||
return predicate.User(sql.FieldGTE(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceLT applies the LT predicate on the "signup_source" field.
|
||||
func SignupSourceLT(v string) predicate.User {
|
||||
return predicate.User(sql.FieldLT(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceLTE applies the LTE predicate on the "signup_source" field.
|
||||
func SignupSourceLTE(v string) predicate.User {
|
||||
return predicate.User(sql.FieldLTE(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceContains applies the Contains predicate on the "signup_source" field.
|
||||
func SignupSourceContains(v string) predicate.User {
|
||||
return predicate.User(sql.FieldContains(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceHasPrefix applies the HasPrefix predicate on the "signup_source" field.
|
||||
func SignupSourceHasPrefix(v string) predicate.User {
|
||||
return predicate.User(sql.FieldHasPrefix(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceHasSuffix applies the HasSuffix predicate on the "signup_source" field.
|
||||
func SignupSourceHasSuffix(v string) predicate.User {
|
||||
return predicate.User(sql.FieldHasSuffix(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceEqualFold applies the EqualFold predicate on the "signup_source" field.
|
||||
func SignupSourceEqualFold(v string) predicate.User {
|
||||
return predicate.User(sql.FieldEqualFold(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// SignupSourceContainsFold applies the ContainsFold predicate on the "signup_source" field.
|
||||
func SignupSourceContainsFold(v string) predicate.User {
|
||||
return predicate.User(sql.FieldContainsFold(FieldSignupSource, v))
|
||||
}
|
||||
|
||||
// LastLoginAtEQ applies the EQ predicate on the "last_login_at" field.
|
||||
func LastLoginAtEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtNEQ applies the NEQ predicate on the "last_login_at" field.
|
||||
func LastLoginAtNEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtIn applies the In predicate on the "last_login_at" field.
|
||||
func LastLoginAtIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldIn(FieldLastLoginAt, vs...))
|
||||
}
|
||||
|
||||
// LastLoginAtNotIn applies the NotIn predicate on the "last_login_at" field.
|
||||
func LastLoginAtNotIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNotIn(FieldLastLoginAt, vs...))
|
||||
}
|
||||
|
||||
// LastLoginAtGT applies the GT predicate on the "last_login_at" field.
|
||||
func LastLoginAtGT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGT(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtGTE applies the GTE predicate on the "last_login_at" field.
|
||||
func LastLoginAtGTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGTE(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtLT applies the LT predicate on the "last_login_at" field.
|
||||
func LastLoginAtLT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLT(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtLTE applies the LTE predicate on the "last_login_at" field.
|
||||
func LastLoginAtLTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLTE(FieldLastLoginAt, v))
|
||||
}
|
||||
|
||||
// LastLoginAtIsNil applies the IsNil predicate on the "last_login_at" field.
|
||||
func LastLoginAtIsNil() predicate.User {
|
||||
return predicate.User(sql.FieldIsNull(FieldLastLoginAt))
|
||||
}
|
||||
|
||||
// LastLoginAtNotNil applies the NotNil predicate on the "last_login_at" field.
|
||||
func LastLoginAtNotNil() predicate.User {
|
||||
return predicate.User(sql.FieldNotNull(FieldLastLoginAt))
|
||||
}
|
||||
|
||||
// LastActiveAtEQ applies the EQ predicate on the "last_active_at" field.
|
||||
func LastActiveAtEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtNEQ applies the NEQ predicate on the "last_active_at" field.
|
||||
func LastActiveAtNEQ(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNEQ(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtIn applies the In predicate on the "last_active_at" field.
|
||||
func LastActiveAtIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldIn(FieldLastActiveAt, vs...))
|
||||
}
|
||||
|
||||
// LastActiveAtNotIn applies the NotIn predicate on the "last_active_at" field.
|
||||
func LastActiveAtNotIn(vs ...time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldNotIn(FieldLastActiveAt, vs...))
|
||||
}
|
||||
|
||||
// LastActiveAtGT applies the GT predicate on the "last_active_at" field.
|
||||
func LastActiveAtGT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGT(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtGTE applies the GTE predicate on the "last_active_at" field.
|
||||
func LastActiveAtGTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldGTE(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtLT applies the LT predicate on the "last_active_at" field.
|
||||
func LastActiveAtLT(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLT(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtLTE applies the LTE predicate on the "last_active_at" field.
|
||||
func LastActiveAtLTE(v time.Time) predicate.User {
|
||||
return predicate.User(sql.FieldLTE(FieldLastActiveAt, v))
|
||||
}
|
||||
|
||||
// LastActiveAtIsNil applies the IsNil predicate on the "last_active_at" field.
|
||||
func LastActiveAtIsNil() predicate.User {
|
||||
return predicate.User(sql.FieldIsNull(FieldLastActiveAt))
|
||||
}
|
||||
|
||||
// LastActiveAtNotNil applies the NotNil predicate on the "last_active_at" field.
|
||||
func LastActiveAtNotNil() predicate.User {
|
||||
return predicate.User(sql.FieldNotNull(FieldLastActiveAt))
|
||||
}
|
||||
|
||||
// BalanceNotifyEnabledEQ applies the EQ predicate on the "balance_notify_enabled" field.
|
||||
func BalanceNotifyEnabledEQ(v bool) predicate.User {
|
||||
return predicate.User(sql.FieldEQ(FieldBalanceNotifyEnabled, v))
|
||||
@ -1345,6 +1525,52 @@ func HasPaymentOrdersWith(preds ...predicate.PaymentOrder) predicate.User {
|
||||
})
|
||||
}
|
||||
|
||||
// HasAuthIdentities applies the HasEdge predicate on the "auth_identities" edge.
|
||||
func HasAuthIdentities() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, AuthIdentitiesTable, AuthIdentitiesColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasAuthIdentitiesWith applies the HasEdge predicate on the "auth_identities" edge with a given conditions (other predicates).
|
||||
func HasAuthIdentitiesWith(preds ...predicate.AuthIdentity) predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := newAuthIdentitiesStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasPendingAuthSessions applies the HasEdge predicate on the "pending_auth_sessions" edge.
|
||||
func HasPendingAuthSessions() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, PendingAuthSessionsTable, PendingAuthSessionsColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasPendingAuthSessionsWith applies the HasEdge predicate on the "pending_auth_sessions" edge with a given conditions (other predicates).
|
||||
func HasPendingAuthSessionsWith(preds ...predicate.PendingAuthSession) predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
step := newPendingAuthSessionsStep()
|
||||
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
|
||||
for _, p := range preds {
|
||||
p(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// HasUserAllowedGroups applies the HasEdge predicate on the "user_allowed_groups" edge.
|
||||
func HasUserAllowedGroups() predicate.User {
|
||||
return predicate.User(func(s *sql.Selector) {
|
||||
|
||||
@ -13,8 +13,10 @@ import (
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
|
||||
"github.com/Wei-Shaw/sub2api/ent/usagelog"
|
||||
@ -211,6 +213,48 @@ func (_c *UserCreate) SetNillableTotpEnabledAt(v *time.Time) *UserCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (_c *UserCreate) SetSignupSource(v string) *UserCreate {
|
||||
_c.mutation.SetSignupSource(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableSignupSource sets the "signup_source" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableSignupSource(v *string) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetSignupSource(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (_c *UserCreate) SetLastLoginAt(v time.Time) *UserCreate {
|
||||
_c.mutation.SetLastLoginAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableLastLoginAt sets the "last_login_at" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableLastLoginAt(v *time.Time) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetLastLoginAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (_c *UserCreate) SetLastActiveAt(v time.Time) *UserCreate {
|
||||
_c.mutation.SetLastActiveAt(v)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableLastActiveAt sets the "last_active_at" field if the given value is not nil.
|
||||
func (_c *UserCreate) SetNillableLastActiveAt(v *time.Time) *UserCreate {
|
||||
if v != nil {
|
||||
_c.SetLastActiveAt(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (_c *UserCreate) SetBalanceNotifyEnabled(v bool) *UserCreate {
|
||||
_c.mutation.SetBalanceNotifyEnabled(v)
|
||||
@ -431,6 +475,36 @@ func (_c *UserCreate) AddPaymentOrders(v ...*PaymentOrder) *UserCreate {
|
||||
return _c.AddPaymentOrderIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAuthIdentityIDs adds the "auth_identities" edge to the AuthIdentity entity by IDs.
|
||||
func (_c *UserCreate) AddAuthIdentityIDs(ids ...int64) *UserCreate {
|
||||
_c.mutation.AddAuthIdentityIDs(ids...)
|
||||
return _c
|
||||
}
|
||||
|
||||
// AddAuthIdentities adds the "auth_identities" edges to the AuthIdentity entity.
|
||||
func (_c *UserCreate) AddAuthIdentities(v ...*AuthIdentity) *UserCreate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _c.AddAuthIdentityIDs(ids...)
|
||||
}
|
||||
|
||||
// AddPendingAuthSessionIDs adds the "pending_auth_sessions" edge to the PendingAuthSession entity by IDs.
|
||||
func (_c *UserCreate) AddPendingAuthSessionIDs(ids ...int64) *UserCreate {
|
||||
_c.mutation.AddPendingAuthSessionIDs(ids...)
|
||||
return _c
|
||||
}
|
||||
|
||||
// AddPendingAuthSessions adds the "pending_auth_sessions" edges to the PendingAuthSession entity.
|
||||
func (_c *UserCreate) AddPendingAuthSessions(v ...*PendingAuthSession) *UserCreate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _c.AddPendingAuthSessionIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the UserMutation object of the builder.
|
||||
func (_c *UserCreate) Mutation() *UserMutation {
|
||||
return _c.mutation
|
||||
@ -510,6 +584,10 @@ func (_c *UserCreate) defaults() error {
|
||||
v := user.DefaultTotpEnabled
|
||||
_c.mutation.SetTotpEnabled(v)
|
||||
}
|
||||
if _, ok := _c.mutation.SignupSource(); !ok {
|
||||
v := user.DefaultSignupSource
|
||||
_c.mutation.SetSignupSource(v)
|
||||
}
|
||||
if _, ok := _c.mutation.BalanceNotifyEnabled(); !ok {
|
||||
v := user.DefaultBalanceNotifyEnabled
|
||||
_c.mutation.SetBalanceNotifyEnabled(v)
|
||||
@ -589,6 +667,14 @@ func (_c *UserCreate) check() error {
|
||||
if _, ok := _c.mutation.TotpEnabled(); !ok {
|
||||
return &ValidationError{Name: "totp_enabled", err: errors.New(`ent: missing required field "User.totp_enabled"`)}
|
||||
}
|
||||
if _, ok := _c.mutation.SignupSource(); !ok {
|
||||
return &ValidationError{Name: "signup_source", err: errors.New(`ent: missing required field "User.signup_source"`)}
|
||||
}
|
||||
if v, ok := _c.mutation.SignupSource(); ok {
|
||||
if err := user.SignupSourceValidator(v); err != nil {
|
||||
return &ValidationError{Name: "signup_source", err: fmt.Errorf(`ent: validator failed for field "User.signup_source": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := _c.mutation.BalanceNotifyEnabled(); !ok {
|
||||
return &ValidationError{Name: "balance_notify_enabled", err: errors.New(`ent: missing required field "User.balance_notify_enabled"`)}
|
||||
}
|
||||
@ -684,6 +770,18 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(user.FieldTotpEnabledAt, field.TypeTime, value)
|
||||
_node.TotpEnabledAt = &value
|
||||
}
|
||||
if value, ok := _c.mutation.SignupSource(); ok {
|
||||
_spec.SetField(user.FieldSignupSource, field.TypeString, value)
|
||||
_node.SignupSource = value
|
||||
}
|
||||
if value, ok := _c.mutation.LastLoginAt(); ok {
|
||||
_spec.SetField(user.FieldLastLoginAt, field.TypeTime, value)
|
||||
_node.LastLoginAt = &value
|
||||
}
|
||||
if value, ok := _c.mutation.LastActiveAt(); ok {
|
||||
_spec.SetField(user.FieldLastActiveAt, field.TypeTime, value)
|
||||
_node.LastActiveAt = &value
|
||||
}
|
||||
if value, ok := _c.mutation.BalanceNotifyEnabled(); ok {
|
||||
_spec.SetField(user.FieldBalanceNotifyEnabled, field.TypeBool, value)
|
||||
_node.BalanceNotifyEnabled = value
|
||||
@ -868,6 +966,38 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
|
||||
}
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.AuthIdentitiesIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
if nodes := _c.mutation.PendingAuthSessionsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges = append(_spec.Edges, edge)
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
@ -1106,6 +1236,54 @@ func (u *UserUpsert) ClearTotpEnabledAt() *UserUpsert {
|
||||
return u
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (u *UserUpsert) SetSignupSource(v string) *UserUpsert {
|
||||
u.Set(user.FieldSignupSource, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateSignupSource sets the "signup_source" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateSignupSource() *UserUpsert {
|
||||
u.SetExcluded(user.FieldSignupSource)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (u *UserUpsert) SetLastLoginAt(v time.Time) *UserUpsert {
|
||||
u.Set(user.FieldLastLoginAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateLastLoginAt sets the "last_login_at" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateLastLoginAt() *UserUpsert {
|
||||
u.SetExcluded(user.FieldLastLoginAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearLastLoginAt clears the value of the "last_login_at" field.
|
||||
func (u *UserUpsert) ClearLastLoginAt() *UserUpsert {
|
||||
u.SetNull(user.FieldLastLoginAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (u *UserUpsert) SetLastActiveAt(v time.Time) *UserUpsert {
|
||||
u.Set(user.FieldLastActiveAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateLastActiveAt sets the "last_active_at" field to the value that was provided on create.
|
||||
func (u *UserUpsert) UpdateLastActiveAt() *UserUpsert {
|
||||
u.SetExcluded(user.FieldLastActiveAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearLastActiveAt clears the value of the "last_active_at" field.
|
||||
func (u *UserUpsert) ClearLastActiveAt() *UserUpsert {
|
||||
u.SetNull(user.FieldLastActiveAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (u *UserUpsert) SetBalanceNotifyEnabled(v bool) *UserUpsert {
|
||||
u.Set(user.FieldBalanceNotifyEnabled, v)
|
||||
@ -1446,6 +1624,62 @@ func (u *UserUpsertOne) ClearTotpEnabledAt() *UserUpsertOne {
|
||||
})
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (u *UserUpsertOne) SetSignupSource(v string) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetSignupSource(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSignupSource sets the "signup_source" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateSignupSource() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateSignupSource()
|
||||
})
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (u *UserUpsertOne) SetLastLoginAt(v time.Time) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetLastLoginAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateLastLoginAt sets the "last_login_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateLastLoginAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateLastLoginAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearLastLoginAt clears the value of the "last_login_at" field.
|
||||
func (u *UserUpsertOne) ClearLastLoginAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearLastLoginAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (u *UserUpsertOne) SetLastActiveAt(v time.Time) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetLastActiveAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateLastActiveAt sets the "last_active_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertOne) UpdateLastActiveAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateLastActiveAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearLastActiveAt clears the value of the "last_active_at" field.
|
||||
func (u *UserUpsertOne) ClearLastActiveAt() *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearLastActiveAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (u *UserUpsertOne) SetBalanceNotifyEnabled(v bool) *UserUpsertOne {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
@ -1965,6 +2199,62 @@ func (u *UserUpsertBulk) ClearTotpEnabledAt() *UserUpsertBulk {
|
||||
})
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (u *UserUpsertBulk) SetSignupSource(v string) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetSignupSource(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSignupSource sets the "signup_source" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateSignupSource() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateSignupSource()
|
||||
})
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (u *UserUpsertBulk) SetLastLoginAt(v time.Time) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetLastLoginAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateLastLoginAt sets the "last_login_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateLastLoginAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateLastLoginAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearLastLoginAt clears the value of the "last_login_at" field.
|
||||
func (u *UserUpsertBulk) ClearLastLoginAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearLastLoginAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (u *UserUpsertBulk) SetLastActiveAt(v time.Time) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.SetLastActiveAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateLastActiveAt sets the "last_active_at" field to the value that was provided on create.
|
||||
func (u *UserUpsertBulk) UpdateLastActiveAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.UpdateLastActiveAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearLastActiveAt clears the value of the "last_active_at" field.
|
||||
func (u *UserUpsertBulk) ClearLastActiveAt() *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
s.ClearLastActiveAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (u *UserUpsertBulk) SetBalanceNotifyEnabled(v bool) *UserUpsertBulk {
|
||||
return u.Update(func(s *UserUpsert) {
|
||||
|
||||
@ -15,8 +15,10 @@ import (
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
|
||||
@ -44,6 +46,8 @@ type UserQuery struct {
|
||||
withAttributeValues *UserAttributeValueQuery
|
||||
withPromoCodeUsages *PromoCodeUsageQuery
|
||||
withPaymentOrders *PaymentOrderQuery
|
||||
withAuthIdentities *AuthIdentityQuery
|
||||
withPendingAuthSessions *PendingAuthSessionQuery
|
||||
withUserAllowedGroups *UserAllowedGroupQuery
|
||||
modifiers []func(*sql.Selector)
|
||||
// intermediate query (i.e. traversal path).
|
||||
@ -302,6 +306,50 @@ func (_q *UserQuery) QueryPaymentOrders() *PaymentOrderQuery {
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryAuthIdentities chains the current query on the "auth_identities" edge.
|
||||
func (_q *UserQuery) QueryAuthIdentities() *AuthIdentityQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, selector),
|
||||
sqlgraph.To(authidentity.Table, authidentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.AuthIdentitiesTable, user.AuthIdentitiesColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryPendingAuthSessions chains the current query on the "pending_auth_sessions" edge.
|
||||
func (_q *UserQuery) QueryPendingAuthSessions() *PendingAuthSessionQuery {
|
||||
query := (&PendingAuthSessionClient{config: _q.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := _q.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := _q.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, selector),
|
||||
sqlgraph.To(pendingauthsession.Table, pendingauthsession.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.PendingAuthSessionsTable, user.PendingAuthSessionsColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// QueryUserAllowedGroups chains the current query on the "user_allowed_groups" edge.
|
||||
func (_q *UserQuery) QueryUserAllowedGroups() *UserAllowedGroupQuery {
|
||||
query := (&UserAllowedGroupClient{config: _q.config}).Query()
|
||||
@ -526,6 +574,8 @@ func (_q *UserQuery) Clone() *UserQuery {
|
||||
withAttributeValues: _q.withAttributeValues.Clone(),
|
||||
withPromoCodeUsages: _q.withPromoCodeUsages.Clone(),
|
||||
withPaymentOrders: _q.withPaymentOrders.Clone(),
|
||||
withAuthIdentities: _q.withAuthIdentities.Clone(),
|
||||
withPendingAuthSessions: _q.withPendingAuthSessions.Clone(),
|
||||
withUserAllowedGroups: _q.withUserAllowedGroups.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: _q.sql.Clone(),
|
||||
@ -643,6 +693,28 @@ func (_q *UserQuery) WithPaymentOrders(opts ...func(*PaymentOrderQuery)) *UserQu
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithAuthIdentities tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "auth_identities" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *UserQuery) WithAuthIdentities(opts ...func(*AuthIdentityQuery)) *UserQuery {
|
||||
query := (&AuthIdentityClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withAuthIdentities = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithPendingAuthSessions tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "pending_auth_sessions" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *UserQuery) WithPendingAuthSessions(opts ...func(*PendingAuthSessionQuery)) *UserQuery {
|
||||
query := (&PendingAuthSessionClient{config: _q.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
_q.withPendingAuthSessions = query
|
||||
return _q
|
||||
}
|
||||
|
||||
// WithUserAllowedGroups tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "user_allowed_groups" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (_q *UserQuery) WithUserAllowedGroups(opts ...func(*UserAllowedGroupQuery)) *UserQuery {
|
||||
@ -732,7 +804,7 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
||||
var (
|
||||
nodes = []*User{}
|
||||
_spec = _q.querySpec()
|
||||
loadedTypes = [11]bool{
|
||||
loadedTypes = [13]bool{
|
||||
_q.withAPIKeys != nil,
|
||||
_q.withRedeemCodes != nil,
|
||||
_q.withSubscriptions != nil,
|
||||
@ -743,6 +815,8 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
||||
_q.withAttributeValues != nil,
|
||||
_q.withPromoCodeUsages != nil,
|
||||
_q.withPaymentOrders != nil,
|
||||
_q.withAuthIdentities != nil,
|
||||
_q.withPendingAuthSessions != nil,
|
||||
_q.withUserAllowedGroups != nil,
|
||||
}
|
||||
)
|
||||
@ -839,6 +913,22 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withAuthIdentities; query != nil {
|
||||
if err := _q.loadAuthIdentities(ctx, query, nodes,
|
||||
func(n *User) { n.Edges.AuthIdentities = []*AuthIdentity{} },
|
||||
func(n *User, e *AuthIdentity) { n.Edges.AuthIdentities = append(n.Edges.AuthIdentities, e) }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withPendingAuthSessions; query != nil {
|
||||
if err := _q.loadPendingAuthSessions(ctx, query, nodes,
|
||||
func(n *User) { n.Edges.PendingAuthSessions = []*PendingAuthSession{} },
|
||||
func(n *User, e *PendingAuthSession) {
|
||||
n.Edges.PendingAuthSessions = append(n.Edges.PendingAuthSessions, e)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if query := _q.withUserAllowedGroups; query != nil {
|
||||
if err := _q.loadUserAllowedGroups(ctx, query, nodes,
|
||||
func(n *User) { n.Edges.UserAllowedGroups = []*UserAllowedGroup{} },
|
||||
@ -1186,6 +1276,69 @@ func (_q *UserQuery) loadPaymentOrders(ctx context.Context, query *PaymentOrderQ
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *UserQuery) loadAuthIdentities(ctx context.Context, query *AuthIdentityQuery, nodes []*User, init func(*User), assign func(*User, *AuthIdentity)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*User)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(authidentity.FieldUserID)
|
||||
}
|
||||
query.Where(predicate.AuthIdentity(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(user.AuthIdentitiesColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.UserID
|
||||
node, ok := nodeids[fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "user_id" returned %v for node %v`, fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *UserQuery) loadPendingAuthSessions(ctx context.Context, query *PendingAuthSessionQuery, nodes []*User, init func(*User), assign func(*User, *PendingAuthSession)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*User)
|
||||
for i := range nodes {
|
||||
fks = append(fks, nodes[i].ID)
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
}
|
||||
}
|
||||
if len(query.ctx.Fields) > 0 {
|
||||
query.ctx.AppendFieldOnce(pendingauthsession.FieldTargetUserID)
|
||||
}
|
||||
query.Where(predicate.PendingAuthSession(func(s *sql.Selector) {
|
||||
s.Where(sql.InValues(s.C(user.PendingAuthSessionsColumn), fks...))
|
||||
}))
|
||||
neighbors, err := query.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, n := range neighbors {
|
||||
fk := n.TargetUserID
|
||||
if fk == nil {
|
||||
return fmt.Errorf(`foreign-key "target_user_id" is nil for node %v`, n.ID)
|
||||
}
|
||||
node, ok := nodeids[*fk]
|
||||
if !ok {
|
||||
return fmt.Errorf(`unexpected referenced foreign-key "target_user_id" returned %v for node %v`, *fk, n.ID)
|
||||
}
|
||||
assign(node, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (_q *UserQuery) loadUserAllowedGroups(ctx context.Context, query *UserAllowedGroupQuery, nodes []*User, init func(*User), assign func(*User, *UserAllowedGroup)) error {
|
||||
fks := make([]driver.Value, 0, len(nodes))
|
||||
nodeids := make(map[int64]*User)
|
||||
|
||||
@ -13,8 +13,10 @@ import (
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/Wei-Shaw/sub2api/ent/announcementread"
|
||||
"github.com/Wei-Shaw/sub2api/ent/apikey"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/group"
|
||||
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/Wei-Shaw/sub2api/ent/predicate"
|
||||
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
|
||||
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
|
||||
@ -243,6 +245,60 @@ func (_u *UserUpdate) ClearTotpEnabledAt() *UserUpdate {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (_u *UserUpdate) SetSignupSource(v string) *UserUpdate {
|
||||
_u.mutation.SetSignupSource(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableSignupSource sets the "signup_source" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableSignupSource(v *string) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetSignupSource(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (_u *UserUpdate) SetLastLoginAt(v time.Time) *UserUpdate {
|
||||
_u.mutation.SetLastLoginAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableLastLoginAt sets the "last_login_at" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableLastLoginAt(v *time.Time) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetLastLoginAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearLastLoginAt clears the value of the "last_login_at" field.
|
||||
func (_u *UserUpdate) ClearLastLoginAt() *UserUpdate {
|
||||
_u.mutation.ClearLastLoginAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (_u *UserUpdate) SetLastActiveAt(v time.Time) *UserUpdate {
|
||||
_u.mutation.SetLastActiveAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableLastActiveAt sets the "last_active_at" field if the given value is not nil.
|
||||
func (_u *UserUpdate) SetNillableLastActiveAt(v *time.Time) *UserUpdate {
|
||||
if v != nil {
|
||||
_u.SetLastActiveAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearLastActiveAt clears the value of the "last_active_at" field.
|
||||
func (_u *UserUpdate) ClearLastActiveAt() *UserUpdate {
|
||||
_u.mutation.ClearLastActiveAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (_u *UserUpdate) SetBalanceNotifyEnabled(v bool) *UserUpdate {
|
||||
_u.mutation.SetBalanceNotifyEnabled(v)
|
||||
@ -483,6 +539,36 @@ func (_u *UserUpdate) AddPaymentOrders(v ...*PaymentOrder) *UserUpdate {
|
||||
return _u.AddPaymentOrderIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAuthIdentityIDs adds the "auth_identities" edge to the AuthIdentity entity by IDs.
|
||||
func (_u *UserUpdate) AddAuthIdentityIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.AddAuthIdentityIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAuthIdentities adds the "auth_identities" edges to the AuthIdentity entity.
|
||||
func (_u *UserUpdate) AddAuthIdentities(v ...*AuthIdentity) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAuthIdentityIDs(ids...)
|
||||
}
|
||||
|
||||
// AddPendingAuthSessionIDs adds the "pending_auth_sessions" edge to the PendingAuthSession entity by IDs.
|
||||
func (_u *UserUpdate) AddPendingAuthSessionIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.AddPendingAuthSessionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddPendingAuthSessions adds the "pending_auth_sessions" edges to the PendingAuthSession entity.
|
||||
func (_u *UserUpdate) AddPendingAuthSessions(v ...*PendingAuthSession) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddPendingAuthSessionIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the UserMutation object of the builder.
|
||||
func (_u *UserUpdate) Mutation() *UserMutation {
|
||||
return _u.mutation
|
||||
@ -698,6 +784,48 @@ func (_u *UserUpdate) RemovePaymentOrders(v ...*PaymentOrder) *UserUpdate {
|
||||
return _u.RemovePaymentOrderIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAuthIdentities clears all "auth_identities" edges to the AuthIdentity entity.
|
||||
func (_u *UserUpdate) ClearAuthIdentities() *UserUpdate {
|
||||
_u.mutation.ClearAuthIdentities()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAuthIdentityIDs removes the "auth_identities" edge to AuthIdentity entities by IDs.
|
||||
func (_u *UserUpdate) RemoveAuthIdentityIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.RemoveAuthIdentityIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAuthIdentities removes "auth_identities" edges to AuthIdentity entities.
|
||||
func (_u *UserUpdate) RemoveAuthIdentities(v ...*AuthIdentity) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAuthIdentityIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearPendingAuthSessions clears all "pending_auth_sessions" edges to the PendingAuthSession entity.
|
||||
func (_u *UserUpdate) ClearPendingAuthSessions() *UserUpdate {
|
||||
_u.mutation.ClearPendingAuthSessions()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemovePendingAuthSessionIDs removes the "pending_auth_sessions" edge to PendingAuthSession entities by IDs.
|
||||
func (_u *UserUpdate) RemovePendingAuthSessionIDs(ids ...int64) *UserUpdate {
|
||||
_u.mutation.RemovePendingAuthSessionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemovePendingAuthSessions removes "pending_auth_sessions" edges to PendingAuthSession entities.
|
||||
func (_u *UserUpdate) RemovePendingAuthSessions(v ...*PendingAuthSession) *UserUpdate {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemovePendingAuthSessionIDs(ids...)
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (_u *UserUpdate) Save(ctx context.Context) (int, error) {
|
||||
if err := _u.defaults(); err != nil {
|
||||
@ -767,6 +895,11 @@ func (_u *UserUpdate) check() error {
|
||||
return &ValidationError{Name: "username", err: fmt.Errorf(`ent: validator failed for field "User.username": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.SignupSource(); ok {
|
||||
if err := user.SignupSourceValidator(v); err != nil {
|
||||
return &ValidationError{Name: "signup_source", err: fmt.Errorf(`ent: validator failed for field "User.signup_source": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -836,6 +969,21 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
if _u.mutation.TotpEnabledAtCleared() {
|
||||
_spec.ClearField(user.FieldTotpEnabledAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.SignupSource(); ok {
|
||||
_spec.SetField(user.FieldSignupSource, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.LastLoginAt(); ok {
|
||||
_spec.SetField(user.FieldLastLoginAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.LastLoginAtCleared() {
|
||||
_spec.ClearField(user.FieldLastLoginAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.LastActiveAt(); ok {
|
||||
_spec.SetField(user.FieldLastActiveAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.LastActiveAtCleared() {
|
||||
_spec.ClearField(user.FieldLastActiveAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.BalanceNotifyEnabled(); ok {
|
||||
_spec.SetField(user.FieldBalanceNotifyEnabled, field.TypeBool, value)
|
||||
}
|
||||
@ -1322,6 +1470,96 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AuthIdentitiesCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAuthIdentitiesIDs(); len(nodes) > 0 && !_u.mutation.AuthIdentitiesCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AuthIdentitiesIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.PendingAuthSessionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedPendingAuthSessionsIDs(); len(nodes) > 0 && !_u.mutation.PendingAuthSessionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.PendingAuthSessionsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{user.Label}
|
||||
@ -1548,6 +1786,60 @@ func (_u *UserUpdateOne) ClearTotpEnabledAt() *UserUpdateOne {
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetSignupSource sets the "signup_source" field.
|
||||
func (_u *UserUpdateOne) SetSignupSource(v string) *UserUpdateOne {
|
||||
_u.mutation.SetSignupSource(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableSignupSource sets the "signup_source" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableSignupSource(v *string) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetSignupSource(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetLastLoginAt sets the "last_login_at" field.
|
||||
func (_u *UserUpdateOne) SetLastLoginAt(v time.Time) *UserUpdateOne {
|
||||
_u.mutation.SetLastLoginAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableLastLoginAt sets the "last_login_at" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableLastLoginAt(v *time.Time) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetLastLoginAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearLastLoginAt clears the value of the "last_login_at" field.
|
||||
func (_u *UserUpdateOne) ClearLastLoginAt() *UserUpdateOne {
|
||||
_u.mutation.ClearLastLoginAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetLastActiveAt sets the "last_active_at" field.
|
||||
func (_u *UserUpdateOne) SetLastActiveAt(v time.Time) *UserUpdateOne {
|
||||
_u.mutation.SetLastActiveAt(v)
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetNillableLastActiveAt sets the "last_active_at" field if the given value is not nil.
|
||||
func (_u *UserUpdateOne) SetNillableLastActiveAt(v *time.Time) *UserUpdateOne {
|
||||
if v != nil {
|
||||
_u.SetLastActiveAt(*v)
|
||||
}
|
||||
return _u
|
||||
}
|
||||
|
||||
// ClearLastActiveAt clears the value of the "last_active_at" field.
|
||||
func (_u *UserUpdateOne) ClearLastActiveAt() *UserUpdateOne {
|
||||
_u.mutation.ClearLastActiveAt()
|
||||
return _u
|
||||
}
|
||||
|
||||
// SetBalanceNotifyEnabled sets the "balance_notify_enabled" field.
|
||||
func (_u *UserUpdateOne) SetBalanceNotifyEnabled(v bool) *UserUpdateOne {
|
||||
_u.mutation.SetBalanceNotifyEnabled(v)
|
||||
@ -1788,6 +2080,36 @@ func (_u *UserUpdateOne) AddPaymentOrders(v ...*PaymentOrder) *UserUpdateOne {
|
||||
return _u.AddPaymentOrderIDs(ids...)
|
||||
}
|
||||
|
||||
// AddAuthIdentityIDs adds the "auth_identities" edge to the AuthIdentity entity by IDs.
|
||||
func (_u *UserUpdateOne) AddAuthIdentityIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.AddAuthIdentityIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddAuthIdentities adds the "auth_identities" edges to the AuthIdentity entity.
|
||||
func (_u *UserUpdateOne) AddAuthIdentities(v ...*AuthIdentity) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddAuthIdentityIDs(ids...)
|
||||
}
|
||||
|
||||
// AddPendingAuthSessionIDs adds the "pending_auth_sessions" edge to the PendingAuthSession entity by IDs.
|
||||
func (_u *UserUpdateOne) AddPendingAuthSessionIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.AddPendingAuthSessionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// AddPendingAuthSessions adds the "pending_auth_sessions" edges to the PendingAuthSession entity.
|
||||
func (_u *UserUpdateOne) AddPendingAuthSessions(v ...*PendingAuthSession) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.AddPendingAuthSessionIDs(ids...)
|
||||
}
|
||||
|
||||
// Mutation returns the UserMutation object of the builder.
|
||||
func (_u *UserUpdateOne) Mutation() *UserMutation {
|
||||
return _u.mutation
|
||||
@ -2003,6 +2325,48 @@ func (_u *UserUpdateOne) RemovePaymentOrders(v ...*PaymentOrder) *UserUpdateOne
|
||||
return _u.RemovePaymentOrderIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearAuthIdentities clears all "auth_identities" edges to the AuthIdentity entity.
|
||||
func (_u *UserUpdateOne) ClearAuthIdentities() *UserUpdateOne {
|
||||
_u.mutation.ClearAuthIdentities()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAuthIdentityIDs removes the "auth_identities" edge to AuthIdentity entities by IDs.
|
||||
func (_u *UserUpdateOne) RemoveAuthIdentityIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.RemoveAuthIdentityIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemoveAuthIdentities removes "auth_identities" edges to AuthIdentity entities.
|
||||
func (_u *UserUpdateOne) RemoveAuthIdentities(v ...*AuthIdentity) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemoveAuthIdentityIDs(ids...)
|
||||
}
|
||||
|
||||
// ClearPendingAuthSessions clears all "pending_auth_sessions" edges to the PendingAuthSession entity.
|
||||
func (_u *UserUpdateOne) ClearPendingAuthSessions() *UserUpdateOne {
|
||||
_u.mutation.ClearPendingAuthSessions()
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemovePendingAuthSessionIDs removes the "pending_auth_sessions" edge to PendingAuthSession entities by IDs.
|
||||
func (_u *UserUpdateOne) RemovePendingAuthSessionIDs(ids ...int64) *UserUpdateOne {
|
||||
_u.mutation.RemovePendingAuthSessionIDs(ids...)
|
||||
return _u
|
||||
}
|
||||
|
||||
// RemovePendingAuthSessions removes "pending_auth_sessions" edges to PendingAuthSession entities.
|
||||
func (_u *UserUpdateOne) RemovePendingAuthSessions(v ...*PendingAuthSession) *UserUpdateOne {
|
||||
ids := make([]int64, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return _u.RemovePendingAuthSessionIDs(ids...)
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the UserUpdate builder.
|
||||
func (_u *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
|
||||
_u.mutation.Where(ps...)
|
||||
@ -2085,6 +2449,11 @@ func (_u *UserUpdateOne) check() error {
|
||||
return &ValidationError{Name: "username", err: fmt.Errorf(`ent: validator failed for field "User.username": %w`, err)}
|
||||
}
|
||||
}
|
||||
if v, ok := _u.mutation.SignupSource(); ok {
|
||||
if err := user.SignupSourceValidator(v); err != nil {
|
||||
return &ValidationError{Name: "signup_source", err: fmt.Errorf(`ent: validator failed for field "User.signup_source": %w`, err)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -2171,6 +2540,21 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
|
||||
if _u.mutation.TotpEnabledAtCleared() {
|
||||
_spec.ClearField(user.FieldTotpEnabledAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.SignupSource(); ok {
|
||||
_spec.SetField(user.FieldSignupSource, field.TypeString, value)
|
||||
}
|
||||
if value, ok := _u.mutation.LastLoginAt(); ok {
|
||||
_spec.SetField(user.FieldLastLoginAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.LastLoginAtCleared() {
|
||||
_spec.ClearField(user.FieldLastLoginAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.LastActiveAt(); ok {
|
||||
_spec.SetField(user.FieldLastActiveAt, field.TypeTime, value)
|
||||
}
|
||||
if _u.mutation.LastActiveAtCleared() {
|
||||
_spec.ClearField(user.FieldLastActiveAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := _u.mutation.BalanceNotifyEnabled(); ok {
|
||||
_spec.SetField(user.FieldBalanceNotifyEnabled, field.TypeBool, value)
|
||||
}
|
||||
@ -2657,6 +3041,96 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.AuthIdentitiesCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedAuthIdentitiesIDs(); len(nodes) > 0 && !_u.mutation.AuthIdentitiesCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.AuthIdentitiesIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.AuthIdentitiesTable,
|
||||
Columns: []string{user.AuthIdentitiesColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(authidentity.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
if _u.mutation.PendingAuthSessionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.RemovedPendingAuthSessionsIDs(); len(nodes) > 0 && !_u.mutation.PendingAuthSessionsCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := _u.mutation.PendingAuthSessionsIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
Inverse: false,
|
||||
Table: user.PendingAuthSessionsTable,
|
||||
Columns: []string{user.PendingAuthSessionsColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(pendingauthsession.FieldID, field.TypeInt64),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &User{config: _u.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
module github.com/Wei-Shaw/sub2api
|
||||
|
||||
go 1.25.0
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
connectrpc.com/connect v1.19.1
|
||||
connectrpc.com/connect v1.19.2
|
||||
entgo.io/ent v0.14.5
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/alitto/pond/v2 v2.6.2
|
||||
@ -41,6 +41,7 @@ require (
|
||||
github.com/zeromicro/go-zero v1.9.4
|
||||
go.uber.org/zap v1.24.0
|
||||
golang.org/x/crypto v0.49.0
|
||||
golang.org/x/image v0.39.0
|
||||
golang.org/x/net v0.52.0
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/term v0.41.0
|
||||
@ -105,7 +106,6 @@ require (
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/subcommands v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
|
||||
@ -174,10 +174,10 @@ require (
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
golang.org/x/mod v0.34.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
golang.org/x/tools v0.43.0 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc=
|
||||
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=
|
||||
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
|
||||
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
|
||||
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
|
||||
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=
|
||||
@ -164,8 +164,6 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||
@ -185,8 +183,6 @@ 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/imroc/req/v3 v3.57.0 h1:LMTUjNRUybUkTPn8oJDq8Kg3JRBOBTcnDhKu7mzupKI=
|
||||
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/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
@ -222,8 +218,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
|
||||
@ -257,8 +251,6 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
@ -288,8 +280,6 @@ github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEv
|
||||
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
@ -322,8 +312,6 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
@ -419,8 +407,10 @@ golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
|
||||
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
|
||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
@ -438,12 +428,12 @@ golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU=
|
||||
|
||||
@ -52,6 +52,11 @@ const (
|
||||
ConnectionPoolIsolationAccountProxy = "account_proxy"
|
||||
)
|
||||
|
||||
// DefaultUpstreamResponseReadMaxBytes 上游非流式响应体的默认读取上限。
|
||||
// 128 MB 可容纳 2-3 张 4K PNG(base64 膨胀 33%,单张 4K PNG 最坏约 67MB base64)。
|
||||
// 可通过 gateway.upstream_response_read_max_bytes 配置项覆盖。
|
||||
const DefaultUpstreamResponseReadMaxBytes int64 = 128 * 1024 * 1024
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
@ -65,6 +70,7 @@ type Config struct {
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Totp TotpConfig `mapstructure:"totp"`
|
||||
LinuxDo LinuxDoConnectConfig `mapstructure:"linuxdo_connect"`
|
||||
WeChat WeChatConnectConfig `mapstructure:"wechat_connect"`
|
||||
OIDC OIDCConnectConfig `mapstructure:"oidc_connect"`
|
||||
Default DefaultConfig `mapstructure:"default"`
|
||||
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
||||
@ -185,26 +191,47 @@ type LinuxDoConnectConfig struct {
|
||||
UserInfoUsernamePath string `mapstructure:"userinfo_username_path"`
|
||||
}
|
||||
|
||||
type WeChatConnectConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
AppID string `mapstructure:"app_id"`
|
||||
AppSecret string `mapstructure:"app_secret"`
|
||||
OpenAppID string `mapstructure:"open_app_id"`
|
||||
OpenAppSecret string `mapstructure:"open_app_secret"`
|
||||
MPAppID string `mapstructure:"mp_app_id"`
|
||||
MPAppSecret string `mapstructure:"mp_app_secret"`
|
||||
MobileAppID string `mapstructure:"mobile_app_id"`
|
||||
MobileAppSecret string `mapstructure:"mobile_app_secret"`
|
||||
OpenEnabled bool `mapstructure:"open_enabled"`
|
||||
MPEnabled bool `mapstructure:"mp_enabled"`
|
||||
MobileEnabled bool `mapstructure:"mobile_enabled"`
|
||||
Mode string `mapstructure:"mode"`
|
||||
Scopes string `mapstructure:"scopes"`
|
||||
RedirectURL string `mapstructure:"redirect_url"`
|
||||
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"`
|
||||
}
|
||||
|
||||
type OIDCConnectConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
ProviderName string `mapstructure:"provider_name"` // 显示名: "Keycloak" 等
|
||||
ClientID string `mapstructure:"client_id"`
|
||||
ClientSecret string `mapstructure:"client_secret"`
|
||||
IssuerURL string `mapstructure:"issuer_url"`
|
||||
DiscoveryURL string `mapstructure:"discovery_url"`
|
||||
AuthorizeURL string `mapstructure:"authorize_url"`
|
||||
TokenURL string `mapstructure:"token_url"`
|
||||
UserInfoURL string `mapstructure:"userinfo_url"`
|
||||
JWKSURL string `mapstructure:"jwks_url"`
|
||||
Scopes string `mapstructure:"scopes"` // 默认 "openid email profile"
|
||||
RedirectURL string `mapstructure:"redirect_url"` // 后端回调地址(需在提供方后台登记)
|
||||
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"` // 前端接收 token 的路由(默认:/auth/oidc/callback)
|
||||
TokenAuthMethod string `mapstructure:"token_auth_method"` // client_secret_post / client_secret_basic / none
|
||||
UsePKCE bool `mapstructure:"use_pkce"`
|
||||
ValidateIDToken bool `mapstructure:"validate_id_token"`
|
||||
AllowedSigningAlgs string `mapstructure:"allowed_signing_algs"` // 默认 "RS256,ES256,PS256"
|
||||
ClockSkewSeconds int `mapstructure:"clock_skew_seconds"` // 默认 120
|
||||
RequireEmailVerified bool `mapstructure:"require_email_verified"` // 默认 false
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
ProviderName string `mapstructure:"provider_name"` // 显示名: "Keycloak" 等
|
||||
ClientID string `mapstructure:"client_id"`
|
||||
ClientSecret string `mapstructure:"client_secret"`
|
||||
IssuerURL string `mapstructure:"issuer_url"`
|
||||
DiscoveryURL string `mapstructure:"discovery_url"`
|
||||
AuthorizeURL string `mapstructure:"authorize_url"`
|
||||
TokenURL string `mapstructure:"token_url"`
|
||||
UserInfoURL string `mapstructure:"userinfo_url"`
|
||||
JWKSURL string `mapstructure:"jwks_url"`
|
||||
Scopes string `mapstructure:"scopes"` // 默认 "openid email profile"
|
||||
RedirectURL string `mapstructure:"redirect_url"` // 后端回调地址(需在提供方后台登记)
|
||||
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"` // 前端接收 token 的路由(默认:/auth/oidc/callback)
|
||||
TokenAuthMethod string `mapstructure:"token_auth_method"` // client_secret_post / client_secret_basic / none
|
||||
UsePKCE bool `mapstructure:"use_pkce"`
|
||||
ValidateIDToken bool `mapstructure:"validate_id_token"`
|
||||
UsePKCEExplicit bool `mapstructure:"-" yaml:"-"`
|
||||
ValidateIDTokenExplicit bool `mapstructure:"-" yaml:"-"`
|
||||
AllowedSigningAlgs string `mapstructure:"allowed_signing_algs"` // 默认 "RS256,ES256,PS256"
|
||||
ClockSkewSeconds int `mapstructure:"clock_skew_seconds"` // 默认 120
|
||||
RequireEmailVerified bool `mapstructure:"require_email_verified"` // 默认 false
|
||||
|
||||
// 可选:用于从 userinfo JSON 中提取字段的 gjson 路径。
|
||||
// 为空时,服务端会尝试一组常见字段名。
|
||||
@ -213,6 +240,225 @@ type OIDCConnectConfig struct {
|
||||
UserInfoUsernamePath string `mapstructure:"userinfo_username_path"`
|
||||
}
|
||||
|
||||
const (
|
||||
defaultWeChatConnectMode = "open"
|
||||
defaultWeChatConnectScopes = "snsapi_login"
|
||||
defaultWeChatConnectFrontendRedirect = "/auth/wechat/callback"
|
||||
)
|
||||
|
||||
func firstNonEmptyString(values ...string) string {
|
||||
for _, value := range values {
|
||||
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
||||
return trimmed
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func normalizeWeChatConnectMode(raw string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(raw)) {
|
||||
case "mp":
|
||||
return "mp"
|
||||
case "mobile":
|
||||
return "mobile"
|
||||
default:
|
||||
return defaultWeChatConnectMode
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeWeChatConnectStoredMode(openEnabled, mpEnabled, mobileEnabled bool, mode string) string {
|
||||
mode = normalizeWeChatConnectMode(mode)
|
||||
switch mode {
|
||||
case "open":
|
||||
if openEnabled {
|
||||
return "open"
|
||||
}
|
||||
case "mp":
|
||||
if mpEnabled {
|
||||
return "mp"
|
||||
}
|
||||
case "mobile":
|
||||
if mobileEnabled {
|
||||
return "mobile"
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case openEnabled:
|
||||
return "open"
|
||||
case mpEnabled:
|
||||
return "mp"
|
||||
case mobileEnabled:
|
||||
return "mobile"
|
||||
default:
|
||||
return mode
|
||||
}
|
||||
}
|
||||
|
||||
func defaultWeChatConnectScopesForMode(mode string) string {
|
||||
switch normalizeWeChatConnectMode(mode) {
|
||||
case "mp":
|
||||
return "snsapi_userinfo"
|
||||
case "mobile":
|
||||
return ""
|
||||
default:
|
||||
return defaultWeChatConnectScopes
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeWeChatConnectScopes(raw, mode string) string {
|
||||
switch normalizeWeChatConnectMode(mode) {
|
||||
case "mp":
|
||||
switch strings.TrimSpace(raw) {
|
||||
case "snsapi_base":
|
||||
return "snsapi_base"
|
||||
case "snsapi_userinfo":
|
||||
return "snsapi_userinfo"
|
||||
default:
|
||||
return defaultWeChatConnectScopesForMode(mode)
|
||||
}
|
||||
case "mobile":
|
||||
return ""
|
||||
default:
|
||||
return defaultWeChatConnectScopes
|
||||
}
|
||||
}
|
||||
|
||||
func shouldApplyLegacyWeChatEnv(configKey, envKey string) bool {
|
||||
if viper.InConfig(configKey) {
|
||||
return false
|
||||
}
|
||||
_, hasNewEnv := os.LookupEnv(envKey)
|
||||
return !hasNewEnv
|
||||
}
|
||||
|
||||
func hasExplicitConfigOrEnv(configKey, envKey string) bool {
|
||||
if viper.InConfig(configKey) {
|
||||
return true
|
||||
}
|
||||
_, ok := os.LookupEnv(envKey)
|
||||
return ok
|
||||
}
|
||||
|
||||
func applyLegacyWeChatConnectEnvCompatibility(cfg *WeChatConnectConfig) {
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
|
||||
legacyOpenAppID := ""
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.open_app_id", "WECHAT_CONNECT_OPEN_APP_ID") &&
|
||||
shouldApplyLegacyWeChatEnv("wechat_connect.app_id", "WECHAT_CONNECT_APP_ID") {
|
||||
legacyOpenAppID = strings.TrimSpace(os.Getenv("WECHAT_OAUTH_OPEN_APP_ID"))
|
||||
if legacyOpenAppID != "" {
|
||||
cfg.OpenAppID = legacyOpenAppID
|
||||
}
|
||||
}
|
||||
|
||||
legacyOpenAppSecret := ""
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.open_app_secret", "WECHAT_CONNECT_OPEN_APP_SECRET") &&
|
||||
shouldApplyLegacyWeChatEnv("wechat_connect.app_secret", "WECHAT_CONNECT_APP_SECRET") {
|
||||
legacyOpenAppSecret = strings.TrimSpace(os.Getenv("WECHAT_OAUTH_OPEN_APP_SECRET"))
|
||||
if legacyOpenAppSecret != "" {
|
||||
cfg.OpenAppSecret = legacyOpenAppSecret
|
||||
}
|
||||
}
|
||||
|
||||
legacyMPAppID := ""
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.mp_app_id", "WECHAT_CONNECT_MP_APP_ID") &&
|
||||
shouldApplyLegacyWeChatEnv("wechat_connect.app_id", "WECHAT_CONNECT_APP_ID") {
|
||||
legacyMPAppID = strings.TrimSpace(os.Getenv("WECHAT_OAUTH_MP_APP_ID"))
|
||||
if legacyMPAppID != "" {
|
||||
cfg.MPAppID = legacyMPAppID
|
||||
}
|
||||
}
|
||||
|
||||
legacyMPAppSecret := ""
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.mp_app_secret", "WECHAT_CONNECT_MP_APP_SECRET") &&
|
||||
shouldApplyLegacyWeChatEnv("wechat_connect.app_secret", "WECHAT_CONNECT_APP_SECRET") {
|
||||
legacyMPAppSecret = strings.TrimSpace(os.Getenv("WECHAT_OAUTH_MP_APP_SECRET"))
|
||||
if legacyMPAppSecret != "" {
|
||||
cfg.MPAppSecret = legacyMPAppSecret
|
||||
}
|
||||
}
|
||||
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.frontend_redirect_url", "WECHAT_CONNECT_FRONTEND_REDIRECT_URL") {
|
||||
if legacyFrontend := strings.TrimSpace(os.Getenv("WECHAT_OAUTH_FRONTEND_REDIRECT_URL")); legacyFrontend != "" {
|
||||
cfg.FrontendRedirectURL = legacyFrontend
|
||||
}
|
||||
}
|
||||
|
||||
hasLegacyOpen := legacyOpenAppID != "" && legacyOpenAppSecret != ""
|
||||
hasLegacyMP := legacyMPAppID != "" && legacyMPAppSecret != ""
|
||||
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.enabled", "WECHAT_CONNECT_ENABLED") && (hasLegacyOpen || hasLegacyMP) {
|
||||
cfg.Enabled = true
|
||||
}
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.open_enabled", "WECHAT_CONNECT_OPEN_ENABLED") && hasLegacyOpen {
|
||||
cfg.OpenEnabled = true
|
||||
}
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.mp_enabled", "WECHAT_CONNECT_MP_ENABLED") && hasLegacyMP {
|
||||
cfg.MPEnabled = true
|
||||
}
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.mode", "WECHAT_CONNECT_MODE") {
|
||||
switch {
|
||||
case hasLegacyMP && !hasLegacyOpen:
|
||||
cfg.Mode = "mp"
|
||||
case hasLegacyOpen:
|
||||
cfg.Mode = "open"
|
||||
}
|
||||
}
|
||||
if shouldApplyLegacyWeChatEnv("wechat_connect.scopes", "WECHAT_CONNECT_SCOPES") {
|
||||
switch {
|
||||
case hasLegacyMP && !hasLegacyOpen:
|
||||
cfg.Scopes = defaultWeChatConnectScopesForMode("mp")
|
||||
case hasLegacyOpen:
|
||||
cfg.Scopes = defaultWeChatConnectScopesForMode("open")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeWeChatConnectConfig(cfg *WeChatConnectConfig) {
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
|
||||
cfg.AppID = strings.TrimSpace(cfg.AppID)
|
||||
cfg.AppSecret = strings.TrimSpace(cfg.AppSecret)
|
||||
cfg.OpenAppID = strings.TrimSpace(cfg.OpenAppID)
|
||||
cfg.OpenAppSecret = strings.TrimSpace(cfg.OpenAppSecret)
|
||||
cfg.MPAppID = strings.TrimSpace(cfg.MPAppID)
|
||||
cfg.MPAppSecret = strings.TrimSpace(cfg.MPAppSecret)
|
||||
cfg.MobileAppID = strings.TrimSpace(cfg.MobileAppID)
|
||||
cfg.MobileAppSecret = strings.TrimSpace(cfg.MobileAppSecret)
|
||||
cfg.Mode = normalizeWeChatConnectMode(cfg.Mode)
|
||||
cfg.RedirectURL = strings.TrimSpace(cfg.RedirectURL)
|
||||
cfg.FrontendRedirectURL = strings.TrimSpace(cfg.FrontendRedirectURL)
|
||||
|
||||
cfg.AppID = firstNonEmptyString(cfg.AppID, cfg.OpenAppID, cfg.MPAppID, cfg.MobileAppID)
|
||||
cfg.AppSecret = firstNonEmptyString(cfg.AppSecret, cfg.OpenAppSecret, cfg.MPAppSecret, cfg.MobileAppSecret)
|
||||
cfg.OpenAppID = firstNonEmptyString(cfg.OpenAppID, cfg.AppID)
|
||||
cfg.OpenAppSecret = firstNonEmptyString(cfg.OpenAppSecret, cfg.AppSecret)
|
||||
cfg.MPAppID = firstNonEmptyString(cfg.MPAppID, cfg.AppID)
|
||||
cfg.MPAppSecret = firstNonEmptyString(cfg.MPAppSecret, cfg.AppSecret)
|
||||
cfg.MobileAppID = firstNonEmptyString(cfg.MobileAppID, cfg.AppID)
|
||||
cfg.MobileAppSecret = firstNonEmptyString(cfg.MobileAppSecret, cfg.AppSecret)
|
||||
|
||||
if !cfg.OpenEnabled && !cfg.MPEnabled && !cfg.MobileEnabled && cfg.Enabled {
|
||||
switch cfg.Mode {
|
||||
case "mp":
|
||||
cfg.MPEnabled = true
|
||||
case "mobile":
|
||||
cfg.MobileEnabled = true
|
||||
default:
|
||||
cfg.OpenEnabled = true
|
||||
}
|
||||
}
|
||||
cfg.Mode = normalizeWeChatConnectStoredMode(cfg.OpenEnabled, cfg.MPEnabled, cfg.MobileEnabled, cfg.Mode)
|
||||
cfg.Scopes = normalizeWeChatConnectScopes(cfg.Scopes, cfg.Mode)
|
||||
if cfg.FrontendRedirectURL == "" {
|
||||
cfg.FrontendRedirectURL = defaultWeChatConnectFrontendRedirect
|
||||
}
|
||||
}
|
||||
|
||||
// TokenRefreshConfig OAuth token自动刷新配置
|
||||
type TokenRefreshConfig struct {
|
||||
// 是否启用自动刷新
|
||||
@ -1067,6 +1313,8 @@ func load(allowMissingJWTSecret bool) (*Config, error) {
|
||||
cfg.LinuxDo.UserInfoEmailPath = strings.TrimSpace(cfg.LinuxDo.UserInfoEmailPath)
|
||||
cfg.LinuxDo.UserInfoIDPath = strings.TrimSpace(cfg.LinuxDo.UserInfoIDPath)
|
||||
cfg.LinuxDo.UserInfoUsernamePath = strings.TrimSpace(cfg.LinuxDo.UserInfoUsernamePath)
|
||||
applyLegacyWeChatConnectEnvCompatibility(&cfg.WeChat)
|
||||
normalizeWeChatConnectConfig(&cfg.WeChat)
|
||||
cfg.OIDC.ProviderName = strings.TrimSpace(cfg.OIDC.ProviderName)
|
||||
cfg.OIDC.ClientID = strings.TrimSpace(cfg.OIDC.ClientID)
|
||||
cfg.OIDC.ClientSecret = strings.TrimSpace(cfg.OIDC.ClientSecret)
|
||||
@ -1084,6 +1332,8 @@ func load(allowMissingJWTSecret bool) (*Config, error) {
|
||||
cfg.OIDC.UserInfoEmailPath = strings.TrimSpace(cfg.OIDC.UserInfoEmailPath)
|
||||
cfg.OIDC.UserInfoIDPath = strings.TrimSpace(cfg.OIDC.UserInfoIDPath)
|
||||
cfg.OIDC.UserInfoUsernamePath = strings.TrimSpace(cfg.OIDC.UserInfoUsernamePath)
|
||||
cfg.OIDC.UsePKCEExplicit = hasExplicitConfigOrEnv("oidc_connect.use_pkce", "OIDC_CONNECT_USE_PKCE")
|
||||
cfg.OIDC.ValidateIDTokenExplicit = hasExplicitConfigOrEnv("oidc_connect.validate_id_token", "OIDC_CONNECT_VALIDATE_ID_TOKEN")
|
||||
cfg.Dashboard.KeyPrefix = strings.TrimSpace(cfg.Dashboard.KeyPrefix)
|
||||
cfg.CORS.AllowedOrigins = normalizeStringSlice(cfg.CORS.AllowedOrigins)
|
||||
cfg.Security.ResponseHeaders.AdditionalAllowed = normalizeStringSlice(cfg.Security.ResponseHeaders.AdditionalAllowed)
|
||||
@ -1262,6 +1512,24 @@ func setDefaults() {
|
||||
viper.SetDefault("linuxdo_connect.userinfo_id_path", "")
|
||||
viper.SetDefault("linuxdo_connect.userinfo_username_path", "")
|
||||
|
||||
// WeChat Connect OAuth 登录
|
||||
viper.SetDefault("wechat_connect.enabled", false)
|
||||
viper.SetDefault("wechat_connect.app_id", "")
|
||||
viper.SetDefault("wechat_connect.app_secret", "")
|
||||
viper.SetDefault("wechat_connect.open_app_id", "")
|
||||
viper.SetDefault("wechat_connect.open_app_secret", "")
|
||||
viper.SetDefault("wechat_connect.mp_app_id", "")
|
||||
viper.SetDefault("wechat_connect.mp_app_secret", "")
|
||||
viper.SetDefault("wechat_connect.mobile_app_id", "")
|
||||
viper.SetDefault("wechat_connect.mobile_app_secret", "")
|
||||
viper.SetDefault("wechat_connect.open_enabled", false)
|
||||
viper.SetDefault("wechat_connect.mp_enabled", false)
|
||||
viper.SetDefault("wechat_connect.mobile_enabled", false)
|
||||
viper.SetDefault("wechat_connect.mode", defaultWeChatConnectMode)
|
||||
viper.SetDefault("wechat_connect.scopes", defaultWeChatConnectScopes)
|
||||
viper.SetDefault("wechat_connect.redirect_url", "")
|
||||
viper.SetDefault("wechat_connect.frontend_redirect_url", defaultWeChatConnectFrontendRedirect)
|
||||
|
||||
// Generic OIDC OAuth 登录
|
||||
viper.SetDefault("oidc_connect.enabled", false)
|
||||
viper.SetDefault("oidc_connect.provider_name", "OIDC")
|
||||
@ -1277,7 +1545,7 @@ func setDefaults() {
|
||||
viper.SetDefault("oidc_connect.redirect_url", "")
|
||||
viper.SetDefault("oidc_connect.frontend_redirect_url", "/auth/oidc/callback")
|
||||
viper.SetDefault("oidc_connect.token_auth_method", "client_secret_post")
|
||||
viper.SetDefault("oidc_connect.use_pkce", false)
|
||||
viper.SetDefault("oidc_connect.use_pkce", true)
|
||||
viper.SetDefault("oidc_connect.validate_id_token", true)
|
||||
viper.SetDefault("oidc_connect.allowed_signing_algs", "RS256,ES256,PS256")
|
||||
viper.SetDefault("oidc_connect.clock_skew_seconds", 120)
|
||||
@ -1476,7 +1744,7 @@ func setDefaults() {
|
||||
viper.SetDefault("gateway.antigravity_fallback_cooldown_minutes", 1)
|
||||
viper.SetDefault("gateway.antigravity_extra_retries", 10)
|
||||
viper.SetDefault("gateway.max_body_size", int64(256*1024*1024))
|
||||
viper.SetDefault("gateway.upstream_response_read_max_bytes", int64(8*1024*1024))
|
||||
viper.SetDefault("gateway.upstream_response_read_max_bytes", DefaultUpstreamResponseReadMaxBytes)
|
||||
viper.SetDefault("gateway.proxy_probe_response_read_max_bytes", int64(1024*1024))
|
||||
viper.SetDefault("gateway.gemini_debug_response_headers", false)
|
||||
viper.SetDefault("gateway.connection_pool_isolation", ConnectionPoolIsolationAccountProxy)
|
||||
@ -1713,9 +1981,6 @@ func (c *Config) Validate() error {
|
||||
default:
|
||||
return fmt.Errorf("linuxdo_connect.token_auth_method must be one of: client_secret_post/client_secret_basic/none")
|
||||
}
|
||||
if method == "none" && !c.LinuxDo.UsePKCE {
|
||||
return fmt.Errorf("linuxdo_connect.use_pkce must be true when linuxdo_connect.token_auth_method=none")
|
||||
}
|
||||
if (method == "" || method == "client_secret_post" || method == "client_secret_basic") &&
|
||||
strings.TrimSpace(c.LinuxDo.ClientSecret) == "" {
|
||||
return fmt.Errorf("linuxdo_connect.client_secret is required when linuxdo_connect.enabled=true and token_auth_method is client_secret_post/client_secret_basic")
|
||||
@ -1746,6 +2011,45 @@ func (c *Config) Validate() error {
|
||||
warnIfInsecureURL("linuxdo_connect.redirect_url", c.LinuxDo.RedirectURL)
|
||||
warnIfInsecureURL("linuxdo_connect.frontend_redirect_url", c.LinuxDo.FrontendRedirectURL)
|
||||
}
|
||||
if c.WeChat.Enabled {
|
||||
weChat := c.WeChat
|
||||
normalizeWeChatConnectConfig(&weChat)
|
||||
|
||||
if weChat.OpenEnabled {
|
||||
if strings.TrimSpace(weChat.OpenAppID) == "" {
|
||||
return fmt.Errorf("wechat_connect.open_app_id is required when wechat_connect.open_enabled=true")
|
||||
}
|
||||
if strings.TrimSpace(weChat.OpenAppSecret) == "" {
|
||||
return fmt.Errorf("wechat_connect.open_app_secret is required when wechat_connect.open_enabled=true")
|
||||
}
|
||||
}
|
||||
if weChat.MPEnabled {
|
||||
if strings.TrimSpace(weChat.MPAppID) == "" {
|
||||
return fmt.Errorf("wechat_connect.mp_app_id is required when wechat_connect.mp_enabled=true")
|
||||
}
|
||||
if strings.TrimSpace(weChat.MPAppSecret) == "" {
|
||||
return fmt.Errorf("wechat_connect.mp_app_secret is required when wechat_connect.mp_enabled=true")
|
||||
}
|
||||
}
|
||||
if weChat.MobileEnabled {
|
||||
if strings.TrimSpace(weChat.MobileAppID) == "" {
|
||||
return fmt.Errorf("wechat_connect.mobile_app_id is required when wechat_connect.mobile_enabled=true")
|
||||
}
|
||||
if strings.TrimSpace(weChat.MobileAppSecret) == "" {
|
||||
return fmt.Errorf("wechat_connect.mobile_app_secret is required when wechat_connect.mobile_enabled=true")
|
||||
}
|
||||
}
|
||||
if v := strings.TrimSpace(weChat.RedirectURL); v != "" {
|
||||
if err := ValidateAbsoluteHTTPURL(v); err != nil {
|
||||
return fmt.Errorf("wechat_connect.redirect_url invalid: %w", err)
|
||||
}
|
||||
warnIfInsecureURL("wechat_connect.redirect_url", v)
|
||||
}
|
||||
if err := ValidateFrontendRedirectURL(weChat.FrontendRedirectURL); err != nil {
|
||||
return fmt.Errorf("wechat_connect.frontend_redirect_url invalid: %w", err)
|
||||
}
|
||||
warnIfInsecureURL("wechat_connect.frontend_redirect_url", weChat.FrontendRedirectURL)
|
||||
}
|
||||
if c.OIDC.Enabled {
|
||||
if strings.TrimSpace(c.OIDC.ClientID) == "" {
|
||||
return fmt.Errorf("oidc_connect.client_id is required when oidc_connect.enabled=true")
|
||||
@ -1769,9 +2073,6 @@ func (c *Config) Validate() error {
|
||||
default:
|
||||
return fmt.Errorf("oidc_connect.token_auth_method must be one of: client_secret_post/client_secret_basic/none")
|
||||
}
|
||||
if method == "none" && !c.OIDC.UsePKCE {
|
||||
return fmt.Errorf("oidc_connect.use_pkce must be true when oidc_connect.token_auth_method=none")
|
||||
}
|
||||
if (method == "" || method == "client_secret_post" || method == "client_secret_basic") &&
|
||||
strings.TrimSpace(c.OIDC.ClientSecret) == "" {
|
||||
return fmt.Errorf("oidc_connect.client_secret is required when oidc_connect.enabled=true and token_auth_method is client_secret_post/client_secret_basic")
|
||||
|
||||
@ -225,6 +225,52 @@ func TestLoadSchedulingConfigFromEnv(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWeChatConnectConfigFromLegacyEnv(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
t.Setenv("WECHAT_OAUTH_OPEN_APP_ID", "wx-open-app")
|
||||
t.Setenv("WECHAT_OAUTH_OPEN_APP_SECRET", "wx-open-secret")
|
||||
t.Setenv("WECHAT_OAUTH_MP_APP_ID", "wx-mp-app")
|
||||
t.Setenv("WECHAT_OAUTH_MP_APP_SECRET", "wx-mp-secret")
|
||||
t.Setenv("WECHAT_OAUTH_FRONTEND_REDIRECT_URL", "/auth/wechat/legacy-callback")
|
||||
|
||||
cfg, err := Load()
|
||||
require.NoError(t, err)
|
||||
require.True(t, cfg.WeChat.Enabled)
|
||||
require.True(t, cfg.WeChat.OpenEnabled)
|
||||
require.True(t, cfg.WeChat.MPEnabled)
|
||||
require.False(t, cfg.WeChat.MobileEnabled)
|
||||
require.Equal(t, "open", cfg.WeChat.Mode)
|
||||
require.Equal(t, "wx-open-app", cfg.WeChat.OpenAppID)
|
||||
require.Equal(t, "wx-open-secret", cfg.WeChat.OpenAppSecret)
|
||||
require.Equal(t, "wx-mp-app", cfg.WeChat.MPAppID)
|
||||
require.Equal(t, "wx-mp-secret", cfg.WeChat.MPAppSecret)
|
||||
require.Equal(t, "/auth/wechat/legacy-callback", cfg.WeChat.FrontendRedirectURL)
|
||||
}
|
||||
|
||||
func TestLoadDefaultOIDCSecurityDefaults(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
|
||||
cfg, err := Load()
|
||||
require.NoError(t, err)
|
||||
require.True(t, cfg.OIDC.UsePKCE)
|
||||
require.True(t, cfg.OIDC.ValidateIDToken)
|
||||
require.False(t, cfg.OIDC.UsePKCEExplicit)
|
||||
require.False(t, cfg.OIDC.ValidateIDTokenExplicit)
|
||||
}
|
||||
|
||||
func TestLoadExplicitOIDCSecurityDefaultsFromEnvMarksFlagsExplicit(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
t.Setenv("OIDC_CONNECT_USE_PKCE", "false")
|
||||
t.Setenv("OIDC_CONNECT_VALIDATE_ID_TOKEN", "false")
|
||||
|
||||
cfg, err := Load()
|
||||
require.NoError(t, err)
|
||||
require.False(t, cfg.OIDC.UsePKCE)
|
||||
require.False(t, cfg.OIDC.ValidateIDToken)
|
||||
require.True(t, cfg.OIDC.UsePKCEExplicit)
|
||||
require.True(t, cfg.OIDC.ValidateIDTokenExplicit)
|
||||
}
|
||||
|
||||
func TestLoadForcedCodexInstructionsTemplate(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
|
||||
@ -334,7 +380,7 @@ func TestValidateLinuxDoFrontendRedirectURL(t *testing.T) {
|
||||
cfg.LinuxDo.ClientSecret = "test-secret"
|
||||
cfg.LinuxDo.RedirectURL = "https://example.com/api/v1/auth/oauth/linuxdo/callback"
|
||||
cfg.LinuxDo.TokenAuthMethod = "client_secret_post"
|
||||
cfg.LinuxDo.UsePKCE = false
|
||||
cfg.LinuxDo.UsePKCE = true
|
||||
|
||||
cfg.LinuxDo.FrontendRedirectURL = "javascript:alert(1)"
|
||||
err = cfg.Validate()
|
||||
@ -346,7 +392,7 @@ func TestValidateLinuxDoFrontendRedirectURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateLinuxDoPKCERequiredForPublicClient(t *testing.T) {
|
||||
func TestValidateLinuxDoAllowsDisablingPKCEForCompatibility(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
|
||||
cfg, err := Load()
|
||||
@ -363,11 +409,8 @@ func TestValidateLinuxDoPKCERequiredForPublicClient(t *testing.T) {
|
||||
cfg.LinuxDo.UsePKCE = false
|
||||
|
||||
err = cfg.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Validate() expected error when token_auth_method=none and use_pkce=false, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "linuxdo_connect.use_pkce") {
|
||||
t.Fatalf("Validate() expected use_pkce error, got: %v", err)
|
||||
if err != nil {
|
||||
t.Fatalf("Validate() expected LinuxDo config without PKCE to pass for compatibility, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,6 +432,7 @@ func TestValidateOIDCScopesMustContainOpenID(t *testing.T) {
|
||||
cfg.OIDC.RedirectURL = "https://example.com/api/v1/auth/oauth/oidc/callback"
|
||||
cfg.OIDC.FrontendRedirectURL = "/auth/oidc/callback"
|
||||
cfg.OIDC.Scopes = "profile email"
|
||||
cfg.OIDC.UsePKCE = true
|
||||
|
||||
err = cfg.Validate()
|
||||
if err == nil {
|
||||
@ -418,6 +462,7 @@ func TestValidateOIDCAllowsIssuerOnlyEndpointsWithDiscoveryFallback(t *testing.T
|
||||
cfg.OIDC.FrontendRedirectURL = "/auth/oidc/callback"
|
||||
cfg.OIDC.Scopes = "openid email profile"
|
||||
cfg.OIDC.ValidateIDToken = true
|
||||
cfg.OIDC.UsePKCE = true
|
||||
|
||||
err = cfg.Validate()
|
||||
if err != nil {
|
||||
@ -425,6 +470,35 @@ func TestValidateOIDCAllowsIssuerOnlyEndpointsWithDiscoveryFallback(t *testing.T
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateOIDCAllowsExplicitCompatibilityOverridesForPKCEAndIDTokenValidation(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
|
||||
cfg, err := Load()
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error: %v", err)
|
||||
}
|
||||
|
||||
cfg.OIDC.Enabled = true
|
||||
cfg.OIDC.ClientID = "oidc-client"
|
||||
cfg.OIDC.ClientSecret = "oidc-secret"
|
||||
cfg.OIDC.IssuerURL = "https://issuer.example.com"
|
||||
cfg.OIDC.AuthorizeURL = "https://issuer.example.com/auth"
|
||||
cfg.OIDC.TokenURL = "https://issuer.example.com/token"
|
||||
cfg.OIDC.UserInfoURL = "https://issuer.example.com/userinfo"
|
||||
cfg.OIDC.RedirectURL = "https://example.com/api/v1/auth/oauth/oidc/callback"
|
||||
cfg.OIDC.FrontendRedirectURL = "/auth/oidc/callback"
|
||||
cfg.OIDC.Scopes = "openid email profile"
|
||||
cfg.OIDC.UsePKCE = false
|
||||
cfg.OIDC.ValidateIDToken = false
|
||||
cfg.OIDC.JWKSURL = ""
|
||||
cfg.OIDC.AllowedSigningAlgs = ""
|
||||
|
||||
err = cfg.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("Validate() expected OIDC config without PKCE/id_token validation to pass for compatibility, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadDefaultDashboardCacheConfig(t *testing.T) {
|
||||
resetViperWithJWTSecret(t)
|
||||
|
||||
@ -840,6 +914,7 @@ func TestValidateConfigWithLinuxDoEnabled(t *testing.T) {
|
||||
cfg.LinuxDo.RedirectURL = "https://example.com/api/v1/auth/oauth/linuxdo/callback"
|
||||
cfg.LinuxDo.FrontendRedirectURL = "/auth/linuxdo/callback"
|
||||
cfg.LinuxDo.TokenAuthMethod = "client_secret_post"
|
||||
cfg.LinuxDo.UsePKCE = true
|
||||
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("Validate() unexpected error: %v", err)
|
||||
@ -990,6 +1065,7 @@ func TestValidateConfigErrors(t *testing.T) {
|
||||
name: "linuxdo client id required",
|
||||
mutate: func(c *Config) {
|
||||
c.LinuxDo.Enabled = true
|
||||
c.LinuxDo.UsePKCE = true
|
||||
c.LinuxDo.ClientID = ""
|
||||
},
|
||||
wantErr: "linuxdo_connect.client_id",
|
||||
@ -998,6 +1074,7 @@ func TestValidateConfigErrors(t *testing.T) {
|
||||
name: "linuxdo token auth method",
|
||||
mutate: func(c *Config) {
|
||||
c.LinuxDo.Enabled = true
|
||||
c.LinuxDo.UsePKCE = true
|
||||
c.LinuxDo.ClientID = "client"
|
||||
c.LinuxDo.ClientSecret = "secret"
|
||||
c.LinuxDo.AuthorizeURL = "https://example.com/authorize"
|
||||
|
||||
@ -23,6 +23,7 @@ func setupAdminRouter() (*gin.Engine, *stubAdminService) {
|
||||
|
||||
router.GET("/api/v1/admin/users", userHandler.List)
|
||||
router.GET("/api/v1/admin/users/:id", userHandler.GetByID)
|
||||
router.POST("/api/v1/admin/users/:id/auth-identities", userHandler.BindAuthIdentity)
|
||||
router.POST("/api/v1/admin/users", userHandler.Create)
|
||||
router.PUT("/api/v1/admin/users/:id", userHandler.Update)
|
||||
router.DELETE("/api/v1/admin/users/:id", userHandler.Delete)
|
||||
@ -75,8 +76,26 @@ func TestUserHandlerEndpoints(t *testing.T) {
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
bindBody := map[string]any{
|
||||
"provider_type": "wechat",
|
||||
"provider_key": "wechat-main",
|
||||
"provider_subject": "union-123",
|
||||
"metadata": map[string]any{"source": "admin-repair"},
|
||||
"channel": map[string]any{
|
||||
"channel": "open",
|
||||
"channel_app_id": "wx-open",
|
||||
"channel_subject": "openid-123",
|
||||
},
|
||||
}
|
||||
body, _ := json.Marshal(bindBody)
|
||||
rec = httptest.NewRecorder()
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/v1/admin/users/1/auth-identities", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
createBody := map[string]any{"email": "new@example.com", "password": "pass123", "balance": 1, "concurrency": 2}
|
||||
body, _ := json.Marshal(createBody)
|
||||
body, _ = json.Marshal(createBody)
|
||||
rec = httptest.NewRecorder()
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/v1/admin/users", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
@ -113,6 +132,33 @@ func TestUserHandlerEndpoints(t *testing.T) {
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
func TestUserHandlerBindAuthIdentityMapsRequest(t *testing.T) {
|
||||
router, adminSvc := setupAdminRouter()
|
||||
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"provider_type": "oidc",
|
||||
"provider_key": "https://issuer.example",
|
||||
"provider_subject": "subject-123",
|
||||
"issuer": "https://issuer.example",
|
||||
"metadata": map[string]any{"report_id": 12},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/admin/users/9/auth-identities", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(rec, req)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, int64(9), adminSvc.boundAuthIdentityFor)
|
||||
require.NotNil(t, adminSvc.boundAuthIdentity)
|
||||
require.Equal(t, "oidc", adminSvc.boundAuthIdentity.ProviderType)
|
||||
require.Equal(t, "https://issuer.example", adminSvc.boundAuthIdentity.ProviderKey)
|
||||
require.Equal(t, "subject-123", adminSvc.boundAuthIdentity.ProviderSubject)
|
||||
require.Nil(t, adminSvc.boundAuthIdentity.Channel)
|
||||
require.Equal(t, float64(12), adminSvc.boundAuthIdentity.Metadata["report_id"])
|
||||
}
|
||||
|
||||
func TestGroupHandlerEndpoints(t *testing.T) {
|
||||
router, _ := setupAdminRouter()
|
||||
|
||||
|
||||
@ -17,6 +17,8 @@ type stubAdminService struct {
|
||||
proxies []service.Proxy
|
||||
proxyCounts []service.ProxyWithAccountCount
|
||||
redeems []service.RedeemCode
|
||||
boundAuthIdentity *service.AdminBindAuthIdentityInput
|
||||
boundAuthIdentityFor int64
|
||||
createdAccounts []*service.CreateAccountInput
|
||||
createdProxies []*service.CreateProxyInput
|
||||
updatedProxyIDs []int64
|
||||
@ -42,6 +44,14 @@ type stubAdminService struct {
|
||||
sortOrder string
|
||||
calls int
|
||||
}
|
||||
lastListUsers struct {
|
||||
page int
|
||||
pageSize int
|
||||
filters service.UserListFilters
|
||||
sortBy string
|
||||
sortOrder string
|
||||
calls int
|
||||
}
|
||||
lastListProxies struct {
|
||||
protocol string
|
||||
status string
|
||||
@ -127,6 +137,12 @@ func newStubAdminService() *stubAdminService {
|
||||
}
|
||||
|
||||
func (s *stubAdminService) ListUsers(ctx context.Context, page, pageSize int, filters service.UserListFilters, sortBy, sortOrder string) ([]service.User, int64, error) {
|
||||
s.lastListUsers.page = page
|
||||
s.lastListUsers.pageSize = pageSize
|
||||
s.lastListUsers.filters = filters
|
||||
s.lastListUsers.sortBy = sortBy
|
||||
s.lastListUsers.sortOrder = sortOrder
|
||||
s.lastListUsers.calls++
|
||||
return s.users, int64(len(s.users)), nil
|
||||
}
|
||||
|
||||
@ -167,6 +183,52 @@ func (s *stubAdminService) GetUserUsageStats(ctx context.Context, userID int64,
|
||||
return map[string]any{"user_id": userID}, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) BindUserAuthIdentity(ctx context.Context, userID int64, input service.AdminBindAuthIdentityInput) (*service.AdminBoundAuthIdentity, error) {
|
||||
s.boundAuthIdentityFor = userID
|
||||
copied := input
|
||||
if input.Metadata != nil {
|
||||
copied.Metadata = map[string]any{}
|
||||
for key, value := range input.Metadata {
|
||||
copied.Metadata[key] = value
|
||||
}
|
||||
}
|
||||
if input.Channel != nil {
|
||||
channel := *input.Channel
|
||||
if input.Channel.Metadata != nil {
|
||||
channel.Metadata = map[string]any{}
|
||||
for key, value := range input.Channel.Metadata {
|
||||
channel.Metadata[key] = value
|
||||
}
|
||||
}
|
||||
copied.Channel = &channel
|
||||
}
|
||||
s.boundAuthIdentity = &copied
|
||||
|
||||
now := time.Now().UTC()
|
||||
result := &service.AdminBoundAuthIdentity{
|
||||
UserID: userID,
|
||||
ProviderType: input.ProviderType,
|
||||
ProviderKey: input.ProviderKey,
|
||||
ProviderSubject: input.ProviderSubject,
|
||||
VerifiedAt: &now,
|
||||
Issuer: input.Issuer,
|
||||
Metadata: input.Metadata,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if input.Channel != nil {
|
||||
result.Channel = &service.AdminBoundAuthIdentityChannel{
|
||||
Channel: input.Channel.Channel,
|
||||
ChannelAppID: input.Channel.ChannelAppID,
|
||||
ChannelSubject: input.Channel.ChannelSubject,
|
||||
Metadata: input.Channel.Metadata,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *stubAdminService) ListGroups(ctx context.Context, page, pageSize int, platform, status, search string, isExclusive *bool, sortBy, sortOrder string) ([]service.Group, int64, error) {
|
||||
return s.groups, int64(len(s.groups)), nil
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package admin
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
|
||||
@ -66,7 +67,7 @@ func (h *PaymentHandler) ListOrders(c *gin.Context) {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
response.Paginated(c, orders, int64(total), page, pageSize)
|
||||
response.Paginated(c, sanitizeAdminPaymentOrdersForResponse(orders), int64(total), page, pageSize)
|
||||
}
|
||||
|
||||
// GetOrderDetail returns detailed information about a single order.
|
||||
@ -82,7 +83,7 @@ func (h *PaymentHandler) GetOrderDetail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
auditLogs, _ := h.paymentService.GetOrderAuditLogs(c.Request.Context(), orderID)
|
||||
response.Success(c, gin.H{"order": order, "auditLogs": auditLogs})
|
||||
response.Success(c, gin.H{"order": sanitizeAdminPaymentOrderForResponse(order), "auditLogs": auditLogs})
|
||||
}
|
||||
|
||||
// CancelOrder cancels a pending order (admin).
|
||||
@ -114,6 +115,26 @@ func (h *PaymentHandler) RetryFulfillment(c *gin.Context) {
|
||||
response.Success(c, gin.H{"message": "fulfillment retried"})
|
||||
}
|
||||
|
||||
func sanitizeAdminPaymentOrdersForResponse(orders []*dbent.PaymentOrder) []*dbent.PaymentOrder {
|
||||
if len(orders) == 0 {
|
||||
return orders
|
||||
}
|
||||
out := make([]*dbent.PaymentOrder, 0, len(orders))
|
||||
for _, order := range orders {
|
||||
out = append(out, sanitizeAdminPaymentOrderForResponse(order))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func sanitizeAdminPaymentOrderForResponse(order *dbent.PaymentOrder) *dbent.PaymentOrder {
|
||||
if order == nil {
|
||||
return nil
|
||||
}
|
||||
cloned := *order
|
||||
cloned.ProviderSnapshot = nil
|
||||
return &cloned
|
||||
}
|
||||
|
||||
// AdminProcessRefundRequest is the request body for admin refund processing.
|
||||
type AdminProcessRefundRequest struct {
|
||||
Amount float64 `json:"amount"`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,503 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type settingHandlerRepoStub struct {
|
||||
values map[string]string
|
||||
lastUpdates map[string]string
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) Get(ctx context.Context, key string) (*service.Setting, error) {
|
||||
panic("unexpected Get call")
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) GetValue(ctx context.Context, key string) (string, error) {
|
||||
panic("unexpected GetValue call")
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) Set(ctx context.Context, key, value string) error {
|
||||
panic("unexpected Set call")
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) GetMultiple(ctx context.Context, keys []string) (map[string]string, error) {
|
||||
out := make(map[string]string, len(keys))
|
||||
for _, key := range keys {
|
||||
if value, ok := s.values[key]; ok {
|
||||
out[key] = value
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) SetMultiple(ctx context.Context, settings map[string]string) error {
|
||||
s.lastUpdates = make(map[string]string, len(settings))
|
||||
for key, value := range settings {
|
||||
s.lastUpdates[key] = value
|
||||
if s.values == nil {
|
||||
s.values = map[string]string{}
|
||||
}
|
||||
s.values[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) GetAll(ctx context.Context) (map[string]string, error) {
|
||||
out := make(map[string]string, len(s.values))
|
||||
for key, value := range s.values {
|
||||
out[key] = value
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *settingHandlerRepoStub) Delete(ctx context.Context, key string) error {
|
||||
panic("unexpected Delete call")
|
||||
}
|
||||
|
||||
type failingAuthSourceSettingsRepoStub struct {
|
||||
values map[string]string
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Get(ctx context.Context, key string) (*service.Setting, error) {
|
||||
panic("unexpected Get call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetValue(ctx context.Context, key string) (string, error) {
|
||||
panic("unexpected GetValue call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Set(ctx context.Context, key, value string) error {
|
||||
panic("unexpected Set call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetMultiple(ctx context.Context, keys []string) (map[string]string, error) {
|
||||
out := make(map[string]string, len(keys))
|
||||
for _, key := range keys {
|
||||
if value, ok := s.values[key]; ok {
|
||||
out[key] = value
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) SetMultiple(ctx context.Context, settings map[string]string) error {
|
||||
if _, ok := settings[service.SettingKeyAuthSourceDefaultEmailBalance]; ok {
|
||||
return s.err
|
||||
}
|
||||
for key, value := range settings {
|
||||
if s.values == nil {
|
||||
s.values = map[string]string{}
|
||||
}
|
||||
s.values[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetAll(ctx context.Context) (map[string]string, error) {
|
||||
out := make(map[string]string, len(s.values))
|
||||
for key, value := range s.values {
|
||||
out[key] = value
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Delete(ctx context.Context, key string) error {
|
||||
panic("unexpected Delete call")
|
||||
}
|
||||
|
||||
func TestSettingHandler_GetSettings_InjectsAuthSourceDefaults(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyRegistrationEnabled: "true",
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyAuthSourceDefaultEmailBalance: "9.5",
|
||||
service.SettingKeyAuthSourceDefaultEmailConcurrency: "8",
|
||||
service.SettingKeyAuthSourceDefaultEmailSubscriptions: `[{"group_id":31,"validity_days":15}]`,
|
||||
service.SettingKeyForceEmailOnThirdPartySignup: "true",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/admin/settings", nil)
|
||||
|
||||
handler.GetSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
var resp response.Response
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
data, ok := resp.Data.(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, 9.5, data["auth_source_default_email_balance"])
|
||||
require.Equal(t, float64(8), data["auth_source_default_email_concurrency"])
|
||||
require.Equal(t, true, data["force_email_on_third_party_signup"])
|
||||
|
||||
subscriptions, ok := data["auth_source_default_email_subscriptions"].([]any)
|
||||
require.True(t, ok)
|
||||
require.Len(t, subscriptions, 1)
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_PreservesOmittedAuthSourceDefaults(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyRegistrationEnabled: "false",
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyAuthSourceDefaultEmailBalance: "9.5",
|
||||
service.SettingKeyAuthSourceDefaultEmailConcurrency: "8",
|
||||
service.SettingKeyAuthSourceDefaultEmailSubscriptions: `[{"group_id":31,"validity_days":15}]`,
|
||||
service.SettingKeyAuthSourceDefaultEmailGrantOnSignup: "true",
|
||||
service.SettingKeyAuthSourceDefaultEmailGrantOnFirstBind: "false",
|
||||
service.SettingKeyForceEmailOnThirdPartySignup: "true",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"registration_enabled": true,
|
||||
"promo_code_enabled": true,
|
||||
"auth_source_default_email_balance": 12.75,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, "12.75000000", repo.values[service.SettingKeyAuthSourceDefaultEmailBalance])
|
||||
require.Equal(t, "8", repo.values[service.SettingKeyAuthSourceDefaultEmailConcurrency])
|
||||
require.Equal(t, `[{"group_id":31,"validity_days":15}]`, repo.values[service.SettingKeyAuthSourceDefaultEmailSubscriptions])
|
||||
require.Equal(t, "true", repo.values[service.SettingKeyForceEmailOnThirdPartySignup])
|
||||
|
||||
var resp response.Response
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
data, ok := resp.Data.(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, 12.75, data["auth_source_default_email_balance"])
|
||||
require.Equal(t, float64(8), data["auth_source_default_email_concurrency"])
|
||||
require.Equal(t, true, data["force_email_on_third_party_signup"])
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_PersistsPaymentVisibleMethodsAndAdvancedScheduler(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"promo_code_enabled": true,
|
||||
"payment_visible_method_alipay_source": "easypay",
|
||||
"payment_visible_method_wxpay_source": "wxpay",
|
||||
"payment_visible_method_alipay_enabled": true,
|
||||
"payment_visible_method_wxpay_enabled": false,
|
||||
"openai_advanced_scheduler_enabled": true,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, service.VisibleMethodSourceEasyPayAlipay, repo.values[service.SettingPaymentVisibleMethodAlipaySource])
|
||||
require.Equal(t, service.VisibleMethodSourceOfficialWechat, repo.values[service.SettingPaymentVisibleMethodWxpaySource])
|
||||
require.Equal(t, "true", repo.values[service.SettingPaymentVisibleMethodAlipayEnabled])
|
||||
require.Equal(t, "false", repo.values[service.SettingPaymentVisibleMethodWxpayEnabled])
|
||||
require.Equal(t, "true", repo.values["openai_advanced_scheduler_enabled"])
|
||||
|
||||
var resp response.Response
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
data, ok := resp.Data.(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, service.VisibleMethodSourceEasyPayAlipay, data["payment_visible_method_alipay_source"])
|
||||
require.Equal(t, service.VisibleMethodSourceOfficialWechat, data["payment_visible_method_wxpay_source"])
|
||||
require.Equal(t, true, data["payment_visible_method_alipay_enabled"])
|
||||
require.Equal(t, false, data["payment_visible_method_wxpay_enabled"])
|
||||
require.Equal(t, true, data["openai_advanced_scheduler_enabled"])
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_PreservesLegacyBlankPaymentVisibleMethodSource(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingPaymentVisibleMethodAlipayEnabled: "true",
|
||||
service.SettingPaymentVisibleMethodAlipaySource: "",
|
||||
service.SettingPaymentVisibleMethodWxpayEnabled: "false",
|
||||
service.SettingPaymentVisibleMethodWxpaySource: "",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"promo_code_enabled": false,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, "", repo.values[service.SettingPaymentVisibleMethodAlipaySource])
|
||||
require.Equal(t, "true", repo.values[service.SettingPaymentVisibleMethodAlipayEnabled])
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_PersistsExplicitFalseOIDCCompatibilityFlags(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyOIDCConnectEnabled: "true",
|
||||
service.SettingKeyOIDCConnectProviderName: "OIDC",
|
||||
service.SettingKeyOIDCConnectClientID: "oidc-client",
|
||||
service.SettingKeyOIDCConnectClientSecret: "oidc-secret",
|
||||
service.SettingKeyOIDCConnectIssuerURL: "https://issuer.example.com",
|
||||
service.SettingKeyOIDCConnectAuthorizeURL: "https://issuer.example.com/auth",
|
||||
service.SettingKeyOIDCConnectTokenURL: "https://issuer.example.com/token",
|
||||
service.SettingKeyOIDCConnectUserInfoURL: "https://issuer.example.com/userinfo",
|
||||
service.SettingKeyOIDCConnectJWKSURL: "https://issuer.example.com/jwks",
|
||||
service.SettingKeyOIDCConnectScopes: "openid email profile",
|
||||
service.SettingKeyOIDCConnectRedirectURL: "https://example.com/api/v1/auth/oauth/oidc/callback",
|
||||
service.SettingKeyOIDCConnectFrontendRedirectURL: "/auth/oidc/callback",
|
||||
service.SettingKeyOIDCConnectTokenAuthMethod: "client_secret_post",
|
||||
service.SettingKeyOIDCConnectUsePKCE: "true",
|
||||
service.SettingKeyOIDCConnectValidateIDToken: "true",
|
||||
service.SettingKeyOIDCConnectAllowedSigningAlgs: "RS256",
|
||||
service.SettingKeyOIDCConnectClockSkewSeconds: "120",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"promo_code_enabled": true,
|
||||
"oidc_connect_enabled": true,
|
||||
"oidc_connect_use_pkce": false,
|
||||
"oidc_connect_validate_id_token": false,
|
||||
"oidc_connect_allowed_signing_algs": "",
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyOIDCConnectUsePKCE])
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyOIDCConnectValidateIDToken])
|
||||
|
||||
var resp response.Response
|
||||
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
||||
data, ok := resp.Data.(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, false, data["oidc_connect_use_pkce"])
|
||||
require.Equal(t, false, data["oidc_connect_validate_id_token"])
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_DoesNotSolidifyImplicitOIDCSecurityDefaultsOnLegacyUpgrade(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyOIDCConnectEnabled: "true",
|
||||
service.SettingKeyOIDCConnectProviderName: "OIDC",
|
||||
service.SettingKeyOIDCConnectClientID: "oidc-client",
|
||||
service.SettingKeyOIDCConnectClientSecret: "oidc-secret",
|
||||
service.SettingKeyOIDCConnectIssuerURL: "https://issuer.example.com",
|
||||
service.SettingKeyOIDCConnectAuthorizeURL: "https://issuer.example.com/auth",
|
||||
service.SettingKeyOIDCConnectTokenURL: "https://issuer.example.com/token",
|
||||
service.SettingKeyOIDCConnectUserInfoURL: "https://issuer.example.com/userinfo",
|
||||
service.SettingKeyOIDCConnectJWKSURL: "https://issuer.example.com/jwks",
|
||||
service.SettingKeyOIDCConnectScopes: "openid email profile",
|
||||
service.SettingKeyOIDCConnectRedirectURL: "https://example.com/api/v1/auth/oauth/oidc/callback",
|
||||
service.SettingKeyOIDCConnectFrontendRedirectURL: "/auth/oidc/callback",
|
||||
service.SettingKeyOIDCConnectTokenAuthMethod: "client_secret_post",
|
||||
service.SettingKeyOIDCConnectAllowedSigningAlgs: "RS256",
|
||||
service.SettingKeyOIDCConnectClockSkewSeconds: "120",
|
||||
service.SettingKeyOIDCConnectRequireEmailVerified: "false",
|
||||
service.SettingKeyOIDCConnectUserInfoEmailPath: "",
|
||||
service.SettingKeyOIDCConnectUserInfoIDPath: "",
|
||||
service.SettingKeyOIDCConnectUserInfoUsernamePath: "",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{
|
||||
Default: config.DefaultConfig{UserConcurrency: 5},
|
||||
OIDC: config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ProviderName: "OIDC",
|
||||
ClientID: "oidc-client",
|
||||
ClientSecret: "oidc-secret",
|
||||
IssuerURL: "https://issuer.example.com",
|
||||
AuthorizeURL: "https://issuer.example.com/auth",
|
||||
TokenURL: "https://issuer.example.com/token",
|
||||
UserInfoURL: "https://issuer.example.com/userinfo",
|
||||
JWKSURL: "https://issuer.example.com/jwks",
|
||||
Scopes: "openid email profile",
|
||||
RedirectURL: "https://example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
ValidateIDToken: true,
|
||||
AllowedSigningAlgs: "RS256",
|
||||
ClockSkewSeconds: 120,
|
||||
},
|
||||
})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"promo_code_enabled": true,
|
||||
"oidc_connect_enabled": true,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyOIDCConnectUsePKCE])
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyOIDCConnectValidateIDToken])
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_RejectsInvalidPaymentVisibleMethodSource(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
},
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"promo_code_enabled": true,
|
||||
"payment_visible_method_alipay_source": "bogus",
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, rec.Code)
|
||||
require.NotContains(t, repo.values, service.SettingPaymentVisibleMethodAlipaySource)
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_DoesNotPersistPartialSystemSettingsWhenAuthSourceDefaultsFail(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &failingAuthSourceSettingsRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyRegistrationEnabled: "false",
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyAuthSourceDefaultEmailBalance: "9.5",
|
||||
service.SettingKeyAuthSourceDefaultEmailConcurrency: "8",
|
||||
service.SettingKeyAuthSourceDefaultEmailSubscriptions: `[{"group_id":31,"validity_days":15}]`,
|
||||
},
|
||||
err: errors.New("write auth source defaults failed"),
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"registration_enabled": true,
|
||||
"promo_code_enabled": true,
|
||||
"auth_source_default_email_balance": 12.75,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyRegistrationEnabled])
|
||||
require.Equal(t, "9.5", repo.values[service.SettingKeyAuthSourceDefaultEmailBalance])
|
||||
}
|
||||
|
||||
func TestDiffSettings_IncludesAuthSourceDefaultsAndForceEmail(t *testing.T) {
|
||||
changed := diffSettings(
|
||||
&service.SystemSettings{},
|
||||
&service.SystemSettings{},
|
||||
&service.AuthSourceDefaultSettings{
|
||||
Email: service.ProviderDefaultGrantSettings{
|
||||
Balance: 0,
|
||||
Concurrency: 5,
|
||||
Subscriptions: nil,
|
||||
GrantOnSignup: true,
|
||||
GrantOnFirstBind: false,
|
||||
},
|
||||
ForceEmailOnThirdPartySignup: false,
|
||||
},
|
||||
&service.AuthSourceDefaultSettings{
|
||||
Email: service.ProviderDefaultGrantSettings{
|
||||
Balance: 12.5,
|
||||
Concurrency: 7,
|
||||
Subscriptions: []service.DefaultSubscriptionSetting{{GroupID: 21, ValidityDays: 30}},
|
||||
GrantOnSignup: false,
|
||||
GrantOnFirstBind: true,
|
||||
},
|
||||
ForceEmailOnThirdPartySignup: true,
|
||||
},
|
||||
UpdateSettingsRequest{},
|
||||
)
|
||||
|
||||
require.Contains(t, changed, "auth_source_default_email_balance")
|
||||
require.Contains(t, changed, "auth_source_default_email_concurrency")
|
||||
require.Contains(t, changed, "auth_source_default_email_subscriptions")
|
||||
require.Contains(t, changed, "auth_source_default_email_grant_on_signup")
|
||||
require.Contains(t, changed, "auth_source_default_email_grant_on_first_bind")
|
||||
require.Contains(t, changed, "force_email_on_third_party_signup")
|
||||
}
|
||||
@ -66,6 +66,22 @@ type UpdateBalanceRequest struct {
|
||||
Notes string `json:"notes"`
|
||||
}
|
||||
|
||||
type BindUserAuthIdentityRequest struct {
|
||||
ProviderType string `json:"provider_type"`
|
||||
ProviderKey string `json:"provider_key"`
|
||||
ProviderSubject string `json:"provider_subject"`
|
||||
Issuer *string `json:"issuer"`
|
||||
Metadata map[string]any `json:"metadata"`
|
||||
Channel *BindUserAuthIdentityChannelRequest `json:"channel"`
|
||||
}
|
||||
|
||||
type BindUserAuthIdentityChannelRequest struct {
|
||||
Channel string `json:"channel"`
|
||||
ChannelAppID string `json:"channel_app_id"`
|
||||
ChannelSubject string `json:"channel_subject"`
|
||||
Metadata map[string]any `json:"metadata"`
|
||||
}
|
||||
|
||||
// List handles listing all users with pagination
|
||||
// GET /api/v1/admin/users
|
||||
// Query params:
|
||||
@ -172,6 +188,45 @@ func (h *UserHandler) GetByID(c *gin.Context) {
|
||||
response.Success(c, dto.UserFromServiceAdmin(user))
|
||||
}
|
||||
|
||||
// BindAuthIdentity manually binds a canonical auth identity to a user.
|
||||
// POST /api/v1/admin/users/:id/auth-identities
|
||||
func (h *UserHandler) BindAuthIdentity(c *gin.Context) {
|
||||
userID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid user ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req BindUserAuthIdentityRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
input := service.AdminBindAuthIdentityInput{
|
||||
ProviderType: req.ProviderType,
|
||||
ProviderKey: req.ProviderKey,
|
||||
ProviderSubject: req.ProviderSubject,
|
||||
Issuer: req.Issuer,
|
||||
Metadata: req.Metadata,
|
||||
}
|
||||
if req.Channel != nil {
|
||||
input.Channel = &service.AdminBindAuthIdentityChannelInput{
|
||||
Channel: req.Channel.Channel,
|
||||
ChannelAppID: req.Channel.ChannelAppID,
|
||||
ChannelSubject: req.Channel.ChannelSubject,
|
||||
Metadata: req.Channel.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
result, err := h.adminService.BindUserAuthIdentity(c.Request.Context(), userID, input)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
// Create handles creating a new user
|
||||
// POST /api/v1/admin/users
|
||||
func (h *UserHandler) Create(c *gin.Context) {
|
||||
|
||||
114
backend/internal/handler/admin/user_handler_activity_test.go
Normal file
114
backend/internal/handler/admin/user_handler_activity_test.go
Normal file
@ -0,0 +1,114 @@
|
||||
//go:build unit
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUserHandlerListIncludesActivityFieldsAndSortParams(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
lastLoginAt := time.Date(2026, 4, 20, 8, 0, 0, 0, time.UTC)
|
||||
lastActiveAt := lastLoginAt.Add(30 * time.Minute)
|
||||
lastUsedAt := lastLoginAt.Add(90 * time.Minute)
|
||||
|
||||
adminSvc := newStubAdminService()
|
||||
adminSvc.users = []service.User{
|
||||
{
|
||||
ID: 7,
|
||||
Email: "activity@example.com",
|
||||
Username: "activity-user",
|
||||
Role: service.RoleUser,
|
||||
Status: service.StatusActive,
|
||||
LastActiveAt: &lastActiveAt,
|
||||
LastUsedAt: &lastUsedAt,
|
||||
CreatedAt: lastLoginAt.Add(-24 * time.Hour),
|
||||
UpdatedAt: lastLoginAt,
|
||||
},
|
||||
}
|
||||
handler := NewUserHandler(adminSvc, nil)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"/api/v1/admin/users?sort_by=last_used_at&sort_order=asc&search=activity",
|
||||
nil,
|
||||
)
|
||||
|
||||
handler.List(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
require.Equal(t, "last_used_at", adminSvc.lastListUsers.sortBy)
|
||||
require.Equal(t, "asc", adminSvc.lastListUsers.sortOrder)
|
||||
require.Equal(t, "activity", adminSvc.lastListUsers.filters.Search)
|
||||
|
||||
var resp struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Items []struct {
|
||||
LastActiveAt *time.Time `json:"last_active_at"`
|
||||
LastUsedAt *time.Time `json:"last_used_at"`
|
||||
} `json:"items"`
|
||||
} `json:"data"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Len(t, resp.Data.Items, 1)
|
||||
require.WithinDuration(t, lastActiveAt, *resp.Data.Items[0].LastActiveAt, time.Second)
|
||||
require.WithinDuration(t, lastUsedAt, *resp.Data.Items[0].LastUsedAt, time.Second)
|
||||
}
|
||||
|
||||
func TestUserHandlerGetByIDIncludesActivityFields(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
lastLoginAt := time.Date(2026, 4, 20, 8, 0, 0, 0, time.UTC)
|
||||
lastActiveAt := lastLoginAt.Add(30 * time.Minute)
|
||||
lastUsedAt := lastLoginAt.Add(90 * time.Minute)
|
||||
|
||||
adminSvc := newStubAdminService()
|
||||
adminSvc.users = []service.User{
|
||||
{
|
||||
ID: 8,
|
||||
Email: "detail@example.com",
|
||||
Username: "detail-user",
|
||||
Role: service.RoleUser,
|
||||
Status: service.StatusActive,
|
||||
LastActiveAt: &lastActiveAt,
|
||||
LastUsedAt: &lastUsedAt,
|
||||
CreatedAt: lastLoginAt.Add(-24 * time.Hour),
|
||||
UpdatedAt: lastLoginAt,
|
||||
},
|
||||
}
|
||||
handler := NewUserHandler(adminSvc, nil)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Params = gin.Params{{Key: "id", Value: "8"}}
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/admin/users/8", nil)
|
||||
|
||||
handler.GetByID(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
var resp struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
LastActiveAt *time.Time `json:"last_active_at"`
|
||||
LastUsedAt *time.Time `json:"last_used_at"`
|
||||
} `json:"data"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.WithinDuration(t, lastActiveAt, *resp.Data.LastActiveAt, time.Second)
|
||||
require.WithinDuration(t, lastUsedAt, *resp.Data.LastUsedAt, time.Second)
|
||||
}
|
||||
86
backend/internal/handler/auth_current_user_test.go
Normal file
86
backend/internal/handler/auth_current_user_test.go
Normal file
@ -0,0 +1,86 @@
|
||||
//go:build unit
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthHandlerGetCurrentUserReturnsProfileCompatibilityFields(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
verifiedAt := time.Date(2026, 4, 20, 8, 30, 0, 0, time.UTC)
|
||||
repo := &userHandlerRepoStub{
|
||||
user: &service.User{
|
||||
ID: 31,
|
||||
Email: "me@example.com",
|
||||
Username: "linuxdo-handle",
|
||||
Role: service.RoleUser,
|
||||
Status: service.StatusActive,
|
||||
AvatarURL: "https://cdn.example.com/linuxdo.png",
|
||||
AvatarSource: "remote_url",
|
||||
},
|
||||
identities: []service.UserAuthIdentityRecord{
|
||||
{
|
||||
ProviderType: "linuxdo",
|
||||
ProviderKey: "linuxdo",
|
||||
ProviderSubject: "linuxdo-subject-31",
|
||||
VerifiedAt: &verifiedAt,
|
||||
Metadata: map[string]any{
|
||||
"username": "linuxdo-handle",
|
||||
"avatar_url": "https://cdn.example.com/linuxdo.png",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
handler := &AuthHandler{
|
||||
userService: service.NewUserService(repo, nil, nil, nil),
|
||||
}
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/auth/me", nil)
|
||||
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 31})
|
||||
|
||||
handler.GetCurrentUser(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
var resp struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]any `json:"data"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Equal(t, true, resp.Data["email_bound"])
|
||||
require.Equal(t, true, resp.Data["linuxdo_bound"])
|
||||
require.Equal(t, "https://cdn.example.com/linuxdo.png", resp.Data["avatar_url"])
|
||||
|
||||
authBindings, ok := resp.Data["auth_bindings"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
linuxdoBinding, ok := authBindings["linuxdo"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, true, linuxdoBinding["bound"])
|
||||
|
||||
avatarSource, ok := resp.Data["avatar_source"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "linuxdo", avatarSource["provider"])
|
||||
require.Equal(t, "linuxdo", avatarSource["source"])
|
||||
|
||||
profileSources, ok := resp.Data["profile_sources"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
usernameSource, ok := profileSources["username"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "linuxdo", usernameSource["provider"])
|
||||
require.Equal(t, "linuxdo", usernameSource["source"])
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/ip"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
@ -76,9 +78,24 @@ type AuthResponse struct {
|
||||
User *dto.User `json:"user"`
|
||||
}
|
||||
|
||||
func ensureLoginUserActive(user *service.User) error {
|
||||
if user == nil {
|
||||
return infraerrors.Unauthorized("INVALID_USER", "user not found")
|
||||
}
|
||||
if !user.IsActive() {
|
||||
return service.ErrUserNotActive
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// respondWithTokenPair 生成 Token 对并返回认证响应
|
||||
// 如果 Token 对生成失败,回退到只返回 Access Token(向后兼容)
|
||||
func (h *AuthHandler) respondWithTokenPair(c *gin.Context, user *service.User) {
|
||||
if err := ensureLoginUserActive(user); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenPair, err := h.authService.GenerateTokenPair(c.Request.Context(), user, "")
|
||||
if err != nil {
|
||||
slog.Error("failed to generate token pair", "error", err, "user_id", user.ID)
|
||||
@ -104,6 +121,34 @@ func (h *AuthHandler) respondWithTokenPair(c *gin.Context, user *service.User) {
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ensureBackendModeAllowsUser(ctx context.Context, user *service.User) error {
|
||||
if user == nil {
|
||||
return infraerrors.Unauthorized("INVALID_USER", "user not found")
|
||||
}
|
||||
if h == nil || !h.isBackendModeEnabled(ctx) || user.IsAdmin() {
|
||||
return nil
|
||||
}
|
||||
return infraerrors.Forbidden("BACKEND_MODE_ADMIN_ONLY", "Backend mode is active. Only admin login is allowed.")
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ensureBackendModeAllowsNewUserLogin(ctx context.Context) error {
|
||||
if h == nil || !h.isBackendModeEnabled(ctx) {
|
||||
return nil
|
||||
}
|
||||
return infraerrors.Forbidden("BACKEND_MODE_ADMIN_ONLY", "Backend mode is active. Only admin login is allowed.")
|
||||
}
|
||||
|
||||
func (h *AuthHandler) isBackendModeEnabled(ctx context.Context) bool {
|
||||
if h == nil || h.settingSvc == nil {
|
||||
return false
|
||||
}
|
||||
settings, err := h.settingSvc.GetPublicSettings(ctx)
|
||||
if err == nil && settings != nil {
|
||||
return settings.BackendModeEnabled
|
||||
}
|
||||
return h.settingSvc.IsBackendModeEnabled(ctx)
|
||||
}
|
||||
|
||||
// Register handles user registration
|
||||
// POST /api/v1/auth/register
|
||||
func (h *AuthHandler) Register(c *gin.Context) {
|
||||
@ -177,6 +222,11 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
}
|
||||
_ = token // token 由 authService.Login 返回但此处由 respondWithTokenPair 重新生成
|
||||
|
||||
if err := h.ensureBackendModeAllowsUser(c.Request.Context(), user); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if TOTP 2FA is enabled for this user
|
||||
if h.totpService != nil && h.settingSvc.IsTotpEnabled(c.Request.Context()) && user.TotpEnabled {
|
||||
// Create a temporary login session for 2FA
|
||||
@ -194,11 +244,7 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Backend mode: only admin can login
|
||||
if h.settingSvc.IsBackendModeEnabled(c.Request.Context()) && !user.IsAdmin() {
|
||||
response.Forbidden(c, "Backend mode is active. Only admin login is allowed.")
|
||||
return
|
||||
}
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
|
||||
h.respondWithTokenPair(c, user)
|
||||
}
|
||||
@ -262,16 +308,80 @@ func (h *AuthHandler) Login2FA(c *gin.Context) {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Backend mode: only admin can login (check BEFORE deleting session)
|
||||
if h.settingSvc.IsBackendModeEnabled(c.Request.Context()) && !user.IsAdmin() {
|
||||
response.Forbidden(c, "Backend mode is active. Only admin login is allowed.")
|
||||
if err := ensureLoginUserActive(user); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.ensureBackendModeAllowsUser(c.Request.Context(), user); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if session.PendingOAuthBind != nil {
|
||||
pendingSvc, err := h.pendingIdentityService()
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
pendingSession, err := pendingSvc.GetBrowserSession(
|
||||
c.Request.Context(),
|
||||
session.PendingOAuthBind.PendingSessionToken,
|
||||
session.PendingOAuthBind.BrowserSessionKey,
|
||||
)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
decision, err := h.ensurePendingOAuthAdoptionDecision(c, pendingSession.ID, oauthAdoptionDecisionRequest{})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := applyPendingOAuthBinding(
|
||||
c.Request.Context(),
|
||||
h.entClient(),
|
||||
h.authService,
|
||||
h.userService,
|
||||
pendingSession,
|
||||
decision,
|
||||
&user.ID,
|
||||
true,
|
||||
true,
|
||||
); err != nil {
|
||||
response.ErrorFrom(c, infraerrors.InternalServer("PENDING_AUTH_BIND_APPLY_FAILED", "failed to bind pending oauth identity").WithCause(err))
|
||||
return
|
||||
}
|
||||
if _, err := pendingSvc.ConsumeBrowserSession(
|
||||
c.Request.Context(),
|
||||
pendingSession.SessionToken,
|
||||
pendingSession.BrowserSessionKey,
|
||||
); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
secureCookie := isRequestHTTPS(c)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
|
||||
user, err = h.userService.GetByID(c.Request.Context(), session.UserID)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the login session (only after all checks pass)
|
||||
_ = h.totpService.DeleteLoginSession(c.Request.Context(), req.TempToken)
|
||||
|
||||
if session.PendingOAuthBind == nil {
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
}
|
||||
|
||||
h.respondWithTokenPair(c, user)
|
||||
}
|
||||
|
||||
@ -290,8 +400,14 @@ func (h *AuthHandler) GetCurrentUser(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
identities, err := h.userService.GetProfileIdentitySummaries(c.Request.Context(), subject.UserID, user)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
type UserResponse struct {
|
||||
*dto.User
|
||||
userProfileResponse
|
||||
RunMode string `json:"run_mode"`
|
||||
}
|
||||
|
||||
@ -300,7 +416,10 @@ func (h *AuthHandler) GetCurrentUser(c *gin.Context) {
|
||||
runMode = h.cfg.RunMode
|
||||
}
|
||||
|
||||
response.Success(c, UserResponse{User: dto.UserFromService(user), RunMode: runMode})
|
||||
response.Success(c, UserResponse{
|
||||
userProfileResponse: userProfileResponseFromService(user, identities),
|
||||
RunMode: runMode,
|
||||
})
|
||||
}
|
||||
|
||||
// ValidatePromoCodeRequest 验证优惠码请求
|
||||
@ -578,6 +697,8 @@ func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
// 不影响登出流程
|
||||
}
|
||||
}
|
||||
h.consumePendingOAuthSessionOnLogout(c)
|
||||
clearOAuthLogoutCookies(c)
|
||||
|
||||
response.Success(c, LogoutResponse{
|
||||
Message: "Logged out successfully",
|
||||
@ -598,7 +719,7 @@ func (h *AuthHandler) RevokeAllSessions(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.authService.RevokeAllUserSessions(c.Request.Context(), subject.UserID); err != nil {
|
||||
if err := h.authService.RevokeAllUserTokens(c.Request.Context(), subject.UserID); err != nil {
|
||||
slog.Error("failed to revoke all sessions", "user_id", subject.UserID, "error", err)
|
||||
response.InternalError(c, "Failed to revoke sessions")
|
||||
return
|
||||
|
||||
@ -2,6 +2,8 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -13,10 +15,13 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
dbuser "github.com/Wei-Shaw/sub2api/ent/user"
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/oauth"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
||||
servermiddleware "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -25,17 +30,24 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
linuxDoOAuthCookiePath = "/api/v1/auth/oauth/linuxdo"
|
||||
linuxDoOAuthStateCookieName = "linuxdo_oauth_state"
|
||||
linuxDoOAuthVerifierCookie = "linuxdo_oauth_verifier"
|
||||
linuxDoOAuthRedirectCookie = "linuxdo_oauth_redirect"
|
||||
linuxDoOAuthCookieMaxAgeSec = 10 * 60 // 10 minutes
|
||||
linuxDoOAuthDefaultRedirectTo = "/dashboard"
|
||||
linuxDoOAuthDefaultFrontendCB = "/auth/linuxdo/callback"
|
||||
linuxDoOAuthCookiePath = "/api/v1/auth/oauth/linuxdo"
|
||||
oauthBindAccessTokenCookiePath = "/api/v1/auth/oauth"
|
||||
linuxDoOAuthStateCookieName = "linuxdo_oauth_state"
|
||||
linuxDoOAuthVerifierCookie = "linuxdo_oauth_verifier"
|
||||
linuxDoOAuthRedirectCookie = "linuxdo_oauth_redirect"
|
||||
linuxDoOAuthIntentCookieName = "linuxdo_oauth_intent"
|
||||
linuxDoOAuthBindUserCookieName = "linuxdo_oauth_bind_user"
|
||||
oauthBindAccessTokenCookieName = "oauth_bind_access_token"
|
||||
linuxDoOAuthCookieMaxAgeSec = 10 * 60 // 10 minutes
|
||||
linuxDoOAuthDefaultRedirectTo = "/dashboard"
|
||||
linuxDoOAuthDefaultFrontendCB = "/auth/linuxdo/callback"
|
||||
|
||||
linuxDoOAuthMaxRedirectLen = 2048
|
||||
linuxDoOAuthMaxFragmentValueLen = 512
|
||||
linuxDoOAuthMaxSubjectLen = 64 - len("linuxdo-")
|
||||
|
||||
oauthIntentLogin = "login"
|
||||
oauthIntentBindCurrentUser = "bind_current_user"
|
||||
)
|
||||
|
||||
type linuxDoTokenResponse struct {
|
||||
@ -87,9 +99,29 @@ func (h *AuthHandler) LinuxDoOAuthStart(c *gin.Context) {
|
||||
redirectTo = linuxDoOAuthDefaultRedirectTo
|
||||
}
|
||||
|
||||
browserSessionKey, err := generateOAuthPendingBrowserSession()
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_BROWSER_SESSION_GEN_FAILED", "failed to generate oauth browser session").WithCause(err))
|
||||
return
|
||||
}
|
||||
|
||||
secureCookie := isRequestHTTPS(c)
|
||||
setCookie(c, linuxDoOAuthStateCookieName, encodeCookieValue(state), linuxDoOAuthCookieMaxAgeSec, secureCookie)
|
||||
setCookie(c, linuxDoOAuthRedirectCookie, encodeCookieValue(redirectTo), linuxDoOAuthCookieMaxAgeSec, secureCookie)
|
||||
intent := normalizeOAuthIntent(c.Query("intent"))
|
||||
setCookie(c, linuxDoOAuthIntentCookieName, encodeCookieValue(intent), linuxDoOAuthCookieMaxAgeSec, secureCookie)
|
||||
setOAuthPendingBrowserCookie(c, browserSessionKey, secureCookie)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
if intent == oauthIntentBindCurrentUser {
|
||||
bindCookieValue, err := h.buildOAuthBindUserCookieFromContext(c)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
setCookie(c, linuxDoOAuthBindUserCookieName, encodeCookieValue(bindCookieValue), linuxDoOAuthCookieMaxAgeSec, secureCookie)
|
||||
} else {
|
||||
clearCookie(c, linuxDoOAuthBindUserCookieName, secureCookie)
|
||||
}
|
||||
|
||||
codeChallenge := ""
|
||||
if cfg.UsePKCE {
|
||||
@ -148,6 +180,8 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
|
||||
clearCookie(c, linuxDoOAuthStateCookieName, secureCookie)
|
||||
clearCookie(c, linuxDoOAuthVerifierCookie, secureCookie)
|
||||
clearCookie(c, linuxDoOAuthRedirectCookie, secureCookie)
|
||||
clearCookie(c, linuxDoOAuthIntentCookieName, secureCookie)
|
||||
clearCookie(c, linuxDoOAuthBindUserCookieName, secureCookie)
|
||||
}()
|
||||
|
||||
expectedState, err := readCookieDecoded(c, linuxDoOAuthStateCookieName)
|
||||
@ -161,6 +195,13 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
|
||||
if redirectTo == "" {
|
||||
redirectTo = linuxDoOAuthDefaultRedirectTo
|
||||
}
|
||||
browserSessionKey, _ := readOAuthPendingBrowserCookie(c)
|
||||
if strings.TrimSpace(browserSessionKey) == "" {
|
||||
redirectOAuthError(c, frontendCallback, "missing_browser_session", "missing oauth browser session", "")
|
||||
return
|
||||
}
|
||||
intent, _ := readCookieDecoded(c, linuxDoOAuthIntentCookieName)
|
||||
intent = normalizeOAuthIntent(intent)
|
||||
|
||||
codeVerifier := ""
|
||||
if cfg.UsePKCE {
|
||||
@ -198,52 +239,204 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
email, username, subject, err := linuxDoFetchUserInfo(c.Request.Context(), cfg, tokenResp)
|
||||
email, username, subject, displayName, avatarURL, err := linuxDoFetchUserInfo(c.Request.Context(), cfg, tokenResp)
|
||||
if err != nil {
|
||||
log.Printf("[LinuxDo OAuth] userinfo fetch failed: %v", err)
|
||||
redirectOAuthError(c, frontendCallback, "userinfo_failed", "failed to fetch user info", "")
|
||||
return
|
||||
}
|
||||
compatEmail := strings.TrimSpace(email)
|
||||
|
||||
// 安全考虑:不要把第三方返回的 email 直接映射到本地账号(可能与本地邮箱用户冲突导致账号被接管)。
|
||||
// 统一使用基于 subject 的稳定合成邮箱来做账号绑定。
|
||||
if subject != "" {
|
||||
email = linuxDoSyntheticEmail(subject)
|
||||
}
|
||||
|
||||
// 传入空邀请码;如果需要邀请码,服务层返回 ErrOAuthInvitationRequired
|
||||
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, "")
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrOAuthInvitationRequired) {
|
||||
pendingToken, tokenErr := h.authService.CreatePendingOAuthToken(email, username)
|
||||
if tokenErr != nil {
|
||||
redirectOAuthError(c, frontendCallback, "login_failed", "service_error", "")
|
||||
return
|
||||
}
|
||||
fragment := url.Values{}
|
||||
fragment.Set("error", "invitation_required")
|
||||
fragment.Set("pending_oauth_token", pendingToken)
|
||||
fragment.Set("redirect", redirectTo)
|
||||
redirectWithFragment(c, frontendCallback, fragment)
|
||||
identityKey := service.PendingAuthIdentityKey{
|
||||
ProviderType: "linuxdo",
|
||||
ProviderKey: "linuxdo",
|
||||
ProviderSubject: subject,
|
||||
}
|
||||
upstreamClaims := map[string]any{
|
||||
"email": email,
|
||||
"username": username,
|
||||
"subject": subject,
|
||||
"suggested_display_name": displayName,
|
||||
"suggested_avatar_url": avatarURL,
|
||||
}
|
||||
if compatEmail != "" && !strings.EqualFold(strings.TrimSpace(compatEmail), strings.TrimSpace(email)) {
|
||||
upstreamClaims["compat_email"] = compatEmail
|
||||
}
|
||||
if intent == oauthIntentBindCurrentUser {
|
||||
targetUserID, err := h.readOAuthBindUserIDFromCookie(c, linuxDoOAuthBindUserCookieName)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "invalid_state", "invalid oauth bind target", "")
|
||||
return
|
||||
}
|
||||
// 避免把内部细节泄露给客户端;给前端保留结构化原因与提示信息即可。
|
||||
redirectOAuthError(c, frontendCallback, "login_failed", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
if err := h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentBindCurrentUser,
|
||||
Identity: identityKey,
|
||||
TargetUserID: &targetUserID,
|
||||
ResolvedEmail: email,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: map[string]any{
|
||||
"redirect": redirectTo,
|
||||
},
|
||||
}); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth bind", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
return
|
||||
}
|
||||
|
||||
fragment := url.Values{}
|
||||
fragment.Set("access_token", tokenPair.AccessToken)
|
||||
fragment.Set("refresh_token", tokenPair.RefreshToken)
|
||||
fragment.Set("expires_in", fmt.Sprintf("%d", tokenPair.ExpiresIn))
|
||||
fragment.Set("token_type", "Bearer")
|
||||
fragment.Set("redirect", redirectTo)
|
||||
redirectWithFragment(c, frontendCallback, fragment)
|
||||
existingIdentityUser, err := h.findOAuthIdentityUser(c.Request.Context(), identityKey)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
return
|
||||
}
|
||||
if existingIdentityUser != nil {
|
||||
if err := h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentLogin,
|
||||
Identity: identityKey,
|
||||
TargetUserID: &existingIdentityUser.ID,
|
||||
ResolvedEmail: existingIdentityUser.Email,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: map[string]any{
|
||||
"redirect": redirectTo,
|
||||
},
|
||||
}); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth login", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
return
|
||||
}
|
||||
|
||||
compatEmailUser, err := h.findLinuxDoCompatEmailUser(c.Request.Context(), compatEmail)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
return
|
||||
}
|
||||
if err := h.createLinuxDoOAuthChoicePendingSession(
|
||||
c,
|
||||
identityKey,
|
||||
email,
|
||||
email,
|
||||
redirectTo,
|
||||
browserSessionKey,
|
||||
upstreamClaims,
|
||||
compatEmail,
|
||||
compatEmailUser,
|
||||
h.isForceEmailOnThirdPartySignup(c.Request.Context()),
|
||||
); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth login", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) findLinuxDoCompatEmailUser(ctx context.Context, email string) (*dbent.User, error) {
|
||||
client := h.entClient()
|
||||
if client == nil {
|
||||
return nil, infraerrors.ServiceUnavailable("PENDING_AUTH_NOT_READY", "pending auth service is not ready")
|
||||
}
|
||||
|
||||
email = strings.TrimSpace(strings.ToLower(email))
|
||||
if email == "" ||
|
||||
strings.HasSuffix(email, service.LinuxDoConnectSyntheticEmailDomain) ||
|
||||
strings.HasSuffix(email, service.OIDCConnectSyntheticEmailDomain) ||
|
||||
strings.HasSuffix(email, service.WeChatConnectSyntheticEmailDomain) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(userNormalizedEmailPredicate(email)).
|
||||
Order(dbent.Asc(dbuser.FieldID)).
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
return nil, infraerrors.InternalServer("COMPAT_EMAIL_LOOKUP_FAILED", "failed to look up compat email user").WithCause(err)
|
||||
}
|
||||
switch len(userEntity) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
case 1:
|
||||
return userEntity[0], nil
|
||||
default:
|
||||
return nil, infraerrors.Conflict("USER_EMAIL_CONFLICT", "normalized email matched multiple users")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) createLinuxDoOAuthChoicePendingSession(
|
||||
c *gin.Context,
|
||||
identity service.PendingAuthIdentityKey,
|
||||
suggestedEmail string,
|
||||
resolvedEmail string,
|
||||
redirectTo string,
|
||||
browserSessionKey string,
|
||||
upstreamClaims map[string]any,
|
||||
compatEmail string,
|
||||
compatEmailUser *dbent.User,
|
||||
forceEmailOnSignup bool,
|
||||
) error {
|
||||
suggestionEmail := strings.TrimSpace(suggestedEmail)
|
||||
canonicalEmail := strings.TrimSpace(resolvedEmail)
|
||||
if suggestionEmail == "" {
|
||||
suggestionEmail = canonicalEmail
|
||||
}
|
||||
|
||||
completionResponse := map[string]any{
|
||||
"step": oauthPendingChoiceStep,
|
||||
"adoption_required": true,
|
||||
"redirect": strings.TrimSpace(redirectTo),
|
||||
"email": suggestionEmail,
|
||||
"resolved_email": canonicalEmail,
|
||||
"existing_account_email": "",
|
||||
"existing_account_bindable": false,
|
||||
"create_account_allowed": true,
|
||||
"force_email_on_signup": forceEmailOnSignup,
|
||||
"choice_reason": "third_party_signup",
|
||||
}
|
||||
if strings.TrimSpace(compatEmail) != "" {
|
||||
completionResponse["compat_email"] = strings.TrimSpace(compatEmail)
|
||||
}
|
||||
resolvedChoiceEmail := suggestionEmail
|
||||
if compatEmailUser != nil {
|
||||
completionResponse["email"] = strings.TrimSpace(compatEmailUser.Email)
|
||||
completionResponse["existing_account_email"] = strings.TrimSpace(compatEmailUser.Email)
|
||||
completionResponse["existing_account_bindable"] = true
|
||||
completionResponse["choice_reason"] = "compat_email_match"
|
||||
resolvedChoiceEmail = strings.TrimSpace(compatEmailUser.Email)
|
||||
}
|
||||
if forceEmailOnSignup && compatEmailUser == nil {
|
||||
completionResponse["choice_reason"] = "force_email_on_signup"
|
||||
}
|
||||
|
||||
var targetUserID *int64
|
||||
if compatEmailUser != nil && compatEmailUser.ID > 0 {
|
||||
targetUserID = &compatEmailUser.ID
|
||||
}
|
||||
|
||||
return h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentLogin,
|
||||
Identity: identity,
|
||||
TargetUserID: targetUserID,
|
||||
ResolvedEmail: resolvedChoiceEmail,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: completionResponse,
|
||||
})
|
||||
}
|
||||
|
||||
type completeLinuxDoOAuthRequest struct {
|
||||
PendingOAuthToken string `json:"pending_oauth_token" binding:"required"`
|
||||
InvitationCode string `json:"invitation_code" binding:"required"`
|
||||
InvitationCode string `json:"invitation_code" binding:"required"`
|
||||
AdoptDisplayName *bool `json:"adopt_display_name,omitempty"`
|
||||
AdoptAvatar *bool `json:"adopt_avatar,omitempty"`
|
||||
}
|
||||
|
||||
// CompleteLinuxDoOAuthRegistration completes a pending OAuth registration by validating
|
||||
@ -256,17 +449,87 @@ func (h *AuthHandler) CompleteLinuxDoOAuthRegistration(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
email, username, err := h.authService.VerifyPendingOAuthToken(req.PendingOAuthToken)
|
||||
secureCookie := isRequestHTTPS(c)
|
||||
sessionToken, err := readOAuthPendingSessionCookie(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "INVALID_TOKEN", "message": "invalid or expired registration token"})
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, service.ErrPendingAuthSessionNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
browserSessionKey, err := readOAuthPendingBrowserCookie(c)
|
||||
if err != nil {
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, service.ErrPendingAuthBrowserMismatch)
|
||||
return
|
||||
}
|
||||
pendingSvc, err := h.pendingIdentityService()
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
session, err := pendingSvc.GetBrowserSession(c.Request.Context(), sessionToken, browserSessionKey)
|
||||
if err != nil {
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := ensurePendingOAuthCompleteRegistrationSession(session); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if updatedSession, handled, err := h.legacyCompleteRegistrationSessionStatus(c, session); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
} else if handled {
|
||||
c.JSON(http.StatusOK, buildPendingOAuthSessionStatusPayload(updatedSession))
|
||||
return
|
||||
} else {
|
||||
session = updatedSession
|
||||
}
|
||||
if err := h.ensureBackendModeAllowsNewUserLogin(c.Request.Context()); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
email := strings.TrimSpace(session.ResolvedEmail)
|
||||
username := pendingSessionStringValue(session.UpstreamIdentityClaims, "username")
|
||||
if email == "" || username == "" {
|
||||
response.ErrorFrom(c, infraerrors.BadRequest("PENDING_AUTH_SESSION_INVALID", "pending auth registration context is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
client := h.entClient()
|
||||
if client == nil {
|
||||
response.ErrorFrom(c, infraerrors.ServiceUnavailable("PENDING_AUTH_NOT_READY", "pending auth service is not ready"))
|
||||
return
|
||||
}
|
||||
if err := ensurePendingOAuthRegistrationIdentityAvailable(c.Request.Context(), client, session); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
decision, err := h.ensurePendingOAuthAdoptionDecision(c, session.ID, oauthAdoptionDecisionRequest{
|
||||
AdoptDisplayName: req.AdoptDisplayName,
|
||||
AdoptAvatar: req.AdoptAvatar,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
tokenPair, user, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := applyPendingOAuthAdoptionAndConsumeSession(c.Request.Context(), client, h.authService, h.userService, session, decision, user.ID); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"access_token": tokenPair.AccessToken,
|
||||
@ -303,7 +566,7 @@ func linuxDoExchangeCode(
|
||||
form.Set("client_id", cfg.ClientID)
|
||||
form.Set("code", code)
|
||||
form.Set("redirect_uri", redirectURI)
|
||||
if cfg.UsePKCE {
|
||||
if strings.TrimSpace(codeVerifier) != "" {
|
||||
form.Set("code_verifier", codeVerifier)
|
||||
}
|
||||
|
||||
@ -353,11 +616,11 @@ func linuxDoFetchUserInfo(
|
||||
ctx context.Context,
|
||||
cfg config.LinuxDoConnectConfig,
|
||||
token *linuxDoTokenResponse,
|
||||
) (email string, username string, subject string, err error) {
|
||||
) (email string, username string, subject string, displayName string, avatarURL string, err error) {
|
||||
client := req.C().SetTimeout(30 * time.Second)
|
||||
authorization, err := buildBearerAuthorization(token.TokenType, token.AccessToken)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("invalid token for userinfo request: %w", err)
|
||||
return "", "", "", "", "", fmt.Errorf("invalid token for userinfo request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := client.R().
|
||||
@ -366,16 +629,16 @@ func linuxDoFetchUserInfo(
|
||||
SetHeader("Authorization", authorization).
|
||||
Get(cfg.UserInfoURL)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("request userinfo: %w", err)
|
||||
return "", "", "", "", "", fmt.Errorf("request userinfo: %w", err)
|
||||
}
|
||||
if !resp.IsSuccessState() {
|
||||
return "", "", "", fmt.Errorf("userinfo status=%d", resp.StatusCode)
|
||||
return "", "", "", "", "", fmt.Errorf("userinfo status=%d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return linuxDoParseUserInfo(resp.String(), cfg)
|
||||
}
|
||||
|
||||
func linuxDoParseUserInfo(body string, cfg config.LinuxDoConnectConfig) (email string, username string, subject string, err error) {
|
||||
func linuxDoParseUserInfo(body string, cfg config.LinuxDoConnectConfig) (email string, username string, subject string, displayName string, avatarURL string, err error) {
|
||||
email = firstNonEmpty(
|
||||
getGJSON(body, cfg.UserInfoEmailPath),
|
||||
getGJSON(body, "email"),
|
||||
@ -400,12 +663,29 @@ func linuxDoParseUserInfo(body string, cfg config.LinuxDoConnectConfig) (email s
|
||||
getGJSON(body, "user.id"),
|
||||
)
|
||||
|
||||
displayName = firstNonEmpty(
|
||||
getGJSON(body, "name"),
|
||||
getGJSON(body, "nickname"),
|
||||
getGJSON(body, "display_name"),
|
||||
getGJSON(body, "user.name"),
|
||||
getGJSON(body, "user.username"),
|
||||
username,
|
||||
)
|
||||
avatarURL = firstNonEmpty(
|
||||
getGJSON(body, "avatar_url"),
|
||||
getGJSON(body, "avatar"),
|
||||
getGJSON(body, "picture"),
|
||||
getGJSON(body, "profile_image_url"),
|
||||
getGJSON(body, "user.avatar"),
|
||||
getGJSON(body, "user.avatar_url"),
|
||||
)
|
||||
|
||||
subject = strings.TrimSpace(subject)
|
||||
if subject == "" {
|
||||
return "", "", "", errors.New("userinfo missing id field")
|
||||
return "", "", "", "", "", errors.New("userinfo missing id field")
|
||||
}
|
||||
if !isSafeLinuxDoSubject(subject) {
|
||||
return "", "", "", errors.New("userinfo returned invalid id field")
|
||||
return "", "", "", "", "", errors.New("userinfo returned invalid id field")
|
||||
}
|
||||
|
||||
email = strings.TrimSpace(email)
|
||||
@ -418,8 +698,13 @@ func linuxDoParseUserInfo(body string, cfg config.LinuxDoConnectConfig) (email s
|
||||
if username == "" {
|
||||
username = "linuxdo_" + subject
|
||||
}
|
||||
displayName = strings.TrimSpace(displayName)
|
||||
if displayName == "" {
|
||||
displayName = username
|
||||
}
|
||||
avatarURL = strings.TrimSpace(avatarURL)
|
||||
|
||||
return email, username, subject, nil
|
||||
return email, username, subject, displayName, avatarURL, nil
|
||||
}
|
||||
|
||||
func buildLinuxDoAuthorizeURL(cfg config.LinuxDoConnectConfig, state string, codeChallenge string, redirectURI string) (string, error) {
|
||||
@ -436,7 +721,7 @@ func buildLinuxDoAuthorizeURL(cfg config.LinuxDoConnectConfig, state string, cod
|
||||
q.Set("scope", cfg.Scopes)
|
||||
}
|
||||
q.Set("state", state)
|
||||
if cfg.UsePKCE {
|
||||
if strings.TrimSpace(codeChallenge) != "" {
|
||||
q.Set("code_challenge", codeChallenge)
|
||||
q.Set("code_challenge_method", "S256")
|
||||
}
|
||||
@ -670,6 +955,30 @@ func clearCookie(c *gin.Context, name string, secure bool) {
|
||||
})
|
||||
}
|
||||
|
||||
func clearOAuthBindAccessTokenCookie(c *gin.Context, secure bool) {
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: oauthBindAccessTokenCookieName,
|
||||
Value: "",
|
||||
Path: oauthBindAccessTokenCookiePath,
|
||||
MaxAge: -1,
|
||||
HttpOnly: true,
|
||||
Secure: secure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
}
|
||||
|
||||
func setOAuthBindAccessTokenCookie(c *gin.Context, token string, secure bool) {
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: oauthBindAccessTokenCookieName,
|
||||
Value: url.QueryEscape(strings.TrimSpace(token)),
|
||||
Path: oauthBindAccessTokenCookiePath,
|
||||
MaxAge: linuxDoOAuthCookieMaxAgeSec,
|
||||
HttpOnly: true,
|
||||
Secure: secure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
}
|
||||
|
||||
func truncateFragmentValue(value string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
@ -728,3 +1037,127 @@ func linuxDoSyntheticEmail(subject string) string {
|
||||
}
|
||||
return "linuxdo-" + subject + service.LinuxDoConnectSyntheticEmailDomain
|
||||
}
|
||||
|
||||
func normalizeOAuthIntent(raw string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(raw)) {
|
||||
case "", oauthIntentLogin:
|
||||
return oauthIntentLogin
|
||||
case "bind", oauthIntentBindCurrentUser:
|
||||
return oauthIntentBindCurrentUser
|
||||
default:
|
||||
return oauthIntentLogin
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) buildOAuthBindUserCookieFromContext(c *gin.Context) (string, error) {
|
||||
userID, err := h.resolveOAuthBindTargetUserID(c)
|
||||
if err != nil || userID == nil || *userID <= 0 {
|
||||
return "", infraerrors.Unauthorized("UNAUTHORIZED", "authentication required")
|
||||
}
|
||||
return buildOAuthBindUserCookieValue(*userID, h.oauthBindCookieSecret())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) PrepareOAuthBindAccessTokenCookie(c *gin.Context) {
|
||||
const bearerPrefix = "Bearer "
|
||||
|
||||
authHeader := strings.TrimSpace(c.GetHeader("Authorization"))
|
||||
if !strings.HasPrefix(strings.ToLower(authHeader), strings.ToLower(bearerPrefix)) {
|
||||
response.ErrorFrom(c, infraerrors.Unauthorized("UNAUTHORIZED", "authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
token := strings.TrimSpace(authHeader[len(bearerPrefix):])
|
||||
if token == "" {
|
||||
response.ErrorFrom(c, infraerrors.Unauthorized("UNAUTHORIZED", "authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
setOAuthBindAccessTokenCookie(c, token, isRequestHTTPS(c))
|
||||
c.Status(http.StatusNoContent)
|
||||
c.Writer.WriteHeaderNow()
|
||||
}
|
||||
|
||||
func (h *AuthHandler) resolveOAuthBindTargetUserID(c *gin.Context) (*int64, error) {
|
||||
if subject, ok := servermiddleware.GetAuthSubjectFromContext(c); ok && subject.UserID > 0 {
|
||||
return &subject.UserID, nil
|
||||
}
|
||||
if h == nil || h.authService == nil || h.userService == nil {
|
||||
return nil, service.ErrInvalidToken
|
||||
}
|
||||
|
||||
ck, err := c.Request.Cookie(oauthBindAccessTokenCookieName)
|
||||
clearOAuthBindAccessTokenCookie(c, isRequestHTTPS(c))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokenString, err := url.QueryUnescape(strings.TrimSpace(ck.Value))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokenString == "" {
|
||||
return nil, service.ErrInvalidToken
|
||||
}
|
||||
|
||||
claims, err := h.authService.ValidateToken(tokenString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := h.userService.GetByID(c.Request.Context(), claims.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil || !user.IsActive() || claims.TokenVersion != user.TokenVersion {
|
||||
return nil, service.ErrInvalidToken
|
||||
}
|
||||
return &user.ID, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) readOAuthBindUserIDFromCookie(c *gin.Context, cookieName string) (int64, error) {
|
||||
value, err := readCookieDecoded(c, cookieName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return parseOAuthBindUserCookieValue(value, h.oauthBindCookieSecret())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) oauthBindCookieSecret() string {
|
||||
if h == nil || h.cfg == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(h.cfg.JWT.Secret)
|
||||
}
|
||||
|
||||
func buildOAuthBindUserCookieValue(userID int64, secret string) (string, error) {
|
||||
secret = strings.TrimSpace(secret)
|
||||
if userID <= 0 || secret == "" {
|
||||
return "", errors.New("invalid oauth bind cookie input")
|
||||
}
|
||||
payload := strconv.FormatInt(userID, 10)
|
||||
mac := hmac.New(sha256.New, []byte(secret))
|
||||
_, _ = mac.Write([]byte(payload))
|
||||
signature := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
|
||||
return payload + "." + signature, nil
|
||||
}
|
||||
|
||||
func parseOAuthBindUserCookieValue(value string, secret string) (int64, error) {
|
||||
secret = strings.TrimSpace(secret)
|
||||
if secret == "" {
|
||||
return 0, errors.New("missing oauth bind cookie secret")
|
||||
}
|
||||
payload, signature, ok := strings.Cut(strings.TrimSpace(value), ".")
|
||||
if !ok || payload == "" || signature == "" {
|
||||
return 0, errors.New("invalid oauth bind cookie")
|
||||
}
|
||||
mac := hmac.New(sha256.New, []byte(secret))
|
||||
_, _ = mac.Write([]byte(payload))
|
||||
expectedSignature := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
|
||||
if !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
|
||||
return 0, errors.New("invalid oauth bind cookie signature")
|
||||
}
|
||||
userID, err := strconv.ParseInt(payload, 10, 64)
|
||||
if err != nil || userID <= 0 {
|
||||
return 0, errors.New("invalid oauth bind cookie user")
|
||||
}
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
@ -1,10 +1,24 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
dbuser "github.com/Wei-Shaw/sub2api/ent/user"
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
servermiddleware "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -41,11 +55,13 @@ func TestLinuxDoParseUserInfoParsesIDAndUsername(t *testing.T) {
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
}
|
||||
|
||||
email, username, subject, err := linuxDoParseUserInfo(`{"id":123,"username":"alice"}`, cfg)
|
||||
email, username, subject, displayName, avatarURL, err := linuxDoParseUserInfo(`{"id":123,"username":"alice","name":"Alice","avatar_url":"https://cdn.example/avatar.png"}`, cfg)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "123", subject)
|
||||
require.Equal(t, "alice", username)
|
||||
require.Equal(t, "linuxdo-123@linuxdo-connect.invalid", email)
|
||||
require.Equal(t, "Alice", displayName)
|
||||
require.Equal(t, "https://cdn.example/avatar.png", avatarURL)
|
||||
}
|
||||
|
||||
func TestLinuxDoParseUserInfoDefaultsUsername(t *testing.T) {
|
||||
@ -53,11 +69,13 @@ func TestLinuxDoParseUserInfoDefaultsUsername(t *testing.T) {
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
}
|
||||
|
||||
email, username, subject, err := linuxDoParseUserInfo(`{"id":"123"}`, cfg)
|
||||
email, username, subject, displayName, avatarURL, err := linuxDoParseUserInfo(`{"id":"123"}`, cfg)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "123", subject)
|
||||
require.Equal(t, "linuxdo_123", username)
|
||||
require.Equal(t, "linuxdo-123@linuxdo-connect.invalid", email)
|
||||
require.Equal(t, "linuxdo_123", displayName)
|
||||
require.Equal(t, "", avatarURL)
|
||||
}
|
||||
|
||||
func TestLinuxDoParseUserInfoRejectsUnsafeSubject(t *testing.T) {
|
||||
@ -65,11 +83,11 @@ func TestLinuxDoParseUserInfoRejectsUnsafeSubject(t *testing.T) {
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
}
|
||||
|
||||
_, _, _, err := linuxDoParseUserInfo(`{"id":"123@456"}`, cfg)
|
||||
_, _, _, _, _, err := linuxDoParseUserInfo(`{"id":"123@456"}`, cfg)
|
||||
require.Error(t, err)
|
||||
|
||||
tooLong := strings.Repeat("a", linuxDoOAuthMaxSubjectLen+1)
|
||||
_, _, _, err = linuxDoParseUserInfo(`{"id":"`+tooLong+`"}`, cfg)
|
||||
_, _, _, _, _, err = linuxDoParseUserInfo(`{"id":"`+tooLong+`"}`, cfg)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
@ -106,3 +124,906 @@ func TestSingleLineStripsWhitespace(t *testing.T) {
|
||||
require.Equal(t, "hello world", singleLine("hello\r\nworld"))
|
||||
require.Equal(t, "", singleLine("\n\t\r"))
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthBindStartRedirectsAndSetsBindCookies(t *testing.T) {
|
||||
handler := newLinuxDoOAuthTestHandler(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: "https://connect.linux.do/oauth/authorize",
|
||||
TokenURL: "https://connect.linux.do/oauth/token",
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/bind/start?intent=bind_current_user&redirect=/settings/connections", nil)
|
||||
c.Request = req
|
||||
c.Set(string(servermiddleware.ContextKeyUser), servermiddleware.AuthSubject{UserID: 42})
|
||||
|
||||
handler.LinuxDoOAuthStart(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
require.Contains(t, location, "connect.linux.do/oauth/authorize")
|
||||
require.Contains(t, location, "client_id=linuxdo-client")
|
||||
require.Contains(t, location, "code_challenge=")
|
||||
|
||||
cookies := recorder.Result().Cookies()
|
||||
require.NotNil(t, findCookie(cookies, linuxDoOAuthStateCookieName))
|
||||
require.NotNil(t, findCookie(cookies, linuxDoOAuthRedirectCookie))
|
||||
require.NotNil(t, findCookie(cookies, linuxDoOAuthVerifierCookie))
|
||||
require.NotNil(t, findCookie(cookies, oauthPendingBrowserCookieName))
|
||||
|
||||
intentCookie := findCookie(cookies, linuxDoOAuthIntentCookieName)
|
||||
require.NotNil(t, intentCookie)
|
||||
require.Equal(t, oauthIntentBindCurrentUser, decodeCookieValueForTest(t, intentCookie.Value))
|
||||
|
||||
bindCookie := findCookie(cookies, linuxDoOAuthBindUserCookieName)
|
||||
require.NotNil(t, bindCookie)
|
||||
userID, err := parseOAuthBindUserCookieValue(decodeCookieValueForTest(t, bindCookie.Value), "test-secret")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(42), userID)
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthStartOmitsPKCEWhenDisabled(t *testing.T) {
|
||||
handler := newLinuxDoOAuthTestHandler(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: "https://connect.linux.do/oauth/authorize",
|
||||
TokenURL: "https://connect.linux.do/oauth/token",
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: false,
|
||||
})
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/start?redirect=/dashboard", nil)
|
||||
|
||||
handler.LinuxDoOAuthStart(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.NotContains(t, recorder.Header().Get("Location"), "code_challenge=")
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), linuxDoOAuthVerifierCookie))
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackAllowsMissingVerifierWhenPKCEDisabled(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
require.NoError(t, r.ParseForm())
|
||||
require.Empty(t, r.PostForm.Get("code_verifier"))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"compat-subject","username":"linuxdo_user","name":"LinuxDo Display"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: false,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=linuxdo-code&state=state-123", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-123"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-123"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/linuxdo/callback", recorder.Header().Get("Location"))
|
||||
require.NotNil(t, findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName))
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthBindStartAcceptsAccessTokenCookie(t *testing.T) {
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: "https://connect.linux.do/oauth/authorize",
|
||||
TokenURL: "https://connect.linux.do/oauth/token",
|
||||
UserInfoURL: "https://connect.linux.do/api/user",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
user, err := client.User.Create().
|
||||
SetEmail("bind-cookie@example.com").
|
||||
SetUsername("bind-cookie-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
token, err := handler.authService.GenerateToken(&service.User{
|
||||
ID: user.ID,
|
||||
Email: user.Email,
|
||||
Username: user.Username,
|
||||
PasswordHash: user.PasswordHash,
|
||||
Role: user.Role,
|
||||
Status: user.Status,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/start?intent=bind_current_user&redirect=/settings/connections", nil)
|
||||
req.AddCookie(&http.Cookie{Name: oauthBindAccessTokenCookieName, Value: token, Path: oauthBindAccessTokenCookiePath})
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthStart(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
|
||||
bindCookie := findCookie(recorder.Result().Cookies(), linuxDoOAuthBindUserCookieName)
|
||||
require.NotNil(t, bindCookie)
|
||||
userID, err := parseOAuthBindUserCookieValue(decodeCookieValueForTest(t, bindCookie.Value), "test-secret")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, user.ID, userID)
|
||||
|
||||
accessTokenCookie := findCookie(recorder.Result().Cookies(), oauthBindAccessTokenCookieName)
|
||||
require.NotNil(t, accessTokenCookie)
|
||||
require.Equal(t, -1, accessTokenCookie.MaxAge)
|
||||
}
|
||||
|
||||
func TestPrepareOAuthBindAccessTokenCookieSetsHttpOnlyCookie(t *testing.T) {
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/bind-token", nil)
|
||||
req.Header.Set("Authorization", "Bearer access-token-value")
|
||||
c.Request = req
|
||||
|
||||
handler.PrepareOAuthBindAccessTokenCookie(c)
|
||||
|
||||
require.Equal(t, http.StatusNoContent, recorder.Code)
|
||||
accessTokenCookie := findCookie(recorder.Result().Cookies(), oauthBindAccessTokenCookieName)
|
||||
require.NotNil(t, accessTokenCookie)
|
||||
require.Equal(t, oauthBindAccessTokenCookiePath, accessTokenCookie.Path)
|
||||
require.Equal(t, linuxDoOAuthCookieMaxAgeSec, accessTokenCookie.MaxAge)
|
||||
require.True(t, accessTokenCookie.HttpOnly)
|
||||
require.Equal(t, url.QueryEscape("access-token-value"), accessTokenCookie.Value)
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackCreatesLoginPendingSessionForExistingIdentityUser(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"321","username":"linuxdo_user","name":"LinuxDo Display","avatar_url":"https://cdn.example/linuxdo.png"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail(linuxDoSyntheticEmail("321")).
|
||||
SetUsername("legacy-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingUser.ID).
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("321").
|
||||
SetMetadata(map[string]any{"username": "legacy-user"}).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=code-123&state=state-123", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-123"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthVerifierCookie, "verifier-123"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-123"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/linuxdo/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, existingUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, linuxDoSyntheticEmail("321"), session.ResolvedEmail)
|
||||
require.Equal(t, "LinuxDo Display", session.UpstreamIdentityClaims["suggested_display_name"])
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
_, hasAccessToken := completion["access_token"]
|
||||
require.False(t, hasAccessToken)
|
||||
_, hasRefreshToken := completion["refresh_token"]
|
||||
require.False(t, hasRefreshToken)
|
||||
require.Nil(t, completion["error"])
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackRejectsDisabledExistingIdentityUser(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"654","username":"linuxdo_disabled","name":"LinuxDo Disabled"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail(linuxDoSyntheticEmail("654")).
|
||||
SetUsername("disabled-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusDisabled).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingUser.ID).
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("654").
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=code-disabled&state=state-disabled", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-disabled"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthVerifierCookie, "verifier-disabled"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-disabled"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName))
|
||||
assertOAuthRedirectError(t, recorder.Header().Get("Location"), "session_error", "USER_NOT_ACTIVE")
|
||||
|
||||
count, err := client.PendingAuthSession.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, count)
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackCreatesBindPendingSessionForCompatEmailUser(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"321","email":"legacy@example.com","username":"linuxdo_user","name":"LinuxDo Display","avatar_url":"https://cdn.example/linuxdo.png"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail(" Legacy@Example.com ").
|
||||
SetUsername("legacy-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=code-compat&state=state-compat", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-compat"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthVerifierCookie, "verifier-compat"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-compat"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/linuxdo/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, existingUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, strings.TrimSpace(existingUser.Email), session.ResolvedEmail)
|
||||
require.Equal(t, "legacy@example.com", session.UpstreamIdentityClaims["compat_email"])
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
require.Equal(t, oauthPendingChoiceStep, completion["step"])
|
||||
require.Equal(t, strings.TrimSpace(existingUser.Email), completion["email"])
|
||||
require.Equal(t, strings.TrimSpace(existingUser.Email), completion["existing_account_email"])
|
||||
require.Equal(t, true, completion["existing_account_bindable"])
|
||||
require.Equal(t, "compat_email_match", completion["choice_reason"])
|
||||
_, hasAccessToken := completion["access_token"]
|
||||
require.False(t, hasAccessToken)
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackCreatesChoicePendingSessionWhenSignupRequiresInvite(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"654","username":"linuxdo_invite","name":"Need Invite","avatar_url":"https://cdn.example/invite.png"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, true, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=code-456&state=state-456", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-456"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthVerifierCookie, "verifier-456"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-456"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/linuxdo/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
ctx := context.Background()
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.Nil(t, session.TargetUserID)
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, oauthPendingChoiceStep, completion["step"])
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
require.Equal(t, "third_party_signup", completion["choice_reason"])
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackCreatesBindPendingSessionForCurrentUser(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"linuxdo-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"id":"999","username":"bind_user","name":"Bind Display","avatar_url":"https://cdn.example/bind.png"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "linuxdo-client",
|
||||
ClientSecret: "linuxdo-secret",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "read",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/linuxdo/callback",
|
||||
FrontendRedirectURL: "/auth/linuxdo/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
currentUser, err := client.User.Create().
|
||||
SetEmail("current@example.com").
|
||||
SetUsername("current-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/linuxdo/callback?code=code-bind&state=state-bind", nil)
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthStateCookieName, "state-bind"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthRedirectCookie, "/settings/connections"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthVerifierCookie, "verifier-bind"))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthIntentCookieName, oauthIntentBindCurrentUser))
|
||||
req.AddCookie(encodedCookie(linuxDoOAuthBindUserCookieName, buildEncodedOAuthBindUserCookie(t, currentUser.ID, "test-secret")))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-bind"))
|
||||
c.Request = req
|
||||
|
||||
handler.LinuxDoOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/linuxdo/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentBindCurrentUser, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, currentUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, linuxDoSyntheticEmail("999"), session.ResolvedEmail)
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/settings/connections", completion["redirect"])
|
||||
require.Empty(t, completion["access_token"])
|
||||
require.Equal(t, "Bind Display", session.UpstreamIdentityClaims["suggested_display_name"])
|
||||
|
||||
userCount, err := client.User.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, userCount)
|
||||
}
|
||||
|
||||
func TestCompleteLinuxDoOAuthRegistrationAppliesPendingAdoptionDecision(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("linuxdo-complete-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-subject-1").
|
||||
SetResolvedEmail("linuxdo-subject-1@linuxdo-connect.invalid").
|
||||
SetBrowserSessionKey("linuxdo-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "linuxdo_user",
|
||||
"suggested_display_name": "LinuxDo Display",
|
||||
"suggested_avatar_url": "https://cdn.example/linuxdo.png",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = service.NewAuthPendingIdentityService(client).UpsertAdoptionDecision(ctx, service.PendingIdentityAdoptionDecisionInput{
|
||||
PendingAuthSessionID: session.ID,
|
||||
AdoptAvatar: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1","adopt_display_name":true}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/linuxdo/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("linuxdo-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteLinuxDoOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.NotEmpty(t, responseData["access_token"])
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ(session.ResolvedEmail)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "LinuxDo Display", userEntity.Username)
|
||||
|
||||
identity, err := client.AuthIdentity.Query().
|
||||
Where(
|
||||
authidentity.ProviderTypeEQ("linuxdo"),
|
||||
authidentity.ProviderKeyEQ("linuxdo"),
|
||||
authidentity.ProviderSubjectEQ("linuxdo-subject-1"),
|
||||
).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, userEntity.ID, identity.UserID)
|
||||
require.Equal(t, "LinuxDo Display", identity.Metadata["display_name"])
|
||||
require.Equal(t, "https://cdn.example/linuxdo.png", identity.Metadata["avatar_url"])
|
||||
|
||||
decision, err := client.IdentityAdoptionDecision.Query().
|
||||
Where(identityadoptiondecision.PendingAuthSessionIDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision.IdentityID)
|
||||
require.Equal(t, identity.ID, *decision.IdentityID)
|
||||
require.True(t, decision.AdoptDisplayName)
|
||||
require.True(t, decision.AdoptAvatar)
|
||||
|
||||
consumed, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.IDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, consumed.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteLinuxDoOAuthRegistrationRejectsAdoptExistingUserSession(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail("owner@example.com").
|
||||
SetUsername("owner-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("linuxdo-complete-invalid-session").
|
||||
SetIntent("adopt_existing_user_by_email").
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-invalid-subject-1").
|
||||
SetTargetUserID(existingUser.ID).
|
||||
SetResolvedEmail(existingUser.Email).
|
||||
SetBrowserSessionKey("linuxdo-invalid-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "linuxdo_user",
|
||||
}).
|
||||
SetLocalFlowState(map[string]any{
|
||||
oauthCompletionResponseKey: map[string]any{
|
||||
"step": "bind_login_required",
|
||||
},
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/linuxdo/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("linuxdo-invalid-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteLinuxDoOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, recorder.Code)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteLinuxDoOAuthRegistrationReturnsPendingSessionWhenChoiceStillRequired(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("linuxdo-complete-choice-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-choice-subject-1").
|
||||
SetResolvedEmail("linuxdo-choice-subject-1@linuxdo-connect.invalid").
|
||||
SetBrowserSessionKey("linuxdo-choice-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "linuxdo_user",
|
||||
}).
|
||||
SetLocalFlowState(map[string]any{
|
||||
oauthCompletionResponseKey: map[string]any{
|
||||
"step": oauthPendingChoiceStep,
|
||||
"redirect": "/dashboard",
|
||||
"email": "fresh@example.com",
|
||||
"resolved_email": "fresh@example.com",
|
||||
"force_email_on_signup": true,
|
||||
},
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/linuxdo/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("linuxdo-choice-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteLinuxDoOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.Equal(t, "pending_session", responseData["auth_result"])
|
||||
require.Equal(t, oauthPendingChoiceStep, responseData["step"])
|
||||
require.Equal(t, true, responseData["force_email_on_signup"])
|
||||
require.Empty(t, responseData["access_token"])
|
||||
|
||||
userCount, err := client.User.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, userCount)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteLinuxDoOAuthRegistrationBindsIdentityWithoutAdoptionFlags(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("linuxdo-complete-no-adoption-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-subject-no-adoption").
|
||||
SetResolvedEmail("linuxdo-subject-no-adoption@linuxdo-connect.invalid").
|
||||
SetBrowserSessionKey("linuxdo-browser-no-adoption").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "linuxdo_user",
|
||||
"suggested_display_name": "LinuxDo Legacy",
|
||||
"suggested_avatar_url": "https://cdn.example/linuxdo-legacy.png",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/linuxdo/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("linuxdo-browser-no-adoption")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteLinuxDoOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.NotEmpty(t, responseData["access_token"])
|
||||
require.NotEmpty(t, responseData["refresh_token"])
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ(session.ResolvedEmail)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "linuxdo_user", userEntity.Username)
|
||||
|
||||
identity, err := client.AuthIdentity.Query().
|
||||
Where(
|
||||
authidentity.ProviderTypeEQ("linuxdo"),
|
||||
authidentity.ProviderKeyEQ("linuxdo"),
|
||||
authidentity.ProviderSubjectEQ("linuxdo-subject-no-adoption"),
|
||||
).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, userEntity.ID, identity.UserID)
|
||||
|
||||
decision, err := client.IdentityAdoptionDecision.Query().
|
||||
Where(identityadoptiondecision.PendingAuthSessionIDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision.IdentityID)
|
||||
require.Equal(t, identity.ID, *decision.IdentityID)
|
||||
require.False(t, decision.AdoptDisplayName)
|
||||
require.False(t, decision.AdoptAvatar)
|
||||
}
|
||||
|
||||
func TestCompleteLinuxDoOAuthRegistrationRejectsIdentityOwnershipConflictBeforeUserCreation(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
existingOwner, err := client.User.Create().
|
||||
SetEmail("owner@example.com").
|
||||
SetUsername("owner-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingOwner.ID).
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-conflict-subject").
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("linuxdo-complete-conflict-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("linuxdo").
|
||||
SetProviderKey("linuxdo").
|
||||
SetProviderSubject("linuxdo-conflict-subject").
|
||||
SetResolvedEmail("linuxdo-conflict-subject@linuxdo-connect.invalid").
|
||||
SetBrowserSessionKey("linuxdo-conflict-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "linuxdo_user",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/linuxdo/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("linuxdo-conflict-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteLinuxDoOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusConflict, recorder.Code)
|
||||
payload := decodeJSONBody(t, recorder)
|
||||
require.Equal(t, "AUTH_IDENTITY_OWNERSHIP_CONFLICT", payload["reason"])
|
||||
|
||||
userCount, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ("linuxdo-conflict-subject@linuxdo-connect.invalid")).
|
||||
Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, userCount)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
func newLinuxDoOAuthTestHandler(t *testing.T, invitationEnabled bool, oauthCfg config.LinuxDoConnectConfig) *AuthHandler {
|
||||
t.Helper()
|
||||
handler, _ := newLinuxDoOAuthHandlerAndClient(t, invitationEnabled, oauthCfg)
|
||||
return handler
|
||||
}
|
||||
|
||||
func newLinuxDoOAuthHandlerAndClient(t *testing.T, invitationEnabled bool, oauthCfg config.LinuxDoConnectConfig) (*AuthHandler, *dbent.Client) {
|
||||
t.Helper()
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, invitationEnabled)
|
||||
handler.settingSvc = nil
|
||||
handler.cfg = &config.Config{
|
||||
JWT: config.JWTConfig{
|
||||
Secret: "test-secret",
|
||||
ExpireHour: 1,
|
||||
AccessTokenExpireMinutes: 60,
|
||||
RefreshTokenExpireDays: 7,
|
||||
},
|
||||
LinuxDo: oauthCfg,
|
||||
}
|
||||
return handler, client
|
||||
}
|
||||
|
||||
68
backend/internal/handler/auth_oauth_logout_test.go
Normal file
68
backend/internal/handler/auth_oauth_logout_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLogoutClearsOAuthStateCookiesAndConsumesPendingSession(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("logout-pending-session-token").
|
||||
SetIntent("login").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example").
|
||||
SetProviderSubject("logout-subject-123").
|
||||
SetBrowserSessionKey("logout-browser-session-key").
|
||||
SetResolvedEmail("logout@example.com").
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
ginCtx, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/logout", nil)
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("logout-browser-session-key")})
|
||||
req.AddCookie(&http.Cookie{Name: oauthBindAccessTokenCookieName, Value: "bind-access-token"})
|
||||
req.AddCookie(&http.Cookie{Name: linuxDoOAuthStateCookieName, Value: encodeCookieValue("linuxdo-state")})
|
||||
req.AddCookie(&http.Cookie{Name: oidcOAuthStateCookieName, Value: encodeCookieValue("oidc-state")})
|
||||
req.AddCookie(&http.Cookie{Name: wechatOAuthStateCookieName, Value: encodeCookieValue("wechat-state")})
|
||||
req.AddCookie(&http.Cookie{Name: wechatPaymentOAuthStateName, Value: encodeCookieValue("wechat-payment-state")})
|
||||
ginCtx.Request = req
|
||||
|
||||
handler.Logout(ginCtx)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
cookies := recorder.Result().Cookies()
|
||||
for _, name := range []string{
|
||||
oauthPendingSessionCookieName,
|
||||
oauthPendingBrowserCookieName,
|
||||
oauthBindAccessTokenCookieName,
|
||||
linuxDoOAuthStateCookieName,
|
||||
oidcOAuthStateCookieName,
|
||||
wechatOAuthStateCookieName,
|
||||
wechatPaymentOAuthStateName,
|
||||
} {
|
||||
cookie := findCookie(cookies, name)
|
||||
require.NotNil(t, cookie, name)
|
||||
require.Equal(t, -1, cookie.MaxAge, name)
|
||||
require.True(t, cookie.HttpOnly, name)
|
||||
}
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.IDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
1944
backend/internal/handler/auth_oauth_pending_flow.go
Normal file
1944
backend/internal/handler/auth_oauth_pending_flow.go
Normal file
File diff suppressed because it is too large
Load Diff
2995
backend/internal/handler/auth_oauth_pending_flow_test.go
Normal file
2995
backend/internal/handler/auth_oauth_pending_flow_test.go
Normal file
File diff suppressed because it is too large
Load Diff
57
backend/internal/handler/auth_oauth_test_helpers_test.go
Normal file
57
backend/internal/handler/auth_oauth_test_helpers_test.go
Normal file
@ -0,0 +1,57 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func buildEncodedOAuthBindUserCookie(t *testing.T, userID int64, secret string) string {
|
||||
t.Helper()
|
||||
value, err := buildOAuthBindUserCookieValue(userID, secret)
|
||||
require.NoError(t, err)
|
||||
return value
|
||||
}
|
||||
|
||||
func encodedCookie(name, value string) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: name,
|
||||
Value: encodeCookieValue(value),
|
||||
Path: "/",
|
||||
}
|
||||
}
|
||||
|
||||
func findCookie(cookies []*http.Cookie, name string) *http.Cookie {
|
||||
for _, cookie := range cookies {
|
||||
if cookie.Name == name {
|
||||
return cookie
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeCookieValueForTest(t *testing.T, value string) string {
|
||||
t.Helper()
|
||||
decoded, err := decodeCookieValue(value)
|
||||
require.NoError(t, err)
|
||||
return decoded
|
||||
}
|
||||
|
||||
func assertOAuthRedirectError(t *testing.T, location string, errorCode string, errorMessage string) {
|
||||
t.Helper()
|
||||
require.NotEmpty(t, location)
|
||||
|
||||
parsed, err := url.Parse(location)
|
||||
require.NoError(t, err)
|
||||
|
||||
rawValues := parsed.RawQuery
|
||||
if rawValues == "" {
|
||||
rawValues = parsed.Fragment
|
||||
}
|
||||
values, err := url.ParseQuery(rawValues)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, errorCode, values.Get("error"))
|
||||
require.Equal(t, errorMessage, values.Get("error_message"))
|
||||
}
|
||||
@ -19,6 +19,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/oauth"
|
||||
@ -32,14 +33,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
oidcOAuthCookiePath = "/api/v1/auth/oauth/oidc"
|
||||
oidcOAuthStateCookieName = "oidc_oauth_state"
|
||||
oidcOAuthVerifierCookie = "oidc_oauth_verifier"
|
||||
oidcOAuthRedirectCookie = "oidc_oauth_redirect"
|
||||
oidcOAuthNonceCookie = "oidc_oauth_nonce"
|
||||
oidcOAuthCookieMaxAgeSec = 10 * 60 // 10 minutes
|
||||
oidcOAuthDefaultRedirectTo = "/dashboard"
|
||||
oidcOAuthDefaultFrontendCB = "/auth/oidc/callback"
|
||||
oidcOAuthCookiePath = "/api/v1/auth/oauth/oidc"
|
||||
oidcOAuthStateCookieName = "oidc_oauth_state"
|
||||
oidcOAuthVerifierCookie = "oidc_oauth_verifier"
|
||||
oidcOAuthRedirectCookie = "oidc_oauth_redirect"
|
||||
oidcOAuthNonceCookie = "oidc_oauth_nonce"
|
||||
oidcOAuthIntentCookieName = "oidc_oauth_intent"
|
||||
oidcOAuthBindUserCookieName = "oidc_oauth_bind_user"
|
||||
oidcOAuthCookieMaxAgeSec = 10 * 60 // 10 minutes
|
||||
oidcOAuthDefaultRedirectTo = "/dashboard"
|
||||
oidcOAuthDefaultFrontendCB = "/auth/oidc/callback"
|
||||
)
|
||||
|
||||
type oidcTokenResponse struct {
|
||||
@ -87,6 +90,8 @@ type oidcUserInfoClaims struct {
|
||||
Username string
|
||||
Subject string
|
||||
EmailVerified *bool
|
||||
DisplayName string
|
||||
AvatarURL string
|
||||
}
|
||||
|
||||
type oidcJWKSet struct {
|
||||
@ -127,9 +132,29 @@ func (h *AuthHandler) OIDCOAuthStart(c *gin.Context) {
|
||||
redirectTo = oidcOAuthDefaultRedirectTo
|
||||
}
|
||||
|
||||
browserSessionKey, err := generateOAuthPendingBrowserSession()
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_BROWSER_SESSION_GEN_FAILED", "failed to generate oauth browser session").WithCause(err))
|
||||
return
|
||||
}
|
||||
|
||||
secureCookie := isRequestHTTPS(c)
|
||||
oidcSetCookie(c, oidcOAuthStateCookieName, encodeCookieValue(state), oidcOAuthCookieMaxAgeSec, secureCookie)
|
||||
oidcSetCookie(c, oidcOAuthRedirectCookie, encodeCookieValue(redirectTo), oidcOAuthCookieMaxAgeSec, secureCookie)
|
||||
intent := normalizeOAuthIntent(c.Query("intent"))
|
||||
oidcSetCookie(c, oidcOAuthIntentCookieName, encodeCookieValue(intent), oidcOAuthCookieMaxAgeSec, secureCookie)
|
||||
setOAuthPendingBrowserCookie(c, browserSessionKey, secureCookie)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
if intent == oauthIntentBindCurrentUser {
|
||||
bindCookieValue, err := h.buildOAuthBindUserCookieFromContext(c)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
oidcSetCookie(c, oidcOAuthBindUserCookieName, encodeCookieValue(bindCookieValue), oidcOAuthCookieMaxAgeSec, secureCookie)
|
||||
} else {
|
||||
oidcClearCookie(c, oidcOAuthBindUserCookieName, secureCookie)
|
||||
}
|
||||
|
||||
codeChallenge := ""
|
||||
if cfg.UsePKCE {
|
||||
@ -199,6 +224,8 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
oidcClearCookie(c, oidcOAuthVerifierCookie, secureCookie)
|
||||
oidcClearCookie(c, oidcOAuthRedirectCookie, secureCookie)
|
||||
oidcClearCookie(c, oidcOAuthNonceCookie, secureCookie)
|
||||
oidcClearCookie(c, oidcOAuthIntentCookieName, secureCookie)
|
||||
oidcClearCookie(c, oidcOAuthBindUserCookieName, secureCookie)
|
||||
}()
|
||||
|
||||
expectedState, err := readCookieDecoded(c, oidcOAuthStateCookieName)
|
||||
@ -212,6 +239,13 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
if redirectTo == "" {
|
||||
redirectTo = oidcOAuthDefaultRedirectTo
|
||||
}
|
||||
browserSessionKey, _ := readOAuthPendingBrowserCookie(c)
|
||||
if strings.TrimSpace(browserSessionKey) == "" {
|
||||
redirectOAuthError(c, frontendCallback, "missing_browser_session", "missing oauth browser session", "")
|
||||
return
|
||||
}
|
||||
intent, _ := readCookieDecoded(c, oidcOAuthIntentCookieName)
|
||||
intent = normalizeOAuthIntent(intent)
|
||||
|
||||
codeVerifier := ""
|
||||
if cfg.UsePKCE {
|
||||
@ -258,16 +292,19 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.ValidateIDToken && strings.TrimSpace(tokenResp.IDToken) == "" {
|
||||
redirectOAuthError(c, frontendCallback, "missing_id_token", "missing id_token", "")
|
||||
return
|
||||
}
|
||||
var idClaims *oidcIDTokenClaims
|
||||
if cfg.ValidateIDToken {
|
||||
if strings.TrimSpace(tokenResp.IDToken) == "" {
|
||||
redirectOAuthError(c, frontendCallback, "missing_id_token", "missing id_token", "")
|
||||
return
|
||||
}
|
||||
|
||||
idClaims, err := oidcParseAndValidateIDToken(c.Request.Context(), cfg, tokenResp.IDToken, expectedNonce)
|
||||
if err != nil {
|
||||
log.Printf("[OIDC OAuth] id_token validation failed: %v", err)
|
||||
redirectOAuthError(c, frontendCallback, "invalid_id_token", "failed to validate id_token", "")
|
||||
return
|
||||
idClaims, err = oidcParseAndValidateIDToken(c.Request.Context(), cfg, tokenResp.IDToken, expectedNonce)
|
||||
if err != nil {
|
||||
log.Printf("[OIDC OAuth] id_token validation failed: %v", err)
|
||||
redirectOAuthError(c, frontendCallback, "invalid_id_token", "failed to validate id_token", "")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userInfoClaims, err := oidcFetchUserInfo(c.Request.Context(), cfg, tokenResp)
|
||||
@ -277,7 +314,10 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
subject := strings.TrimSpace(idClaims.Subject)
|
||||
subject := ""
|
||||
if idClaims != nil {
|
||||
subject = strings.TrimSpace(idClaims.Subject)
|
||||
}
|
||||
if subject == "" {
|
||||
subject = strings.TrimSpace(userInfoClaims.Subject)
|
||||
}
|
||||
@ -285,7 +325,10 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
redirectOAuthError(c, frontendCallback, "missing_subject", "missing subject claim", "")
|
||||
return
|
||||
}
|
||||
issuer := strings.TrimSpace(idClaims.Issuer)
|
||||
issuer := ""
|
||||
if idClaims != nil {
|
||||
issuer = strings.TrimSpace(idClaims.Issuer)
|
||||
}
|
||||
if issuer == "" {
|
||||
issuer = strings.TrimSpace(cfg.IssuerURL)
|
||||
}
|
||||
@ -295,9 +338,115 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
}
|
||||
|
||||
emailVerified := userInfoClaims.EmailVerified
|
||||
if emailVerified == nil {
|
||||
if emailVerified == nil && idClaims != nil {
|
||||
emailVerified = idClaims.EmailVerified
|
||||
}
|
||||
if idClaims != nil && userInfoClaims.Subject != "" && idClaims.Subject != "" && strings.TrimSpace(userInfoClaims.Subject) != strings.TrimSpace(idClaims.Subject) {
|
||||
redirectOAuthError(c, frontendCallback, "subject_mismatch", "userinfo subject does not match id_token", "")
|
||||
return
|
||||
}
|
||||
|
||||
identityKey := oidcIdentityKey(issuer, subject)
|
||||
compatEmail := strings.TrimSpace(userInfoClaims.Email)
|
||||
if compatEmail == "" && idClaims != nil {
|
||||
compatEmail = strings.TrimSpace(idClaims.Email)
|
||||
}
|
||||
email := oidcSyntheticEmailFromIdentityKey(identityKey)
|
||||
username := firstNonEmpty(
|
||||
userInfoClaims.Username,
|
||||
func() string {
|
||||
if idClaims != nil {
|
||||
return idClaims.PreferredUsername
|
||||
}
|
||||
return ""
|
||||
}(),
|
||||
func() string {
|
||||
if idClaims != nil {
|
||||
return idClaims.Name
|
||||
}
|
||||
return ""
|
||||
}(),
|
||||
oidcFallbackUsername(subject),
|
||||
)
|
||||
identityRef := service.PendingAuthIdentityKey{
|
||||
ProviderType: "oidc",
|
||||
ProviderKey: issuer,
|
||||
ProviderSubject: subject,
|
||||
}
|
||||
upstreamClaims := map[string]any{
|
||||
"email": email,
|
||||
"username": username,
|
||||
"subject": subject,
|
||||
"issuer": issuer,
|
||||
"email_verified": emailVerified != nil && *emailVerified,
|
||||
"provider_fallback": strings.TrimSpace(cfg.ProviderName),
|
||||
"suggested_display_name": firstNonEmpty(userInfoClaims.DisplayName, func() string {
|
||||
if idClaims != nil {
|
||||
return idClaims.Name
|
||||
}
|
||||
return ""
|
||||
}(), username),
|
||||
"suggested_avatar_url": userInfoClaims.AvatarURL,
|
||||
}
|
||||
if compatEmail != "" && !strings.EqualFold(strings.TrimSpace(compatEmail), strings.TrimSpace(email)) {
|
||||
upstreamClaims["compat_email"] = compatEmail
|
||||
}
|
||||
if intent == oauthIntentBindCurrentUser {
|
||||
targetUserID, err := h.readOAuthBindUserIDFromCookie(c, oidcOAuthBindUserCookieName)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "invalid_state", "invalid oauth bind target", "")
|
||||
return
|
||||
}
|
||||
if err := h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentBindCurrentUser,
|
||||
Identity: identityRef,
|
||||
TargetUserID: &targetUserID,
|
||||
ResolvedEmail: email,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: map[string]any{
|
||||
"redirect": redirectTo,
|
||||
},
|
||||
}); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth bind", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
return
|
||||
}
|
||||
|
||||
existingIdentityUser, err := h.findOAuthIdentityUser(c.Request.Context(), identityRef)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
return
|
||||
}
|
||||
if existingIdentityUser != nil {
|
||||
if err := h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentLogin,
|
||||
Identity: identityRef,
|
||||
TargetUserID: &existingIdentityUser.ID,
|
||||
ResolvedEmail: existingIdentityUser.Email,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: map[string]any{
|
||||
"redirect": redirectTo,
|
||||
},
|
||||
}); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth login", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
return
|
||||
}
|
||||
|
||||
compatEmailUser, err := h.findOIDCCompatEmailUser(c.Request.Context(), compatEmail)
|
||||
if err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.RequireEmailVerified {
|
||||
if emailVerified == nil || !*emailVerified {
|
||||
redirectOAuthError(c, frontendCallback, "email_not_verified", "email is not verified", "")
|
||||
@ -305,47 +454,136 @@ func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
identityKey := oidcIdentityKey(issuer, subject)
|
||||
email := oidcSelectLoginEmail(userInfoClaims.Email, idClaims.Email, identityKey)
|
||||
username := firstNonEmpty(
|
||||
userInfoClaims.Username,
|
||||
idClaims.PreferredUsername,
|
||||
idClaims.Name,
|
||||
oidcFallbackUsername(subject),
|
||||
)
|
||||
|
||||
// 传入空邀请码;如果需要邀请码,服务层返回 ErrOAuthInvitationRequired
|
||||
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, "")
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrOAuthInvitationRequired) {
|
||||
pendingToken, tokenErr := h.authService.CreatePendingOAuthToken(email, username)
|
||||
if tokenErr != nil {
|
||||
redirectOAuthError(c, frontendCallback, "login_failed", "service_error", "")
|
||||
return
|
||||
}
|
||||
fragment := url.Values{}
|
||||
fragment.Set("error", "invitation_required")
|
||||
fragment.Set("pending_oauth_token", pendingToken)
|
||||
fragment.Set("redirect", redirectTo)
|
||||
redirectWithFragment(c, frontendCallback, fragment)
|
||||
if h.isForceEmailOnThirdPartySignup(c.Request.Context()) {
|
||||
if err := h.createOIDCOAuthChoicePendingSession(
|
||||
c,
|
||||
identityRef,
|
||||
email,
|
||||
email,
|
||||
redirectTo,
|
||||
browserSessionKey,
|
||||
upstreamClaims,
|
||||
compatEmail,
|
||||
compatEmailUser,
|
||||
true,
|
||||
); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth login", "")
|
||||
return
|
||||
}
|
||||
redirectOAuthError(c, frontendCallback, "login_failed", infraerrors.Reason(err), infraerrors.Message(err))
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
return
|
||||
}
|
||||
|
||||
fragment := url.Values{}
|
||||
fragment.Set("access_token", tokenPair.AccessToken)
|
||||
fragment.Set("refresh_token", tokenPair.RefreshToken)
|
||||
fragment.Set("expires_in", fmt.Sprintf("%d", tokenPair.ExpiresIn))
|
||||
fragment.Set("token_type", "Bearer")
|
||||
fragment.Set("redirect", redirectTo)
|
||||
redirectWithFragment(c, frontendCallback, fragment)
|
||||
if err := h.createOIDCOAuthChoicePendingSession(
|
||||
c,
|
||||
identityRef,
|
||||
email,
|
||||
email,
|
||||
redirectTo,
|
||||
browserSessionKey,
|
||||
upstreamClaims,
|
||||
compatEmail,
|
||||
compatEmailUser,
|
||||
h.isForceEmailOnThirdPartySignup(c.Request.Context()),
|
||||
); err != nil {
|
||||
redirectOAuthError(c, frontendCallback, "session_error", "failed to continue oauth login", "")
|
||||
return
|
||||
}
|
||||
redirectToFrontendCallback(c, frontendCallback)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) findOIDCCompatEmailUser(ctx context.Context, email string) (*dbent.User, error) {
|
||||
client := h.entClient()
|
||||
if client == nil {
|
||||
return nil, infraerrors.ServiceUnavailable("PENDING_AUTH_NOT_READY", "pending auth service is not ready")
|
||||
}
|
||||
|
||||
email = strings.TrimSpace(strings.ToLower(email))
|
||||
if email == "" ||
|
||||
strings.HasSuffix(email, service.LinuxDoConnectSyntheticEmailDomain) ||
|
||||
strings.HasSuffix(email, service.OIDCConnectSyntheticEmailDomain) ||
|
||||
strings.HasSuffix(email, service.WeChatConnectSyntheticEmailDomain) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userEntity, err := findUserByNormalizedEmail(ctx, client, email)
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrUserNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, infraerrors.InternalServer("COMPAT_EMAIL_LOOKUP_FAILED", "failed to look up compat email user").WithCause(err)
|
||||
}
|
||||
return userEntity, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) createOIDCOAuthChoicePendingSession(
|
||||
c *gin.Context,
|
||||
identity service.PendingAuthIdentityKey,
|
||||
suggestedEmail string,
|
||||
resolvedEmail string,
|
||||
redirectTo string,
|
||||
browserSessionKey string,
|
||||
upstreamClaims map[string]any,
|
||||
compatEmail string,
|
||||
compatEmailUser *dbent.User,
|
||||
forceEmailOnSignup bool,
|
||||
) error {
|
||||
suggestionEmail := strings.TrimSpace(suggestedEmail)
|
||||
canonicalEmail := strings.TrimSpace(resolvedEmail)
|
||||
if suggestionEmail == "" {
|
||||
suggestionEmail = canonicalEmail
|
||||
}
|
||||
|
||||
completionResponse := map[string]any{
|
||||
"step": oauthPendingChoiceStep,
|
||||
"adoption_required": true,
|
||||
"redirect": strings.TrimSpace(redirectTo),
|
||||
"email": suggestionEmail,
|
||||
"resolved_email": canonicalEmail,
|
||||
"existing_account_email": "",
|
||||
"existing_account_bindable": false,
|
||||
"create_account_allowed": true,
|
||||
"force_email_on_signup": forceEmailOnSignup,
|
||||
"choice_reason": "third_party_signup",
|
||||
}
|
||||
if strings.TrimSpace(compatEmail) != "" {
|
||||
completionResponse["compat_email"] = strings.TrimSpace(compatEmail)
|
||||
}
|
||||
if compatEmailUser != nil {
|
||||
completionResponse["email"] = strings.TrimSpace(compatEmailUser.Email)
|
||||
completionResponse["existing_account_email"] = strings.TrimSpace(compatEmailUser.Email)
|
||||
completionResponse["existing_account_bindable"] = true
|
||||
completionResponse["choice_reason"] = "compat_email_match"
|
||||
}
|
||||
if forceEmailOnSignup && compatEmailUser == nil {
|
||||
completionResponse["choice_reason"] = "force_email_on_signup"
|
||||
}
|
||||
|
||||
resolvedChoiceEmail := suggestionEmail
|
||||
if compatEmailUser != nil {
|
||||
resolvedChoiceEmail = strings.TrimSpace(compatEmailUser.Email)
|
||||
}
|
||||
var targetUserID *int64
|
||||
if compatEmailUser != nil && compatEmailUser.ID > 0 {
|
||||
targetUserID = &compatEmailUser.ID
|
||||
}
|
||||
|
||||
return h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentLogin,
|
||||
Identity: identity,
|
||||
TargetUserID: targetUserID,
|
||||
ResolvedEmail: resolvedChoiceEmail,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
UpstreamIdentityClaims: upstreamClaims,
|
||||
CompletionResponse: completionResponse,
|
||||
})
|
||||
}
|
||||
|
||||
type completeOIDCOAuthRequest struct {
|
||||
PendingOAuthToken string `json:"pending_oauth_token" binding:"required"`
|
||||
InvitationCode string `json:"invitation_code" binding:"required"`
|
||||
InvitationCode string `json:"invitation_code" binding:"required"`
|
||||
AdoptDisplayName *bool `json:"adopt_display_name,omitempty"`
|
||||
AdoptAvatar *bool `json:"adopt_avatar,omitempty"`
|
||||
}
|
||||
|
||||
// CompleteOIDCOAuthRegistration completes a pending OAuth registration by validating
|
||||
@ -358,17 +596,87 @@ func (h *AuthHandler) CompleteOIDCOAuthRegistration(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
email, username, err := h.authService.VerifyPendingOAuthToken(req.PendingOAuthToken)
|
||||
secureCookie := isRequestHTTPS(c)
|
||||
sessionToken, err := readOAuthPendingSessionCookie(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "INVALID_TOKEN", "message": "invalid or expired registration token"})
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, service.ErrPendingAuthSessionNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
browserSessionKey, err := readOAuthPendingBrowserCookie(c)
|
||||
if err != nil {
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, service.ErrPendingAuthBrowserMismatch)
|
||||
return
|
||||
}
|
||||
pendingSvc, err := h.pendingIdentityService()
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
session, err := pendingSvc.GetBrowserSession(c.Request.Context(), sessionToken, browserSessionKey)
|
||||
if err != nil {
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := ensurePendingOAuthCompleteRegistrationSession(session); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if updatedSession, handled, err := h.legacyCompleteRegistrationSessionStatus(c, session); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
} else if handled {
|
||||
c.JSON(http.StatusOK, buildPendingOAuthSessionStatusPayload(updatedSession))
|
||||
return
|
||||
} else {
|
||||
session = updatedSession
|
||||
}
|
||||
if err := h.ensureBackendModeAllowsNewUserLogin(c.Request.Context()); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
email := strings.TrimSpace(session.ResolvedEmail)
|
||||
username := pendingSessionStringValue(session.UpstreamIdentityClaims, "username")
|
||||
if email == "" || username == "" {
|
||||
response.ErrorFrom(c, infraerrors.BadRequest("PENDING_AUTH_SESSION_INVALID", "pending auth registration context is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
client := h.entClient()
|
||||
if client == nil {
|
||||
response.ErrorFrom(c, infraerrors.ServiceUnavailable("PENDING_AUTH_NOT_READY", "pending auth service is not ready"))
|
||||
return
|
||||
}
|
||||
if err := ensurePendingOAuthRegistrationIdentityAvailable(c.Request.Context(), client, session); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
decision, err := h.ensurePendingOAuthAdoptionDecision(c, session.ID, oauthAdoptionDecisionRequest{
|
||||
AdoptDisplayName: req.AdoptDisplayName,
|
||||
AdoptAvatar: req.AdoptAvatar,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
tokenPair, user, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := applyPendingOAuthAdoptionAndConsumeSession(c.Request.Context(), client, h.authService, h.userService, session, decision, user.ID); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"access_token": tokenPair.AccessToken,
|
||||
@ -405,7 +713,7 @@ func oidcExchangeCode(
|
||||
form.Set("client_id", cfg.ClientID)
|
||||
form.Set("code", code)
|
||||
form.Set("redirect_uri", redirectURI)
|
||||
if cfg.UsePKCE {
|
||||
if strings.TrimSpace(codeVerifier) != "" {
|
||||
form.Set("code_verifier", codeVerifier)
|
||||
}
|
||||
|
||||
@ -560,9 +868,26 @@ func oidcParseUserInfo(body string, cfg config.OIDCConnectConfig) *oidcUserInfoC
|
||||
if verified, ok := getGJSONBool(body, "email_verified"); ok {
|
||||
claims.EmailVerified = &verified
|
||||
}
|
||||
claims.DisplayName = firstNonEmpty(
|
||||
getGJSON(body, "name"),
|
||||
getGJSON(body, "nickname"),
|
||||
getGJSON(body, "display_name"),
|
||||
getGJSON(body, "preferred_username"),
|
||||
getGJSON(body, "username"),
|
||||
)
|
||||
claims.AvatarURL = firstNonEmpty(
|
||||
getGJSON(body, "picture"),
|
||||
getGJSON(body, "avatar_url"),
|
||||
getGJSON(body, "avatar"),
|
||||
getGJSON(body, "profile_image_url"),
|
||||
getGJSON(body, "user.avatar"),
|
||||
getGJSON(body, "user.avatar_url"),
|
||||
)
|
||||
claims.Email = strings.TrimSpace(claims.Email)
|
||||
claims.Username = strings.TrimSpace(claims.Username)
|
||||
claims.Subject = strings.TrimSpace(claims.Subject)
|
||||
claims.DisplayName = strings.TrimSpace(claims.DisplayName)
|
||||
claims.AvatarURL = strings.TrimSpace(claims.AvatarURL)
|
||||
return claims
|
||||
}
|
||||
|
||||
@ -595,7 +920,7 @@ func buildOIDCAuthorizeURL(cfg config.OIDCConnectConfig, state, nonce, codeChall
|
||||
if strings.TrimSpace(nonce) != "" {
|
||||
q.Set("nonce", nonce)
|
||||
}
|
||||
if cfg.UsePKCE {
|
||||
if strings.TrimSpace(codeChallenge) != "" {
|
||||
q.Set("code_challenge", codeChallenge)
|
||||
q.Set("code_challenge_method", "S256")
|
||||
}
|
||||
@ -831,14 +1156,6 @@ func oidcSyntheticEmailFromIdentityKey(identityKey string) string {
|
||||
return "oidc-" + hex.EncodeToString(sum[:16]) + service.OIDCConnectSyntheticEmailDomain
|
||||
}
|
||||
|
||||
func oidcSelectLoginEmail(userInfoEmail, idTokenEmail, identityKey string) string {
|
||||
email := strings.TrimSpace(firstNonEmpty(userInfoEmail, idTokenEmail))
|
||||
if email != "" {
|
||||
return email
|
||||
}
|
||||
return oidcSyntheticEmailFromIdentityKey(identityKey)
|
||||
}
|
||||
|
||||
func oidcFallbackUsername(subject string) string {
|
||||
subject = strings.TrimSpace(subject)
|
||||
if subject == "" {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@ -12,7 +13,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/ent/authidentity"
|
||||
"github.com/Wei-Shaw/sub2api/ent/identityadoptiondecision"
|
||||
"github.com/Wei-Shaw/sub2api/ent/pendingauthsession"
|
||||
dbuser "github.com/Wei-Shaw/sub2api/ent/user"
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
servermiddleware "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -30,26 +39,11 @@ func TestOIDCSyntheticEmailStableAndDistinct(t *testing.T) {
|
||||
require.Contains(t, e1, "@oidc-connect.invalid")
|
||||
}
|
||||
|
||||
func TestOIDCSelectLoginEmailPrefersRealEmail(t *testing.T) {
|
||||
identityKey := oidcIdentityKey("https://issuer.example.com", "subject-a")
|
||||
|
||||
email := oidcSelectLoginEmail("user@example.com", "idtoken@example.com", identityKey)
|
||||
require.Equal(t, "user@example.com", email)
|
||||
|
||||
email = oidcSelectLoginEmail("", "idtoken@example.com", identityKey)
|
||||
require.Equal(t, "idtoken@example.com", email)
|
||||
|
||||
email = oidcSelectLoginEmail("", "", identityKey)
|
||||
require.Contains(t, email, "@oidc-connect.invalid")
|
||||
require.Equal(t, oidcSyntheticEmailFromIdentityKey(identityKey), email)
|
||||
}
|
||||
|
||||
func TestBuildOIDCAuthorizeURLIncludesNonceAndPKCE(t *testing.T) {
|
||||
cfg := config.OIDCConnectConfig{
|
||||
AuthorizeURL: "https://issuer.example.com/auth",
|
||||
ClientID: "cid",
|
||||
Scopes: "openid email profile",
|
||||
UsePKCE: true,
|
||||
}
|
||||
|
||||
u, err := buildOIDCAuthorizeURL(cfg, "state123", "nonce123", "challenge123", "https://app.example.com/callback")
|
||||
@ -106,6 +100,26 @@ func TestOIDCParseAndValidateIDToken(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestOIDCParseUserInfoIncludesSuggestedProfile(t *testing.T) {
|
||||
cfg := config.OIDCConnectConfig{}
|
||||
|
||||
claims := oidcParseUserInfo(`{
|
||||
"sub":"subject-1",
|
||||
"preferred_username":"alice",
|
||||
"name":"Alice Example",
|
||||
"picture":"https://cdn.example/avatar.png",
|
||||
"email":"alice@example.com",
|
||||
"email_verified":true
|
||||
}`, cfg)
|
||||
|
||||
require.Equal(t, "subject-1", claims.Subject)
|
||||
require.Equal(t, "alice", claims.Username)
|
||||
require.Equal(t, "Alice Example", claims.DisplayName)
|
||||
require.Equal(t, "https://cdn.example/avatar.png", claims.AvatarURL)
|
||||
require.NotNil(t, claims.EmailVerified)
|
||||
require.True(t, *claims.EmailVerified)
|
||||
}
|
||||
|
||||
func buildRSAJWK(kid string, pub *rsa.PublicKey) oidcJWK {
|
||||
n := base64.RawURLEncoding.EncodeToString(pub.N.Bytes())
|
||||
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pub.E)).Bytes())
|
||||
@ -118,3 +132,909 @@ func buildRSAJWK(kid string, pub *rsa.PublicKey) oidcJWK {
|
||||
E: e,
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDCOAuthBindStartRedirectsAndSetsBindCookies(t *testing.T) {
|
||||
handler := newOIDCOAuthTestHandler(t, false, config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "oidc-client",
|
||||
ClientSecret: "oidc-secret",
|
||||
IssuerURL: "https://issuer.example.com",
|
||||
AuthorizeURL: "https://issuer.example.com/oauth/authorize",
|
||||
TokenURL: "https://issuer.example.com/oauth/token",
|
||||
UserInfoURL: "https://issuer.example.com/oauth/userinfo",
|
||||
JWKSURL: "https://issuer.example.com/oauth/jwks",
|
||||
Scopes: "openid profile email",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
ValidateIDToken: true,
|
||||
AllowedSigningAlgs: "RS256",
|
||||
ClockSkewSeconds: 120,
|
||||
RequireEmailVerified: false,
|
||||
})
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/bind/start?intent=bind_current_user&redirect=/settings/connections", nil)
|
||||
c.Request = req
|
||||
c.Set(string(servermiddleware.ContextKeyUser), servermiddleware.AuthSubject{UserID: 84})
|
||||
|
||||
handler.OIDCOAuthStart(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
require.Contains(t, location, "issuer.example.com/oauth/authorize")
|
||||
require.Contains(t, location, "client_id=oidc-client")
|
||||
require.Contains(t, location, "nonce=")
|
||||
|
||||
cookies := recorder.Result().Cookies()
|
||||
require.NotNil(t, findCookie(cookies, oidcOAuthStateCookieName))
|
||||
require.NotNil(t, findCookie(cookies, oidcOAuthRedirectCookie))
|
||||
require.NotNil(t, findCookie(cookies, oidcOAuthVerifierCookie))
|
||||
require.NotNil(t, findCookie(cookies, oidcOAuthNonceCookie))
|
||||
require.NotNil(t, findCookie(cookies, oauthPendingBrowserCookieName))
|
||||
|
||||
intentCookie := findCookie(cookies, oidcOAuthIntentCookieName)
|
||||
require.NotNil(t, intentCookie)
|
||||
require.Equal(t, oauthIntentBindCurrentUser, decodeCookieValueForTest(t, intentCookie.Value))
|
||||
|
||||
bindCookie := findCookie(cookies, oidcOAuthBindUserCookieName)
|
||||
require.NotNil(t, bindCookie)
|
||||
userID, err := parseOAuthBindUserCookieValue(decodeCookieValueForTest(t, bindCookie.Value), "test-secret")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(84), userID)
|
||||
}
|
||||
|
||||
func TestOIDCOAuthStartOmitsPKCEAndNonceWhenDisabled(t *testing.T) {
|
||||
handler := newOIDCOAuthTestHandler(t, false, config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "oidc-client",
|
||||
ClientSecret: "oidc-secret",
|
||||
IssuerURL: "https://issuer.example.com",
|
||||
AuthorizeURL: "https://issuer.example.com/oauth/authorize",
|
||||
TokenURL: "https://issuer.example.com/oauth/token",
|
||||
UserInfoURL: "https://issuer.example.com/oauth/userinfo",
|
||||
Scopes: "openid profile email",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: false,
|
||||
ValidateIDToken: false,
|
||||
RequireEmailVerified: false,
|
||||
})
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/start?redirect=/dashboard", nil)
|
||||
|
||||
handler.OIDCOAuthStart(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
require.NotContains(t, location, "code_challenge=")
|
||||
require.NotContains(t, location, "nonce=")
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), oidcOAuthVerifierCookie))
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), oidcOAuthNonceCookie))
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackAllowsOptionalPKCEAndIDTokenValidation(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
require.NoError(t, r.ParseForm())
|
||||
require.Empty(t, r.PostForm.Get("code_verifier"))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"access_token":"oidc-access","token_type":"Bearer","expires_in":3600}`))
|
||||
case "/userinfo":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"sub":"oidc-subject-compat","preferred_username":"oidc_user","name":"OIDC Display","email":"oidc@example.com"}`))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ClientID: "oidc-client",
|
||||
ClientSecret: "oidc-secret",
|
||||
IssuerURL: "https://issuer.example.com",
|
||||
AuthorizeURL: upstream.URL + "/authorize",
|
||||
TokenURL: upstream.URL + "/token",
|
||||
UserInfoURL: upstream.URL + "/userinfo",
|
||||
Scopes: "openid profile email",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: false,
|
||||
ValidateIDToken: false,
|
||||
RequireEmailVerified: false,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-123", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-123"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-123"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback", recorder.Header().Get("Location"))
|
||||
require.NotNil(t, findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName))
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackCreatesLoginPendingSessionForExistingIdentityUser(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-subject-login",
|
||||
PreferredUsername: "oidc_login",
|
||||
DisplayName: "OIDC Login Display",
|
||||
AvatarURL: "https://cdn.example/oidc-login.png",
|
||||
Email: "oidc-login@example.com",
|
||||
EmailVerified: true,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail(oidcSyntheticEmailFromIdentityKey(oidcIdentityKey(cfg.IssuerURL, "oidc-subject-login"))).
|
||||
SetUsername("legacy-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingUser.ID).
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey(cfg.IssuerURL).
|
||||
SetProviderSubject("oidc-subject-login").
|
||||
SetMetadata(map[string]any{"username": "legacy-user"}).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-123", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-123"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-123"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-subject-login"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-123"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, existingUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, cfg.IssuerURL, session.ProviderKey)
|
||||
require.Equal(t, "OIDC Login Display", session.UpstreamIdentityClaims["suggested_display_name"])
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
_, hasAccessToken := completion["access_token"]
|
||||
require.False(t, hasAccessToken)
|
||||
_, hasRefreshToken := completion["refresh_token"]
|
||||
require.False(t, hasRefreshToken)
|
||||
require.Nil(t, completion["error"])
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackRejectsDisabledExistingIdentityUser(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-disabled-subject",
|
||||
PreferredUsername: "oidc_disabled",
|
||||
DisplayName: "OIDC Disabled",
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail(oidcSyntheticEmailFromIdentityKey(oidcIdentityKey(cfg.IssuerURL, "oidc-disabled-subject"))).
|
||||
SetUsername("disabled-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusDisabled).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingUser.ID).
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey(cfg.IssuerURL).
|
||||
SetProviderSubject("oidc-disabled-subject").
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-disabled", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-disabled"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-disabled"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-disabled-subject"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-disabled"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName))
|
||||
assertOAuthRedirectError(t, recorder.Header().Get("Location"), "session_error", "USER_NOT_ACTIVE")
|
||||
|
||||
count, err := client.PendingAuthSession.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, count)
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackCreatesBindPendingSessionForCompatEmailUser(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-subject-compat",
|
||||
PreferredUsername: "oidc_compat",
|
||||
DisplayName: "OIDC Compat Display",
|
||||
AvatarURL: "https://cdn.example/oidc-compat.png",
|
||||
Email: "legacy@example.com",
|
||||
EmailVerified: true,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail("legacy@example.com").
|
||||
SetUsername("legacy-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-compat", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-subject-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-compat"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, existingUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, existingUser.Email, session.ResolvedEmail)
|
||||
require.Equal(t, "legacy@example.com", session.UpstreamIdentityClaims["compat_email"])
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
require.Equal(t, oauthPendingChoiceStep, completion["step"])
|
||||
require.Equal(t, existingUser.Email, completion["email"])
|
||||
require.Equal(t, existingUser.Email, completion["existing_account_email"])
|
||||
require.Equal(t, true, completion["existing_account_bindable"])
|
||||
require.Equal(t, "compat_email_match", completion["choice_reason"])
|
||||
_, hasAccessToken := completion["access_token"]
|
||||
require.False(t, hasAccessToken)
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackAllowsCompatEmailBindWhenUpstreamEmailIsUnverified(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-subject-unverified-compat",
|
||||
PreferredUsername: "oidc_unverified",
|
||||
DisplayName: "OIDC Unverified Compat Display",
|
||||
AvatarURL: "https://cdn.example/oidc-unverified.png",
|
||||
Email: "owner@example.com",
|
||||
EmailVerified: false,
|
||||
})
|
||||
defer cleanup()
|
||||
cfg.RequireEmailVerified = true
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := client.User.Create().
|
||||
SetEmail("owner@example.com").
|
||||
SetUsername("owner-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-unverified-compat", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-unverified-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/settings/connections"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-unverified-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-subject-unverified-compat"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-unverified-compat"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback#error=email_not_verified&error_message=email+is+not+verified", recorder.Header().Get("Location"))
|
||||
require.Nil(t, findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName))
|
||||
|
||||
count, err := client.PendingAuthSession.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, count)
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackCreatesChoicePendingSessionWhenSignupRequiresInvite(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-subject-invite",
|
||||
PreferredUsername: "oidc_invite",
|
||||
DisplayName: "OIDC Invite Display",
|
||||
AvatarURL: "https://cdn.example/oidc-invite.png",
|
||||
Email: "oidc-invite@example.com",
|
||||
EmailVerified: true,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, true, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-456", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-456"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/dashboard"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-456"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-subject-invite"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentLogin))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-456"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
ctx := context.Background()
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentLogin, session.Intent)
|
||||
require.Nil(t, session.TargetUserID)
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, oauthPendingChoiceStep, completion["step"])
|
||||
require.Equal(t, "/dashboard", completion["redirect"])
|
||||
require.Equal(t, "third_party_signup", completion["choice_reason"])
|
||||
}
|
||||
|
||||
func TestOIDCOAuthCallbackCreatesBindPendingSessionForCurrentUser(t *testing.T) {
|
||||
cfg, cleanup := newOIDCTestProvider(t, oidcProviderFixture{
|
||||
Subject: "oidc-subject-bind",
|
||||
PreferredUsername: "oidc_bind",
|
||||
DisplayName: "OIDC Bind Display",
|
||||
AvatarURL: "https://cdn.example/oidc-bind.png",
|
||||
Email: "oidc-bind@example.com",
|
||||
EmailVerified: true,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
handler, client := newOIDCOAuthHandlerAndClient(t, false, cfg)
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
ctx := context.Background()
|
||||
currentUser, err := client.User.Create().
|
||||
SetEmail("current@example.com").
|
||||
SetUsername("current-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/oidc/callback?code=oidc-code&state=state-bind", nil)
|
||||
req.AddCookie(encodedCookie(oidcOAuthStateCookieName, "state-bind"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthRedirectCookie, "/settings/connections"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthVerifierCookie, "verifier-bind"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthNonceCookie, "nonce-oidc-subject-bind"))
|
||||
req.AddCookie(encodedCookie(oidcOAuthIntentCookieName, oauthIntentBindCurrentUser))
|
||||
req.AddCookie(encodedCookie(oidcOAuthBindUserCookieName, buildEncodedOAuthBindUserCookie(t, currentUser.ID, "test-secret")))
|
||||
req.AddCookie(encodedCookie(oauthPendingBrowserCookieName, "browser-bind"))
|
||||
c.Request = req
|
||||
|
||||
handler.OIDCOAuthCallback(c)
|
||||
|
||||
require.Equal(t, http.StatusFound, recorder.Code)
|
||||
require.Equal(t, "/auth/oidc/callback", recorder.Header().Get("Location"))
|
||||
|
||||
sessionCookie := findCookie(recorder.Result().Cookies(), oauthPendingSessionCookieName)
|
||||
require.NotNil(t, sessionCookie)
|
||||
|
||||
session, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.SessionTokenEQ(decodeCookieValueForTest(t, sessionCookie.Value))).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, oauthIntentBindCurrentUser, session.Intent)
|
||||
require.NotNil(t, session.TargetUserID)
|
||||
require.Equal(t, currentUser.ID, *session.TargetUserID)
|
||||
require.Equal(t, cfg.IssuerURL, session.ProviderKey)
|
||||
require.Equal(t, "OIDC Bind Display", session.UpstreamIdentityClaims["suggested_display_name"])
|
||||
|
||||
completion, ok := session.LocalFlowState[oauthCompletionResponseKey].(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "/settings/connections", completion["redirect"])
|
||||
require.Empty(t, completion["access_token"])
|
||||
|
||||
userCount, err := client.User.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, userCount)
|
||||
}
|
||||
|
||||
func TestCompleteOIDCOAuthRegistrationAppliesPendingAdoptionDecision(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("oidc-complete-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-subject-1").
|
||||
SetResolvedEmail("93a310f4c1944c5bbd2e246df1f76485@oidc-connect.invalid").
|
||||
SetBrowserSessionKey("oidc-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "oidc_user",
|
||||
"issuer": "https://issuer.example.com",
|
||||
"suggested_display_name": "OIDC Display",
|
||||
"suggested_avatar_url": "https://cdn.example/oidc.png",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = service.NewAuthPendingIdentityService(client).UpsertAdoptionDecision(ctx, service.PendingIdentityAdoptionDecisionInput{
|
||||
PendingAuthSessionID: session.ID,
|
||||
AdoptAvatar: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1","adopt_display_name":true}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/oidc/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("oidc-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteOIDCOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.NotEmpty(t, responseData["access_token"])
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ(session.ResolvedEmail)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "OIDC Display", userEntity.Username)
|
||||
|
||||
identity, err := client.AuthIdentity.Query().
|
||||
Where(
|
||||
authidentity.ProviderTypeEQ("oidc"),
|
||||
authidentity.ProviderKeyEQ("https://issuer.example.com"),
|
||||
authidentity.ProviderSubjectEQ("oidc-subject-1"),
|
||||
).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, userEntity.ID, identity.UserID)
|
||||
require.Equal(t, "OIDC Display", identity.Metadata["display_name"])
|
||||
require.Equal(t, "https://cdn.example/oidc.png", identity.Metadata["avatar_url"])
|
||||
|
||||
decision, err := client.IdentityAdoptionDecision.Query().
|
||||
Where(identityadoptiondecision.PendingAuthSessionIDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision.IdentityID)
|
||||
require.Equal(t, identity.ID, *decision.IdentityID)
|
||||
require.True(t, decision.AdoptDisplayName)
|
||||
require.True(t, decision.AdoptAvatar)
|
||||
|
||||
consumed, err := client.PendingAuthSession.Query().
|
||||
Where(pendingauthsession.IDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, consumed.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteOIDCOAuthRegistrationRejectsAdoptExistingUserSession(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
existingUser, err := client.User.Create().
|
||||
SetEmail("owner@example.com").
|
||||
SetUsername("owner-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("oidc-complete-invalid-session").
|
||||
SetIntent("adopt_existing_user_by_email").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-invalid-subject-1").
|
||||
SetTargetUserID(existingUser.ID).
|
||||
SetResolvedEmail(existingUser.Email).
|
||||
SetBrowserSessionKey("oidc-invalid-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "oidc_user",
|
||||
}).
|
||||
SetLocalFlowState(map[string]any{
|
||||
oauthCompletionResponseKey: map[string]any{
|
||||
"step": "bind_login_required",
|
||||
},
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/oidc/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("oidc-invalid-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteOIDCOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, recorder.Code)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteOIDCOAuthRegistrationReturnsPendingSessionWhenChoiceStillRequired(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("oidc-complete-choice-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-choice-subject-1").
|
||||
SetResolvedEmail("oidc-choice-subject-1@oidc-connect.invalid").
|
||||
SetBrowserSessionKey("oidc-choice-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "oidc_user",
|
||||
"issuer": "https://issuer.example.com",
|
||||
}).
|
||||
SetLocalFlowState(map[string]any{
|
||||
oauthCompletionResponseKey: map[string]any{
|
||||
"step": oauthPendingChoiceStep,
|
||||
"redirect": "/dashboard",
|
||||
"email": "fresh@example.com",
|
||||
"resolved_email": "fresh@example.com",
|
||||
"force_email_on_signup": true,
|
||||
},
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/oidc/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("oidc-choice-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteOIDCOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.Equal(t, "pending_session", responseData["auth_result"])
|
||||
require.Equal(t, oauthPendingChoiceStep, responseData["step"])
|
||||
require.Equal(t, true, responseData["force_email_on_signup"])
|
||||
require.Empty(t, responseData["access_token"])
|
||||
|
||||
userCount, err := client.User.Query().Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, userCount)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
func TestCompleteOIDCOAuthRegistrationBindsIdentityWithoutAdoptionFlags(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("oidc-complete-no-adoption-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-subject-no-adoption").
|
||||
SetResolvedEmail("8c9f12b2a2e14b1db9efc08b27e0ef5c@oidc-connect.invalid").
|
||||
SetBrowserSessionKey("oidc-browser-no-adoption").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "oidc_user",
|
||||
"issuer": "https://issuer.example.com",
|
||||
"suggested_display_name": "OIDC Legacy",
|
||||
"suggested_avatar_url": "https://cdn.example/oidc-legacy.png",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/oidc/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("oidc-browser-no-adoption")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteOIDCOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
responseData := decodeJSONBody(t, recorder)
|
||||
require.NotEmpty(t, responseData["access_token"])
|
||||
require.NotEmpty(t, responseData["refresh_token"])
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ(session.ResolvedEmail)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "oidc_user", userEntity.Username)
|
||||
|
||||
identity, err := client.AuthIdentity.Query().
|
||||
Where(
|
||||
authidentity.ProviderTypeEQ("oidc"),
|
||||
authidentity.ProviderKeyEQ("https://issuer.example.com"),
|
||||
authidentity.ProviderSubjectEQ("oidc-subject-no-adoption"),
|
||||
).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, userEntity.ID, identity.UserID)
|
||||
|
||||
decision, err := client.IdentityAdoptionDecision.Query().
|
||||
Where(identityadoptiondecision.PendingAuthSessionIDEQ(session.ID)).
|
||||
Only(ctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision.IdentityID)
|
||||
require.Equal(t, identity.ID, *decision.IdentityID)
|
||||
require.False(t, decision.AdoptDisplayName)
|
||||
require.False(t, decision.AdoptAvatar)
|
||||
}
|
||||
|
||||
func TestCompleteOIDCOAuthRegistrationRejectsIdentityOwnershipConflictBeforeUserCreation(t *testing.T) {
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, false)
|
||||
ctx := context.Background()
|
||||
|
||||
existingOwner, err := client.User.Create().
|
||||
SetEmail("owner@example.com").
|
||||
SetUsername("owner-user").
|
||||
SetPasswordHash("hash").
|
||||
SetRole(service.RoleUser).
|
||||
SetStatus(service.StatusActive).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = client.AuthIdentity.Create().
|
||||
SetUserID(existingOwner.ID).
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-conflict-subject").
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
session, err := client.PendingAuthSession.Create().
|
||||
SetSessionToken("oidc-complete-conflict-session").
|
||||
SetIntent("login").
|
||||
SetProviderType("oidc").
|
||||
SetProviderKey("https://issuer.example.com").
|
||||
SetProviderSubject("oidc-conflict-subject").
|
||||
SetResolvedEmail("f6f5f1f16f9248ccb11e0d633963b290@oidc-connect.invalid").
|
||||
SetBrowserSessionKey("oidc-conflict-browser").
|
||||
SetUpstreamIdentityClaims(map[string]any{
|
||||
"username": "oidc_user",
|
||||
"issuer": "https://issuer.example.com",
|
||||
}).
|
||||
SetExpiresAt(time.Now().UTC().Add(10 * time.Minute)).
|
||||
Save(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
body := bytes.NewBufferString(`{"invitation_code":"invite-1"}`)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/oidc/complete-registration", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingSessionCookieName, Value: encodeCookieValue(session.SessionToken)})
|
||||
req.AddCookie(&http.Cookie{Name: oauthPendingBrowserCookieName, Value: encodeCookieValue("oidc-conflict-browser")})
|
||||
c.Request = req
|
||||
|
||||
handler.CompleteOIDCOAuthRegistration(c)
|
||||
|
||||
require.Equal(t, http.StatusConflict, recorder.Code)
|
||||
payload := decodeJSONBody(t, recorder)
|
||||
require.Equal(t, "AUTH_IDENTITY_OWNERSHIP_CONFLICT", payload["reason"])
|
||||
|
||||
userCount, err := client.User.Query().
|
||||
Where(dbuser.EmailEQ("f6f5f1f16f9248ccb11e0d633963b290@oidc-connect.invalid")).
|
||||
Count(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, userCount)
|
||||
|
||||
storedSession, err := client.PendingAuthSession.Get(ctx, session.ID)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, storedSession.ConsumedAt)
|
||||
}
|
||||
|
||||
type oidcProviderFixture struct {
|
||||
Subject string
|
||||
PreferredUsername string
|
||||
DisplayName string
|
||||
AvatarURL string
|
||||
Email string
|
||||
EmailVerified bool
|
||||
}
|
||||
|
||||
func newOIDCOAuthTestHandler(t *testing.T, invitationEnabled bool, oauthCfg config.OIDCConnectConfig) *AuthHandler {
|
||||
t.Helper()
|
||||
handler, _ := newOIDCOAuthHandlerAndClient(t, invitationEnabled, oauthCfg)
|
||||
return handler
|
||||
}
|
||||
|
||||
func newOIDCOAuthHandlerAndClient(t *testing.T, invitationEnabled bool, oauthCfg config.OIDCConnectConfig) (*AuthHandler, *dbent.Client) {
|
||||
t.Helper()
|
||||
handler, client := newOAuthPendingFlowTestHandler(t, invitationEnabled)
|
||||
handler.settingSvc = nil
|
||||
handler.cfg = &config.Config{
|
||||
JWT: config.JWTConfig{
|
||||
Secret: "test-secret",
|
||||
ExpireHour: 1,
|
||||
AccessTokenExpireMinutes: 60,
|
||||
RefreshTokenExpireDays: 7,
|
||||
},
|
||||
OIDC: oauthCfg,
|
||||
}
|
||||
return handler, client
|
||||
}
|
||||
|
||||
func newOIDCTestProvider(t *testing.T, fixture oidcProviderFixture) (config.OIDCConnectConfig, func()) {
|
||||
t.Helper()
|
||||
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
kid := "test-kid"
|
||||
jwks := oidcJWKSet{Keys: []oidcJWK{buildRSAJWK(kid, &privateKey.PublicKey)}}
|
||||
tokenResponse := oidcTokenResponse{
|
||||
AccessToken: "oidc-access-token",
|
||||
TokenType: "Bearer",
|
||||
ExpiresIn: 3600,
|
||||
}
|
||||
|
||||
userInfoPayload := map[string]any{
|
||||
"sub": fixture.Subject,
|
||||
"preferred_username": fixture.PreferredUsername,
|
||||
"name": fixture.DisplayName,
|
||||
"picture": fixture.AvatarURL,
|
||||
"email": fixture.Email,
|
||||
"email_verified": fixture.EmailVerified,
|
||||
}
|
||||
|
||||
var issuer string
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/token":
|
||||
require.NoError(t, json.NewEncoder(w).Encode(tokenResponse))
|
||||
case "/userinfo":
|
||||
require.NoError(t, json.NewEncoder(w).Encode(userInfoPayload))
|
||||
case "/jwks":
|
||||
require.NoError(t, json.NewEncoder(w).Encode(jwks))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
|
||||
issuer = server.URL
|
||||
now := time.Now()
|
||||
claims := oidcIDTokenClaims{
|
||||
Email: fixture.Email,
|
||||
EmailVerified: boolPtr(fixture.EmailVerified),
|
||||
PreferredUsername: fixture.PreferredUsername,
|
||||
Name: fixture.DisplayName,
|
||||
Nonce: "nonce-" + fixture.Subject,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Issuer: issuer,
|
||||
Subject: fixture.Subject,
|
||||
Audience: jwt.ClaimStrings{"oidc-client"},
|
||||
IssuedAt: jwt.NewNumericDate(now),
|
||||
NotBefore: jwt.NewNumericDate(now.Add(-30 * time.Second)),
|
||||
ExpiresAt: jwt.NewNumericDate(now.Add(5 * time.Minute)),
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
||||
token.Header["kid"] = kid
|
||||
tokenResponse.IDToken, err = token.SignedString(privateKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ProviderName: "Test OIDC",
|
||||
ClientID: "oidc-client",
|
||||
ClientSecret: "oidc-secret",
|
||||
IssuerURL: issuer,
|
||||
AuthorizeURL: issuer + "/authorize",
|
||||
TokenURL: issuer + "/token",
|
||||
UserInfoURL: issuer + "/userinfo",
|
||||
JWKSURL: issuer + "/jwks",
|
||||
Scopes: "openid profile email",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
ValidateIDToken: true,
|
||||
AllowedSigningAlgs: "RS256",
|
||||
ClockSkewSeconds: 120,
|
||||
RequireEmailVerified: false,
|
||||
}
|
||||
return cfg, server.Close
|
||||
}
|
||||
|
||||
61
backend/internal/handler/auth_session_revocation_test.go
Normal file
61
backend/internal/handler/auth_session_revocation_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
//go:build unit
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthHandlerRevokeAllSessionsInvalidatesAccessTokens(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
repo := &userHandlerRepoStub{
|
||||
user: &service.User{
|
||||
ID: 29,
|
||||
Email: "session@example.com",
|
||||
Username: "session-user",
|
||||
Role: service.RoleUser,
|
||||
Status: service.StatusActive,
|
||||
TokenVersion: 7,
|
||||
},
|
||||
}
|
||||
refreshTokenCache := &userHandlerRefreshTokenCacheStub{}
|
||||
cfg := &config.Config{
|
||||
JWT: config.JWTConfig{
|
||||
Secret: "test-secret",
|
||||
ExpireHour: 1,
|
||||
},
|
||||
}
|
||||
authService := service.NewAuthService(nil, repo, nil, refreshTokenCache, cfg, nil, nil, nil, nil, nil, nil)
|
||||
handler := &AuthHandler{authService: authService}
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/api/v1/auth/revoke-all-sessions", nil)
|
||||
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 29})
|
||||
|
||||
handler.RevokeAllSessions(c)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
require.Equal(t, []int64{29}, refreshTokenCache.revokedUserIDs)
|
||||
require.Equal(t, int64(8), repo.user.TokenVersion)
|
||||
|
||||
var resp struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"data"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &resp))
|
||||
require.Equal(t, 0, resp.Code)
|
||||
require.Equal(t, "All sessions have been revoked. Please log in again.", resp.Data.Message)
|
||||
}
|
||||
1349
backend/internal/handler/auth_wechat_oauth.go
Normal file
1349
backend/internal/handler/auth_wechat_oauth.go
Normal file
File diff suppressed because it is too large
Load Diff
1497
backend/internal/handler/auth_wechat_oauth_test.go
Normal file
1497
backend/internal/handler/auth_wechat_oauth_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ func UserFromServiceShallow(u *service.User) *User {
|
||||
Concurrency: u.Concurrency,
|
||||
Status: u.Status,
|
||||
AllowedGroups: u.AllowedGroups,
|
||||
LastActiveAt: u.LastActiveAt,
|
||||
CreatedAt: u.CreatedAt,
|
||||
UpdatedAt: u.UpdatedAt,
|
||||
BalanceNotifyEnabled: u.BalanceNotifyEnabled,
|
||||
@ -66,6 +67,7 @@ func UserFromServiceAdmin(u *service.User) *AdminUser {
|
||||
return &AdminUser{
|
||||
User: *base,
|
||||
Notes: u.Notes,
|
||||
LastUsedAt: u.LastUsedAt,
|
||||
GroupRates: u.GroupRates,
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +51,23 @@ type SystemSettings struct {
|
||||
LinuxDoConnectClientSecretConfigured bool `json:"linuxdo_connect_client_secret_configured"`
|
||||
LinuxDoConnectRedirectURL string `json:"linuxdo_connect_redirect_url"`
|
||||
|
||||
WeChatConnectEnabled bool `json:"wechat_connect_enabled"`
|
||||
WeChatConnectAppID string `json:"wechat_connect_app_id"`
|
||||
WeChatConnectAppSecretConfigured bool `json:"wechat_connect_app_secret_configured"`
|
||||
WeChatConnectOpenAppID string `json:"wechat_connect_open_app_id"`
|
||||
WeChatConnectOpenAppSecretConfigured bool `json:"wechat_connect_open_app_secret_configured"`
|
||||
WeChatConnectMPAppID string `json:"wechat_connect_mp_app_id"`
|
||||
WeChatConnectMPAppSecretConfigured bool `json:"wechat_connect_mp_app_secret_configured"`
|
||||
WeChatConnectMobileAppID string `json:"wechat_connect_mobile_app_id"`
|
||||
WeChatConnectMobileAppSecretConfigured bool `json:"wechat_connect_mobile_app_secret_configured"`
|
||||
WeChatConnectOpenEnabled bool `json:"wechat_connect_open_enabled"`
|
||||
WeChatConnectMPEnabled bool `json:"wechat_connect_mp_enabled"`
|
||||
WeChatConnectMobileEnabled bool `json:"wechat_connect_mobile_enabled"`
|
||||
WeChatConnectMode string `json:"wechat_connect_mode"`
|
||||
WeChatConnectScopes string `json:"wechat_connect_scopes"`
|
||||
WeChatConnectRedirectURL string `json:"wechat_connect_redirect_url"`
|
||||
WeChatConnectFrontendRedirectURL string `json:"wechat_connect_frontend_redirect_url"`
|
||||
|
||||
OIDCConnectEnabled bool `json:"oidc_connect_enabled"`
|
||||
OIDCConnectProviderName string `json:"oidc_connect_provider_name"`
|
||||
OIDCConnectClientID string `json:"oidc_connect_client_id"`
|
||||
@ -127,6 +144,15 @@ type SystemSettings struct {
|
||||
// Web Search Emulation
|
||||
WebSearchEmulationEnabled bool `json:"web_search_emulation_enabled"`
|
||||
|
||||
// Payment visible method routing
|
||||
PaymentVisibleMethodAlipaySource string `json:"payment_visible_method_alipay_source"`
|
||||
PaymentVisibleMethodWxpaySource string `json:"payment_visible_method_wxpay_source"`
|
||||
PaymentVisibleMethodAlipayEnabled bool `json:"payment_visible_method_alipay_enabled"`
|
||||
PaymentVisibleMethodWxpayEnabled bool `json:"payment_visible_method_wxpay_enabled"`
|
||||
|
||||
// OpenAI account scheduling
|
||||
OpenAIAdvancedSchedulerEnabled bool `json:"openai_advanced_scheduler_enabled"`
|
||||
|
||||
// Payment configuration
|
||||
PaymentEnabled bool `json:"payment_enabled"`
|
||||
PaymentMinAmount float64 `json:"payment_min_amount"`
|
||||
@ -167,6 +193,7 @@ type DefaultSubscriptionSetting struct {
|
||||
type PublicSettings struct {
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
ForceEmailOnThirdPartySignup bool `json:"force_email_on_third_party_signup"`
|
||||
RegistrationEmailSuffixWhitelist []string `json:"registration_email_suffix_whitelist"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
@ -189,6 +216,10 @@ type PublicSettings struct {
|
||||
CustomMenuItems []CustomMenuItem `json:"custom_menu_items"`
|
||||
CustomEndpoints []CustomEndpoint `json:"custom_endpoints"`
|
||||
LinuxDoOAuthEnabled bool `json:"linuxdo_oauth_enabled"`
|
||||
WeChatOAuthEnabled bool `json:"wechat_oauth_enabled"`
|
||||
WeChatOAuthOpenEnabled bool `json:"wechat_oauth_open_enabled"`
|
||||
WeChatOAuthMPEnabled bool `json:"wechat_oauth_mp_enabled"`
|
||||
WeChatOAuthMobileEnabled bool `json:"wechat_oauth_mobile_enabled"`
|
||||
OIDCOAuthEnabled bool `json:"oidc_oauth_enabled"`
|
||||
OIDCOAuthProviderName string `json:"oidc_oauth_provider_name"`
|
||||
SoraClientEnabled bool `json:"sora_client_enabled"`
|
||||
|
||||
@ -7,16 +7,17 @@ import (
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
Balance float64 `json:"balance"`
|
||||
Concurrency int `json:"concurrency"`
|
||||
Status string `json:"status"`
|
||||
AllowedGroups []int64 `json:"allowed_groups"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
Balance float64 `json:"balance"`
|
||||
Concurrency int `json:"concurrency"`
|
||||
Status string `json:"status"`
|
||||
AllowedGroups []int64 `json:"allowed_groups"`
|
||||
LastActiveAt *time.Time `json:"last_active_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// 余额不足通知
|
||||
BalanceNotifyEnabled bool `json:"balance_notify_enabled"`
|
||||
@ -34,7 +35,8 @@ type User struct {
|
||||
type AdminUser struct {
|
||||
User
|
||||
|
||||
Notes string `json:"notes"`
|
||||
Notes string `json:"notes"`
|
||||
LastUsedAt *time.Time `json:"last_used_at"`
|
||||
// GroupRates 用户专属分组倍率配置
|
||||
// map[groupID]rateMultiplier
|
||||
GroupRates map[int64]float64 `json:"group_rates,omitempty"`
|
||||
|
||||
33
backend/internal/handler/dto/user_mapper_activity_test.go
Normal file
33
backend/internal/handler/dto/user_mapper_activity_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUserFromServiceAdmin_MapsActivityTimestamps(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
lastLoginAt := time.Date(2026, time.April, 20, 10, 0, 0, 0, time.UTC)
|
||||
lastActiveAt := lastLoginAt.Add(15 * time.Minute)
|
||||
lastUsedAt := lastLoginAt.Add(45 * time.Minute)
|
||||
|
||||
out := UserFromServiceAdmin(&service.User{
|
||||
ID: 42,
|
||||
Email: "admin@example.com",
|
||||
Username: "admin",
|
||||
Role: service.RoleAdmin,
|
||||
Status: service.StatusActive,
|
||||
LastActiveAt: &lastActiveAt,
|
||||
LastUsedAt: &lastUsedAt,
|
||||
})
|
||||
|
||||
require.NotNil(t, out)
|
||||
require.NotNil(t, out.LastActiveAt)
|
||||
require.NotNil(t, out.LastUsedAt)
|
||||
require.WithinDuration(t, lastActiveAt, *out.LastActiveAt, time.Second)
|
||||
require.WithinDuration(t, lastUsedAt, *out.LastUsedAt, time.Second)
|
||||
}
|
||||
@ -15,10 +15,12 @@ import (
|
||||
// ──────────────────────────────────────────────────────────
|
||||
|
||||
const (
|
||||
EndpointMessages = "/v1/messages"
|
||||
EndpointChatCompletions = "/v1/chat/completions"
|
||||
EndpointResponses = "/v1/responses"
|
||||
EndpointGeminiModels = "/v1beta/models"
|
||||
EndpointMessages = "/v1/messages"
|
||||
EndpointChatCompletions = "/v1/chat/completions"
|
||||
EndpointResponses = "/v1/responses"
|
||||
EndpointImagesGenerations = "/v1/images/generations"
|
||||
EndpointImagesEdits = "/v1/images/edits"
|
||||
EndpointGeminiModels = "/v1beta/models"
|
||||
)
|
||||
|
||||
// gin.Context keys used by the middleware and helpers below.
|
||||
@ -44,6 +46,10 @@ func NormalizeInboundEndpoint(path string) string {
|
||||
return EndpointChatCompletions
|
||||
case strings.Contains(path, EndpointMessages):
|
||||
return EndpointMessages
|
||||
case strings.Contains(path, EndpointImagesGenerations) || strings.Contains(path, "/images/generations"):
|
||||
return EndpointImagesGenerations
|
||||
case strings.Contains(path, EndpointImagesEdits) || strings.Contains(path, "/images/edits"):
|
||||
return EndpointImagesEdits
|
||||
case strings.Contains(path, EndpointResponses):
|
||||
return EndpointResponses
|
||||
case strings.Contains(path, EndpointGeminiModels):
|
||||
@ -69,6 +75,9 @@ func DeriveUpstreamEndpoint(inbound, rawRequestPath, platform string) string {
|
||||
|
||||
switch platform {
|
||||
case service.PlatformOpenAI:
|
||||
if inbound == EndpointImagesGenerations || inbound == EndpointImagesEdits {
|
||||
return inbound
|
||||
}
|
||||
// OpenAI forwards everything to the Responses API.
|
||||
// Preserve subresource suffix (e.g. /v1/responses/compact).
|
||||
if suffix := responsesSubpathSuffix(rawRequestPath); suffix != "" {
|
||||
|
||||
@ -25,12 +25,16 @@ func TestNormalizeInboundEndpoint(t *testing.T) {
|
||||
{"/v1/messages", EndpointMessages},
|
||||
{"/v1/chat/completions", EndpointChatCompletions},
|
||||
{"/v1/responses", EndpointResponses},
|
||||
{"/v1/images/generations", EndpointImagesGenerations},
|
||||
{"/v1/images/edits", EndpointImagesEdits},
|
||||
{"/v1beta/models", EndpointGeminiModels},
|
||||
|
||||
// Prefixed paths (antigravity, openai).
|
||||
{"/antigravity/v1/messages", EndpointMessages},
|
||||
{"/openai/v1/responses", EndpointResponses},
|
||||
{"/openai/v1/responses/compact", EndpointResponses},
|
||||
{"/openai/v1/images/generations", EndpointImagesGenerations},
|
||||
{"/openai/v1/images/edits", EndpointImagesEdits},
|
||||
{"/antigravity/v1beta/models/gemini:generateContent", EndpointGeminiModels},
|
||||
|
||||
// Gin route patterns with wildcards.
|
||||
@ -73,6 +77,8 @@ func TestDeriveUpstreamEndpoint(t *testing.T) {
|
||||
{"openai responses nested", EndpointResponses, "/openai/v1/responses/compact/detail", service.PlatformOpenAI, "/v1/responses/compact/detail"},
|
||||
{"openai from messages", EndpointMessages, "/v1/messages", service.PlatformOpenAI, EndpointResponses},
|
||||
{"openai from completions", EndpointChatCompletions, "/v1/chat/completions", service.PlatformOpenAI, EndpointResponses},
|
||||
{"openai image generations", EndpointImagesGenerations, "/v1/images/generations", service.PlatformOpenAI, EndpointImagesGenerations},
|
||||
{"openai image edits", EndpointImagesEdits, "/openai/v1/images/edits", service.PlatformOpenAI, EndpointImagesEdits},
|
||||
|
||||
// Antigravity — uses inbound to pick Claude vs Gemini upstream.
|
||||
{"antigravity claude", EndpointMessages, "/antigravity/v1/messages", service.PlatformAntigravity, EndpointMessages},
|
||||
|
||||
@ -187,6 +187,11 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "previous_response_id must be a response.id (resp_*), not a message id")
|
||||
return
|
||||
}
|
||||
reqLog.Warn("openai.request_validation_failed",
|
||||
zap.String("reason", "previous_response_id_requires_wsv2"),
|
||||
)
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "previous_response_id is only supported on Responses WebSocket v2")
|
||||
return
|
||||
}
|
||||
|
||||
setOpsRequestContext(c, reqModel, reqStream, body)
|
||||
@ -856,7 +861,7 @@ func (h *OpenAIGatewayHandler) validateFunctionCallOutputRequest(c *gin.Context,
|
||||
reqLog.Warn("openai.request_validation_failed",
|
||||
zap.String("reason", "function_call_output_missing_call_id"),
|
||||
)
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "function_call_output requires call_id or previous_response_id; if relying on history, ensure store=true and reuse previous_response_id")
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "function_call_output requires call_id on HTTP requests; continuation via previous_response_id is only supported on Responses WebSocket v2")
|
||||
return false
|
||||
}
|
||||
if validation.HasItemReferenceForAllCallIDs {
|
||||
@ -866,7 +871,7 @@ func (h *OpenAIGatewayHandler) validateFunctionCallOutputRequest(c *gin.Context,
|
||||
reqLog.Warn("openai.request_validation_failed",
|
||||
zap.String("reason", "function_call_output_missing_item_reference"),
|
||||
)
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "function_call_output requires item_reference ids matching each call_id, or previous_response_id/tool_call context; if relying on history, ensure store=true and reuse previous_response_id")
|
||||
h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "function_call_output requires item_reference ids matching each call_id on HTTP requests; continuation via previous_response_id is only supported on Responses WebSocket v2")
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@ -494,6 +494,64 @@ func TestOpenAIResponses_RejectsMessageIDAsPreviousResponseID(t *testing.T) {
|
||||
require.Contains(t, w.Body.String(), "previous_response_id must be a response.id")
|
||||
}
|
||||
|
||||
func TestOpenAIResponses_RejectsHTTPContinuationPreviousResponseID(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/openai/v1/responses", strings.NewReader(
|
||||
`{"model":"gpt-5.1","stream":false,"previous_response_id":"resp_123456","input":[{"type":"input_text","text":"hello"}]}`,
|
||||
))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
groupID := int64(2)
|
||||
c.Set(string(middleware.ContextKeyAPIKey), &service.APIKey{
|
||||
ID: 101,
|
||||
GroupID: &groupID,
|
||||
User: &service.User{ID: 1},
|
||||
})
|
||||
c.Set(string(middleware.ContextKeyUser), middleware.AuthSubject{
|
||||
UserID: 1,
|
||||
Concurrency: 1,
|
||||
})
|
||||
|
||||
h := newOpenAIHandlerForPreviousResponseIDValidation(t, nil)
|
||||
h.Responses(c)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, w.Code)
|
||||
require.Contains(t, w.Body.String(), "Responses WebSocket v2")
|
||||
require.Contains(t, w.Body.String(), "previous_response_id")
|
||||
}
|
||||
|
||||
func TestOpenAIResponses_FunctionCallOutputHTTPGuidanceDoesNotSuggestPreviousResponseReuse(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/openai/v1/responses", strings.NewReader(
|
||||
`{"model":"gpt-5.1","stream":false,"input":[{"type":"function_call_output","output":"{}"}]}`,
|
||||
))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
groupID := int64(2)
|
||||
c.Set(string(middleware.ContextKeyAPIKey), &service.APIKey{
|
||||
ID: 101,
|
||||
GroupID: &groupID,
|
||||
User: &service.User{ID: 1},
|
||||
})
|
||||
c.Set(string(middleware.ContextKeyUser), middleware.AuthSubject{
|
||||
UserID: 1,
|
||||
Concurrency: 1,
|
||||
})
|
||||
|
||||
h := newOpenAIHandlerForPreviousResponseIDValidation(t, nil)
|
||||
h.Responses(c)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, w.Code)
|
||||
require.Contains(t, w.Body.String(), "Responses WebSocket v2")
|
||||
require.NotContains(t, w.Body.String(), "reuse previous_response_id")
|
||||
}
|
||||
|
||||
func TestOpenAIResponsesWebSocket_SetsClientTransportWSWhenUpgradeValid(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user