Merge PR #142: feat: 多平台网关优化与用户系统增强

主要功能:
- Gemini OAuth 配额系统优化:Google One tier 自动推断
- Antigravity 网关增强:Thinking Block 重试、Claude 模型 signature 透传
- 账号调度改进:临时不可调度功能、负载感知调度优化
- 前端用户体验:账号管理界面优化、使用教程改进

冲突解决:保留 handleUpstreamError 的 prefix 参数和日志记录能力,
同时合并 PR 的 thinking block 重试和 model fallback 功能。
This commit is contained in:
shaw
2026-01-04 20:30:19 +08:00
183 changed files with 8223 additions and 3839 deletions

3
.gitignore vendored
View File

@@ -48,6 +48,7 @@ pnpm-debug.log*
.env.*.local
*.env
!.env.example
docker-compose.override.yml
# ===================
# IDE / 编辑器
@@ -118,3 +119,5 @@ docs/
code-reviews/
AGENTS.md
backend/cmd/server/server
deploy/docker-compose.override.yml
.gocache/

View File

@@ -83,7 +83,14 @@ linters:
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"]
# Run `GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck` to see all available checks and enabled by config checks.
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
# Temporarily disable style checks to allow CI to pass
checks:
- all
- -ST1000 # Package comment format
- -ST1003 # Poorly chosen identifier (ApiKey vs APIKey)
- -ST1020 # Comment on exported method format
- -ST1021 # Comment on exported type format
- -ST1022 # Comment on exported variable format
# Invalid regular expression.
# https://staticcheck.dev/docs/checks/#SA1000
- SA1000
@@ -369,15 +376,7 @@ linters:
# Ineffectual Go compiler directive.
# https://staticcheck.dev/docs/checks/#SA9009
- SA9009
# Incorrect or missing package comment.
# https://staticcheck.dev/docs/checks/#ST1000
- ST1000
# Dot imports are discouraged.
# https://staticcheck.dev/docs/checks/#ST1001
- ST1001
# Poorly chosen identifier.
# https://staticcheck.dev/docs/checks/#ST1003
- ST1003
# NOTE: ST1000, ST1001, ST1003, ST1020, ST1021, ST1022 are disabled above
# Incorrectly formatted error string.
# https://staticcheck.dev/docs/checks/#ST1005
- ST1005
@@ -411,15 +410,7 @@ linters:
# Importing the same package multiple times.
# https://staticcheck.dev/docs/checks/#ST1019
- ST1019
# The documentation of an exported function should start with the function's name.
# https://staticcheck.dev/docs/checks/#ST1020
- ST1020
# The documentation of an exported type should start with type's name.
# https://staticcheck.dev/docs/checks/#ST1021
- ST1021
# The documentation of an exported variable or constant should start with variable's name.
# https://staticcheck.dev/docs/checks/#ST1022
- ST1022
# NOTE: ST1020, ST1021, ST1022 removed (disabled above)
# Redundant type in variable declaration.
# https://staticcheck.dev/docs/checks/#ST1023
- ST1023

View File

@@ -0,0 +1,57 @@
package main
import (
"context"
"flag"
"fmt"
"log"
"time"
_ "github.com/Wei-Shaw/sub2api/ent/runtime"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/repository"
"github.com/Wei-Shaw/sub2api/internal/service"
)
func main() {
email := flag.String("email", "", "Admin email to issue a JWT for (defaults to first active admin)")
flag.Parse()
cfg, err := config.Load()
if err != nil {
log.Fatalf("failed to load config: %v", err)
}
client, sqlDB, err := repository.InitEnt(cfg)
if err != nil {
log.Fatalf("failed to init db: %v", err)
}
defer func() {
if err := client.Close(); err != nil {
log.Printf("failed to close db: %v", err)
}
}()
userRepo := repository.NewUserRepository(client, sqlDB)
authService := service.NewAuthService(userRepo, cfg, nil, nil, nil, nil)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var user *service.User
if *email != "" {
user, err = userRepo.GetByEmail(ctx, *email)
} else {
user, err = userRepo.GetFirstAdmin(ctx)
}
if err != nil {
log.Fatalf("failed to resolve admin user: %v", err)
}
token, err := authService.GenerateToken(user)
if err != nil {
log.Fatalf("failed to generate token: %v", err)
}
fmt.Printf("ADMIN_EMAIL=%s\nADMIN_USER_ID=%d\nJWT=%s\n", user.Email, user.ID, token)
}

View File

@@ -55,14 +55,14 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
userService := service.NewUserService(userRepository)
authHandler := handler.NewAuthHandler(configConfig, authService, userService)
userHandler := handler.NewUserHandler(userService)
apiKeyRepository := repository.NewApiKeyRepository(client)
apiKeyRepository := repository.NewAPIKeyRepository(client)
groupRepository := repository.NewGroupRepository(client, db)
userSubscriptionRepository := repository.NewUserSubscriptionRepository(client)
apiKeyCache := repository.NewApiKeyCache(redisClient)
apiKeyService := service.NewApiKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
apiKeyCache := repository.NewAPIKeyCache(redisClient)
apiKeyService := service.NewAPIKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
usageLogRepository := repository.NewUsageLogRepository(client, db)
usageService := service.NewUsageService(usageLogRepository, userRepository)
usageService := service.NewUsageService(usageLogRepository, userRepository, client)
usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
redeemCodeRepository := repository.NewRedeemCodeRepository(client)
billingCache := repository.NewBillingCache(redisClient)
@@ -88,7 +88,8 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
geminiCliCodeAssistClient := repository.NewGeminiCliCodeAssistClient()
geminiOAuthService := service.NewGeminiOAuthService(proxyRepository, geminiOAuthClient, geminiCliCodeAssistClient, configConfig)
geminiQuotaService := service.NewGeminiQuotaService(configConfig, settingRepository)
rateLimitService := service.NewRateLimitService(accountRepository, usageLogRepository, configConfig, geminiQuotaService)
tempUnschedCache := repository.NewTempUnschedCache(redisClient)
rateLimitService := service.NewRateLimitService(accountRepository, usageLogRepository, configConfig, geminiQuotaService, tempUnschedCache)
claudeUsageFetcher := repository.NewClaudeUsageFetcher()
antigravityQuotaFetcher := service.NewAntigravityQuotaFetcher(proxyRepository)
usageCache := service.NewUsageCache()
@@ -99,7 +100,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
antigravityOAuthService := service.NewAntigravityOAuthService(proxyRepository)
antigravityTokenProvider := service.NewAntigravityTokenProvider(accountRepository, geminiTokenCache, antigravityOAuthService)
httpUpstream := repository.NewHTTPUpstream(configConfig)
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, antigravityTokenProvider, rateLimitService, httpUpstream)
antigravityGatewayService := service.NewAntigravityGatewayService(accountRepository, gatewayCache, antigravityTokenProvider, rateLimitService, httpUpstream, settingService)
accountTestService := service.NewAccountTestService(accountRepository, geminiTokenProvider, antigravityGatewayService, httpUpstream)
concurrencyCache := repository.ProvideConcurrencyCache(redisClient, configConfig)
concurrencyService := service.ProvideConcurrencyService(concurrencyCache, accountRepository, configConfig)
@@ -143,7 +144,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler)
jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService)
adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService)
apiKeyAuthMiddleware := middleware.NewApiKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
apiKeyAuthMiddleware := middleware.NewAPIKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
engine := server.ProvideRouter(configConfig, handlers, jwtAuthMiddleware, adminAuthMiddleware, apiKeyAuthMiddleware, apiKeyService, subscriptionService)
httpServer := server.ProvideHTTPServer(configConfig, engine)
tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, configConfig)

View File

@@ -14,8 +14,8 @@ import (
"github.com/Wei-Shaw/sub2api/ent/user"
)
// ApiKey is the model entity for the ApiKey schema.
type ApiKey struct {
// APIKey is the model entity for the APIKey schema.
type APIKey struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
@@ -36,13 +36,13 @@ type ApiKey struct {
// Status holds the value of the "status" field.
Status string `json:"status,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the ApiKeyQuery when eager-loading is set.
Edges ApiKeyEdges `json:"edges"`
// The values are being populated by the APIKeyQuery when eager-loading is set.
Edges APIKeyEdges `json:"edges"`
selectValues sql.SelectValues
}
// ApiKeyEdges holds the relations/edges for other nodes in the graph.
type ApiKeyEdges struct {
// APIKeyEdges holds the relations/edges for other nodes in the graph.
type APIKeyEdges struct {
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// Group holds the value of the group edge.
@@ -56,7 +56,7 @@ type ApiKeyEdges struct {
// UserOrErr returns the User value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ApiKeyEdges) UserOrErr() (*User, error) {
func (e APIKeyEdges) UserOrErr() (*User, error) {
if e.User != nil {
return e.User, nil
} else if e.loadedTypes[0] {
@@ -67,7 +67,7 @@ func (e ApiKeyEdges) UserOrErr() (*User, error) {
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ApiKeyEdges) GroupOrErr() (*Group, error) {
func (e APIKeyEdges) GroupOrErr() (*Group, error) {
if e.Group != nil {
return e.Group, nil
} else if e.loadedTypes[1] {
@@ -78,7 +78,7 @@ func (e ApiKeyEdges) GroupOrErr() (*Group, error) {
// UsageLogsOrErr returns the UsageLogs value or an error if the edge
// was not loaded in eager-loading.
func (e ApiKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
func (e APIKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
if e.loadedTypes[2] {
return e.UsageLogs, nil
}
@@ -86,7 +86,7 @@ func (e ApiKeyEdges) UsageLogsOrErr() ([]*UsageLog, error) {
}
// scanValues returns the types for scanning values from sql.Rows.
func (*ApiKey) scanValues(columns []string) ([]any, error) {
func (*APIKey) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
@@ -104,8 +104,8 @@ func (*ApiKey) scanValues(columns []string) ([]any, error) {
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the ApiKey fields.
func (_m *ApiKey) assignValues(columns []string, values []any) error {
// to the APIKey fields.
func (_m *APIKey) 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)
}
@@ -174,49 +174,49 @@ func (_m *ApiKey) assignValues(columns []string, values []any) error {
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the ApiKey.
// Value returns the ent.Value that was dynamically selected and assigned to the APIKey.
// This includes values selected through modifiers, order, etc.
func (_m *ApiKey) Value(name string) (ent.Value, error) {
func (_m *APIKey) Value(name string) (ent.Value, error) {
return _m.selectValues.Get(name)
}
// QueryUser queries the "user" edge of the ApiKey entity.
func (_m *ApiKey) QueryUser() *UserQuery {
return NewApiKeyClient(_m.config).QueryUser(_m)
// QueryUser queries the "user" edge of the APIKey entity.
func (_m *APIKey) QueryUser() *UserQuery {
return NewAPIKeyClient(_m.config).QueryUser(_m)
}
// QueryGroup queries the "group" edge of the ApiKey entity.
func (_m *ApiKey) QueryGroup() *GroupQuery {
return NewApiKeyClient(_m.config).QueryGroup(_m)
// QueryGroup queries the "group" edge of the APIKey entity.
func (_m *APIKey) QueryGroup() *GroupQuery {
return NewAPIKeyClient(_m.config).QueryGroup(_m)
}
// QueryUsageLogs queries the "usage_logs" edge of the ApiKey entity.
func (_m *ApiKey) QueryUsageLogs() *UsageLogQuery {
return NewApiKeyClient(_m.config).QueryUsageLogs(_m)
// QueryUsageLogs queries the "usage_logs" edge of the APIKey entity.
func (_m *APIKey) QueryUsageLogs() *UsageLogQuery {
return NewAPIKeyClient(_m.config).QueryUsageLogs(_m)
}
// Update returns a builder for updating this ApiKey.
// Note that you need to call ApiKey.Unwrap() before calling this method if this ApiKey
// Update returns a builder for updating this APIKey.
// Note that you need to call APIKey.Unwrap() before calling this method if this APIKey
// was returned from a transaction, and the transaction was committed or rolled back.
func (_m *ApiKey) Update() *ApiKeyUpdateOne {
return NewApiKeyClient(_m.config).UpdateOne(_m)
func (_m *APIKey) Update() *APIKeyUpdateOne {
return NewAPIKeyClient(_m.config).UpdateOne(_m)
}
// Unwrap unwraps the ApiKey entity that was returned from a transaction after it was closed,
// Unwrap unwraps the APIKey entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (_m *ApiKey) Unwrap() *ApiKey {
func (_m *APIKey) Unwrap() *APIKey {
_tx, ok := _m.config.driver.(*txDriver)
if !ok {
panic("ent: ApiKey is not a transactional entity")
panic("ent: APIKey is not a transactional entity")
}
_m.config.driver = _tx.drv
return _m
}
// String implements the fmt.Stringer.
func (_m *ApiKey) String() string {
func (_m *APIKey) String() string {
var builder strings.Builder
builder.WriteString("ApiKey(")
builder.WriteString("APIKey(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("created_at=")
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
@@ -249,5 +249,5 @@ func (_m *ApiKey) String() string {
return builder.String()
}
// ApiKeys is a parsable slice of ApiKey.
type ApiKeys []*ApiKey
// APIKeys is a parsable slice of APIKey.
type APIKeys []*APIKey

View File

@@ -109,7 +109,7 @@ var (
StatusValidator func(string) error
)
// OrderOption defines the ordering options for the ApiKey queries.
// OrderOption defines the ordering options for the APIKey queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.

View File

@@ -11,468 +11,468 @@ import (
)
// ID filters vertices based on their ID field.
func ID(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldID, id))
func ID(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldID, id))
func IDEQ(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldID, id))
func IDNEQ(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldID, ids...))
func IDIn(ids ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldID, ids...))
func IDNotIn(ids ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldID, id))
func IDGT(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldID, id))
func IDGTE(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldID, id))
func IDLT(id int64) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldID, id))
func IDLTE(id int64) predicate.APIKey {
return predicate.APIKey(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.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldCreatedAt, v))
func CreatedAt(v time.Time) predicate.APIKey {
return predicate.APIKey(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.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldUpdatedAt, v))
func UpdatedAt(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldUpdatedAt, v))
}
// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
func DeletedAt(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldDeletedAt, v))
func DeletedAt(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldDeletedAt, v))
}
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
func UserID(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldUserID, v))
func UserID(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldUserID, v))
}
// Key applies equality check predicate on the "key" field. It's identical to KeyEQ.
func Key(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldKey, v))
func Key(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldKey, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldName, v))
func Name(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldName, v))
}
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
func GroupID(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldGroupID, v))
func GroupID(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldGroupID, v))
}
// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
func Status(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldStatus, v))
func Status(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldCreatedAt, v))
func CreatedAtEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldCreatedAt, v))
func CreatedAtNEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldCreatedAt, vs...))
func CreatedAtIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldCreatedAt, vs...))
func CreatedAtNotIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldCreatedAt, v))
func CreatedAtGT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldCreatedAt, v))
func CreatedAtGTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldCreatedAt, v))
func CreatedAtLT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldCreatedAt, v))
func CreatedAtLTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldUpdatedAt, v))
func UpdatedAtEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldUpdatedAt, v))
func UpdatedAtNEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldUpdatedAt, vs...))
func UpdatedAtIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldUpdatedAt, vs...))
func UpdatedAtNotIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldUpdatedAt, v))
func UpdatedAtGT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldUpdatedAt, v))
func UpdatedAtGTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldUpdatedAt, v))
func UpdatedAtLT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldUpdatedAt, v))
func UpdatedAtLTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldUpdatedAt, v))
}
// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
func DeletedAtEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldDeletedAt, v))
func DeletedAtEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldDeletedAt, v))
}
// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
func DeletedAtNEQ(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldDeletedAt, v))
func DeletedAtNEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldDeletedAt, v))
}
// DeletedAtIn applies the In predicate on the "deleted_at" field.
func DeletedAtIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldDeletedAt, vs...))
func DeletedAtIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldDeletedAt, vs...))
}
// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
func DeletedAtNotIn(vs ...time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldDeletedAt, vs...))
func DeletedAtNotIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldDeletedAt, vs...))
}
// DeletedAtGT applies the GT predicate on the "deleted_at" field.
func DeletedAtGT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldDeletedAt, v))
func DeletedAtGT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldDeletedAt, v))
}
// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
func DeletedAtGTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldDeletedAt, v))
func DeletedAtGTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldDeletedAt, v))
}
// DeletedAtLT applies the LT predicate on the "deleted_at" field.
func DeletedAtLT(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldDeletedAt, v))
func DeletedAtLT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldDeletedAt, v))
}
// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
func DeletedAtLTE(v time.Time) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldDeletedAt, v))
func DeletedAtLTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldDeletedAt, v))
}
// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
func DeletedAtIsNil() predicate.ApiKey {
return predicate.ApiKey(sql.FieldIsNull(FieldDeletedAt))
func DeletedAtIsNil() predicate.APIKey {
return predicate.APIKey(sql.FieldIsNull(FieldDeletedAt))
}
// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
func DeletedAtNotNil() predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotNull(FieldDeletedAt))
func DeletedAtNotNil() predicate.APIKey {
return predicate.APIKey(sql.FieldNotNull(FieldDeletedAt))
}
// UserIDEQ applies the EQ predicate on the "user_id" field.
func UserIDEQ(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldUserID, v))
func UserIDEQ(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldUserID, v))
}
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
func UserIDNEQ(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldUserID, v))
func UserIDNEQ(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldUserID, v))
}
// UserIDIn applies the In predicate on the "user_id" field.
func UserIDIn(vs ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldUserID, vs...))
func UserIDIn(vs ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldUserID, vs...))
}
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
func UserIDNotIn(vs ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldUserID, vs...))
func UserIDNotIn(vs ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldUserID, vs...))
}
// KeyEQ applies the EQ predicate on the "key" field.
func KeyEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldKey, v))
func KeyEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldKey, v))
}
// KeyNEQ applies the NEQ predicate on the "key" field.
func KeyNEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldKey, v))
func KeyNEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldKey, v))
}
// KeyIn applies the In predicate on the "key" field.
func KeyIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldKey, vs...))
func KeyIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldKey, vs...))
}
// KeyNotIn applies the NotIn predicate on the "key" field.
func KeyNotIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldKey, vs...))
func KeyNotIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldKey, vs...))
}
// KeyGT applies the GT predicate on the "key" field.
func KeyGT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldKey, v))
func KeyGT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldKey, v))
}
// KeyGTE applies the GTE predicate on the "key" field.
func KeyGTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldKey, v))
func KeyGTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldKey, v))
}
// KeyLT applies the LT predicate on the "key" field.
func KeyLT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldKey, v))
func KeyLT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldKey, v))
}
// KeyLTE applies the LTE predicate on the "key" field.
func KeyLTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldKey, v))
func KeyLTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldKey, v))
}
// KeyContains applies the Contains predicate on the "key" field.
func KeyContains(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContains(FieldKey, v))
func KeyContains(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContains(FieldKey, v))
}
// KeyHasPrefix applies the HasPrefix predicate on the "key" field.
func KeyHasPrefix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasPrefix(FieldKey, v))
func KeyHasPrefix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasPrefix(FieldKey, v))
}
// KeyHasSuffix applies the HasSuffix predicate on the "key" field.
func KeyHasSuffix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasSuffix(FieldKey, v))
func KeyHasSuffix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasSuffix(FieldKey, v))
}
// KeyEqualFold applies the EqualFold predicate on the "key" field.
func KeyEqualFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEqualFold(FieldKey, v))
func KeyEqualFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEqualFold(FieldKey, v))
}
// KeyContainsFold applies the ContainsFold predicate on the "key" field.
func KeyContainsFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContainsFold(FieldKey, v))
func KeyContainsFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContainsFold(FieldKey, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldName, v))
func NameEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldName, v))
func NameNEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldName, vs...))
func NameIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldName, vs...))
func NameNotIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldName, v))
func NameGT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldName, v))
func NameGTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldName, v))
func NameLT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldName, v))
func NameLTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContains(FieldName, v))
func NameContains(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasPrefix(FieldName, v))
func NameHasPrefix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasSuffix(FieldName, v))
func NameHasSuffix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEqualFold(FieldName, v))
func NameEqualFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContainsFold(FieldName, v))
func NameContainsFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContainsFold(FieldName, v))
}
// GroupIDEQ applies the EQ predicate on the "group_id" field.
func GroupIDEQ(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldGroupID, v))
func GroupIDEQ(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldGroupID, v))
}
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
func GroupIDNEQ(v int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldGroupID, v))
func GroupIDNEQ(v int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldGroupID, v))
}
// GroupIDIn applies the In predicate on the "group_id" field.
func GroupIDIn(vs ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldGroupID, vs...))
func GroupIDIn(vs ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldGroupID, vs...))
}
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
func GroupIDNotIn(vs ...int64) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldGroupID, vs...))
func GroupIDNotIn(vs ...int64) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldGroupID, vs...))
}
// GroupIDIsNil applies the IsNil predicate on the "group_id" field.
func GroupIDIsNil() predicate.ApiKey {
return predicate.ApiKey(sql.FieldIsNull(FieldGroupID))
func GroupIDIsNil() predicate.APIKey {
return predicate.APIKey(sql.FieldIsNull(FieldGroupID))
}
// GroupIDNotNil applies the NotNil predicate on the "group_id" field.
func GroupIDNotNil() predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotNull(FieldGroupID))
func GroupIDNotNil() predicate.APIKey {
return predicate.APIKey(sql.FieldNotNull(FieldGroupID))
}
// StatusEQ applies the EQ predicate on the "status" field.
func StatusEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEQ(FieldStatus, v))
func StatusEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
}
// StatusNEQ applies the NEQ predicate on the "status" field.
func StatusNEQ(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNEQ(FieldStatus, v))
func StatusNEQ(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldStatus, v))
}
// StatusIn applies the In predicate on the "status" field.
func StatusIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldIn(FieldStatus, vs...))
func StatusIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldStatus, vs...))
}
// StatusNotIn applies the NotIn predicate on the "status" field.
func StatusNotIn(vs ...string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldNotIn(FieldStatus, vs...))
func StatusNotIn(vs ...string) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldStatus, vs...))
}
// StatusGT applies the GT predicate on the "status" field.
func StatusGT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGT(FieldStatus, v))
func StatusGT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldStatus, v))
}
// StatusGTE applies the GTE predicate on the "status" field.
func StatusGTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldGTE(FieldStatus, v))
func StatusGTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldStatus, v))
}
// StatusLT applies the LT predicate on the "status" field.
func StatusLT(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLT(FieldStatus, v))
func StatusLT(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldStatus, v))
}
// StatusLTE applies the LTE predicate on the "status" field.
func StatusLTE(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldLTE(FieldStatus, v))
func StatusLTE(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldStatus, v))
}
// StatusContains applies the Contains predicate on the "status" field.
func StatusContains(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContains(FieldStatus, v))
func StatusContains(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContains(FieldStatus, v))
}
// StatusHasPrefix applies the HasPrefix predicate on the "status" field.
func StatusHasPrefix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasPrefix(FieldStatus, v))
func StatusHasPrefix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasPrefix(FieldStatus, v))
}
// StatusHasSuffix applies the HasSuffix predicate on the "status" field.
func StatusHasSuffix(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldHasSuffix(FieldStatus, v))
func StatusHasSuffix(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldHasSuffix(FieldStatus, v))
}
// StatusEqualFold applies the EqualFold predicate on the "status" field.
func StatusEqualFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldEqualFold(FieldStatus, v))
func StatusEqualFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEqualFold(FieldStatus, v))
}
// StatusContainsFold applies the ContainsFold predicate on the "status" field.
func StatusContainsFold(v string) predicate.ApiKey {
return predicate.ApiKey(sql.FieldContainsFold(FieldStatus, v))
func StatusContainsFold(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldContainsFold(FieldStatus, v))
}
// HasUser applies the HasEdge predicate on the "user" edge.
func HasUser() predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasUser() predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
@@ -482,8 +482,8 @@ func HasUser() predicate.ApiKey {
}
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
func HasUserWith(preds ...predicate.User) predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasUserWith(preds ...predicate.User) predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := newUserStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
@@ -494,8 +494,8 @@ func HasUserWith(preds ...predicate.User) predicate.ApiKey {
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasGroup() predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
@@ -505,8 +505,8 @@ func HasGroup() predicate.ApiKey {
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasGroupWith(preds ...predicate.Group) predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := newGroupStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
@@ -517,8 +517,8 @@ func HasGroupWith(preds ...predicate.Group) predicate.ApiKey {
}
// HasUsageLogs applies the HasEdge predicate on the "usage_logs" edge.
func HasUsageLogs() predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasUsageLogs() predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, UsageLogsTable, UsageLogsColumn),
@@ -528,8 +528,8 @@ func HasUsageLogs() predicate.ApiKey {
}
// HasUsageLogsWith applies the HasEdge predicate on the "usage_logs" edge with a given conditions (other predicates).
func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.ApiKey {
return predicate.ApiKey(func(s *sql.Selector) {
func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
step := newUsageLogsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
@@ -540,16 +540,16 @@ func HasUsageLogsWith(preds ...predicate.UsageLog) predicate.ApiKey {
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.ApiKey) predicate.ApiKey {
return predicate.ApiKey(sql.AndPredicates(predicates...))
func And(predicates ...predicate.APIKey) predicate.APIKey {
return predicate.APIKey(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.ApiKey) predicate.ApiKey {
return predicate.ApiKey(sql.OrPredicates(predicates...))
func Or(predicates ...predicate.APIKey) predicate.APIKey {
return predicate.APIKey(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.ApiKey) predicate.ApiKey {
return predicate.ApiKey(sql.NotPredicates(p))
func Not(p predicate.APIKey) predicate.APIKey {
return predicate.APIKey(sql.NotPredicates(p))
}

View File

@@ -17,22 +17,22 @@ import (
"github.com/Wei-Shaw/sub2api/ent/user"
)
// ApiKeyCreate is the builder for creating a ApiKey entity.
type ApiKeyCreate struct {
// APIKeyCreate is the builder for creating a APIKey entity.
type APIKeyCreate struct {
config
mutation *ApiKeyMutation
mutation *APIKeyMutation
hooks []Hook
conflict []sql.ConflictOption
}
// SetCreatedAt sets the "created_at" field.
func (_c *ApiKeyCreate) SetCreatedAt(v time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetCreatedAt(v time.Time) *APIKeyCreate {
_c.mutation.SetCreatedAt(v)
return _c
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (_c *ApiKeyCreate) SetNillableCreatedAt(v *time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetNillableCreatedAt(v *time.Time) *APIKeyCreate {
if v != nil {
_c.SetCreatedAt(*v)
}
@@ -40,13 +40,13 @@ func (_c *ApiKeyCreate) SetNillableCreatedAt(v *time.Time) *ApiKeyCreate {
}
// SetUpdatedAt sets the "updated_at" field.
func (_c *ApiKeyCreate) SetUpdatedAt(v time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetUpdatedAt(v time.Time) *APIKeyCreate {
_c.mutation.SetUpdatedAt(v)
return _c
}
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
func (_c *ApiKeyCreate) SetNillableUpdatedAt(v *time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetNillableUpdatedAt(v *time.Time) *APIKeyCreate {
if v != nil {
_c.SetUpdatedAt(*v)
}
@@ -54,13 +54,13 @@ func (_c *ApiKeyCreate) SetNillableUpdatedAt(v *time.Time) *ApiKeyCreate {
}
// SetDeletedAt sets the "deleted_at" field.
func (_c *ApiKeyCreate) SetDeletedAt(v time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetDeletedAt(v time.Time) *APIKeyCreate {
_c.mutation.SetDeletedAt(v)
return _c
}
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
func (_c *ApiKeyCreate) SetNillableDeletedAt(v *time.Time) *ApiKeyCreate {
func (_c *APIKeyCreate) SetNillableDeletedAt(v *time.Time) *APIKeyCreate {
if v != nil {
_c.SetDeletedAt(*v)
}
@@ -68,31 +68,31 @@ func (_c *ApiKeyCreate) SetNillableDeletedAt(v *time.Time) *ApiKeyCreate {
}
// SetUserID sets the "user_id" field.
func (_c *ApiKeyCreate) SetUserID(v int64) *ApiKeyCreate {
func (_c *APIKeyCreate) SetUserID(v int64) *APIKeyCreate {
_c.mutation.SetUserID(v)
return _c
}
// SetKey sets the "key" field.
func (_c *ApiKeyCreate) SetKey(v string) *ApiKeyCreate {
func (_c *APIKeyCreate) SetKey(v string) *APIKeyCreate {
_c.mutation.SetKey(v)
return _c
}
// SetName sets the "name" field.
func (_c *ApiKeyCreate) SetName(v string) *ApiKeyCreate {
func (_c *APIKeyCreate) SetName(v string) *APIKeyCreate {
_c.mutation.SetName(v)
return _c
}
// SetGroupID sets the "group_id" field.
func (_c *ApiKeyCreate) SetGroupID(v int64) *ApiKeyCreate {
func (_c *APIKeyCreate) SetGroupID(v int64) *APIKeyCreate {
_c.mutation.SetGroupID(v)
return _c
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (_c *ApiKeyCreate) SetNillableGroupID(v *int64) *ApiKeyCreate {
func (_c *APIKeyCreate) SetNillableGroupID(v *int64) *APIKeyCreate {
if v != nil {
_c.SetGroupID(*v)
}
@@ -100,13 +100,13 @@ func (_c *ApiKeyCreate) SetNillableGroupID(v *int64) *ApiKeyCreate {
}
// SetStatus sets the "status" field.
func (_c *ApiKeyCreate) SetStatus(v string) *ApiKeyCreate {
func (_c *APIKeyCreate) SetStatus(v string) *APIKeyCreate {
_c.mutation.SetStatus(v)
return _c
}
// SetNillableStatus sets the "status" field if the given value is not nil.
func (_c *ApiKeyCreate) SetNillableStatus(v *string) *ApiKeyCreate {
func (_c *APIKeyCreate) SetNillableStatus(v *string) *APIKeyCreate {
if v != nil {
_c.SetStatus(*v)
}
@@ -114,23 +114,23 @@ func (_c *ApiKeyCreate) SetNillableStatus(v *string) *ApiKeyCreate {
}
// SetUser sets the "user" edge to the User entity.
func (_c *ApiKeyCreate) SetUser(v *User) *ApiKeyCreate {
func (_c *APIKeyCreate) SetUser(v *User) *APIKeyCreate {
return _c.SetUserID(v.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (_c *ApiKeyCreate) SetGroup(v *Group) *ApiKeyCreate {
func (_c *APIKeyCreate) SetGroup(v *Group) *APIKeyCreate {
return _c.SetGroupID(v.ID)
}
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
func (_c *ApiKeyCreate) AddUsageLogIDs(ids ...int64) *ApiKeyCreate {
func (_c *APIKeyCreate) AddUsageLogIDs(ids ...int64) *APIKeyCreate {
_c.mutation.AddUsageLogIDs(ids...)
return _c
}
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
func (_c *ApiKeyCreate) AddUsageLogs(v ...*UsageLog) *ApiKeyCreate {
func (_c *APIKeyCreate) AddUsageLogs(v ...*UsageLog) *APIKeyCreate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -138,13 +138,13 @@ func (_c *ApiKeyCreate) AddUsageLogs(v ...*UsageLog) *ApiKeyCreate {
return _c.AddUsageLogIDs(ids...)
}
// Mutation returns the ApiKeyMutation object of the builder.
func (_c *ApiKeyCreate) Mutation() *ApiKeyMutation {
// Mutation returns the APIKeyMutation object of the builder.
func (_c *APIKeyCreate) Mutation() *APIKeyMutation {
return _c.mutation
}
// Save creates the ApiKey in the database.
func (_c *ApiKeyCreate) Save(ctx context.Context) (*ApiKey, error) {
// Save creates the APIKey in the database.
func (_c *APIKeyCreate) Save(ctx context.Context) (*APIKey, error) {
if err := _c.defaults(); err != nil {
return nil, err
}
@@ -152,7 +152,7 @@ func (_c *ApiKeyCreate) Save(ctx context.Context) (*ApiKey, error) {
}
// SaveX calls Save and panics if Save returns an error.
func (_c *ApiKeyCreate) SaveX(ctx context.Context) *ApiKey {
func (_c *APIKeyCreate) SaveX(ctx context.Context) *APIKey {
v, err := _c.Save(ctx)
if err != nil {
panic(err)
@@ -161,20 +161,20 @@ func (_c *ApiKeyCreate) SaveX(ctx context.Context) *ApiKey {
}
// Exec executes the query.
func (_c *ApiKeyCreate) Exec(ctx context.Context) error {
func (_c *APIKeyCreate) Exec(ctx context.Context) error {
_, err := _c.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_c *ApiKeyCreate) ExecX(ctx context.Context) {
func (_c *APIKeyCreate) ExecX(ctx context.Context) {
if err := _c.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_c *ApiKeyCreate) defaults() error {
func (_c *APIKeyCreate) defaults() error {
if _, ok := _c.mutation.CreatedAt(); !ok {
if apikey.DefaultCreatedAt == nil {
return fmt.Errorf("ent: uninitialized apikey.DefaultCreatedAt (forgotten import ent/runtime?)")
@@ -197,47 +197,47 @@ func (_c *ApiKeyCreate) defaults() error {
}
// check runs all checks and user-defined validators on the builder.
func (_c *ApiKeyCreate) check() error {
func (_c *APIKeyCreate) check() error {
if _, ok := _c.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ApiKey.created_at"`)}
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "APIKey.created_at"`)}
}
if _, ok := _c.mutation.UpdatedAt(); !ok {
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ApiKey.updated_at"`)}
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "APIKey.updated_at"`)}
}
if _, ok := _c.mutation.UserID(); !ok {
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "ApiKey.user_id"`)}
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "APIKey.user_id"`)}
}
if _, ok := _c.mutation.Key(); !ok {
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "ApiKey.key"`)}
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "APIKey.key"`)}
}
if v, ok := _c.mutation.Key(); ok {
if err := apikey.KeyValidator(v); err != nil {
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
}
}
if _, ok := _c.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ApiKey.name"`)}
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "APIKey.name"`)}
}
if v, ok := _c.mutation.Name(); ok {
if err := apikey.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
}
}
if _, ok := _c.mutation.Status(); !ok {
return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "ApiKey.status"`)}
return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "APIKey.status"`)}
}
if v, ok := _c.mutation.Status(); ok {
if err := apikey.StatusValidator(v); err != nil {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
}
}
if len(_c.mutation.UserIDs()) == 0 {
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "ApiKey.user"`)}
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "APIKey.user"`)}
}
return nil
}
func (_c *ApiKeyCreate) sqlSave(ctx context.Context) (*ApiKey, error) {
func (_c *APIKeyCreate) sqlSave(ctx context.Context) (*APIKey, error) {
if err := _c.check(); err != nil {
return nil, err
}
@@ -255,9 +255,9 @@ func (_c *ApiKeyCreate) sqlSave(ctx context.Context) (*ApiKey, error) {
return _node, nil
}
func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
func (_c *APIKeyCreate) createSpec() (*APIKey, *sqlgraph.CreateSpec) {
var (
_node = &ApiKey{config: _c.config}
_node = &APIKey{config: _c.config}
_spec = sqlgraph.NewCreateSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
)
_spec.OnConflict = _c.conflict
@@ -341,7 +341,7 @@ func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// SetCreatedAt(v).
// OnConflict(
// // Update the row with the new values
@@ -350,13 +350,13 @@ func (_c *ApiKeyCreate) createSpec() (*ApiKey, *sqlgraph.CreateSpec) {
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.ApiKeyUpsert) {
// Update(func(u *ent.APIKeyUpsert) {
// SetCreatedAt(v+v).
// }).
// Exec(ctx)
func (_c *ApiKeyCreate) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertOne {
func (_c *APIKeyCreate) OnConflict(opts ...sql.ConflictOption) *APIKeyUpsertOne {
_c.conflict = opts
return &ApiKeyUpsertOne{
return &APIKeyUpsertOne{
create: _c,
}
}
@@ -364,121 +364,121 @@ func (_c *ApiKeyCreate) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertOne
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (_c *ApiKeyCreate) OnConflictColumns(columns ...string) *ApiKeyUpsertOne {
func (_c *APIKeyCreate) OnConflictColumns(columns ...string) *APIKeyUpsertOne {
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
return &ApiKeyUpsertOne{
return &APIKeyUpsertOne{
create: _c,
}
}
type (
// ApiKeyUpsertOne is the builder for "upsert"-ing
// one ApiKey node.
ApiKeyUpsertOne struct {
create *ApiKeyCreate
// APIKeyUpsertOne is the builder for "upsert"-ing
// one APIKey node.
APIKeyUpsertOne struct {
create *APIKeyCreate
}
// ApiKeyUpsert is the "OnConflict" setter.
ApiKeyUpsert struct {
// APIKeyUpsert is the "OnConflict" setter.
APIKeyUpsert struct {
*sql.UpdateSet
}
)
// SetUpdatedAt sets the "updated_at" field.
func (u *ApiKeyUpsert) SetUpdatedAt(v time.Time) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetUpdatedAt(v time.Time) *APIKeyUpsert {
u.Set(apikey.FieldUpdatedAt, v)
return u
}
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateUpdatedAt() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateUpdatedAt() *APIKeyUpsert {
u.SetExcluded(apikey.FieldUpdatedAt)
return u
}
// SetDeletedAt sets the "deleted_at" field.
func (u *ApiKeyUpsert) SetDeletedAt(v time.Time) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetDeletedAt(v time.Time) *APIKeyUpsert {
u.Set(apikey.FieldDeletedAt, v)
return u
}
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateDeletedAt() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateDeletedAt() *APIKeyUpsert {
u.SetExcluded(apikey.FieldDeletedAt)
return u
}
// ClearDeletedAt clears the value of the "deleted_at" field.
func (u *ApiKeyUpsert) ClearDeletedAt() *ApiKeyUpsert {
func (u *APIKeyUpsert) ClearDeletedAt() *APIKeyUpsert {
u.SetNull(apikey.FieldDeletedAt)
return u
}
// SetUserID sets the "user_id" field.
func (u *ApiKeyUpsert) SetUserID(v int64) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetUserID(v int64) *APIKeyUpsert {
u.Set(apikey.FieldUserID, v)
return u
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateUserID() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateUserID() *APIKeyUpsert {
u.SetExcluded(apikey.FieldUserID)
return u
}
// SetKey sets the "key" field.
func (u *ApiKeyUpsert) SetKey(v string) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetKey(v string) *APIKeyUpsert {
u.Set(apikey.FieldKey, v)
return u
}
// UpdateKey sets the "key" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateKey() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateKey() *APIKeyUpsert {
u.SetExcluded(apikey.FieldKey)
return u
}
// SetName sets the "name" field.
func (u *ApiKeyUpsert) SetName(v string) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetName(v string) *APIKeyUpsert {
u.Set(apikey.FieldName, v)
return u
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateName() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateName() *APIKeyUpsert {
u.SetExcluded(apikey.FieldName)
return u
}
// SetGroupID sets the "group_id" field.
func (u *ApiKeyUpsert) SetGroupID(v int64) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetGroupID(v int64) *APIKeyUpsert {
u.Set(apikey.FieldGroupID, v)
return u
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateGroupID() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateGroupID() *APIKeyUpsert {
u.SetExcluded(apikey.FieldGroupID)
return u
}
// ClearGroupID clears the value of the "group_id" field.
func (u *ApiKeyUpsert) ClearGroupID() *ApiKeyUpsert {
func (u *APIKeyUpsert) ClearGroupID() *APIKeyUpsert {
u.SetNull(apikey.FieldGroupID)
return u
}
// SetStatus sets the "status" field.
func (u *ApiKeyUpsert) SetStatus(v string) *ApiKeyUpsert {
func (u *APIKeyUpsert) SetStatus(v string) *APIKeyUpsert {
u.Set(apikey.FieldStatus, v)
return u
}
// UpdateStatus sets the "status" field to the value that was provided on create.
func (u *ApiKeyUpsert) UpdateStatus() *ApiKeyUpsert {
func (u *APIKeyUpsert) UpdateStatus() *APIKeyUpsert {
u.SetExcluded(apikey.FieldStatus)
return u
}
@@ -486,12 +486,12 @@ func (u *ApiKeyUpsert) UpdateStatus() *ApiKeyUpsert {
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *ApiKeyUpsertOne) UpdateNewValues() *ApiKeyUpsertOne {
func (u *APIKeyUpsertOne) UpdateNewValues() *APIKeyUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
if _, exists := u.create.mutation.CreatedAt(); exists {
@@ -504,159 +504,159 @@ func (u *ApiKeyUpsertOne) UpdateNewValues() *ApiKeyUpsertOne {
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *ApiKeyUpsertOne) Ignore() *ApiKeyUpsertOne {
func (u *APIKeyUpsertOne) Ignore() *APIKeyUpsertOne {
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 *ApiKeyUpsertOne) DoNothing() *ApiKeyUpsertOne {
func (u *APIKeyUpsertOne) DoNothing() *APIKeyUpsertOne {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the ApiKeyCreate.OnConflict
// Update allows overriding fields `UPDATE` values. See the APIKeyCreate.OnConflict
// documentation for more info.
func (u *ApiKeyUpsertOne) Update(set func(*ApiKeyUpsert)) *ApiKeyUpsertOne {
func (u *APIKeyUpsertOne) Update(set func(*APIKeyUpsert)) *APIKeyUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&ApiKeyUpsert{UpdateSet: update})
set(&APIKeyUpsert{UpdateSet: update})
}))
return u
}
// SetUpdatedAt sets the "updated_at" field.
func (u *ApiKeyUpsertOne) SetUpdatedAt(v time.Time) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetUpdatedAt(v time.Time) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetUpdatedAt(v)
})
}
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateUpdatedAt() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateUpdatedAt() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateUpdatedAt()
})
}
// SetDeletedAt sets the "deleted_at" field.
func (u *ApiKeyUpsertOne) SetDeletedAt(v time.Time) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetDeletedAt(v time.Time) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetDeletedAt(v)
})
}
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateDeletedAt() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateDeletedAt() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateDeletedAt()
})
}
// ClearDeletedAt clears the value of the "deleted_at" field.
func (u *ApiKeyUpsertOne) ClearDeletedAt() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) ClearDeletedAt() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.ClearDeletedAt()
})
}
// SetUserID sets the "user_id" field.
func (u *ApiKeyUpsertOne) SetUserID(v int64) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetUserID(v int64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetUserID(v)
})
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateUserID() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateUserID() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateUserID()
})
}
// SetKey sets the "key" field.
func (u *ApiKeyUpsertOne) SetKey(v string) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetKey(v string) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetKey(v)
})
}
// UpdateKey sets the "key" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateKey() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateKey() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateKey()
})
}
// SetName sets the "name" field.
func (u *ApiKeyUpsertOne) SetName(v string) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetName(v string) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetName(v)
})
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateName() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateName() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateName()
})
}
// SetGroupID sets the "group_id" field.
func (u *ApiKeyUpsertOne) SetGroupID(v int64) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetGroupID(v int64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetGroupID(v)
})
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateGroupID() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateGroupID() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateGroupID()
})
}
// ClearGroupID clears the value of the "group_id" field.
func (u *ApiKeyUpsertOne) ClearGroupID() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) ClearGroupID() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.ClearGroupID()
})
}
// SetStatus sets the "status" field.
func (u *ApiKeyUpsertOne) SetStatus(v string) *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) SetStatus(v string) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetStatus(v)
})
}
// UpdateStatus sets the "status" field to the value that was provided on create.
func (u *ApiKeyUpsertOne) UpdateStatus() *ApiKeyUpsertOne {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertOne) UpdateStatus() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateStatus()
})
}
// Exec executes the query.
func (u *ApiKeyUpsertOne) Exec(ctx context.Context) error {
func (u *APIKeyUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for ApiKeyCreate.OnConflict")
return errors.New("ent: missing options for APIKeyCreate.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *ApiKeyUpsertOne) ExecX(ctx context.Context) {
func (u *APIKeyUpsertOne) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}
// Exec executes the UPSERT query and returns the inserted/updated ID.
func (u *ApiKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
func (u *APIKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
node, err := u.create.Save(ctx)
if err != nil {
return id, err
@@ -665,7 +665,7 @@ func (u *ApiKeyUpsertOne) ID(ctx context.Context) (id int64, err error) {
}
// IDX is like ID, but panics if an error occurs.
func (u *ApiKeyUpsertOne) IDX(ctx context.Context) int64 {
func (u *APIKeyUpsertOne) IDX(ctx context.Context) int64 {
id, err := u.ID(ctx)
if err != nil {
panic(err)
@@ -673,28 +673,28 @@ func (u *ApiKeyUpsertOne) IDX(ctx context.Context) int64 {
return id
}
// ApiKeyCreateBulk is the builder for creating many ApiKey entities in bulk.
type ApiKeyCreateBulk struct {
// APIKeyCreateBulk is the builder for creating many APIKey entities in bulk.
type APIKeyCreateBulk struct {
config
err error
builders []*ApiKeyCreate
builders []*APIKeyCreate
conflict []sql.ConflictOption
}
// Save creates the ApiKey entities in the database.
func (_c *ApiKeyCreateBulk) Save(ctx context.Context) ([]*ApiKey, error) {
// Save creates the APIKey entities in the database.
func (_c *APIKeyCreateBulk) Save(ctx context.Context) ([]*APIKey, error) {
if _c.err != nil {
return nil, _c.err
}
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
nodes := make([]*ApiKey, len(_c.builders))
nodes := make([]*APIKey, len(_c.builders))
mutators := make([]Mutator, len(_c.builders))
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.(*ApiKeyMutation)
mutation, ok := m.(*APIKeyMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
@@ -742,7 +742,7 @@ func (_c *ApiKeyCreateBulk) Save(ctx context.Context) ([]*ApiKey, error) {
}
// SaveX is like Save, but panics if an error occurs.
func (_c *ApiKeyCreateBulk) SaveX(ctx context.Context) []*ApiKey {
func (_c *APIKeyCreateBulk) SaveX(ctx context.Context) []*APIKey {
v, err := _c.Save(ctx)
if err != nil {
panic(err)
@@ -751,13 +751,13 @@ func (_c *ApiKeyCreateBulk) SaveX(ctx context.Context) []*ApiKey {
}
// Exec executes the query.
func (_c *ApiKeyCreateBulk) Exec(ctx context.Context) error {
func (_c *APIKeyCreateBulk) Exec(ctx context.Context) error {
_, err := _c.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
func (_c *APIKeyCreateBulk) ExecX(ctx context.Context) {
if err := _c.Exec(ctx); err != nil {
panic(err)
}
@@ -766,7 +766,7 @@ func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.ApiKey.CreateBulk(builders...).
// client.APIKey.CreateBulk(builders...).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
@@ -774,13 +774,13 @@ func (_c *ApiKeyCreateBulk) ExecX(ctx context.Context) {
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.ApiKeyUpsert) {
// Update(func(u *ent.APIKeyUpsert) {
// SetCreatedAt(v+v).
// }).
// Exec(ctx)
func (_c *ApiKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsertBulk {
func (_c *APIKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *APIKeyUpsertBulk {
_c.conflict = opts
return &ApiKeyUpsertBulk{
return &APIKeyUpsertBulk{
create: _c,
}
}
@@ -788,31 +788,31 @@ func (_c *ApiKeyCreateBulk) OnConflict(opts ...sql.ConflictOption) *ApiKeyUpsert
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (_c *ApiKeyCreateBulk) OnConflictColumns(columns ...string) *ApiKeyUpsertBulk {
func (_c *APIKeyCreateBulk) OnConflictColumns(columns ...string) *APIKeyUpsertBulk {
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
return &ApiKeyUpsertBulk{
return &APIKeyUpsertBulk{
create: _c,
}
}
// ApiKeyUpsertBulk is the builder for "upsert"-ing
// a bulk of ApiKey nodes.
type ApiKeyUpsertBulk struct {
create *ApiKeyCreateBulk
// APIKeyUpsertBulk is the builder for "upsert"-ing
// a bulk of APIKey nodes.
type APIKeyUpsertBulk struct {
create *APIKeyCreateBulk
}
// UpdateNewValues updates the mutable fields using the new values that
// were set on create. Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *ApiKeyUpsertBulk) UpdateNewValues() *ApiKeyUpsertBulk {
func (u *APIKeyUpsertBulk) UpdateNewValues() *APIKeyUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
for _, b := range u.create.builders {
@@ -827,160 +827,160 @@ func (u *ApiKeyUpsertBulk) UpdateNewValues() *ApiKeyUpsertBulk {
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.ApiKey.Create().
// client.APIKey.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *ApiKeyUpsertBulk) Ignore() *ApiKeyUpsertBulk {
func (u *APIKeyUpsertBulk) Ignore() *APIKeyUpsertBulk {
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 *ApiKeyUpsertBulk) DoNothing() *ApiKeyUpsertBulk {
func (u *APIKeyUpsertBulk) DoNothing() *APIKeyUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the ApiKeyCreateBulk.OnConflict
// Update allows overriding fields `UPDATE` values. See the APIKeyCreateBulk.OnConflict
// documentation for more info.
func (u *ApiKeyUpsertBulk) Update(set func(*ApiKeyUpsert)) *ApiKeyUpsertBulk {
func (u *APIKeyUpsertBulk) Update(set func(*APIKeyUpsert)) *APIKeyUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&ApiKeyUpsert{UpdateSet: update})
set(&APIKeyUpsert{UpdateSet: update})
}))
return u
}
// SetUpdatedAt sets the "updated_at" field.
func (u *ApiKeyUpsertBulk) SetUpdatedAt(v time.Time) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetUpdatedAt(v time.Time) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetUpdatedAt(v)
})
}
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateUpdatedAt() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateUpdatedAt() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateUpdatedAt()
})
}
// SetDeletedAt sets the "deleted_at" field.
func (u *ApiKeyUpsertBulk) SetDeletedAt(v time.Time) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetDeletedAt(v time.Time) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetDeletedAt(v)
})
}
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateDeletedAt() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateDeletedAt() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateDeletedAt()
})
}
// ClearDeletedAt clears the value of the "deleted_at" field.
func (u *ApiKeyUpsertBulk) ClearDeletedAt() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) ClearDeletedAt() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.ClearDeletedAt()
})
}
// SetUserID sets the "user_id" field.
func (u *ApiKeyUpsertBulk) SetUserID(v int64) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetUserID(v int64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetUserID(v)
})
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateUserID() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateUserID() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateUserID()
})
}
// SetKey sets the "key" field.
func (u *ApiKeyUpsertBulk) SetKey(v string) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetKey(v string) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetKey(v)
})
}
// UpdateKey sets the "key" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateKey() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateKey() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateKey()
})
}
// SetName sets the "name" field.
func (u *ApiKeyUpsertBulk) SetName(v string) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetName(v string) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetName(v)
})
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateName() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateName() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateName()
})
}
// SetGroupID sets the "group_id" field.
func (u *ApiKeyUpsertBulk) SetGroupID(v int64) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetGroupID(v int64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetGroupID(v)
})
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateGroupID() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateGroupID() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateGroupID()
})
}
// ClearGroupID clears the value of the "group_id" field.
func (u *ApiKeyUpsertBulk) ClearGroupID() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) ClearGroupID() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.ClearGroupID()
})
}
// SetStatus sets the "status" field.
func (u *ApiKeyUpsertBulk) SetStatus(v string) *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) SetStatus(v string) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetStatus(v)
})
}
// UpdateStatus sets the "status" field to the value that was provided on create.
func (u *ApiKeyUpsertBulk) UpdateStatus() *ApiKeyUpsertBulk {
return u.Update(func(s *ApiKeyUpsert) {
func (u *APIKeyUpsertBulk) UpdateStatus() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateStatus()
})
}
// Exec executes the query.
func (u *ApiKeyUpsertBulk) Exec(ctx context.Context) error {
func (u *APIKeyUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {
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 ApiKeyCreateBulk instead", i)
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the APIKeyCreateBulk instead", i)
}
}
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for ApiKeyCreateBulk.OnConflict")
return errors.New("ent: missing options for APIKeyCreateBulk.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *ApiKeyUpsertBulk) ExecX(ctx context.Context) {
func (u *APIKeyUpsertBulk) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}

View File

@@ -12,26 +12,26 @@ import (
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// ApiKeyDelete is the builder for deleting a ApiKey entity.
type ApiKeyDelete struct {
// APIKeyDelete is the builder for deleting a APIKey entity.
type APIKeyDelete struct {
config
hooks []Hook
mutation *ApiKeyMutation
mutation *APIKeyMutation
}
// Where appends a list predicates to the ApiKeyDelete builder.
func (_d *ApiKeyDelete) Where(ps ...predicate.ApiKey) *ApiKeyDelete {
// Where appends a list predicates to the APIKeyDelete builder.
func (_d *APIKeyDelete) Where(ps ...predicate.APIKey) *APIKeyDelete {
_d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (_d *ApiKeyDelete) Exec(ctx context.Context) (int, error) {
func (_d *APIKeyDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *ApiKeyDelete) ExecX(ctx context.Context) int {
func (_d *APIKeyDelete) ExecX(ctx context.Context) int {
n, err := _d.Exec(ctx)
if err != nil {
panic(err)
@@ -39,7 +39,7 @@ func (_d *ApiKeyDelete) ExecX(ctx context.Context) int {
return n
}
func (_d *ApiKeyDelete) sqlExec(ctx context.Context) (int, error) {
func (_d *APIKeyDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(apikey.Table, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
if ps := _d.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
@@ -56,19 +56,19 @@ func (_d *ApiKeyDelete) sqlExec(ctx context.Context) (int, error) {
return affected, err
}
// ApiKeyDeleteOne is the builder for deleting a single ApiKey entity.
type ApiKeyDeleteOne struct {
_d *ApiKeyDelete
// APIKeyDeleteOne is the builder for deleting a single APIKey entity.
type APIKeyDeleteOne struct {
_d *APIKeyDelete
}
// Where appends a list predicates to the ApiKeyDelete builder.
func (_d *ApiKeyDeleteOne) Where(ps ...predicate.ApiKey) *ApiKeyDeleteOne {
// Where appends a list predicates to the APIKeyDelete builder.
func (_d *APIKeyDeleteOne) Where(ps ...predicate.APIKey) *APIKeyDeleteOne {
_d._d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query.
func (_d *ApiKeyDeleteOne) Exec(ctx context.Context) error {
func (_d *APIKeyDeleteOne) Exec(ctx context.Context) error {
n, err := _d._d.Exec(ctx)
switch {
case err != nil:
@@ -81,7 +81,7 @@ func (_d *ApiKeyDeleteOne) Exec(ctx context.Context) error {
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *ApiKeyDeleteOne) ExecX(ctx context.Context) {
func (_d *APIKeyDeleteOne) ExecX(ctx context.Context) {
if err := _d.Exec(ctx); err != nil {
panic(err)
}

View File

@@ -19,13 +19,13 @@ import (
"github.com/Wei-Shaw/sub2api/ent/user"
)
// ApiKeyQuery is the builder for querying ApiKey entities.
type ApiKeyQuery struct {
// APIKeyQuery is the builder for querying APIKey entities.
type APIKeyQuery struct {
config
ctx *QueryContext
order []apikey.OrderOption
inters []Interceptor
predicates []predicate.ApiKey
predicates []predicate.APIKey
withUser *UserQuery
withGroup *GroupQuery
withUsageLogs *UsageLogQuery
@@ -34,39 +34,39 @@ type ApiKeyQuery struct {
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the ApiKeyQuery builder.
func (_q *ApiKeyQuery) Where(ps ...predicate.ApiKey) *ApiKeyQuery {
// Where adds a new predicate for the APIKeyQuery builder.
func (_q *APIKeyQuery) Where(ps ...predicate.APIKey) *APIKeyQuery {
_q.predicates = append(_q.predicates, ps...)
return _q
}
// Limit the number of records to be returned by this query.
func (_q *ApiKeyQuery) Limit(limit int) *ApiKeyQuery {
func (_q *APIKeyQuery) Limit(limit int) *APIKeyQuery {
_q.ctx.Limit = &limit
return _q
}
// Offset to start from.
func (_q *ApiKeyQuery) Offset(offset int) *ApiKeyQuery {
func (_q *APIKeyQuery) Offset(offset int) *APIKeyQuery {
_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 *ApiKeyQuery) Unique(unique bool) *ApiKeyQuery {
func (_q *APIKeyQuery) Unique(unique bool) *APIKeyQuery {
_q.ctx.Unique = &unique
return _q
}
// Order specifies how the records should be ordered.
func (_q *ApiKeyQuery) Order(o ...apikey.OrderOption) *ApiKeyQuery {
func (_q *APIKeyQuery) Order(o ...apikey.OrderOption) *APIKeyQuery {
_q.order = append(_q.order, o...)
return _q
}
// QueryUser chains the current query on the "user" edge.
func (_q *ApiKeyQuery) QueryUser() *UserQuery {
func (_q *APIKeyQuery) QueryUser() *UserQuery {
query := (&UserClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
@@ -88,7 +88,7 @@ func (_q *ApiKeyQuery) QueryUser() *UserQuery {
}
// QueryGroup chains the current query on the "group" edge.
func (_q *ApiKeyQuery) QueryGroup() *GroupQuery {
func (_q *APIKeyQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
@@ -110,7 +110,7 @@ func (_q *ApiKeyQuery) QueryGroup() *GroupQuery {
}
// QueryUsageLogs chains the current query on the "usage_logs" edge.
func (_q *ApiKeyQuery) QueryUsageLogs() *UsageLogQuery {
func (_q *APIKeyQuery) QueryUsageLogs() *UsageLogQuery {
query := (&UsageLogClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
@@ -131,9 +131,9 @@ func (_q *ApiKeyQuery) QueryUsageLogs() *UsageLogQuery {
return query
}
// First returns the first ApiKey entity from the query.
// Returns a *NotFoundError when no ApiKey was found.
func (_q *ApiKeyQuery) First(ctx context.Context) (*ApiKey, error) {
// First returns the first APIKey entity from the query.
// Returns a *NotFoundError when no APIKey was found.
func (_q *APIKeyQuery) First(ctx context.Context) (*APIKey, error) {
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
@@ -145,7 +145,7 @@ func (_q *ApiKeyQuery) First(ctx context.Context) (*ApiKey, error) {
}
// FirstX is like First, but panics if an error occurs.
func (_q *ApiKeyQuery) FirstX(ctx context.Context) *ApiKey {
func (_q *APIKeyQuery) FirstX(ctx context.Context) *APIKey {
node, err := _q.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
@@ -153,9 +153,9 @@ func (_q *ApiKeyQuery) FirstX(ctx context.Context) *ApiKey {
return node
}
// FirstID returns the first ApiKey ID from the query.
// Returns a *NotFoundError when no ApiKey ID was found.
func (_q *ApiKeyQuery) FirstID(ctx context.Context) (id int64, err error) {
// FirstID returns the first APIKey ID from the query.
// Returns a *NotFoundError when no APIKey ID was found.
func (_q *APIKeyQuery) 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
@@ -168,7 +168,7 @@ func (_q *ApiKeyQuery) FirstID(ctx context.Context) (id int64, err error) {
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (_q *ApiKeyQuery) FirstIDX(ctx context.Context) int64 {
func (_q *APIKeyQuery) FirstIDX(ctx context.Context) int64 {
id, err := _q.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
@@ -176,10 +176,10 @@ func (_q *ApiKeyQuery) FirstIDX(ctx context.Context) int64 {
return id
}
// Only returns a single ApiKey entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one ApiKey entity is found.
// Returns a *NotFoundError when no ApiKey entities are found.
func (_q *ApiKeyQuery) Only(ctx context.Context) (*ApiKey, error) {
// Only returns a single APIKey entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one APIKey entity is found.
// Returns a *NotFoundError when no APIKey entities are found.
func (_q *APIKeyQuery) Only(ctx context.Context) (*APIKey, error) {
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
@@ -195,7 +195,7 @@ func (_q *ApiKeyQuery) Only(ctx context.Context) (*ApiKey, error) {
}
// OnlyX is like Only, but panics if an error occurs.
func (_q *ApiKeyQuery) OnlyX(ctx context.Context) *ApiKey {
func (_q *APIKeyQuery) OnlyX(ctx context.Context) *APIKey {
node, err := _q.Only(ctx)
if err != nil {
panic(err)
@@ -203,10 +203,10 @@ func (_q *ApiKeyQuery) OnlyX(ctx context.Context) *ApiKey {
return node
}
// OnlyID is like Only, but returns the only ApiKey ID in the query.
// Returns a *NotSingularError when more than one ApiKey ID is found.
// OnlyID is like Only, but returns the only APIKey ID in the query.
// Returns a *NotSingularError when more than one APIKey ID is found.
// Returns a *NotFoundError when no entities are found.
func (_q *ApiKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
func (_q *APIKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
return
@@ -223,7 +223,7 @@ func (_q *ApiKeyQuery) OnlyID(ctx context.Context) (id int64, err error) {
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (_q *ApiKeyQuery) OnlyIDX(ctx context.Context) int64 {
func (_q *APIKeyQuery) OnlyIDX(ctx context.Context) int64 {
id, err := _q.OnlyID(ctx)
if err != nil {
panic(err)
@@ -231,18 +231,18 @@ func (_q *ApiKeyQuery) OnlyIDX(ctx context.Context) int64 {
return id
}
// All executes the query and returns a list of ApiKeys.
func (_q *ApiKeyQuery) All(ctx context.Context) ([]*ApiKey, error) {
// All executes the query and returns a list of APIKeys.
func (_q *APIKeyQuery) All(ctx context.Context) ([]*APIKey, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*ApiKey, *ApiKeyQuery]()
return withInterceptors[[]*ApiKey](ctx, _q, qr, _q.inters)
qr := querierAll[[]*APIKey, *APIKeyQuery]()
return withInterceptors[[]*APIKey](ctx, _q, qr, _q.inters)
}
// AllX is like All, but panics if an error occurs.
func (_q *ApiKeyQuery) AllX(ctx context.Context) []*ApiKey {
func (_q *APIKeyQuery) AllX(ctx context.Context) []*APIKey {
nodes, err := _q.All(ctx)
if err != nil {
panic(err)
@@ -250,8 +250,8 @@ func (_q *ApiKeyQuery) AllX(ctx context.Context) []*ApiKey {
return nodes
}
// IDs executes the query and returns a list of ApiKey IDs.
func (_q *ApiKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
// IDs executes the query and returns a list of APIKey IDs.
func (_q *APIKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
if _q.ctx.Unique == nil && _q.path != nil {
_q.Unique(true)
}
@@ -263,7 +263,7 @@ func (_q *ApiKeyQuery) IDs(ctx context.Context) (ids []int64, err error) {
}
// IDsX is like IDs, but panics if an error occurs.
func (_q *ApiKeyQuery) IDsX(ctx context.Context) []int64 {
func (_q *APIKeyQuery) IDsX(ctx context.Context) []int64 {
ids, err := _q.IDs(ctx)
if err != nil {
panic(err)
@@ -272,16 +272,16 @@ func (_q *ApiKeyQuery) IDsX(ctx context.Context) []int64 {
}
// Count returns the count of the given query.
func (_q *ApiKeyQuery) Count(ctx context.Context) (int, error) {
func (_q *APIKeyQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
if err := _q.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, _q, querierCount[*ApiKeyQuery](), _q.inters)
return withInterceptors[int](ctx, _q, querierCount[*APIKeyQuery](), _q.inters)
}
// CountX is like Count, but panics if an error occurs.
func (_q *ApiKeyQuery) CountX(ctx context.Context) int {
func (_q *APIKeyQuery) CountX(ctx context.Context) int {
count, err := _q.Count(ctx)
if err != nil {
panic(err)
@@ -290,7 +290,7 @@ func (_q *ApiKeyQuery) CountX(ctx context.Context) int {
}
// Exist returns true if the query has elements in the graph.
func (_q *ApiKeyQuery) Exist(ctx context.Context) (bool, error) {
func (_q *APIKeyQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
switch _, err := _q.FirstID(ctx); {
case IsNotFound(err):
@@ -303,7 +303,7 @@ func (_q *ApiKeyQuery) Exist(ctx context.Context) (bool, error) {
}
// ExistX is like Exist, but panics if an error occurs.
func (_q *ApiKeyQuery) ExistX(ctx context.Context) bool {
func (_q *APIKeyQuery) ExistX(ctx context.Context) bool {
exist, err := _q.Exist(ctx)
if err != nil {
panic(err)
@@ -311,18 +311,18 @@ func (_q *ApiKeyQuery) ExistX(ctx context.Context) bool {
return exist
}
// Clone returns a duplicate of the ApiKeyQuery builder, including all associated steps. It can be
// Clone returns a duplicate of the APIKeyQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (_q *ApiKeyQuery) Clone() *ApiKeyQuery {
func (_q *APIKeyQuery) Clone() *APIKeyQuery {
if _q == nil {
return nil
}
return &ApiKeyQuery{
return &APIKeyQuery{
config: _q.config,
ctx: _q.ctx.Clone(),
order: append([]apikey.OrderOption{}, _q.order...),
inters: append([]Interceptor{}, _q.inters...),
predicates: append([]predicate.ApiKey{}, _q.predicates...),
predicates: append([]predicate.APIKey{}, _q.predicates...),
withUser: _q.withUser.Clone(),
withGroup: _q.withGroup.Clone(),
withUsageLogs: _q.withUsageLogs.Clone(),
@@ -334,7 +334,7 @@ func (_q *ApiKeyQuery) Clone() *ApiKeyQuery {
// WithUser tells the query-builder to eager-load the nodes that are connected to
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *ApiKeyQuery) WithUser(opts ...func(*UserQuery)) *ApiKeyQuery {
func (_q *APIKeyQuery) WithUser(opts ...func(*UserQuery)) *APIKeyQuery {
query := (&UserClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
@@ -345,7 +345,7 @@ func (_q *ApiKeyQuery) WithUser(opts ...func(*UserQuery)) *ApiKeyQuery {
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *ApiKeyQuery) WithGroup(opts ...func(*GroupQuery)) *ApiKeyQuery {
func (_q *APIKeyQuery) WithGroup(opts ...func(*GroupQuery)) *APIKeyQuery {
query := (&GroupClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
@@ -356,7 +356,7 @@ func (_q *ApiKeyQuery) WithGroup(opts ...func(*GroupQuery)) *ApiKeyQuery {
// WithUsageLogs tells the query-builder to eager-load the nodes that are connected to
// the "usage_logs" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *ApiKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *ApiKeyQuery {
func (_q *APIKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *APIKeyQuery {
query := (&UsageLogClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
@@ -375,13 +375,13 @@ func (_q *ApiKeyQuery) WithUsageLogs(opts ...func(*UsageLogQuery)) *ApiKeyQuery
// Count int `json:"count,omitempty"`
// }
//
// client.ApiKey.Query().
// client.APIKey.Query().
// GroupBy(apikey.FieldCreatedAt).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *ApiKeyQuery) GroupBy(field string, fields ...string) *ApiKeyGroupBy {
func (_q *APIKeyQuery) GroupBy(field string, fields ...string) *APIKeyGroupBy {
_q.ctx.Fields = append([]string{field}, fields...)
grbuild := &ApiKeyGroupBy{build: _q}
grbuild := &APIKeyGroupBy{build: _q}
grbuild.flds = &_q.ctx.Fields
grbuild.label = apikey.Label
grbuild.scan = grbuild.Scan
@@ -397,23 +397,23 @@ func (_q *ApiKeyQuery) GroupBy(field string, fields ...string) *ApiKeyGroupBy {
// CreatedAt time.Time `json:"created_at,omitempty"`
// }
//
// client.ApiKey.Query().
// client.APIKey.Query().
// Select(apikey.FieldCreatedAt).
// Scan(ctx, &v)
func (_q *ApiKeyQuery) Select(fields ...string) *ApiKeySelect {
func (_q *APIKeyQuery) Select(fields ...string) *APIKeySelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
sbuild := &ApiKeySelect{ApiKeyQuery: _q}
sbuild := &APIKeySelect{APIKeyQuery: _q}
sbuild.label = apikey.Label
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a ApiKeySelect configured with the given aggregations.
func (_q *ApiKeyQuery) Aggregate(fns ...AggregateFunc) *ApiKeySelect {
// Aggregate returns a APIKeySelect configured with the given aggregations.
func (_q *APIKeyQuery) Aggregate(fns ...AggregateFunc) *APIKeySelect {
return _q.Select().Aggregate(fns...)
}
func (_q *ApiKeyQuery) prepareQuery(ctx context.Context) error {
func (_q *APIKeyQuery) prepareQuery(ctx context.Context) error {
for _, inter := range _q.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
@@ -439,9 +439,9 @@ func (_q *ApiKeyQuery) prepareQuery(ctx context.Context) error {
return nil
}
func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKey, error) {
func (_q *APIKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*APIKey, error) {
var (
nodes = []*ApiKey{}
nodes = []*APIKey{}
_spec = _q.querySpec()
loadedTypes = [3]bool{
_q.withUser != nil,
@@ -450,10 +450,10 @@ func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKe
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*ApiKey).scanValues(nil, columns)
return (*APIKey).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &ApiKey{config: _q.config}
node := &APIKey{config: _q.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
@@ -469,29 +469,29 @@ func (_q *ApiKeyQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ApiKe
}
if query := _q.withUser; query != nil {
if err := _q.loadUser(ctx, query, nodes, nil,
func(n *ApiKey, e *User) { n.Edges.User = e }); err != nil {
func(n *APIKey, e *User) { n.Edges.User = e }); err != nil {
return nil, err
}
}
if query := _q.withGroup; query != nil {
if err := _q.loadGroup(ctx, query, nodes, nil,
func(n *ApiKey, e *Group) { n.Edges.Group = e }); err != nil {
func(n *APIKey, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := _q.withUsageLogs; query != nil {
if err := _q.loadUsageLogs(ctx, query, nodes,
func(n *ApiKey) { n.Edges.UsageLogs = []*UsageLog{} },
func(n *ApiKey, e *UsageLog) { n.Edges.UsageLogs = append(n.Edges.UsageLogs, e) }); err != nil {
func(n *APIKey) { n.Edges.UsageLogs = []*UsageLog{} },
func(n *APIKey, e *UsageLog) { n.Edges.UsageLogs = append(n.Edges.UsageLogs, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (_q *ApiKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *User)) error {
func (_q *APIKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *User)) error {
ids := make([]int64, 0, len(nodes))
nodeids := make(map[int64][]*ApiKey)
nodeids := make(map[int64][]*APIKey)
for i := range nodes {
fk := nodes[i].UserID
if _, ok := nodeids[fk]; !ok {
@@ -518,9 +518,9 @@ func (_q *ApiKeyQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*
}
return nil
}
func (_q *ApiKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *Group)) error {
func (_q *APIKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *Group)) error {
ids := make([]int64, 0, len(nodes))
nodeids := make(map[int64][]*ApiKey)
nodeids := make(map[int64][]*APIKey)
for i := range nodes {
if nodes[i].GroupID == nil {
continue
@@ -550,9 +550,9 @@ func (_q *ApiKeyQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes [
}
return nil
}
func (_q *ApiKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery, nodes []*ApiKey, init func(*ApiKey), assign func(*ApiKey, *UsageLog)) error {
func (_q *APIKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery, nodes []*APIKey, init func(*APIKey), assign func(*APIKey, *UsageLog)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*ApiKey)
nodeids := make(map[int64]*APIKey)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
@@ -581,7 +581,7 @@ func (_q *ApiKeyQuery) loadUsageLogs(ctx context.Context, query *UsageLogQuery,
return nil
}
func (_q *ApiKeyQuery) sqlCount(ctx context.Context) (int, error) {
func (_q *APIKeyQuery) sqlCount(ctx context.Context) (int, error) {
_spec := _q.querySpec()
_spec.Node.Columns = _q.ctx.Fields
if len(_q.ctx.Fields) > 0 {
@@ -590,7 +590,7 @@ func (_q *ApiKeyQuery) sqlCount(ctx context.Context) (int, error) {
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
}
func (_q *ApiKeyQuery) querySpec() *sqlgraph.QuerySpec {
func (_q *APIKeyQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
_spec.From = _q.sql
if unique := _q.ctx.Unique; unique != nil {
@@ -636,7 +636,7 @@ func (_q *ApiKeyQuery) querySpec() *sqlgraph.QuerySpec {
return _spec
}
func (_q *ApiKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
func (_q *APIKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(_q.driver.Dialect())
t1 := builder.Table(apikey.Table)
columns := _q.ctx.Fields
@@ -668,28 +668,28 @@ func (_q *ApiKeyQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// ApiKeyGroupBy is the group-by builder for ApiKey entities.
type ApiKeyGroupBy struct {
// APIKeyGroupBy is the group-by builder for APIKey entities.
type APIKeyGroupBy struct {
selector
build *ApiKeyQuery
build *APIKeyQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (_g *ApiKeyGroupBy) Aggregate(fns ...AggregateFunc) *ApiKeyGroupBy {
func (_g *APIKeyGroupBy) Aggregate(fns ...AggregateFunc) *APIKeyGroupBy {
_g.fns = append(_g.fns, fns...)
return _g
}
// Scan applies the selector query and scans the result into the given value.
func (_g *ApiKeyGroupBy) Scan(ctx context.Context, v any) error {
func (_g *APIKeyGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
if err := _g.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*ApiKeyQuery, *ApiKeyGroupBy](ctx, _g.build, _g, _g.build.inters, v)
return scanWithInterceptors[*APIKeyQuery, *APIKeyGroupBy](ctx, _g.build, _g, _g.build.inters, v)
}
func (_g *ApiKeyGroupBy) sqlScan(ctx context.Context, root *ApiKeyQuery, v any) error {
func (_g *APIKeyGroupBy) sqlScan(ctx context.Context, root *APIKeyQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(_g.fns))
for _, fn := range _g.fns {
@@ -716,28 +716,28 @@ func (_g *ApiKeyGroupBy) sqlScan(ctx context.Context, root *ApiKeyQuery, v any)
return sql.ScanSlice(rows, v)
}
// ApiKeySelect is the builder for selecting fields of ApiKey entities.
type ApiKeySelect struct {
*ApiKeyQuery
// APIKeySelect is the builder for selecting fields of APIKey entities.
type APIKeySelect struct {
*APIKeyQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (_s *ApiKeySelect) Aggregate(fns ...AggregateFunc) *ApiKeySelect {
func (_s *APIKeySelect) Aggregate(fns ...AggregateFunc) *APIKeySelect {
_s.fns = append(_s.fns, fns...)
return _s
}
// Scan applies the selector query and scans the result into the given value.
func (_s *ApiKeySelect) Scan(ctx context.Context, v any) error {
func (_s *APIKeySelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
if err := _s.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*ApiKeyQuery, *ApiKeySelect](ctx, _s.ApiKeyQuery, _s, _s.inters, v)
return scanWithInterceptors[*APIKeyQuery, *APIKeySelect](ctx, _s.APIKeyQuery, _s, _s.inters, v)
}
func (_s *ApiKeySelect) sqlScan(ctx context.Context, root *ApiKeyQuery, v any) error {
func (_s *APIKeySelect) sqlScan(ctx context.Context, root *APIKeyQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(_s.fns))
for _, fn := range _s.fns {

View File

@@ -18,33 +18,33 @@ import (
"github.com/Wei-Shaw/sub2api/ent/user"
)
// ApiKeyUpdate is the builder for updating ApiKey entities.
type ApiKeyUpdate struct {
// APIKeyUpdate is the builder for updating APIKey entities.
type APIKeyUpdate struct {
config
hooks []Hook
mutation *ApiKeyMutation
mutation *APIKeyMutation
}
// Where appends a list predicates to the ApiKeyUpdate builder.
func (_u *ApiKeyUpdate) Where(ps ...predicate.ApiKey) *ApiKeyUpdate {
// Where appends a list predicates to the APIKeyUpdate builder.
func (_u *APIKeyUpdate) Where(ps ...predicate.APIKey) *APIKeyUpdate {
_u.mutation.Where(ps...)
return _u
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *ApiKeyUpdate) SetUpdatedAt(v time.Time) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetUpdatedAt(v time.Time) *APIKeyUpdate {
_u.mutation.SetUpdatedAt(v)
return _u
}
// SetDeletedAt sets the "deleted_at" field.
func (_u *ApiKeyUpdate) SetDeletedAt(v time.Time) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetDeletedAt(v time.Time) *APIKeyUpdate {
_u.mutation.SetDeletedAt(v)
return _u
}
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableDeletedAt(v *time.Time) *APIKeyUpdate {
if v != nil {
_u.SetDeletedAt(*v)
}
@@ -52,19 +52,19 @@ func (_u *ApiKeyUpdate) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdate {
}
// ClearDeletedAt clears the value of the "deleted_at" field.
func (_u *ApiKeyUpdate) ClearDeletedAt() *ApiKeyUpdate {
func (_u *APIKeyUpdate) ClearDeletedAt() *APIKeyUpdate {
_u.mutation.ClearDeletedAt()
return _u
}
// SetUserID sets the "user_id" field.
func (_u *ApiKeyUpdate) SetUserID(v int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetUserID(v int64) *APIKeyUpdate {
_u.mutation.SetUserID(v)
return _u
}
// SetNillableUserID sets the "user_id" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableUserID(v *int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableUserID(v *int64) *APIKeyUpdate {
if v != nil {
_u.SetUserID(*v)
}
@@ -72,13 +72,13 @@ func (_u *ApiKeyUpdate) SetNillableUserID(v *int64) *ApiKeyUpdate {
}
// SetKey sets the "key" field.
func (_u *ApiKeyUpdate) SetKey(v string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetKey(v string) *APIKeyUpdate {
_u.mutation.SetKey(v)
return _u
}
// SetNillableKey sets the "key" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableKey(v *string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableKey(v *string) *APIKeyUpdate {
if v != nil {
_u.SetKey(*v)
}
@@ -86,13 +86,13 @@ func (_u *ApiKeyUpdate) SetNillableKey(v *string) *ApiKeyUpdate {
}
// SetName sets the "name" field.
func (_u *ApiKeyUpdate) SetName(v string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetName(v string) *APIKeyUpdate {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableName(v *string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableName(v *string) *APIKeyUpdate {
if v != nil {
_u.SetName(*v)
}
@@ -100,13 +100,13 @@ func (_u *ApiKeyUpdate) SetNillableName(v *string) *ApiKeyUpdate {
}
// SetGroupID sets the "group_id" field.
func (_u *ApiKeyUpdate) SetGroupID(v int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetGroupID(v int64) *APIKeyUpdate {
_u.mutation.SetGroupID(v)
return _u
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableGroupID(v *int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableGroupID(v *int64) *APIKeyUpdate {
if v != nil {
_u.SetGroupID(*v)
}
@@ -114,19 +114,19 @@ func (_u *ApiKeyUpdate) SetNillableGroupID(v *int64) *ApiKeyUpdate {
}
// ClearGroupID clears the value of the "group_id" field.
func (_u *ApiKeyUpdate) ClearGroupID() *ApiKeyUpdate {
func (_u *APIKeyUpdate) ClearGroupID() *APIKeyUpdate {
_u.mutation.ClearGroupID()
return _u
}
// SetStatus sets the "status" field.
func (_u *ApiKeyUpdate) SetStatus(v string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetStatus(v string) *APIKeyUpdate {
_u.mutation.SetStatus(v)
return _u
}
// SetNillableStatus sets the "status" field if the given value is not nil.
func (_u *ApiKeyUpdate) SetNillableStatus(v *string) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetNillableStatus(v *string) *APIKeyUpdate {
if v != nil {
_u.SetStatus(*v)
}
@@ -134,23 +134,23 @@ func (_u *ApiKeyUpdate) SetNillableStatus(v *string) *ApiKeyUpdate {
}
// SetUser sets the "user" edge to the User entity.
func (_u *ApiKeyUpdate) SetUser(v *User) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetUser(v *User) *APIKeyUpdate {
return _u.SetUserID(v.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (_u *ApiKeyUpdate) SetGroup(v *Group) *ApiKeyUpdate {
func (_u *APIKeyUpdate) SetGroup(v *Group) *APIKeyUpdate {
return _u.SetGroupID(v.ID)
}
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
func (_u *ApiKeyUpdate) AddUsageLogIDs(ids ...int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) AddUsageLogIDs(ids ...int64) *APIKeyUpdate {
_u.mutation.AddUsageLogIDs(ids...)
return _u
}
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
func (_u *ApiKeyUpdate) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
func (_u *APIKeyUpdate) AddUsageLogs(v ...*UsageLog) *APIKeyUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -158,37 +158,37 @@ func (_u *ApiKeyUpdate) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
return _u.AddUsageLogIDs(ids...)
}
// Mutation returns the ApiKeyMutation object of the builder.
func (_u *ApiKeyUpdate) Mutation() *ApiKeyMutation {
// Mutation returns the APIKeyMutation object of the builder.
func (_u *APIKeyUpdate) Mutation() *APIKeyMutation {
return _u.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (_u *ApiKeyUpdate) ClearUser() *ApiKeyUpdate {
func (_u *APIKeyUpdate) ClearUser() *APIKeyUpdate {
_u.mutation.ClearUser()
return _u
}
// ClearGroup clears the "group" edge to the Group entity.
func (_u *ApiKeyUpdate) ClearGroup() *ApiKeyUpdate {
func (_u *APIKeyUpdate) ClearGroup() *APIKeyUpdate {
_u.mutation.ClearGroup()
return _u
}
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
func (_u *ApiKeyUpdate) ClearUsageLogs() *ApiKeyUpdate {
func (_u *APIKeyUpdate) ClearUsageLogs() *APIKeyUpdate {
_u.mutation.ClearUsageLogs()
return _u
}
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
func (_u *ApiKeyUpdate) RemoveUsageLogIDs(ids ...int64) *ApiKeyUpdate {
func (_u *APIKeyUpdate) RemoveUsageLogIDs(ids ...int64) *APIKeyUpdate {
_u.mutation.RemoveUsageLogIDs(ids...)
return _u
}
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
func (_u *ApiKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
func (_u *APIKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *APIKeyUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -197,7 +197,7 @@ func (_u *ApiKeyUpdate) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdate {
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (_u *ApiKeyUpdate) Save(ctx context.Context) (int, error) {
func (_u *APIKeyUpdate) Save(ctx context.Context) (int, error) {
if err := _u.defaults(); err != nil {
return 0, err
}
@@ -205,7 +205,7 @@ func (_u *ApiKeyUpdate) Save(ctx context.Context) (int, error) {
}
// SaveX is like Save, but panics if an error occurs.
func (_u *ApiKeyUpdate) SaveX(ctx context.Context) int {
func (_u *APIKeyUpdate) SaveX(ctx context.Context) int {
affected, err := _u.Save(ctx)
if err != nil {
panic(err)
@@ -214,20 +214,20 @@ func (_u *ApiKeyUpdate) SaveX(ctx context.Context) int {
}
// Exec executes the query.
func (_u *ApiKeyUpdate) Exec(ctx context.Context) error {
func (_u *APIKeyUpdate) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *ApiKeyUpdate) ExecX(ctx context.Context) {
func (_u *APIKeyUpdate) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *ApiKeyUpdate) defaults() error {
func (_u *APIKeyUpdate) defaults() error {
if _, ok := _u.mutation.UpdatedAt(); !ok {
if apikey.UpdateDefaultUpdatedAt == nil {
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
@@ -239,29 +239,29 @@ func (_u *ApiKeyUpdate) defaults() error {
}
// check runs all checks and user-defined validators on the builder.
func (_u *ApiKeyUpdate) check() error {
func (_u *APIKeyUpdate) check() error {
if v, ok := _u.mutation.Key(); ok {
if err := apikey.KeyValidator(v); err != nil {
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
}
}
if v, ok := _u.mutation.Name(); ok {
if err := apikey.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
}
}
if v, ok := _u.mutation.Status(); ok {
if err := apikey.StatusValidator(v); err != nil {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
}
}
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "ApiKey.user"`)
return errors.New(`ent: clearing a required unique edge "APIKey.user"`)
}
return nil
}
func (_u *ApiKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
func (_u *APIKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if err := _u.check(); err != nil {
return _node, err
}
@@ -406,28 +406,28 @@ func (_u *ApiKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
return _node, nil
}
// ApiKeyUpdateOne is the builder for updating a single ApiKey entity.
type ApiKeyUpdateOne struct {
// APIKeyUpdateOne is the builder for updating a single APIKey entity.
type APIKeyUpdateOne struct {
config
fields []string
hooks []Hook
mutation *ApiKeyMutation
mutation *APIKeyMutation
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *ApiKeyUpdateOne) SetUpdatedAt(v time.Time) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetUpdatedAt(v time.Time) *APIKeyUpdateOne {
_u.mutation.SetUpdatedAt(v)
return _u
}
// SetDeletedAt sets the "deleted_at" field.
func (_u *ApiKeyUpdateOne) SetDeletedAt(v time.Time) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetDeletedAt(v time.Time) *APIKeyUpdateOne {
_u.mutation.SetDeletedAt(v)
return _u
}
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *APIKeyUpdateOne {
if v != nil {
_u.SetDeletedAt(*v)
}
@@ -435,19 +435,19 @@ func (_u *ApiKeyUpdateOne) SetNillableDeletedAt(v *time.Time) *ApiKeyUpdateOne {
}
// ClearDeletedAt clears the value of the "deleted_at" field.
func (_u *ApiKeyUpdateOne) ClearDeletedAt() *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) ClearDeletedAt() *APIKeyUpdateOne {
_u.mutation.ClearDeletedAt()
return _u
}
// SetUserID sets the "user_id" field.
func (_u *ApiKeyUpdateOne) SetUserID(v int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetUserID(v int64) *APIKeyUpdateOne {
_u.mutation.SetUserID(v)
return _u
}
// SetNillableUserID sets the "user_id" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableUserID(v *int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableUserID(v *int64) *APIKeyUpdateOne {
if v != nil {
_u.SetUserID(*v)
}
@@ -455,13 +455,13 @@ func (_u *ApiKeyUpdateOne) SetNillableUserID(v *int64) *ApiKeyUpdateOne {
}
// SetKey sets the "key" field.
func (_u *ApiKeyUpdateOne) SetKey(v string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetKey(v string) *APIKeyUpdateOne {
_u.mutation.SetKey(v)
return _u
}
// SetNillableKey sets the "key" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableKey(v *string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableKey(v *string) *APIKeyUpdateOne {
if v != nil {
_u.SetKey(*v)
}
@@ -469,13 +469,13 @@ func (_u *ApiKeyUpdateOne) SetNillableKey(v *string) *ApiKeyUpdateOne {
}
// SetName sets the "name" field.
func (_u *ApiKeyUpdateOne) SetName(v string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetName(v string) *APIKeyUpdateOne {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableName(v *string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableName(v *string) *APIKeyUpdateOne {
if v != nil {
_u.SetName(*v)
}
@@ -483,13 +483,13 @@ func (_u *ApiKeyUpdateOne) SetNillableName(v *string) *ApiKeyUpdateOne {
}
// SetGroupID sets the "group_id" field.
func (_u *ApiKeyUpdateOne) SetGroupID(v int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetGroupID(v int64) *APIKeyUpdateOne {
_u.mutation.SetGroupID(v)
return _u
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableGroupID(v *int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableGroupID(v *int64) *APIKeyUpdateOne {
if v != nil {
_u.SetGroupID(*v)
}
@@ -497,19 +497,19 @@ func (_u *ApiKeyUpdateOne) SetNillableGroupID(v *int64) *ApiKeyUpdateOne {
}
// ClearGroupID clears the value of the "group_id" field.
func (_u *ApiKeyUpdateOne) ClearGroupID() *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) ClearGroupID() *APIKeyUpdateOne {
_u.mutation.ClearGroupID()
return _u
}
// SetStatus sets the "status" field.
func (_u *ApiKeyUpdateOne) SetStatus(v string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetStatus(v string) *APIKeyUpdateOne {
_u.mutation.SetStatus(v)
return _u
}
// SetNillableStatus sets the "status" field if the given value is not nil.
func (_u *ApiKeyUpdateOne) SetNillableStatus(v *string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetNillableStatus(v *string) *APIKeyUpdateOne {
if v != nil {
_u.SetStatus(*v)
}
@@ -517,23 +517,23 @@ func (_u *ApiKeyUpdateOne) SetNillableStatus(v *string) *ApiKeyUpdateOne {
}
// SetUser sets the "user" edge to the User entity.
func (_u *ApiKeyUpdateOne) SetUser(v *User) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetUser(v *User) *APIKeyUpdateOne {
return _u.SetUserID(v.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (_u *ApiKeyUpdateOne) SetGroup(v *Group) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) SetGroup(v *Group) *APIKeyUpdateOne {
return _u.SetGroupID(v.ID)
}
// AddUsageLogIDs adds the "usage_logs" edge to the UsageLog entity by IDs.
func (_u *ApiKeyUpdateOne) AddUsageLogIDs(ids ...int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) AddUsageLogIDs(ids ...int64) *APIKeyUpdateOne {
_u.mutation.AddUsageLogIDs(ids...)
return _u
}
// AddUsageLogs adds the "usage_logs" edges to the UsageLog entity.
func (_u *ApiKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *APIKeyUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -541,37 +541,37 @@ func (_u *ApiKeyUpdateOne) AddUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
return _u.AddUsageLogIDs(ids...)
}
// Mutation returns the ApiKeyMutation object of the builder.
func (_u *ApiKeyUpdateOne) Mutation() *ApiKeyMutation {
// Mutation returns the APIKeyMutation object of the builder.
func (_u *APIKeyUpdateOne) Mutation() *APIKeyMutation {
return _u.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (_u *ApiKeyUpdateOne) ClearUser() *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) ClearUser() *APIKeyUpdateOne {
_u.mutation.ClearUser()
return _u
}
// ClearGroup clears the "group" edge to the Group entity.
func (_u *ApiKeyUpdateOne) ClearGroup() *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) ClearGroup() *APIKeyUpdateOne {
_u.mutation.ClearGroup()
return _u
}
// ClearUsageLogs clears all "usage_logs" edges to the UsageLog entity.
func (_u *ApiKeyUpdateOne) ClearUsageLogs() *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) ClearUsageLogs() *APIKeyUpdateOne {
_u.mutation.ClearUsageLogs()
return _u
}
// RemoveUsageLogIDs removes the "usage_logs" edge to UsageLog entities by IDs.
func (_u *ApiKeyUpdateOne) RemoveUsageLogIDs(ids ...int64) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) RemoveUsageLogIDs(ids ...int64) *APIKeyUpdateOne {
_u.mutation.RemoveUsageLogIDs(ids...)
return _u
}
// RemoveUsageLogs removes "usage_logs" edges to UsageLog entities.
func (_u *ApiKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *APIKeyUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -579,21 +579,21 @@ func (_u *ApiKeyUpdateOne) RemoveUsageLogs(v ...*UsageLog) *ApiKeyUpdateOne {
return _u.RemoveUsageLogIDs(ids...)
}
// Where appends a list predicates to the ApiKeyUpdate builder.
func (_u *ApiKeyUpdateOne) Where(ps ...predicate.ApiKey) *ApiKeyUpdateOne {
// Where appends a list predicates to the APIKeyUpdate builder.
func (_u *APIKeyUpdateOne) Where(ps ...predicate.APIKey) *APIKeyUpdateOne {
_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 *ApiKeyUpdateOne) Select(field string, fields ...string) *ApiKeyUpdateOne {
func (_u *APIKeyUpdateOne) Select(field string, fields ...string) *APIKeyUpdateOne {
_u.fields = append([]string{field}, fields...)
return _u
}
// Save executes the query and returns the updated ApiKey entity.
func (_u *ApiKeyUpdateOne) Save(ctx context.Context) (*ApiKey, error) {
// Save executes the query and returns the updated APIKey entity.
func (_u *APIKeyUpdateOne) Save(ctx context.Context) (*APIKey, error) {
if err := _u.defaults(); err != nil {
return nil, err
}
@@ -601,7 +601,7 @@ func (_u *ApiKeyUpdateOne) Save(ctx context.Context) (*ApiKey, error) {
}
// SaveX is like Save, but panics if an error occurs.
func (_u *ApiKeyUpdateOne) SaveX(ctx context.Context) *ApiKey {
func (_u *APIKeyUpdateOne) SaveX(ctx context.Context) *APIKey {
node, err := _u.Save(ctx)
if err != nil {
panic(err)
@@ -610,20 +610,20 @@ func (_u *ApiKeyUpdateOne) SaveX(ctx context.Context) *ApiKey {
}
// Exec executes the query on the entity.
func (_u *ApiKeyUpdateOne) Exec(ctx context.Context) error {
func (_u *APIKeyUpdateOne) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *ApiKeyUpdateOne) ExecX(ctx context.Context) {
func (_u *APIKeyUpdateOne) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *ApiKeyUpdateOne) defaults() error {
func (_u *APIKeyUpdateOne) defaults() error {
if _, ok := _u.mutation.UpdatedAt(); !ok {
if apikey.UpdateDefaultUpdatedAt == nil {
return fmt.Errorf("ent: uninitialized apikey.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
@@ -635,36 +635,36 @@ func (_u *ApiKeyUpdateOne) defaults() error {
}
// check runs all checks and user-defined validators on the builder.
func (_u *ApiKeyUpdateOne) check() error {
func (_u *APIKeyUpdateOne) check() error {
if v, ok := _u.mutation.Key(); ok {
if err := apikey.KeyValidator(v); err != nil {
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "ApiKey.key": %w`, err)}
return &ValidationError{Name: "key", err: fmt.Errorf(`ent: validator failed for field "APIKey.key": %w`, err)}
}
}
if v, ok := _u.mutation.Name(); ok {
if err := apikey.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ApiKey.name": %w`, err)}
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "APIKey.name": %w`, err)}
}
}
if v, ok := _u.mutation.Status(); ok {
if err := apikey.StatusValidator(v); err != nil {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "ApiKey.status": %w`, err)}
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
}
}
if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "ApiKey.user"`)
return errors.New(`ent: clearing a required unique edge "APIKey.user"`)
}
return nil
}
func (_u *ApiKeyUpdateOne) sqlSave(ctx context.Context) (_node *ApiKey, err error) {
func (_u *APIKeyUpdateOne) sqlSave(ctx context.Context) (_node *APIKey, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(apikey.Table, apikey.Columns, sqlgraph.NewFieldSpec(apikey.FieldID, field.TypeInt64))
id, ok := _u.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ApiKey.id" for update`)}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "APIKey.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := _u.fields; len(fields) > 0 {
@@ -807,7 +807,7 @@ func (_u *ApiKeyUpdateOne) sqlSave(ctx context.Context) (_node *ApiKey, err erro
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &ApiKey{config: _u.config}
_node = &APIKey{config: _u.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {

View File

@@ -37,12 +37,12 @@ type Client struct {
config
// Schema is the client for creating, migrating and dropping schema.
Schema *migrate.Schema
// APIKey is the client for interacting with the APIKey builders.
APIKey *APIKeyClient
// Account is the client for interacting with the Account builders.
Account *AccountClient
// AccountGroup is the client for interacting with the AccountGroup builders.
AccountGroup *AccountGroupClient
// ApiKey is the client for interacting with the ApiKey builders.
ApiKey *ApiKeyClient
// Group is the client for interacting with the Group builders.
Group *GroupClient
// Proxy is the client for interacting with the Proxy builders.
@@ -74,9 +74,9 @@ func NewClient(opts ...Option) *Client {
func (c *Client) init() {
c.Schema = migrate.NewSchema(c.driver)
c.APIKey = NewAPIKeyClient(c.config)
c.Account = NewAccountClient(c.config)
c.AccountGroup = NewAccountGroupClient(c.config)
c.ApiKey = NewApiKeyClient(c.config)
c.Group = NewGroupClient(c.config)
c.Proxy = NewProxyClient(c.config)
c.RedeemCode = NewRedeemCodeClient(c.config)
@@ -179,9 +179,9 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
return &Tx{
ctx: ctx,
config: cfg,
APIKey: NewAPIKeyClient(cfg),
Account: NewAccountClient(cfg),
AccountGroup: NewAccountGroupClient(cfg),
ApiKey: NewApiKeyClient(cfg),
Group: NewGroupClient(cfg),
Proxy: NewProxyClient(cfg),
RedeemCode: NewRedeemCodeClient(cfg),
@@ -211,9 +211,9 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
return &Tx{
ctx: ctx,
config: cfg,
APIKey: NewAPIKeyClient(cfg),
Account: NewAccountClient(cfg),
AccountGroup: NewAccountGroupClient(cfg),
ApiKey: NewApiKeyClient(cfg),
Group: NewGroupClient(cfg),
Proxy: NewProxyClient(cfg),
RedeemCode: NewRedeemCodeClient(cfg),
@@ -230,7 +230,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
//
// client.Debug().
// Account.
// APIKey.
// Query().
// Count(ctx)
func (c *Client) Debug() *Client {
@@ -253,7 +253,7 @@ func (c *Client) Close() error {
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...Hook) }{
c.Account, c.AccountGroup, c.ApiKey, c.Group, c.Proxy, c.RedeemCode, c.Setting,
c.APIKey, c.Account, c.AccountGroup, c.Group, c.Proxy, c.RedeemCode, c.Setting,
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
c.UserAttributeValue, c.UserSubscription,
} {
@@ -265,7 +265,7 @@ func (c *Client) Use(hooks ...Hook) {
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...Interceptor) }{
c.Account, c.AccountGroup, c.ApiKey, c.Group, c.Proxy, c.RedeemCode, c.Setting,
c.APIKey, c.Account, c.AccountGroup, c.Group, c.Proxy, c.RedeemCode, c.Setting,
c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition,
c.UserAttributeValue, c.UserSubscription,
} {
@@ -276,12 +276,12 @@ func (c *Client) Intercept(interceptors ...Interceptor) {
// Mutate implements the ent.Mutator interface.
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
switch m := m.(type) {
case *APIKeyMutation:
return c.APIKey.mutate(ctx, m)
case *AccountMutation:
return c.Account.mutate(ctx, m)
case *AccountGroupMutation:
return c.AccountGroup.mutate(ctx, m)
case *ApiKeyMutation:
return c.ApiKey.mutate(ctx, m)
case *GroupMutation:
return c.Group.mutate(ctx, m)
case *ProxyMutation:
@@ -307,6 +307,189 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
}
}
// APIKeyClient is a client for the APIKey schema.
type APIKeyClient struct {
config
}
// NewAPIKeyClient returns a client for the APIKey from the given config.
func NewAPIKeyClient(c config) *APIKeyClient {
return &APIKeyClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `apikey.Hooks(f(g(h())))`.
func (c *APIKeyClient) Use(hooks ...Hook) {
c.hooks.APIKey = append(c.hooks.APIKey, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `apikey.Intercept(f(g(h())))`.
func (c *APIKeyClient) Intercept(interceptors ...Interceptor) {
c.inters.APIKey = append(c.inters.APIKey, interceptors...)
}
// Create returns a builder for creating a APIKey entity.
func (c *APIKeyClient) Create() *APIKeyCreate {
mutation := newAPIKeyMutation(c.config, OpCreate)
return &APIKeyCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of APIKey entities.
func (c *APIKeyClient) CreateBulk(builders ...*APIKeyCreate) *APIKeyCreateBulk {
return &APIKeyCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *APIKeyClient) MapCreateBulk(slice any, setFunc func(*APIKeyCreate, int)) *APIKeyCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &APIKeyCreateBulk{err: fmt.Errorf("calling to APIKeyClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*APIKeyCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &APIKeyCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for APIKey.
func (c *APIKeyClient) Update() *APIKeyUpdate {
mutation := newAPIKeyMutation(c.config, OpUpdate)
return &APIKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *APIKeyClient) UpdateOne(_m *APIKey) *APIKeyUpdateOne {
mutation := newAPIKeyMutation(c.config, OpUpdateOne, withAPIKey(_m))
return &APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *APIKeyClient) UpdateOneID(id int64) *APIKeyUpdateOne {
mutation := newAPIKeyMutation(c.config, OpUpdateOne, withAPIKeyID(id))
return &APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for APIKey.
func (c *APIKeyClient) Delete() *APIKeyDelete {
mutation := newAPIKeyMutation(c.config, OpDelete)
return &APIKeyDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *APIKeyClient) DeleteOne(_m *APIKey) *APIKeyDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *APIKeyClient) DeleteOneID(id int64) *APIKeyDeleteOne {
builder := c.Delete().Where(apikey.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &APIKeyDeleteOne{builder}
}
// Query returns a query builder for APIKey.
func (c *APIKeyClient) Query() *APIKeyQuery {
return &APIKeyQuery{
config: c.config,
ctx: &QueryContext{Type: TypeAPIKey},
inters: c.Interceptors(),
}
}
// Get returns a APIKey entity by its id.
func (c *APIKeyClient) Get(ctx context.Context, id int64) (*APIKey, error) {
return c.Query().Where(apikey.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *APIKeyClient) GetX(ctx context.Context, id int64) *APIKey {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUser queries the user edge of a APIKey.
func (c *APIKeyClient) QueryUser(_m *APIKey) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, apikey.UserTable, apikey.UserColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryGroup queries the group edge of a APIKey.
func (c *APIKeyClient) QueryGroup(_m *APIKey) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, apikey.GroupTable, apikey.GroupColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryUsageLogs queries the usage_logs edge of a APIKey.
func (c *APIKeyClient) QueryUsageLogs(_m *APIKey) *UsageLogQuery {
query := (&UsageLogClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(usagelog.Table, usagelog.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, apikey.UsageLogsTable, apikey.UsageLogsColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *APIKeyClient) Hooks() []Hook {
hooks := c.hooks.APIKey
return append(hooks[:len(hooks):len(hooks)], apikey.Hooks[:]...)
}
// Interceptors returns the client interceptors.
func (c *APIKeyClient) Interceptors() []Interceptor {
inters := c.inters.APIKey
return append(inters[:len(inters):len(inters)], apikey.Interceptors[:]...)
}
func (c *APIKeyClient) mutate(ctx context.Context, m *APIKeyMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&APIKeyCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&APIKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&APIKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&APIKeyDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown APIKey mutation op: %q", m.Op())
}
}
// AccountClient is a client for the Account schema.
type AccountClient struct {
config
@@ -622,189 +805,6 @@ func (c *AccountGroupClient) mutate(ctx context.Context, m *AccountGroupMutation
}
}
// ApiKeyClient is a client for the ApiKey schema.
type ApiKeyClient struct {
config
}
// NewApiKeyClient returns a client for the ApiKey from the given config.
func NewApiKeyClient(c config) *ApiKeyClient {
return &ApiKeyClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `apikey.Hooks(f(g(h())))`.
func (c *ApiKeyClient) Use(hooks ...Hook) {
c.hooks.ApiKey = append(c.hooks.ApiKey, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `apikey.Intercept(f(g(h())))`.
func (c *ApiKeyClient) Intercept(interceptors ...Interceptor) {
c.inters.ApiKey = append(c.inters.ApiKey, interceptors...)
}
// Create returns a builder for creating a ApiKey entity.
func (c *ApiKeyClient) Create() *ApiKeyCreate {
mutation := newApiKeyMutation(c.config, OpCreate)
return &ApiKeyCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of ApiKey entities.
func (c *ApiKeyClient) CreateBulk(builders ...*ApiKeyCreate) *ApiKeyCreateBulk {
return &ApiKeyCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *ApiKeyClient) MapCreateBulk(slice any, setFunc func(*ApiKeyCreate, int)) *ApiKeyCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &ApiKeyCreateBulk{err: fmt.Errorf("calling to ApiKeyClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*ApiKeyCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &ApiKeyCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for ApiKey.
func (c *ApiKeyClient) Update() *ApiKeyUpdate {
mutation := newApiKeyMutation(c.config, OpUpdate)
return &ApiKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *ApiKeyClient) UpdateOne(_m *ApiKey) *ApiKeyUpdateOne {
mutation := newApiKeyMutation(c.config, OpUpdateOne, withApiKey(_m))
return &ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *ApiKeyClient) UpdateOneID(id int64) *ApiKeyUpdateOne {
mutation := newApiKeyMutation(c.config, OpUpdateOne, withApiKeyID(id))
return &ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for ApiKey.
func (c *ApiKeyClient) Delete() *ApiKeyDelete {
mutation := newApiKeyMutation(c.config, OpDelete)
return &ApiKeyDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *ApiKeyClient) DeleteOne(_m *ApiKey) *ApiKeyDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *ApiKeyClient) DeleteOneID(id int64) *ApiKeyDeleteOne {
builder := c.Delete().Where(apikey.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &ApiKeyDeleteOne{builder}
}
// Query returns a query builder for ApiKey.
func (c *ApiKeyClient) Query() *ApiKeyQuery {
return &ApiKeyQuery{
config: c.config,
ctx: &QueryContext{Type: TypeApiKey},
inters: c.Interceptors(),
}
}
// Get returns a ApiKey entity by its id.
func (c *ApiKeyClient) Get(ctx context.Context, id int64) (*ApiKey, error) {
return c.Query().Where(apikey.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *ApiKeyClient) GetX(ctx context.Context, id int64) *ApiKey {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUser queries the user edge of a ApiKey.
func (c *ApiKeyClient) QueryUser(_m *ApiKey) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, apikey.UserTable, apikey.UserColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryGroup queries the group edge of a ApiKey.
func (c *ApiKeyClient) QueryGroup(_m *ApiKey) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, apikey.GroupTable, apikey.GroupColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryUsageLogs queries the usage_logs edge of a ApiKey.
func (c *ApiKeyClient) QueryUsageLogs(_m *ApiKey) *UsageLogQuery {
query := (&UsageLogClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(apikey.Table, apikey.FieldID, id),
sqlgraph.To(usagelog.Table, usagelog.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, apikey.UsageLogsTable, apikey.UsageLogsColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *ApiKeyClient) Hooks() []Hook {
hooks := c.hooks.ApiKey
return append(hooks[:len(hooks):len(hooks)], apikey.Hooks[:]...)
}
// Interceptors returns the client interceptors.
func (c *ApiKeyClient) Interceptors() []Interceptor {
inters := c.inters.ApiKey
return append(inters[:len(inters):len(inters)], apikey.Interceptors[:]...)
}
func (c *ApiKeyClient) mutate(ctx context.Context, m *ApiKeyMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&ApiKeyCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&ApiKeyUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&ApiKeyUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&ApiKeyDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown ApiKey mutation op: %q", m.Op())
}
}
// GroupClient is a client for the Group schema.
type GroupClient struct {
config
@@ -914,8 +914,8 @@ func (c *GroupClient) GetX(ctx context.Context, id int64) *Group {
}
// QueryAPIKeys queries the api_keys edge of a Group.
func (c *GroupClient) QueryAPIKeys(_m *Group) *ApiKeyQuery {
query := (&ApiKeyClient{config: c.config}).Query()
func (c *GroupClient) QueryAPIKeys(_m *Group) *APIKeyQuery {
query := (&APIKeyClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
@@ -1642,8 +1642,8 @@ func (c *UsageLogClient) QueryUser(_m *UsageLog) *UserQuery {
}
// QueryAPIKey queries the api_key edge of a UsageLog.
func (c *UsageLogClient) QueryAPIKey(_m *UsageLog) *ApiKeyQuery {
query := (&ApiKeyClient{config: c.config}).Query()
func (c *UsageLogClient) QueryAPIKey(_m *UsageLog) *APIKeyQuery {
query := (&APIKeyClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
@@ -1839,8 +1839,8 @@ func (c *UserClient) GetX(ctx context.Context, id int64) *User {
}
// QueryAPIKeys queries the api_keys edge of a User.
func (c *UserClient) QueryAPIKeys(_m *User) *ApiKeyQuery {
query := (&ApiKeyClient{config: c.config}).Query()
func (c *UserClient) QueryAPIKeys(_m *User) *APIKeyQuery {
query := (&APIKeyClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
@@ -2627,12 +2627,12 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription
// hooks and interceptors per client, for fast access.
type (
hooks struct {
Account, AccountGroup, ApiKey, Group, Proxy, RedeemCode, Setting, UsageLog,
APIKey, Account, AccountGroup, Group, Proxy, RedeemCode, Setting, UsageLog,
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
UserSubscription []ent.Hook
}
inters struct {
Account, AccountGroup, ApiKey, Group, Proxy, RedeemCode, Setting, UsageLog,
APIKey, Account, AccountGroup, Group, Proxy, RedeemCode, Setting, UsageLog,
User, UserAllowedGroup, UserAttributeDefinition, UserAttributeValue,
UserSubscription []ent.Interceptor
}

View File

@@ -85,9 +85,9 @@ 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,
apikey.Table: apikey.ValidColumn,
group.Table: group.ValidColumn,
proxy.Table: proxy.ValidColumn,
redeemcode.Table: redeemcode.ValidColumn,

View File

@@ -1,3 +1,4 @@
// Package ent provides the generated ORM code for database entities.
package ent
// 启用 sql/execquery 以生成 ExecContext/QueryContext 的透传接口,便于事务内执行原生 SQL。

View File

@@ -54,7 +54,7 @@ type Group struct {
// GroupEdges holds the relations/edges for other nodes in the graph.
type GroupEdges struct {
// APIKeys holds the value of the api_keys edge.
APIKeys []*ApiKey `json:"api_keys,omitempty"`
APIKeys []*APIKey `json:"api_keys,omitempty"`
// RedeemCodes holds the value of the redeem_codes edge.
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
// Subscriptions holds the value of the subscriptions edge.
@@ -76,7 +76,7 @@ type GroupEdges struct {
// APIKeysOrErr returns the APIKeys value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) APIKeysOrErr() ([]*ApiKey, error) {
func (e GroupEdges) APIKeysOrErr() ([]*APIKey, error) {
if e.loadedTypes[0] {
return e.APIKeys, nil
}
@@ -285,7 +285,7 @@ func (_m *Group) Value(name string) (ent.Value, error) {
}
// QueryAPIKeys queries the "api_keys" edge of the Group entity.
func (_m *Group) QueryAPIKeys() *ApiKeyQuery {
func (_m *Group) QueryAPIKeys() *APIKeyQuery {
return NewGroupClient(_m.config).QueryAPIKeys(_m)
}

View File

@@ -63,7 +63,7 @@ const (
Table = "groups"
// APIKeysTable is the table that holds the api_keys relation/edge.
APIKeysTable = "api_keys"
// APIKeysInverseTable is the table name for the ApiKey entity.
// APIKeysInverseTable is the table name for the APIKey entity.
// It exists in this package in order to avoid circular dependency with the "apikey" package.
APIKeysInverseTable = "api_keys"
// APIKeysColumn is the table column denoting the api_keys relation/edge.

View File

@@ -842,7 +842,7 @@ func HasAPIKeys() predicate.Group {
}
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
func HasAPIKeysWith(preds ...predicate.ApiKey) predicate.Group {
func HasAPIKeysWith(preds ...predicate.APIKey) predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := newAPIKeysStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {

View File

@@ -216,14 +216,14 @@ func (_c *GroupCreate) SetNillableDefaultValidityDays(v *int) *GroupCreate {
return _c
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
_c.mutation.AddAPIKeyIDs(ids...)
return _c
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_c *GroupCreate) AddAPIKeys(v ...*ApiKey) *GroupCreate {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_c *GroupCreate) AddAPIKeys(v ...*APIKey) *GroupCreate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID

View File

@@ -31,7 +31,7 @@ type GroupQuery struct {
order []group.OrderOption
inters []Interceptor
predicates []predicate.Group
withAPIKeys *ApiKeyQuery
withAPIKeys *APIKeyQuery
withRedeemCodes *RedeemCodeQuery
withSubscriptions *UserSubscriptionQuery
withUsageLogs *UsageLogQuery
@@ -76,8 +76,8 @@ func (_q *GroupQuery) Order(o ...group.OrderOption) *GroupQuery {
}
// QueryAPIKeys chains the current query on the "api_keys" edge.
func (_q *GroupQuery) QueryAPIKeys() *ApiKeyQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *GroupQuery) QueryAPIKeys() *APIKeyQuery {
query := (&APIKeyClient{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
@@ -459,8 +459,8 @@ func (_q *GroupQuery) Clone() *GroupQuery {
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *GroupQuery) WithAPIKeys(opts ...func(*ApiKeyQuery)) *GroupQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *GroupQuery) WithAPIKeys(opts ...func(*APIKeyQuery)) *GroupQuery {
query := (&APIKeyClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
@@ -654,8 +654,8 @@ func (_q *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
}
if query := _q.withAPIKeys; query != nil {
if err := _q.loadAPIKeys(ctx, query, nodes,
func(n *Group) { n.Edges.APIKeys = []*ApiKey{} },
func(n *Group, e *ApiKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
func(n *Group) { n.Edges.APIKeys = []*APIKey{} },
func(n *Group, e *APIKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
return nil, err
}
}
@@ -711,7 +711,7 @@ func (_q *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
return nodes, nil
}
func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes []*Group, init func(*Group), assign func(*Group, *ApiKey)) error {
func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *APIKeyQuery, nodes []*Group, init func(*Group), assign func(*Group, *APIKey)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*Group)
for i := range nodes {
@@ -724,7 +724,7 @@ func (_q *GroupQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes
if len(query.ctx.Fields) > 0 {
query.ctx.AppendFieldOnce(apikey.FieldGroupID)
}
query.Where(predicate.ApiKey(func(s *sql.Selector) {
query.Where(predicate.APIKey(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(group.APIKeysColumn), fks...))
}))
neighbors, err := query.All(ctx)

View File

@@ -273,14 +273,14 @@ func (_u *GroupUpdate) AddDefaultValidityDays(v int) *GroupUpdate {
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
_u.mutation.AddAPIKeyIDs(ids...)
return _u
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_u *GroupUpdate) AddAPIKeys(v ...*ApiKey) *GroupUpdate {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_u *GroupUpdate) AddAPIKeys(v ...*APIKey) *GroupUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -368,20 +368,20 @@ func (_u *GroupUpdate) Mutation() *GroupMutation {
return _u.mutation
}
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
func (_u *GroupUpdate) ClearAPIKeys() *GroupUpdate {
_u.mutation.ClearAPIKeys()
return _u
}
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
func (_u *GroupUpdate) RemoveAPIKeyIDs(ids ...int64) *GroupUpdate {
_u.mutation.RemoveAPIKeyIDs(ids...)
return _u
}
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
func (_u *GroupUpdate) RemoveAPIKeys(v ...*ApiKey) *GroupUpdate {
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
func (_u *GroupUpdate) RemoveAPIKeys(v ...*APIKey) *GroupUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -1195,14 +1195,14 @@ func (_u *GroupUpdateOne) AddDefaultValidityDays(v int) *GroupUpdateOne {
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
_u.mutation.AddAPIKeyIDs(ids...)
return _u
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_u *GroupUpdateOne) AddAPIKeys(v ...*ApiKey) *GroupUpdateOne {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_u *GroupUpdateOne) AddAPIKeys(v ...*APIKey) *GroupUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -1290,20 +1290,20 @@ func (_u *GroupUpdateOne) Mutation() *GroupMutation {
return _u.mutation
}
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
func (_u *GroupUpdateOne) ClearAPIKeys() *GroupUpdateOne {
_u.mutation.ClearAPIKeys()
return _u
}
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
func (_u *GroupUpdateOne) RemoveAPIKeyIDs(ids ...int64) *GroupUpdateOne {
_u.mutation.RemoveAPIKeyIDs(ids...)
return _u
}
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
func (_u *GroupUpdateOne) RemoveAPIKeys(v ...*ApiKey) *GroupUpdateOne {
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
func (_u *GroupUpdateOne) RemoveAPIKeys(v ...*APIKey) *GroupUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID

View File

@@ -9,6 +9,18 @@ import (
"github.com/Wei-Shaw/sub2api/ent"
)
// The APIKeyFunc type is an adapter to allow the use of ordinary
// function as APIKey mutator.
type APIKeyFunc func(context.Context, *ent.APIKeyMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f APIKeyFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.APIKeyMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.APIKeyMutation", m)
}
// The AccountFunc type is an adapter to allow the use of ordinary
// function as Account mutator.
type AccountFunc func(context.Context, *ent.AccountMutation) (ent.Value, error)
@@ -33,18 +45,6 @@ func (f AccountGroupFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AccountGroupMutation", m)
}
// The ApiKeyFunc type is an adapter to allow the use of ordinary
// function as ApiKey mutator.
type ApiKeyFunc func(context.Context, *ent.ApiKeyMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f ApiKeyFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.ApiKeyMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ApiKeyMutation", m)
}
// The GroupFunc type is an adapter to allow the use of ordinary
// function as Group mutator.
type GroupFunc func(context.Context, *ent.GroupMutation) (ent.Value, error)

View File

@@ -80,6 +80,33 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error {
return f(ctx, query)
}
// The APIKeyFunc type is an adapter to allow the use of ordinary function as a Querier.
type APIKeyFunc func(context.Context, *ent.APIKeyQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f APIKeyFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.APIKeyQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.APIKeyQuery", q)
}
// The TraverseAPIKey type is an adapter to allow the use of ordinary function as Traverser.
type TraverseAPIKey func(context.Context, *ent.APIKeyQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraverseAPIKey) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraverseAPIKey) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.APIKeyQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.APIKeyQuery", q)
}
// The AccountFunc type is an adapter to allow the use of ordinary function as a Querier.
type AccountFunc func(context.Context, *ent.AccountQuery) (ent.Value, error)
@@ -134,33 +161,6 @@ func (f TraverseAccountGroup) Traverse(ctx context.Context, q ent.Query) error {
return fmt.Errorf("unexpected query type %T. expect *ent.AccountGroupQuery", q)
}
// The ApiKeyFunc type is an adapter to allow the use of ordinary function as a Querier.
type ApiKeyFunc func(context.Context, *ent.ApiKeyQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f ApiKeyFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.ApiKeyQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.ApiKeyQuery", q)
}
// The TraverseApiKey type is an adapter to allow the use of ordinary function as Traverser.
type TraverseApiKey func(context.Context, *ent.ApiKeyQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraverseApiKey) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraverseApiKey) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.ApiKeyQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.ApiKeyQuery", q)
}
// The GroupFunc type is an adapter to allow the use of ordinary function as a Querier.
type GroupFunc func(context.Context, *ent.GroupQuery) (ent.Value, error)
@@ -434,12 +434,12 @@ func (f TraverseUserSubscription) Traverse(ctx context.Context, q ent.Query) err
// NewQuery returns the generic Query interface for the given typed query.
func NewQuery(q ent.Query) (Query, error) {
switch q := q.(type) {
case *ent.APIKeyQuery:
return &query[*ent.APIKeyQuery, predicate.APIKey, apikey.OrderOption]{typ: ent.TypeAPIKey, tq: q}, nil
case *ent.AccountQuery:
return &query[*ent.AccountQuery, predicate.Account, account.OrderOption]{typ: ent.TypeAccount, tq: q}, nil
case *ent.AccountGroupQuery:
return &query[*ent.AccountGroupQuery, predicate.AccountGroup, accountgroup.OrderOption]{typ: ent.TypeAccountGroup, tq: q}, nil
case *ent.ApiKeyQuery:
return &query[*ent.ApiKeyQuery, predicate.ApiKey, apikey.OrderOption]{typ: ent.TypeApiKey, tq: q}, nil
case *ent.GroupQuery:
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
case *ent.ProxyQuery:

View File

@@ -9,6 +9,60 @@ import (
)
var (
// APIKeysColumns holds the columns for the "api_keys" table.
APIKeysColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "key", Type: field.TypeString, Unique: true, Size: 128},
{Name: "name", Type: field.TypeString, Size: 100},
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
{Name: "user_id", Type: field.TypeInt64},
}
// APIKeysTable holds the schema information for the "api_keys" table.
APIKeysTable = &schema.Table{
Name: "api_keys",
Columns: APIKeysColumns,
PrimaryKey: []*schema.Column{APIKeysColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "api_keys_groups_api_keys",
Columns: []*schema.Column{APIKeysColumns[7]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "api_keys_users_api_keys",
Columns: []*schema.Column{APIKeysColumns[8]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
Indexes: []*schema.Index{
{
Name: "apikey_user_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[8]},
},
{
Name: "apikey_group_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[7]},
},
{
Name: "apikey_status",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[6]},
},
{
Name: "apikey_deleted_at",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[3]},
},
},
}
// AccountsColumns holds the columns for the "accounts" table.
AccountsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
@@ -144,60 +198,6 @@ var (
},
},
}
// APIKeysColumns holds the columns for the "api_keys" table.
APIKeysColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "key", Type: field.TypeString, Unique: true, Size: 128},
{Name: "name", Type: field.TypeString, Size: 100},
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
{Name: "user_id", Type: field.TypeInt64},
}
// APIKeysTable holds the schema information for the "api_keys" table.
APIKeysTable = &schema.Table{
Name: "api_keys",
Columns: APIKeysColumns,
PrimaryKey: []*schema.Column{APIKeysColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "api_keys_groups_api_keys",
Columns: []*schema.Column{APIKeysColumns[7]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "api_keys_users_api_keys",
Columns: []*schema.Column{APIKeysColumns[8]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
Indexes: []*schema.Index{
{
Name: "apikey_user_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[8]},
},
{
Name: "apikey_group_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[7]},
},
{
Name: "apikey_status",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[6]},
},
{
Name: "apikey_deleted_at",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[3]},
},
},
}
// GroupsColumns holds the columns for the "groups" table.
GroupsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
@@ -368,8 +368,8 @@ var (
{Name: "duration_ms", Type: field.TypeInt, Nullable: true},
{Name: "first_token_ms", Type: field.TypeInt, Nullable: true},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "account_id", Type: field.TypeInt64},
{Name: "api_key_id", Type: field.TypeInt64},
{Name: "account_id", Type: field.TypeInt64},
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
{Name: "user_id", Type: field.TypeInt64},
{Name: "subscription_id", Type: field.TypeInt64, Nullable: true},
@@ -381,15 +381,15 @@ var (
PrimaryKey: []*schema.Column{UsageLogsColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "usage_logs_accounts_usage_logs",
Symbol: "usage_logs_api_keys_usage_logs",
Columns: []*schema.Column{UsageLogsColumns[21]},
RefColumns: []*schema.Column{AccountsColumns[0]},
RefColumns: []*schema.Column{APIKeysColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "usage_logs_api_keys_usage_logs",
Symbol: "usage_logs_accounts_usage_logs",
Columns: []*schema.Column{UsageLogsColumns[22]},
RefColumns: []*schema.Column{APIKeysColumns[0]},
RefColumns: []*schema.Column{AccountsColumns[0]},
OnDelete: schema.NoAction,
},
{
@@ -420,12 +420,12 @@ var (
{
Name: "usagelog_api_key_id",
Unique: false,
Columns: []*schema.Column{UsageLogsColumns[22]},
Columns: []*schema.Column{UsageLogsColumns[21]},
},
{
Name: "usagelog_account_id",
Unique: false,
Columns: []*schema.Column{UsageLogsColumns[21]},
Columns: []*schema.Column{UsageLogsColumns[22]},
},
{
Name: "usagelog_group_id",
@@ -460,7 +460,7 @@ var (
{
Name: "usagelog_api_key_id_created_at",
Unique: false,
Columns: []*schema.Column{UsageLogsColumns[22], UsageLogsColumns[20]},
Columns: []*schema.Column{UsageLogsColumns[21], UsageLogsColumns[20]},
},
},
}
@@ -702,9 +702,9 @@ var (
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
APIKeysTable,
AccountsTable,
AccountGroupsTable,
APIKeysTable,
GroupsTable,
ProxiesTable,
RedeemCodesTable,
@@ -719,6 +719,11 @@ var (
)
func init() {
APIKeysTable.ForeignKeys[0].RefTable = GroupsTable
APIKeysTable.ForeignKeys[1].RefTable = UsersTable
APIKeysTable.Annotation = &entsql.Annotation{
Table: "api_keys",
}
AccountsTable.ForeignKeys[0].RefTable = ProxiesTable
AccountsTable.Annotation = &entsql.Annotation{
Table: "accounts",
@@ -728,11 +733,6 @@ func init() {
AccountGroupsTable.Annotation = &entsql.Annotation{
Table: "account_groups",
}
APIKeysTable.ForeignKeys[0].RefTable = GroupsTable
APIKeysTable.ForeignKeys[1].RefTable = UsersTable
APIKeysTable.Annotation = &entsql.Annotation{
Table: "api_keys",
}
GroupsTable.Annotation = &entsql.Annotation{
Table: "groups",
}
@@ -747,8 +747,8 @@ func init() {
SettingsTable.Annotation = &entsql.Annotation{
Table: "settings",
}
UsageLogsTable.ForeignKeys[0].RefTable = AccountsTable
UsageLogsTable.ForeignKeys[1].RefTable = APIKeysTable
UsageLogsTable.ForeignKeys[0].RefTable = APIKeysTable
UsageLogsTable.ForeignKeys[1].RefTable = AccountsTable
UsageLogsTable.ForeignKeys[2].RefTable = GroupsTable
UsageLogsTable.ForeignKeys[3].RefTable = UsersTable
UsageLogsTable.ForeignKeys[4].RefTable = UserSubscriptionsTable

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,15 @@ import (
"entgo.io/ent/dialect/sql"
)
// APIKey is the predicate function for apikey builders.
type APIKey func(*sql.Selector)
// Account is the predicate function for account builders.
type Account func(*sql.Selector)
// AccountGroup is the predicate function for accountgroup builders.
type AccountGroup func(*sql.Selector)
// ApiKey is the predicate function for apikey builders.
type ApiKey func(*sql.Selector)
// Group is the predicate function for group builders.
type Group func(*sql.Selector)

View File

@@ -25,6 +25,67 @@ import (
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
apikeyMixin := schema.APIKey{}.Mixin()
apikeyMixinHooks1 := apikeyMixin[1].Hooks()
apikey.Hooks[0] = apikeyMixinHooks1[0]
apikeyMixinInters1 := apikeyMixin[1].Interceptors()
apikey.Interceptors[0] = apikeyMixinInters1[0]
apikeyMixinFields0 := apikeyMixin[0].Fields()
_ = apikeyMixinFields0
apikeyFields := schema.APIKey{}.Fields()
_ = apikeyFields
// apikeyDescCreatedAt is the schema descriptor for created_at field.
apikeyDescCreatedAt := apikeyMixinFields0[0].Descriptor()
// apikey.DefaultCreatedAt holds the default value on creation for the created_at field.
apikey.DefaultCreatedAt = apikeyDescCreatedAt.Default.(func() time.Time)
// apikeyDescUpdatedAt is the schema descriptor for updated_at field.
apikeyDescUpdatedAt := apikeyMixinFields0[1].Descriptor()
// apikey.DefaultUpdatedAt holds the default value on creation for the updated_at field.
apikey.DefaultUpdatedAt = apikeyDescUpdatedAt.Default.(func() time.Time)
// apikey.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
apikey.UpdateDefaultUpdatedAt = apikeyDescUpdatedAt.UpdateDefault.(func() time.Time)
// apikeyDescKey is the schema descriptor for key field.
apikeyDescKey := apikeyFields[1].Descriptor()
// apikey.KeyValidator is a validator for the "key" field. It is called by the builders before save.
apikey.KeyValidator = func() func(string) error {
validators := apikeyDescKey.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(key string) error {
for _, fn := range fns {
if err := fn(key); err != nil {
return err
}
}
return nil
}
}()
// apikeyDescName is the schema descriptor for name field.
apikeyDescName := apikeyFields[2].Descriptor()
// apikey.NameValidator is a validator for the "name" field. It is called by the builders before save.
apikey.NameValidator = func() func(string) error {
validators := apikeyDescName.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(name string) error {
for _, fn := range fns {
if err := fn(name); err != nil {
return err
}
}
return nil
}
}()
// apikeyDescStatus is the schema descriptor for status field.
apikeyDescStatus := apikeyFields[4].Descriptor()
// apikey.DefaultStatus holds the default value on creation for the status field.
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
// apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save.
apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error)
accountMixin := schema.Account{}.Mixin()
accountMixinHooks1 := accountMixin[1].Hooks()
account.Hooks[0] = accountMixinHooks1[0]
@@ -138,67 +199,6 @@ func init() {
accountgroupDescCreatedAt := accountgroupFields[3].Descriptor()
// accountgroup.DefaultCreatedAt holds the default value on creation for the created_at field.
accountgroup.DefaultCreatedAt = accountgroupDescCreatedAt.Default.(func() time.Time)
apikeyMixin := schema.ApiKey{}.Mixin()
apikeyMixinHooks1 := apikeyMixin[1].Hooks()
apikey.Hooks[0] = apikeyMixinHooks1[0]
apikeyMixinInters1 := apikeyMixin[1].Interceptors()
apikey.Interceptors[0] = apikeyMixinInters1[0]
apikeyMixinFields0 := apikeyMixin[0].Fields()
_ = apikeyMixinFields0
apikeyFields := schema.ApiKey{}.Fields()
_ = apikeyFields
// apikeyDescCreatedAt is the schema descriptor for created_at field.
apikeyDescCreatedAt := apikeyMixinFields0[0].Descriptor()
// apikey.DefaultCreatedAt holds the default value on creation for the created_at field.
apikey.DefaultCreatedAt = apikeyDescCreatedAt.Default.(func() time.Time)
// apikeyDescUpdatedAt is the schema descriptor for updated_at field.
apikeyDescUpdatedAt := apikeyMixinFields0[1].Descriptor()
// apikey.DefaultUpdatedAt holds the default value on creation for the updated_at field.
apikey.DefaultUpdatedAt = apikeyDescUpdatedAt.Default.(func() time.Time)
// apikey.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
apikey.UpdateDefaultUpdatedAt = apikeyDescUpdatedAt.UpdateDefault.(func() time.Time)
// apikeyDescKey is the schema descriptor for key field.
apikeyDescKey := apikeyFields[1].Descriptor()
// apikey.KeyValidator is a validator for the "key" field. It is called by the builders before save.
apikey.KeyValidator = func() func(string) error {
validators := apikeyDescKey.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(key string) error {
for _, fn := range fns {
if err := fn(key); err != nil {
return err
}
}
return nil
}
}()
// apikeyDescName is the schema descriptor for name field.
apikeyDescName := apikeyFields[2].Descriptor()
// apikey.NameValidator is a validator for the "name" field. It is called by the builders before save.
apikey.NameValidator = func() func(string) error {
validators := apikeyDescName.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(name string) error {
for _, fn := range fns {
if err := fn(name); err != nil {
return err
}
}
return nil
}
}()
// apikeyDescStatus is the schema descriptor for status field.
apikeyDescStatus := apikeyFields[4].Descriptor()
// apikey.DefaultStatus holds the default value on creation for the status field.
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
// apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save.
apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error)
groupMixin := schema.Group{}.Mixin()
groupMixinHooks1 := groupMixin[1].Hooks()
group.Hooks[0] = groupMixinHooks1[0]

View File

@@ -12,25 +12,25 @@ import (
"entgo.io/ent/schema/index"
)
// ApiKey holds the schema definition for the ApiKey entity.
type ApiKey struct {
// APIKey holds the schema definition for the APIKey entity.
type APIKey struct {
ent.Schema
}
func (ApiKey) Annotations() []schema.Annotation {
func (APIKey) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "api_keys"},
}
}
func (ApiKey) Mixin() []ent.Mixin {
func (APIKey) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.TimeMixin{},
mixins.SoftDeleteMixin{},
}
}
func (ApiKey) Fields() []ent.Field {
func (APIKey) Fields() []ent.Field {
return []ent.Field{
field.Int64("user_id"),
field.String("key").
@@ -49,7 +49,7 @@ func (ApiKey) Fields() []ent.Field {
}
}
func (ApiKey) Edges() []ent.Edge {
func (APIKey) Edges() []ent.Edge {
return []ent.Edge{
edge.From("user", User.Type).
Ref("api_keys").
@@ -64,7 +64,7 @@ func (ApiKey) Edges() []ent.Edge {
}
}
func (ApiKey) Indexes() []ent.Index {
func (APIKey) Indexes() []ent.Index {
return []ent.Index{
// key 字段已在 Fields() 中声明 Unique(),无需重复索引
index.Fields("user_id"),

View File

@@ -77,7 +77,7 @@ func (Group) Fields() []ent.Field {
func (Group) Edges() []ent.Edge {
return []ent.Edge{
edge.To("api_keys", ApiKey.Type),
edge.To("api_keys", APIKey.Type),
edge.To("redeem_codes", RedeemCode.Type),
edge.To("subscriptions", UserSubscription.Type),
edge.To("usage_logs", UsageLog.Type),

View File

@@ -113,7 +113,7 @@ func (UsageLog) Edges() []ent.Edge {
Field("user_id").
Required().
Unique(),
edge.From("api_key", ApiKey.Type).
edge.From("api_key", APIKey.Type).
Ref("usage_logs").
Field("api_key_id").
Required().

View File

@@ -66,7 +66,7 @@ func (User) Fields() []ent.Field {
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("api_keys", ApiKey.Type),
edge.To("api_keys", APIKey.Type),
edge.To("redeem_codes", RedeemCode.Type),
edge.To("subscriptions", UserSubscription.Type),
edge.To("assigned_subscriptions", UserSubscription.Type),

View File

@@ -14,12 +14,12 @@ import (
// Tx is a transactional client that is created by calling Client.Tx().
type Tx struct {
config
// APIKey is the client for interacting with the APIKey builders.
APIKey *APIKeyClient
// Account is the client for interacting with the Account builders.
Account *AccountClient
// AccountGroup is the client for interacting with the AccountGroup builders.
AccountGroup *AccountGroupClient
// ApiKey is the client for interacting with the ApiKey builders.
ApiKey *ApiKeyClient
// Group is the client for interacting with the Group builders.
Group *GroupClient
// Proxy is the client for interacting with the Proxy builders.
@@ -171,9 +171,9 @@ func (tx *Tx) Client() *Client {
}
func (tx *Tx) init() {
tx.APIKey = NewAPIKeyClient(tx.config)
tx.Account = NewAccountClient(tx.config)
tx.AccountGroup = NewAccountGroupClient(tx.config)
tx.ApiKey = NewApiKeyClient(tx.config)
tx.Group = NewGroupClient(tx.config)
tx.Proxy = NewProxyClient(tx.config)
tx.RedeemCode = NewRedeemCodeClient(tx.config)
@@ -193,7 +193,7 @@ func (tx *Tx) init() {
// of them in order to commit or rollback the transaction.
//
// If a closed transaction is embedded in one of the generated entities, and the entity
// applies a query, for example: Account.QueryXXX(), the query will be executed
// applies a query, for example: APIKey.QueryXXX(), the query will be executed
// through the driver which created this transaction.
//
// Note that txDriver is not goroutine safe.

View File

@@ -83,7 +83,7 @@ type UsageLogEdges struct {
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// APIKey holds the value of the api_key edge.
APIKey *ApiKey `json:"api_key,omitempty"`
APIKey *APIKey `json:"api_key,omitempty"`
// Account holds the value of the account edge.
Account *Account `json:"account,omitempty"`
// Group holds the value of the group edge.
@@ -108,7 +108,7 @@ func (e UsageLogEdges) UserOrErr() (*User, error) {
// APIKeyOrErr returns the APIKey value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e UsageLogEdges) APIKeyOrErr() (*ApiKey, error) {
func (e UsageLogEdges) APIKeyOrErr() (*APIKey, error) {
if e.APIKey != nil {
return e.APIKey, nil
} else if e.loadedTypes[1] {
@@ -359,7 +359,7 @@ func (_m *UsageLog) QueryUser() *UserQuery {
}
// QueryAPIKey queries the "api_key" edge of the UsageLog entity.
func (_m *UsageLog) QueryAPIKey() *ApiKeyQuery {
func (_m *UsageLog) QueryAPIKey() *APIKeyQuery {
return NewUsageLogClient(_m.config).QueryAPIKey(_m)
}

View File

@@ -85,7 +85,7 @@ const (
UserColumn = "user_id"
// APIKeyTable is the table that holds the api_key relation/edge.
APIKeyTable = "usage_logs"
// APIKeyInverseTable is the table name for the ApiKey entity.
// APIKeyInverseTable is the table name for the APIKey entity.
// It exists in this package in order to avoid circular dependency with the "apikey" package.
APIKeyInverseTable = "api_keys"
// APIKeyColumn is the table column denoting the api_key relation/edge.

View File

@@ -1175,7 +1175,7 @@ func HasAPIKey() predicate.UsageLog {
}
// HasAPIKeyWith applies the HasEdge predicate on the "api_key" edge with a given conditions (other predicates).
func HasAPIKeyWith(preds ...predicate.ApiKey) predicate.UsageLog {
func HasAPIKeyWith(preds ...predicate.APIKey) predicate.UsageLog {
return predicate.UsageLog(func(s *sql.Selector) {
step := newAPIKeyStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {

View File

@@ -342,8 +342,8 @@ func (_c *UsageLogCreate) SetUser(v *User) *UsageLogCreate {
return _c.SetUserID(v.ID)
}
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
func (_c *UsageLogCreate) SetAPIKey(v *ApiKey) *UsageLogCreate {
// SetAPIKey sets the "api_key" edge to the APIKey entity.
func (_c *UsageLogCreate) SetAPIKey(v *APIKey) *UsageLogCreate {
return _c.SetAPIKeyID(v.ID)
}

View File

@@ -28,7 +28,7 @@ type UsageLogQuery struct {
inters []Interceptor
predicates []predicate.UsageLog
withUser *UserQuery
withAPIKey *ApiKeyQuery
withAPIKey *APIKeyQuery
withAccount *AccountQuery
withGroup *GroupQuery
withSubscription *UserSubscriptionQuery
@@ -91,8 +91,8 @@ func (_q *UsageLogQuery) QueryUser() *UserQuery {
}
// QueryAPIKey chains the current query on the "api_key" edge.
func (_q *UsageLogQuery) QueryAPIKey() *ApiKeyQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *UsageLogQuery) QueryAPIKey() *APIKeyQuery {
query := (&APIKeyClient{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
@@ -394,8 +394,8 @@ func (_q *UsageLogQuery) WithUser(opts ...func(*UserQuery)) *UsageLogQuery {
// WithAPIKey tells the query-builder to eager-load the nodes that are connected to
// the "api_key" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UsageLogQuery) WithAPIKey(opts ...func(*ApiKeyQuery)) *UsageLogQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *UsageLogQuery) WithAPIKey(opts ...func(*APIKeyQuery)) *UsageLogQuery {
query := (&APIKeyClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
@@ -548,7 +548,7 @@ func (_q *UsageLogQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Usa
}
if query := _q.withAPIKey; query != nil {
if err := _q.loadAPIKey(ctx, query, nodes, nil,
func(n *UsageLog, e *ApiKey) { n.Edges.APIKey = e }); err != nil {
func(n *UsageLog, e *APIKey) { n.Edges.APIKey = e }); err != nil {
return nil, err
}
}
@@ -602,7 +602,7 @@ func (_q *UsageLogQuery) loadUser(ctx context.Context, query *UserQuery, nodes [
}
return nil
}
func (_q *UsageLogQuery) loadAPIKey(ctx context.Context, query *ApiKeyQuery, nodes []*UsageLog, init func(*UsageLog), assign func(*UsageLog, *ApiKey)) error {
func (_q *UsageLogQuery) loadAPIKey(ctx context.Context, query *APIKeyQuery, nodes []*UsageLog, init func(*UsageLog), assign func(*UsageLog, *APIKey)) error {
ids := make([]int64, 0, len(nodes))
nodeids := make(map[int64][]*UsageLog)
for i := range nodes {

View File

@@ -509,8 +509,8 @@ func (_u *UsageLogUpdate) SetUser(v *User) *UsageLogUpdate {
return _u.SetUserID(v.ID)
}
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
func (_u *UsageLogUpdate) SetAPIKey(v *ApiKey) *UsageLogUpdate {
// SetAPIKey sets the "api_key" edge to the APIKey entity.
func (_u *UsageLogUpdate) SetAPIKey(v *APIKey) *UsageLogUpdate {
return _u.SetAPIKeyID(v.ID)
}
@@ -540,7 +540,7 @@ func (_u *UsageLogUpdate) ClearUser() *UsageLogUpdate {
return _u
}
// ClearAPIKey clears the "api_key" edge to the ApiKey entity.
// ClearAPIKey clears the "api_key" edge to the APIKey entity.
func (_u *UsageLogUpdate) ClearAPIKey() *UsageLogUpdate {
_u.mutation.ClearAPIKey()
return _u
@@ -1380,8 +1380,8 @@ func (_u *UsageLogUpdateOne) SetUser(v *User) *UsageLogUpdateOne {
return _u.SetUserID(v.ID)
}
// SetAPIKey sets the "api_key" edge to the ApiKey entity.
func (_u *UsageLogUpdateOne) SetAPIKey(v *ApiKey) *UsageLogUpdateOne {
// SetAPIKey sets the "api_key" edge to the APIKey entity.
func (_u *UsageLogUpdateOne) SetAPIKey(v *APIKey) *UsageLogUpdateOne {
return _u.SetAPIKeyID(v.ID)
}
@@ -1411,7 +1411,7 @@ func (_u *UsageLogUpdateOne) ClearUser() *UsageLogUpdateOne {
return _u
}
// ClearAPIKey clears the "api_key" edge to the ApiKey entity.
// ClearAPIKey clears the "api_key" edge to the APIKey entity.
func (_u *UsageLogUpdateOne) ClearAPIKey() *UsageLogUpdateOne {
_u.mutation.ClearAPIKey()
return _u

View File

@@ -48,7 +48,7 @@ type User struct {
// UserEdges holds the relations/edges for other nodes in the graph.
type UserEdges struct {
// APIKeys holds the value of the api_keys edge.
APIKeys []*ApiKey `json:"api_keys,omitempty"`
APIKeys []*APIKey `json:"api_keys,omitempty"`
// RedeemCodes holds the value of the redeem_codes edge.
RedeemCodes []*RedeemCode `json:"redeem_codes,omitempty"`
// Subscriptions holds the value of the subscriptions edge.
@@ -70,7 +70,7 @@ type UserEdges struct {
// APIKeysOrErr returns the APIKeys value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) APIKeysOrErr() ([]*ApiKey, error) {
func (e UserEdges) APIKeysOrErr() ([]*APIKey, error) {
if e.loadedTypes[0] {
return e.APIKeys, nil
}
@@ -255,7 +255,7 @@ func (_m *User) Value(name string) (ent.Value, error) {
}
// QueryAPIKeys queries the "api_keys" edge of the User entity.
func (_m *User) QueryAPIKeys() *ApiKeyQuery {
func (_m *User) QueryAPIKeys() *APIKeyQuery {
return NewUserClient(_m.config).QueryAPIKeys(_m)
}

View File

@@ -57,7 +57,7 @@ const (
Table = "users"
// APIKeysTable is the table that holds the api_keys relation/edge.
APIKeysTable = "api_keys"
// APIKeysInverseTable is the table name for the ApiKey entity.
// APIKeysInverseTable is the table name for the APIKey entity.
// It exists in this package in order to avoid circular dependency with the "apikey" package.
APIKeysInverseTable = "api_keys"
// APIKeysColumn is the table column denoting the api_keys relation/edge.

View File

@@ -722,7 +722,7 @@ func HasAPIKeys() predicate.User {
}
// HasAPIKeysWith applies the HasEdge predicate on the "api_keys" edge with a given conditions (other predicates).
func HasAPIKeysWith(preds ...predicate.ApiKey) predicate.User {
func HasAPIKeysWith(preds ...predicate.APIKey) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newAPIKeysStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {

View File

@@ -166,14 +166,14 @@ func (_c *UserCreate) SetNillableNotes(v *string) *UserCreate {
return _c
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_c *UserCreate) AddAPIKeyIDs(ids ...int64) *UserCreate {
_c.mutation.AddAPIKeyIDs(ids...)
return _c
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_c *UserCreate) AddAPIKeys(v ...*ApiKey) *UserCreate {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_c *UserCreate) AddAPIKeys(v ...*APIKey) *UserCreate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID

View File

@@ -30,7 +30,7 @@ type UserQuery struct {
order []user.OrderOption
inters []Interceptor
predicates []predicate.User
withAPIKeys *ApiKeyQuery
withAPIKeys *APIKeyQuery
withRedeemCodes *RedeemCodeQuery
withSubscriptions *UserSubscriptionQuery
withAssignedSubscriptions *UserSubscriptionQuery
@@ -75,8 +75,8 @@ func (_q *UserQuery) Order(o ...user.OrderOption) *UserQuery {
}
// QueryAPIKeys chains the current query on the "api_keys" edge.
func (_q *UserQuery) QueryAPIKeys() *ApiKeyQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *UserQuery) QueryAPIKeys() *APIKeyQuery {
query := (&APIKeyClient{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
@@ -458,8 +458,8 @@ func (_q *UserQuery) Clone() *UserQuery {
// WithAPIKeys tells the query-builder to eager-load the nodes that are connected to
// the "api_keys" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UserQuery) WithAPIKeys(opts ...func(*ApiKeyQuery)) *UserQuery {
query := (&ApiKeyClient{config: _q.config}).Query()
func (_q *UserQuery) WithAPIKeys(opts ...func(*APIKeyQuery)) *UserQuery {
query := (&APIKeyClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
@@ -653,8 +653,8 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
}
if query := _q.withAPIKeys; query != nil {
if err := _q.loadAPIKeys(ctx, query, nodes,
func(n *User) { n.Edges.APIKeys = []*ApiKey{} },
func(n *User, e *ApiKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
func(n *User) { n.Edges.APIKeys = []*APIKey{} },
func(n *User, e *APIKey) { n.Edges.APIKeys = append(n.Edges.APIKeys, e) }); err != nil {
return nil, err
}
}
@@ -712,7 +712,7 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nodes, nil
}
func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes []*User, init func(*User), assign func(*User, *ApiKey)) error {
func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *APIKeyQuery, nodes []*User, init func(*User), assign func(*User, *APIKey)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*User)
for i := range nodes {
@@ -725,7 +725,7 @@ func (_q *UserQuery) loadAPIKeys(ctx context.Context, query *ApiKeyQuery, nodes
if len(query.ctx.Fields) > 0 {
query.ctx.AppendFieldOnce(apikey.FieldUserID)
}
query.Where(predicate.ApiKey(func(s *sql.Selector) {
query.Where(predicate.APIKey(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(user.APIKeysColumn), fks...))
}))
neighbors, err := query.All(ctx)

View File

@@ -186,14 +186,14 @@ func (_u *UserUpdate) SetNillableNotes(v *string) *UserUpdate {
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *UserUpdate) AddAPIKeyIDs(ids ...int64) *UserUpdate {
_u.mutation.AddAPIKeyIDs(ids...)
return _u
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_u *UserUpdate) AddAPIKeys(v ...*ApiKey) *UserUpdate {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_u *UserUpdate) AddAPIKeys(v ...*APIKey) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -296,20 +296,20 @@ func (_u *UserUpdate) Mutation() *UserMutation {
return _u.mutation
}
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
func (_u *UserUpdate) ClearAPIKeys() *UserUpdate {
_u.mutation.ClearAPIKeys()
return _u
}
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
func (_u *UserUpdate) RemoveAPIKeyIDs(ids ...int64) *UserUpdate {
_u.mutation.RemoveAPIKeyIDs(ids...)
return _u
}
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
func (_u *UserUpdate) RemoveAPIKeys(v ...*ApiKey) *UserUpdate {
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
func (_u *UserUpdate) RemoveAPIKeys(v ...*APIKey) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -1065,14 +1065,14 @@ func (_u *UserUpdateOne) SetNillableNotes(v *string) *UserUpdateOne {
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the ApiKey entity by IDs.
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *UserUpdateOne) AddAPIKeyIDs(ids ...int64) *UserUpdateOne {
_u.mutation.AddAPIKeyIDs(ids...)
return _u
}
// AddAPIKeys adds the "api_keys" edges to the ApiKey entity.
func (_u *UserUpdateOne) AddAPIKeys(v ...*ApiKey) *UserUpdateOne {
// AddAPIKeys adds the "api_keys" edges to the APIKey entity.
func (_u *UserUpdateOne) AddAPIKeys(v ...*APIKey) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
@@ -1175,20 +1175,20 @@ func (_u *UserUpdateOne) Mutation() *UserMutation {
return _u.mutation
}
// ClearAPIKeys clears all "api_keys" edges to the ApiKey entity.
// ClearAPIKeys clears all "api_keys" edges to the APIKey entity.
func (_u *UserUpdateOne) ClearAPIKeys() *UserUpdateOne {
_u.mutation.ClearAPIKeys()
return _u
}
// RemoveAPIKeyIDs removes the "api_keys" edge to ApiKey entities by IDs.
// RemoveAPIKeyIDs removes the "api_keys" edge to APIKey entities by IDs.
func (_u *UserUpdateOne) RemoveAPIKeyIDs(ids ...int64) *UserUpdateOne {
_u.mutation.RemoveAPIKeyIDs(ids...)
return _u
}
// RemoveAPIKeys removes "api_keys" edges to ApiKey entities.
func (_u *UserUpdateOne) RemoveAPIKeys(v ...*ApiKey) *UserUpdateOne {
// RemoveAPIKeys removes "api_keys" edges to APIKey entities.
func (_u *UserUpdateOne) RemoveAPIKeys(v ...*APIKey) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID

View File

@@ -1,3 +1,4 @@
// Package config provides configuration loading, defaults, and validation.
package config
import (
@@ -139,7 +140,7 @@ type GatewayConfig struct {
LogUpstreamErrorBodyMaxBytes int `mapstructure:"log_upstream_error_body_max_bytes"`
// API-key 账号在客户端未提供 anthropic-beta 时,是否按需自动补齐(默认关闭以保持兼容)
InjectBetaForApiKey bool `mapstructure:"inject_beta_for_apikey"`
InjectBetaForAPIKey bool `mapstructure:"inject_beta_for_apikey"`
// 是否允许对部分 400 错误触发 failover默认关闭以避免改变语义
FailoverOn400 bool `mapstructure:"failover_on_400"`
@@ -241,7 +242,7 @@ type DefaultConfig struct {
AdminPassword string `mapstructure:"admin_password"`
UserConcurrency int `mapstructure:"user_concurrency"`
UserBalance float64 `mapstructure:"user_balance"`
ApiKeyPrefix string `mapstructure:"api_key_prefix"`
APIKeyPrefix string `mapstructure:"api_key_prefix"`
RateMultiplier float64 `mapstructure:"rate_multiplier"`
}

View File

@@ -1,9 +1,12 @@
// Package admin provides HTTP handlers for administrative operations.
package admin
import (
"errors"
"strconv"
"strings"
"sync"
"time"
"github.com/Wei-Shaw/sub2api/internal/handler/dto"
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
@@ -69,42 +72,45 @@ func NewAccountHandler(
// CreateAccountRequest represents create account request
type CreateAccountRequest struct {
Name string `json:"name" binding:"required"`
Platform string `json:"platform" binding:"required"`
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey"`
Credentials map[string]any `json:"credentials" binding:"required"`
Extra map[string]any `json:"extra"`
ProxyID *int64 `json:"proxy_id"`
Concurrency int `json:"concurrency"`
Priority int `json:"priority"`
GroupIDs []int64 `json:"group_ids"`
Name string `json:"name" binding:"required"`
Platform string `json:"platform" binding:"required"`
Type string `json:"type" binding:"required,oneof=oauth setup-token apikey"`
Credentials map[string]any `json:"credentials" binding:"required"`
Extra map[string]any `json:"extra"`
ProxyID *int64 `json:"proxy_id"`
Concurrency int `json:"concurrency"`
Priority int `json:"priority"`
GroupIDs []int64 `json:"group_ids"`
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
}
// UpdateAccountRequest represents update account request
// 使用指针类型来区分"未提供"和"设置为0"
type UpdateAccountRequest struct {
Name string `json:"name"`
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
Credentials map[string]any `json:"credentials"`
Extra map[string]any `json:"extra"`
ProxyID *int64 `json:"proxy_id"`
Concurrency *int `json:"concurrency"`
Priority *int `json:"priority"`
Status string `json:"status" binding:"omitempty,oneof=active inactive"`
GroupIDs *[]int64 `json:"group_ids"`
Name string `json:"name"`
Type string `json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
Credentials map[string]any `json:"credentials"`
Extra map[string]any `json:"extra"`
ProxyID *int64 `json:"proxy_id"`
Concurrency *int `json:"concurrency"`
Priority *int `json:"priority"`
Status string `json:"status" binding:"omitempty,oneof=active inactive"`
GroupIDs *[]int64 `json:"group_ids"`
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
}
// BulkUpdateAccountsRequest represents the payload for bulk editing accounts
type BulkUpdateAccountsRequest struct {
AccountIDs []int64 `json:"account_ids" binding:"required,min=1"`
Name string `json:"name"`
ProxyID *int64 `json:"proxy_id"`
Concurrency *int `json:"concurrency"`
Priority *int `json:"priority"`
Status string `json:"status" binding:"omitempty,oneof=active inactive error"`
GroupIDs *[]int64 `json:"group_ids"`
Credentials map[string]any `json:"credentials"`
Extra map[string]any `json:"extra"`
AccountIDs []int64 `json:"account_ids" binding:"required,min=1"`
Name string `json:"name"`
ProxyID *int64 `json:"proxy_id"`
Concurrency *int `json:"concurrency"`
Priority *int `json:"priority"`
Status string `json:"status" binding:"omitempty,oneof=active inactive error"`
GroupIDs *[]int64 `json:"group_ids"`
Credentials map[string]any `json:"credentials"`
Extra map[string]any `json:"extra"`
ConfirmMixedChannelRisk *bool `json:"confirm_mixed_channel_risk"` // 用户确认混合渠道风险
}
// AccountWithConcurrency extends Account with real-time concurrency info
@@ -179,18 +185,40 @@ func (h *AccountHandler) Create(c *gin.Context) {
return
}
// 确定是否跳过混合渠道检查
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
account, err := h.adminService.CreateAccount(c.Request.Context(), &service.CreateAccountInput{
Name: req.Name,
Platform: req.Platform,
Type: req.Type,
Credentials: req.Credentials,
Extra: req.Extra,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency,
Priority: req.Priority,
GroupIDs: req.GroupIDs,
Name: req.Name,
Platform: req.Platform,
Type: req.Type,
Credentials: req.Credentials,
Extra: req.Extra,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency,
Priority: req.Priority,
GroupIDs: req.GroupIDs,
SkipMixedChannelCheck: skipCheck,
})
if err != nil {
// 检查是否为混合渠道错误
var mixedErr *service.MixedChannelError
if errors.As(err, &mixedErr) {
// 返回特殊错误码要求确认
c.JSON(409, gin.H{
"error": "mixed_channel_warning",
"message": mixedErr.Error(),
"details": gin.H{
"group_id": mixedErr.GroupID,
"group_name": mixedErr.GroupName,
"current_platform": mixedErr.CurrentPlatform,
"other_platform": mixedErr.OtherPlatform,
},
"require_confirmation": true,
})
return
}
response.ErrorFrom(c, err)
return
}
@@ -213,18 +241,40 @@ func (h *AccountHandler) Update(c *gin.Context) {
return
}
// 确定是否跳过混合渠道检查
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
account, err := h.adminService.UpdateAccount(c.Request.Context(), accountID, &service.UpdateAccountInput{
Name: req.Name,
Type: req.Type,
Credentials: req.Credentials,
Extra: req.Extra,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency, // 指针类型nil 表示未提供
Priority: req.Priority, // 指针类型nil 表示未提供
Status: req.Status,
GroupIDs: req.GroupIDs,
Name: req.Name,
Type: req.Type,
Credentials: req.Credentials,
Extra: req.Extra,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency, // 指针类型nil 表示未提供
Priority: req.Priority, // 指针类型nil 表示未提供
Status: req.Status,
GroupIDs: req.GroupIDs,
SkipMixedChannelCheck: skipCheck,
})
if err != nil {
// 检查是否为混合渠道错误
var mixedErr *service.MixedChannelError
if errors.As(err, &mixedErr) {
// 返回特殊错误码要求确认
c.JSON(409, gin.H{
"error": "mixed_channel_warning",
"message": mixedErr.Error(),
"details": gin.H{
"group_id": mixedErr.GroupID,
"group_name": mixedErr.GroupName,
"current_platform": mixedErr.CurrentPlatform,
"other_platform": mixedErr.OtherPlatform,
},
"require_confirmation": true,
})
return
}
response.ErrorFrom(c, err)
return
}
@@ -568,6 +618,9 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
return
}
// 确定是否跳过混合渠道检查
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
hasUpdates := req.Name != "" ||
req.ProxyID != nil ||
req.Concurrency != nil ||
@@ -583,15 +636,16 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
}
result, err := h.adminService.BulkUpdateAccounts(c.Request.Context(), &service.BulkUpdateAccountsInput{
AccountIDs: req.AccountIDs,
Name: req.Name,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency,
Priority: req.Priority,
Status: req.Status,
GroupIDs: req.GroupIDs,
Credentials: req.Credentials,
Extra: req.Extra,
AccountIDs: req.AccountIDs,
Name: req.Name,
ProxyID: req.ProxyID,
Concurrency: req.Concurrency,
Priority: req.Priority,
Status: req.Status,
GroupIDs: req.GroupIDs,
Credentials: req.Credentials,
Extra: req.Extra,
SkipMixedChannelCheck: skipCheck,
})
if err != nil {
response.ErrorFrom(c, err)
@@ -781,6 +835,49 @@ func (h *AccountHandler) ClearRateLimit(c *gin.Context) {
response.Success(c, gin.H{"message": "Rate limit cleared successfully"})
}
// GetTempUnschedulable handles getting temporary unschedulable status
// GET /api/v1/admin/accounts/:id/temp-unschedulable
func (h *AccountHandler) GetTempUnschedulable(c *gin.Context) {
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "Invalid account ID")
return
}
state, err := h.rateLimitService.GetTempUnschedStatus(c.Request.Context(), accountID)
if err != nil {
response.ErrorFrom(c, err)
return
}
if state == nil || state.UntilUnix <= time.Now().Unix() {
response.Success(c, gin.H{"active": false})
return
}
response.Success(c, gin.H{
"active": true,
"state": state,
})
}
// ClearTempUnschedulable handles clearing temporary unschedulable status
// DELETE /api/v1/admin/accounts/:id/temp-unschedulable
func (h *AccountHandler) ClearTempUnschedulable(c *gin.Context) {
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "Invalid account ID")
return
}
if err := h.rateLimitService.ClearTempUnschedulable(c.Request.Context(), accountID); err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{"message": "Temp unschedulable cleared successfully"})
}
// GetTodayStats handles getting account today statistics
// GET /api/v1/admin/accounts/:id/today-stats
func (h *AccountHandler) GetTodayStats(c *gin.Context) {

View File

@@ -75,8 +75,8 @@ func (h *DashboardHandler) GetStats(c *gin.Context) {
"active_users": stats.ActiveUsers,
// API Key 统计
"total_api_keys": stats.TotalApiKeys,
"active_api_keys": stats.ActiveApiKeys,
"total_api_keys": stats.TotalAPIKeys,
"active_api_keys": stats.ActiveAPIKeys,
// 账户统计
"total_accounts": stats.TotalAccounts,
@@ -193,10 +193,10 @@ func (h *DashboardHandler) GetModelStats(c *gin.Context) {
})
}
// GetApiKeyUsageTrend handles getting API key usage trend data
// GetAPIKeyUsageTrend handles getting API key usage trend data
// GET /api/v1/admin/dashboard/api-keys-trend
// Query params: start_date, end_date (YYYY-MM-DD), granularity (day/hour), limit (default 5)
func (h *DashboardHandler) GetApiKeyUsageTrend(c *gin.Context) {
func (h *DashboardHandler) GetAPIKeyUsageTrend(c *gin.Context) {
startTime, endTime := parseTimeRange(c)
granularity := c.DefaultQuery("granularity", "day")
limitStr := c.DefaultQuery("limit", "5")
@@ -205,7 +205,7 @@ func (h *DashboardHandler) GetApiKeyUsageTrend(c *gin.Context) {
limit = 5
}
trend, err := h.dashboardService.GetApiKeyUsageTrend(c.Request.Context(), startTime, endTime, granularity, limit)
trend, err := h.dashboardService.GetAPIKeyUsageTrend(c.Request.Context(), startTime, endTime, granularity, limit)
if err != nil {
response.Error(c, 500, "Failed to get API key usage trend")
return
@@ -273,26 +273,26 @@ func (h *DashboardHandler) GetBatchUsersUsage(c *gin.Context) {
response.Success(c, gin.H{"stats": stats})
}
// BatchApiKeysUsageRequest represents the request body for batch api key usage stats
type BatchApiKeysUsageRequest struct {
ApiKeyIDs []int64 `json:"api_key_ids" binding:"required"`
// BatchAPIKeysUsageRequest represents the request body for batch api key usage stats
type BatchAPIKeysUsageRequest struct {
APIKeyIDs []int64 `json:"api_key_ids" binding:"required"`
}
// GetBatchApiKeysUsage handles getting usage stats for multiple API keys
// GetBatchAPIKeysUsage handles getting usage stats for multiple API keys
// POST /api/v1/admin/dashboard/api-keys-usage
func (h *DashboardHandler) GetBatchApiKeysUsage(c *gin.Context) {
var req BatchApiKeysUsageRequest
func (h *DashboardHandler) GetBatchAPIKeysUsage(c *gin.Context) {
var req BatchAPIKeysUsageRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
if len(req.ApiKeyIDs) == 0 {
if len(req.APIKeyIDs) == 0 {
response.Success(c, gin.H{"stats": map[string]any{}})
return
}
stats, err := h.dashboardService.GetBatchApiKeyUsageStats(c.Request.Context(), req.ApiKeyIDs)
stats, err := h.dashboardService.GetBatchAPIKeyUsageStats(c.Request.Context(), req.APIKeyIDs)
if err != nil {
response.Error(c, 500, "Failed to get API key usage stats")
return

View File

@@ -18,6 +18,7 @@ func NewGeminiOAuthHandler(geminiOAuthService *service.GeminiOAuthService) *Gemi
return &GeminiOAuthHandler{geminiOAuthService: geminiOAuthService}
}
// GetCapabilities returns the Gemini OAuth configuration capabilities.
// GET /api/v1/admin/gemini/oauth/capabilities
func (h *GeminiOAuthHandler) GetCapabilities(c *gin.Context) {
cfg := h.geminiOAuthService.GetOAuthConfig()
@@ -30,6 +31,8 @@ type GeminiGenerateAuthURLRequest struct {
// OAuth 类型: "code_assist" (需要 project_id) 或 "ai_studio" (不需要 project_id)
// 默认为 "code_assist" 以保持向后兼容
OAuthType string `json:"oauth_type"`
// TierID is a user-selected tier to be used when auto detection is unavailable or fails.
TierID string `json:"tier_id"`
}
// GenerateAuthURL generates Google OAuth authorization URL for Gemini.
@@ -54,7 +57,7 @@ func (h *GeminiOAuthHandler) GenerateAuthURL(c *gin.Context) {
// Always pass the "hosted" callback URI; the OAuth service may override it depending on
// oauth_type and whether the built-in Gemini CLI OAuth client is used.
redirectURI := deriveGeminiRedirectURI(c)
result, err := h.geminiOAuthService.GenerateAuthURL(c.Request.Context(), req.ProxyID, redirectURI, req.ProjectID, oauthType)
result, err := h.geminiOAuthService.GenerateAuthURL(c.Request.Context(), req.ProxyID, redirectURI, req.ProjectID, oauthType, req.TierID)
if err != nil {
msg := err.Error()
// Treat missing/invalid OAuth client configuration as a user/config error.
@@ -76,6 +79,9 @@ type GeminiExchangeCodeRequest struct {
ProxyID *int64 `json:"proxy_id"`
// OAuth 类型: "code_assist" 或 "ai_studio",需要与 GenerateAuthURL 时的类型一致
OAuthType string `json:"oauth_type"`
// TierID is a user-selected tier to be used when auto detection is unavailable or fails.
// This field is optional; when omitted, the server uses the tier stored in the OAuth session.
TierID string `json:"tier_id"`
}
// ExchangeCode exchanges authorization code for tokens.
@@ -103,6 +109,7 @@ func (h *GeminiOAuthHandler) ExchangeCode(c *gin.Context) {
Code: req.Code,
ProxyID: req.ProxyID,
OAuthType: oauthType,
TierID: req.TierID,
})
if err != nil {
response.BadRequest(c, "Failed to exchange code: "+err.Error())

View File

@@ -237,9 +237,9 @@ func (h *GroupHandler) GetGroupAPIKeys(c *gin.Context) {
return
}
outKeys := make([]dto.ApiKey, 0, len(keys))
outKeys := make([]dto.APIKey, 0, len(keys))
for i := range keys {
outKeys = append(outKeys, *dto.ApiKeyFromService(&keys[i]))
outKeys = append(outKeys, *dto.APIKeyFromService(&keys[i]))
}
response.Paginated(c, outKeys, total, page, pageSize)
}

View File

@@ -34,26 +34,31 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
}
response.Success(c, dto.SystemSettings{
RegistrationEnabled: settings.RegistrationEnabled,
EmailVerifyEnabled: settings.EmailVerifyEnabled,
SmtpHost: settings.SmtpHost,
SmtpPort: settings.SmtpPort,
SmtpUsername: settings.SmtpUsername,
SmtpPassword: settings.SmtpPassword,
SmtpFrom: settings.SmtpFrom,
SmtpFromName: settings.SmtpFromName,
SmtpUseTLS: settings.SmtpUseTLS,
TurnstileEnabled: settings.TurnstileEnabled,
TurnstileSiteKey: settings.TurnstileSiteKey,
TurnstileSecretKey: settings.TurnstileSecretKey,
SiteName: settings.SiteName,
SiteLogo: settings.SiteLogo,
SiteSubtitle: settings.SiteSubtitle,
ApiBaseUrl: settings.ApiBaseUrl,
ContactInfo: settings.ContactInfo,
DocUrl: settings.DocUrl,
DefaultConcurrency: settings.DefaultConcurrency,
DefaultBalance: settings.DefaultBalance,
RegistrationEnabled: settings.RegistrationEnabled,
EmailVerifyEnabled: settings.EmailVerifyEnabled,
SMTPHost: settings.SMTPHost,
SMTPPort: settings.SMTPPort,
SMTPUsername: settings.SMTPUsername,
SMTPPassword: settings.SMTPPassword,
SMTPFrom: settings.SMTPFrom,
SMTPFromName: settings.SMTPFromName,
SMTPUseTLS: settings.SMTPUseTLS,
TurnstileEnabled: settings.TurnstileEnabled,
TurnstileSiteKey: settings.TurnstileSiteKey,
TurnstileSecretKey: settings.TurnstileSecretKey,
SiteName: settings.SiteName,
SiteLogo: settings.SiteLogo,
SiteSubtitle: settings.SiteSubtitle,
APIBaseURL: settings.APIBaseURL,
ContactInfo: settings.ContactInfo,
DocURL: settings.DocURL,
DefaultConcurrency: settings.DefaultConcurrency,
DefaultBalance: settings.DefaultBalance,
EnableModelFallback: settings.EnableModelFallback,
FallbackModelAnthropic: settings.FallbackModelAnthropic,
FallbackModelOpenAI: settings.FallbackModelOpenAI,
FallbackModelGemini: settings.FallbackModelGemini,
FallbackModelAntigravity: settings.FallbackModelAntigravity,
})
}
@@ -64,13 +69,13 @@ type UpdateSettingsRequest struct {
EmailVerifyEnabled bool `json:"email_verify_enabled"`
// 邮件服务设置
SmtpHost string `json:"smtp_host"`
SmtpPort int `json:"smtp_port"`
SmtpUsername string `json:"smtp_username"`
SmtpPassword string `json:"smtp_password"`
SmtpFrom string `json:"smtp_from_email"`
SmtpFromName string `json:"smtp_from_name"`
SmtpUseTLS bool `json:"smtp_use_tls"`
SMTPHost string `json:"smtp_host"`
SMTPPort int `json:"smtp_port"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
SMTPFrom string `json:"smtp_from_email"`
SMTPFromName string `json:"smtp_from_name"`
SMTPUseTLS bool `json:"smtp_use_tls"`
// Cloudflare Turnstile 设置
TurnstileEnabled bool `json:"turnstile_enabled"`
@@ -81,13 +86,20 @@ type UpdateSettingsRequest struct {
SiteName string `json:"site_name"`
SiteLogo string `json:"site_logo"`
SiteSubtitle string `json:"site_subtitle"`
ApiBaseUrl string `json:"api_base_url"`
APIBaseURL string `json:"api_base_url"`
ContactInfo string `json:"contact_info"`
DocUrl string `json:"doc_url"`
DocURL string `json:"doc_url"`
// 默认配置
DefaultConcurrency int `json:"default_concurrency"`
DefaultBalance float64 `json:"default_balance"`
// Model fallback configuration
EnableModelFallback bool `json:"enable_model_fallback"`
FallbackModelAnthropic string `json:"fallback_model_anthropic"`
FallbackModelOpenAI string `json:"fallback_model_openai"`
FallbackModelGemini string `json:"fallback_model_gemini"`
FallbackModelAntigravity string `json:"fallback_model_antigravity"`
}
// UpdateSettings 更新系统设置
@@ -106,8 +118,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
if req.DefaultBalance < 0 {
req.DefaultBalance = 0
}
if req.SmtpPort <= 0 {
req.SmtpPort = 587
if req.SMTPPort <= 0 {
req.SMTPPort = 587
}
// Turnstile 参数验证
@@ -141,26 +153,31 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
}
settings := &service.SystemSettings{
RegistrationEnabled: req.RegistrationEnabled,
EmailVerifyEnabled: req.EmailVerifyEnabled,
SmtpHost: req.SmtpHost,
SmtpPort: req.SmtpPort,
SmtpUsername: req.SmtpUsername,
SmtpPassword: req.SmtpPassword,
SmtpFrom: req.SmtpFrom,
SmtpFromName: req.SmtpFromName,
SmtpUseTLS: req.SmtpUseTLS,
TurnstileEnabled: req.TurnstileEnabled,
TurnstileSiteKey: req.TurnstileSiteKey,
TurnstileSecretKey: req.TurnstileSecretKey,
SiteName: req.SiteName,
SiteLogo: req.SiteLogo,
SiteSubtitle: req.SiteSubtitle,
ApiBaseUrl: req.ApiBaseUrl,
ContactInfo: req.ContactInfo,
DocUrl: req.DocUrl,
DefaultConcurrency: req.DefaultConcurrency,
DefaultBalance: req.DefaultBalance,
RegistrationEnabled: req.RegistrationEnabled,
EmailVerifyEnabled: req.EmailVerifyEnabled,
SMTPHost: req.SMTPHost,
SMTPPort: req.SMTPPort,
SMTPUsername: req.SMTPUsername,
SMTPPassword: req.SMTPPassword,
SMTPFrom: req.SMTPFrom,
SMTPFromName: req.SMTPFromName,
SMTPUseTLS: req.SMTPUseTLS,
TurnstileEnabled: req.TurnstileEnabled,
TurnstileSiteKey: req.TurnstileSiteKey,
TurnstileSecretKey: req.TurnstileSecretKey,
SiteName: req.SiteName,
SiteLogo: req.SiteLogo,
SiteSubtitle: req.SiteSubtitle,
APIBaseURL: req.APIBaseURL,
ContactInfo: req.ContactInfo,
DocURL: req.DocURL,
DefaultConcurrency: req.DefaultConcurrency,
DefaultBalance: req.DefaultBalance,
EnableModelFallback: req.EnableModelFallback,
FallbackModelAnthropic: req.FallbackModelAnthropic,
FallbackModelOpenAI: req.FallbackModelOpenAI,
FallbackModelGemini: req.FallbackModelGemini,
FallbackModelAntigravity: req.FallbackModelAntigravity,
}
if err := h.settingService.UpdateSettings(c.Request.Context(), settings); err != nil {
@@ -176,69 +193,74 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
}
response.Success(c, dto.SystemSettings{
RegistrationEnabled: updatedSettings.RegistrationEnabled,
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
SmtpHost: updatedSettings.SmtpHost,
SmtpPort: updatedSettings.SmtpPort,
SmtpUsername: updatedSettings.SmtpUsername,
SmtpPassword: updatedSettings.SmtpPassword,
SmtpFrom: updatedSettings.SmtpFrom,
SmtpFromName: updatedSettings.SmtpFromName,
SmtpUseTLS: updatedSettings.SmtpUseTLS,
TurnstileEnabled: updatedSettings.TurnstileEnabled,
TurnstileSiteKey: updatedSettings.TurnstileSiteKey,
TurnstileSecretKey: updatedSettings.TurnstileSecretKey,
SiteName: updatedSettings.SiteName,
SiteLogo: updatedSettings.SiteLogo,
SiteSubtitle: updatedSettings.SiteSubtitle,
ApiBaseUrl: updatedSettings.ApiBaseUrl,
ContactInfo: updatedSettings.ContactInfo,
DocUrl: updatedSettings.DocUrl,
DefaultConcurrency: updatedSettings.DefaultConcurrency,
DefaultBalance: updatedSettings.DefaultBalance,
RegistrationEnabled: updatedSettings.RegistrationEnabled,
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
SMTPHost: updatedSettings.SMTPHost,
SMTPPort: updatedSettings.SMTPPort,
SMTPUsername: updatedSettings.SMTPUsername,
SMTPPassword: updatedSettings.SMTPPassword,
SMTPFrom: updatedSettings.SMTPFrom,
SMTPFromName: updatedSettings.SMTPFromName,
SMTPUseTLS: updatedSettings.SMTPUseTLS,
TurnstileEnabled: updatedSettings.TurnstileEnabled,
TurnstileSiteKey: updatedSettings.TurnstileSiteKey,
TurnstileSecretKey: updatedSettings.TurnstileSecretKey,
SiteName: updatedSettings.SiteName,
SiteLogo: updatedSettings.SiteLogo,
SiteSubtitle: updatedSettings.SiteSubtitle,
APIBaseURL: updatedSettings.APIBaseURL,
ContactInfo: updatedSettings.ContactInfo,
DocURL: updatedSettings.DocURL,
DefaultConcurrency: updatedSettings.DefaultConcurrency,
DefaultBalance: updatedSettings.DefaultBalance,
EnableModelFallback: updatedSettings.EnableModelFallback,
FallbackModelAnthropic: updatedSettings.FallbackModelAnthropic,
FallbackModelOpenAI: updatedSettings.FallbackModelOpenAI,
FallbackModelGemini: updatedSettings.FallbackModelGemini,
FallbackModelAntigravity: updatedSettings.FallbackModelAntigravity,
})
}
// TestSmtpRequest 测试SMTP连接请求
type TestSmtpRequest struct {
SmtpHost string `json:"smtp_host" binding:"required"`
SmtpPort int `json:"smtp_port"`
SmtpUsername string `json:"smtp_username"`
SmtpPassword string `json:"smtp_password"`
SmtpUseTLS bool `json:"smtp_use_tls"`
// TestSMTPRequest 测试SMTP连接请求
type TestSMTPRequest struct {
SMTPHost string `json:"smtp_host" binding:"required"`
SMTPPort int `json:"smtp_port"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
SMTPUseTLS bool `json:"smtp_use_tls"`
}
// TestSmtpConnection 测试SMTP连接
// TestSMTPConnection 测试SMTP连接
// POST /api/v1/admin/settings/test-smtp
func (h *SettingHandler) TestSmtpConnection(c *gin.Context) {
var req TestSmtpRequest
func (h *SettingHandler) TestSMTPConnection(c *gin.Context) {
var req TestSMTPRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
if req.SmtpPort <= 0 {
req.SmtpPort = 587
if req.SMTPPort <= 0 {
req.SMTPPort = 587
}
// 如果未提供密码,从数据库获取已保存的密码
password := req.SmtpPassword
password := req.SMTPPassword
if password == "" {
savedConfig, err := h.emailService.GetSmtpConfig(c.Request.Context())
savedConfig, err := h.emailService.GetSMTPConfig(c.Request.Context())
if err == nil && savedConfig != nil {
password = savedConfig.Password
}
}
config := &service.SmtpConfig{
Host: req.SmtpHost,
Port: req.SmtpPort,
Username: req.SmtpUsername,
config := &service.SMTPConfig{
Host: req.SMTPHost,
Port: req.SMTPPort,
Username: req.SMTPUsername,
Password: password,
UseTLS: req.SmtpUseTLS,
UseTLS: req.SMTPUseTLS,
}
err := h.emailService.TestSmtpConnectionWithConfig(config)
err := h.emailService.TestSMTPConnectionWithConfig(config)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -250,13 +272,13 @@ func (h *SettingHandler) TestSmtpConnection(c *gin.Context) {
// SendTestEmailRequest 发送测试邮件请求
type SendTestEmailRequest struct {
Email string `json:"email" binding:"required,email"`
SmtpHost string `json:"smtp_host" binding:"required"`
SmtpPort int `json:"smtp_port"`
SmtpUsername string `json:"smtp_username"`
SmtpPassword string `json:"smtp_password"`
SmtpFrom string `json:"smtp_from_email"`
SmtpFromName string `json:"smtp_from_name"`
SmtpUseTLS bool `json:"smtp_use_tls"`
SMTPHost string `json:"smtp_host" binding:"required"`
SMTPPort int `json:"smtp_port"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
SMTPFrom string `json:"smtp_from_email"`
SMTPFromName string `json:"smtp_from_name"`
SMTPUseTLS bool `json:"smtp_use_tls"`
}
// SendTestEmail 发送测试邮件
@@ -268,27 +290,27 @@ func (h *SettingHandler) SendTestEmail(c *gin.Context) {
return
}
if req.SmtpPort <= 0 {
req.SmtpPort = 587
if req.SMTPPort <= 0 {
req.SMTPPort = 587
}
// 如果未提供密码,从数据库获取已保存的密码
password := req.SmtpPassword
password := req.SMTPPassword
if password == "" {
savedConfig, err := h.emailService.GetSmtpConfig(c.Request.Context())
savedConfig, err := h.emailService.GetSMTPConfig(c.Request.Context())
if err == nil && savedConfig != nil {
password = savedConfig.Password
}
}
config := &service.SmtpConfig{
Host: req.SmtpHost,
Port: req.SmtpPort,
Username: req.SmtpUsername,
config := &service.SMTPConfig{
Host: req.SMTPHost,
Port: req.SMTPPort,
Username: req.SMTPUsername,
Password: password,
From: req.SmtpFrom,
FromName: req.SmtpFromName,
UseTLS: req.SmtpUseTLS,
From: req.SMTPFrom,
FromName: req.SMTPFromName,
UseTLS: req.SMTPUseTLS,
}
siteName := h.settingService.GetSiteName(c.Request.Context())
@@ -333,10 +355,10 @@ func (h *SettingHandler) SendTestEmail(c *gin.Context) {
response.Success(c, gin.H{"message": "Test email sent successfully"})
}
// GetAdminApiKey 获取管理员 API Key 状态
// GetAdminAPIKey 获取管理员 API Key 状态
// GET /api/v1/admin/settings/admin-api-key
func (h *SettingHandler) GetAdminApiKey(c *gin.Context) {
maskedKey, exists, err := h.settingService.GetAdminApiKeyStatus(c.Request.Context())
func (h *SettingHandler) GetAdminAPIKey(c *gin.Context) {
maskedKey, exists, err := h.settingService.GetAdminAPIKeyStatus(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
@@ -348,10 +370,10 @@ func (h *SettingHandler) GetAdminApiKey(c *gin.Context) {
})
}
// RegenerateAdminApiKey 生成/重新生成管理员 API Key
// RegenerateAdminAPIKey 生成/重新生成管理员 API Key
// POST /api/v1/admin/settings/admin-api-key/regenerate
func (h *SettingHandler) RegenerateAdminApiKey(c *gin.Context) {
key, err := h.settingService.GenerateAdminApiKey(c.Request.Context())
func (h *SettingHandler) RegenerateAdminAPIKey(c *gin.Context) {
key, err := h.settingService.GenerateAdminAPIKey(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
@@ -362,10 +384,10 @@ func (h *SettingHandler) RegenerateAdminApiKey(c *gin.Context) {
})
}
// DeleteAdminApiKey 删除管理员 API Key
// DeleteAdminAPIKey 删除管理员 API Key
// DELETE /api/v1/admin/settings/admin-api-key
func (h *SettingHandler) DeleteAdminApiKey(c *gin.Context) {
if err := h.settingService.DeleteAdminApiKey(c.Request.Context()); err != nil {
func (h *SettingHandler) DeleteAdminAPIKey(c *gin.Context) {
if err := h.settingService.DeleteAdminAPIKey(c.Request.Context()); err != nil {
response.ErrorFrom(c, err)
return
}

View File

@@ -17,14 +17,14 @@ import (
// UsageHandler handles admin usage-related requests
type UsageHandler struct {
usageService *service.UsageService
apiKeyService *service.ApiKeyService
apiKeyService *service.APIKeyService
adminService service.AdminService
}
// NewUsageHandler creates a new admin usage handler
func NewUsageHandler(
usageService *service.UsageService,
apiKeyService *service.ApiKeyService,
apiKeyService *service.APIKeyService,
adminService service.AdminService,
) *UsageHandler {
return &UsageHandler{
@@ -125,7 +125,7 @@ func (h *UsageHandler) List(c *gin.Context) {
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
filters := usagestats.UsageLogFilters{
UserID: userID,
ApiKeyID: apiKeyID,
APIKeyID: apiKeyID,
AccountID: accountID,
GroupID: groupID,
Model: model,
@@ -207,7 +207,7 @@ func (h *UsageHandler) Stats(c *gin.Context) {
}
if apiKeyID > 0 {
stats, err := h.usageService.GetStatsByApiKey(c.Request.Context(), apiKeyID, startTime, endTime)
stats, err := h.usageService.GetStatsByAPIKey(c.Request.Context(), apiKeyID, startTime, endTime)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -269,9 +269,9 @@ func (h *UsageHandler) SearchUsers(c *gin.Context) {
response.Success(c, result)
}
// SearchApiKeys handles searching API keys by user
// SearchAPIKeys handles searching API keys by user
// GET /api/v1/admin/usage/search-api-keys
func (h *UsageHandler) SearchApiKeys(c *gin.Context) {
func (h *UsageHandler) SearchAPIKeys(c *gin.Context) {
userIDStr := c.Query("user_id")
keyword := c.Query("q")
@@ -285,22 +285,22 @@ func (h *UsageHandler) SearchApiKeys(c *gin.Context) {
userID = id
}
keys, err := h.apiKeyService.SearchApiKeys(c.Request.Context(), userID, keyword, 30)
keys, err := h.apiKeyService.SearchAPIKeys(c.Request.Context(), userID, keyword, 30)
if err != nil {
response.ErrorFrom(c, err)
return
}
// Return simplified API key list (only id and name)
type SimpleApiKey struct {
type SimpleAPIKey struct {
ID int64 `json:"id"`
Name string `json:"name"`
UserID int64 `json:"user_id"`
}
result := make([]SimpleApiKey, len(keys))
result := make([]SimpleAPIKey, len(keys))
for i, k := range keys {
result[i] = SimpleApiKey{
result[i] = SimpleAPIKey{
ID: k.ID,
Name: k.Name,
UserID: k.UserID,

View File

@@ -243,9 +243,9 @@ func (h *UserHandler) GetUserAPIKeys(c *gin.Context) {
return
}
out := make([]dto.ApiKey, 0, len(keys))
out := make([]dto.APIKey, 0, len(keys))
for i := range keys {
out = append(out, *dto.ApiKeyFromService(&keys[i]))
out = append(out, *dto.APIKeyFromService(&keys[i]))
}
response.Paginated(c, out, total, page, pageSize)
}

View File

@@ -1,3 +1,4 @@
// Package handler provides HTTP request handlers for the application.
package handler
import (
@@ -14,11 +15,11 @@ import (
// APIKeyHandler handles API key-related requests
type APIKeyHandler struct {
apiKeyService *service.ApiKeyService
apiKeyService *service.APIKeyService
}
// NewAPIKeyHandler creates a new APIKeyHandler
func NewAPIKeyHandler(apiKeyService *service.ApiKeyService) *APIKeyHandler {
func NewAPIKeyHandler(apiKeyService *service.APIKeyService) *APIKeyHandler {
return &APIKeyHandler{
apiKeyService: apiKeyService,
}
@@ -56,9 +57,9 @@ func (h *APIKeyHandler) List(c *gin.Context) {
return
}
out := make([]dto.ApiKey, 0, len(keys))
out := make([]dto.APIKey, 0, len(keys))
for i := range keys {
out = append(out, *dto.ApiKeyFromService(&keys[i]))
out = append(out, *dto.APIKeyFromService(&keys[i]))
}
response.Paginated(c, out, result.Total, page, pageSize)
}
@@ -90,7 +91,7 @@ func (h *APIKeyHandler) GetByID(c *gin.Context) {
return
}
response.Success(c, dto.ApiKeyFromService(key))
response.Success(c, dto.APIKeyFromService(key))
}
// Create handles creating a new API key
@@ -108,7 +109,7 @@ func (h *APIKeyHandler) Create(c *gin.Context) {
return
}
svcReq := service.CreateApiKeyRequest{
svcReq := service.CreateAPIKeyRequest{
Name: req.Name,
GroupID: req.GroupID,
CustomKey: req.CustomKey,
@@ -119,7 +120,7 @@ func (h *APIKeyHandler) Create(c *gin.Context) {
return
}
response.Success(c, dto.ApiKeyFromService(key))
response.Success(c, dto.APIKeyFromService(key))
}
// Update handles updating an API key
@@ -143,7 +144,7 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
return
}
svcReq := service.UpdateApiKeyRequest{}
svcReq := service.UpdateAPIKeyRequest{}
if req.Name != "" {
svcReq.Name = &req.Name
}
@@ -158,7 +159,7 @@ func (h *APIKeyHandler) Update(c *gin.Context) {
return
}
response.Success(c, dto.ApiKeyFromService(key))
response.Success(c, dto.APIKeyFromService(key))
}
// Delete handles deleting an API key

View File

@@ -1,3 +1,4 @@
// Package dto provides data transfer objects for HTTP handlers.
package dto
import "github.com/Wei-Shaw/sub2api/internal/service"
@@ -26,11 +27,11 @@ func UserFromService(u *service.User) *User {
return nil
}
out := UserFromServiceShallow(u)
if len(u.ApiKeys) > 0 {
out.ApiKeys = make([]ApiKey, 0, len(u.ApiKeys))
for i := range u.ApiKeys {
k := u.ApiKeys[i]
out.ApiKeys = append(out.ApiKeys, *ApiKeyFromService(&k))
if len(u.APIKeys) > 0 {
out.APIKeys = make([]APIKey, 0, len(u.APIKeys))
for i := range u.APIKeys {
k := u.APIKeys[i]
out.APIKeys = append(out.APIKeys, *APIKeyFromService(&k))
}
}
if len(u.Subscriptions) > 0 {
@@ -43,11 +44,11 @@ func UserFromService(u *service.User) *User {
return out
}
func ApiKeyFromService(k *service.ApiKey) *ApiKey {
func APIKeyFromService(k *service.APIKey) *APIKey {
if k == nil {
return nil
}
return &ApiKey{
return &APIKey{
ID: k.ID,
UserID: k.UserID,
Key: k.Key,
@@ -103,28 +104,30 @@ func AccountFromServiceShallow(a *service.Account) *Account {
return nil
}
return &Account{
ID: a.ID,
Name: a.Name,
Platform: a.Platform,
Type: a.Type,
Credentials: a.Credentials,
Extra: a.Extra,
ProxyID: a.ProxyID,
Concurrency: a.Concurrency,
Priority: a.Priority,
Status: a.Status,
ErrorMessage: a.ErrorMessage,
LastUsedAt: a.LastUsedAt,
CreatedAt: a.CreatedAt,
UpdatedAt: a.UpdatedAt,
Schedulable: a.Schedulable,
RateLimitedAt: a.RateLimitedAt,
RateLimitResetAt: a.RateLimitResetAt,
OverloadUntil: a.OverloadUntil,
SessionWindowStart: a.SessionWindowStart,
SessionWindowEnd: a.SessionWindowEnd,
SessionWindowStatus: a.SessionWindowStatus,
GroupIDs: a.GroupIDs,
ID: a.ID,
Name: a.Name,
Platform: a.Platform,
Type: a.Type,
Credentials: a.Credentials,
Extra: a.Extra,
ProxyID: a.ProxyID,
Concurrency: a.Concurrency,
Priority: a.Priority,
Status: a.Status,
ErrorMessage: a.ErrorMessage,
LastUsedAt: a.LastUsedAt,
CreatedAt: a.CreatedAt,
UpdatedAt: a.UpdatedAt,
Schedulable: a.Schedulable,
RateLimitedAt: a.RateLimitedAt,
RateLimitResetAt: a.RateLimitResetAt,
OverloadUntil: a.OverloadUntil,
TempUnschedulableUntil: a.TempUnschedulableUntil,
TempUnschedulableReason: a.TempUnschedulableReason,
SessionWindowStart: a.SessionWindowStart,
SessionWindowEnd: a.SessionWindowEnd,
SessionWindowStatus: a.SessionWindowStatus,
GroupIDs: a.GroupIDs,
}
}
@@ -220,7 +223,7 @@ func UsageLogFromService(l *service.UsageLog) *UsageLog {
return &UsageLog{
ID: l.ID,
UserID: l.UserID,
ApiKeyID: l.ApiKeyID,
APIKeyID: l.APIKeyID,
AccountID: l.AccountID,
RequestID: l.RequestID,
Model: l.Model,
@@ -245,7 +248,7 @@ func UsageLogFromService(l *service.UsageLog) *UsageLog {
FirstTokenMs: l.FirstTokenMs,
CreatedAt: l.CreatedAt,
User: UserFromServiceShallow(l.User),
ApiKey: ApiKeyFromService(l.ApiKey),
APIKey: APIKeyFromService(l.APIKey),
Account: AccountFromService(l.Account),
Group: GroupFromServiceShallow(l.Group),
Subscription: UserSubscriptionFromService(l.Subscription),

View File

@@ -5,13 +5,13 @@ type SystemSettings struct {
RegistrationEnabled bool `json:"registration_enabled"`
EmailVerifyEnabled bool `json:"email_verify_enabled"`
SmtpHost string `json:"smtp_host"`
SmtpPort int `json:"smtp_port"`
SmtpUsername string `json:"smtp_username"`
SmtpPassword string `json:"smtp_password,omitempty"`
SmtpFrom string `json:"smtp_from_email"`
SmtpFromName string `json:"smtp_from_name"`
SmtpUseTLS bool `json:"smtp_use_tls"`
SMTPHost string `json:"smtp_host"`
SMTPPort int `json:"smtp_port"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password,omitempty"`
SMTPFrom string `json:"smtp_from_email"`
SMTPFromName string `json:"smtp_from_name"`
SMTPUseTLS bool `json:"smtp_use_tls"`
TurnstileEnabled bool `json:"turnstile_enabled"`
TurnstileSiteKey string `json:"turnstile_site_key"`
@@ -20,12 +20,19 @@ type SystemSettings struct {
SiteName string `json:"site_name"`
SiteLogo string `json:"site_logo"`
SiteSubtitle string `json:"site_subtitle"`
ApiBaseUrl string `json:"api_base_url"`
APIBaseURL string `json:"api_base_url"`
ContactInfo string `json:"contact_info"`
DocUrl string `json:"doc_url"`
DocURL string `json:"doc_url"`
DefaultConcurrency int `json:"default_concurrency"`
DefaultBalance float64 `json:"default_balance"`
// Model fallback configuration
EnableModelFallback bool `json:"enable_model_fallback"`
FallbackModelAnthropic string `json:"fallback_model_anthropic"`
FallbackModelOpenAI string `json:"fallback_model_openai"`
FallbackModelGemini string `json:"fallback_model_gemini"`
FallbackModelAntigravity string `json:"fallback_model_antigravity"`
}
type PublicSettings struct {
@@ -36,8 +43,8 @@ type PublicSettings struct {
SiteName string `json:"site_name"`
SiteLogo string `json:"site_logo"`
SiteSubtitle string `json:"site_subtitle"`
ApiBaseUrl string `json:"api_base_url"`
APIBaseURL string `json:"api_base_url"`
ContactInfo string `json:"contact_info"`
DocUrl string `json:"doc_url"`
DocURL string `json:"doc_url"`
Version string `json:"version"`
}

View File

@@ -15,11 +15,11 @@ type User struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ApiKeys []ApiKey `json:"api_keys,omitempty"`
APIKeys []APIKey `json:"api_keys,omitempty"`
Subscriptions []UserSubscription `json:"subscriptions,omitempty"`
}
type ApiKey struct {
type APIKey struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Key string `json:"key"`
@@ -76,6 +76,9 @@ type Account struct {
RateLimitResetAt *time.Time `json:"rate_limit_reset_at"`
OverloadUntil *time.Time `json:"overload_until"`
TempUnschedulableUntil *time.Time `json:"temp_unschedulable_until"`
TempUnschedulableReason string `json:"temp_unschedulable_reason"`
SessionWindowStart *time.Time `json:"session_window_start"`
SessionWindowEnd *time.Time `json:"session_window_end"`
SessionWindowStatus string `json:"session_window_status"`
@@ -136,7 +139,7 @@ type RedeemCode struct {
type UsageLog struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
ApiKeyID int64 `json:"api_key_id"`
APIKeyID int64 `json:"api_key_id"`
AccountID int64 `json:"account_id"`
RequestID string `json:"request_id"`
Model string `json:"model"`
@@ -168,7 +171,7 @@ type UsageLog struct {
CreatedAt time.Time `json:"created_at"`
User *User `json:"user,omitempty"`
ApiKey *ApiKey `json:"api_key,omitempty"`
APIKey *APIKey `json:"api_key,omitempty"`
Account *Account `json:"account,omitempty"`
Group *Group `json:"group,omitempty"`
Subscription *UserSubscription `json:"subscription,omitempty"`

View File

@@ -53,7 +53,7 @@ func NewGatewayHandler(
// POST /v1/messages
func (h *GatewayHandler) Messages(c *gin.Context) {
// 从context获取apiKey和userApiKeyAuth中间件已设置
apiKey, ok := middleware2.GetApiKeyFromContext(c)
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
if !ok {
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
return
@@ -259,7 +259,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
defer cancel()
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
Result: result,
ApiKey: apiKey,
APIKey: apiKey,
User: apiKey.User,
Account: usedAccount,
Subscription: subscription,
@@ -383,7 +383,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
defer cancel()
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
Result: result,
ApiKey: apiKey,
APIKey: apiKey,
User: apiKey.User,
Account: usedAccount,
Subscription: subscription,
@@ -400,7 +400,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
// Returns models based on account configurations (model_mapping whitelist)
// Falls back to default models if no whitelist is configured
func (h *GatewayHandler) Models(c *gin.Context) {
apiKey, _ := middleware2.GetApiKeyFromContext(c)
apiKey, _ := middleware2.GetAPIKeyFromContext(c)
var groupID *int64
var platform string
@@ -458,7 +458,7 @@ func (h *GatewayHandler) AntigravityModels(c *gin.Context) {
// Usage handles getting account balance for CC Switch integration
// GET /v1/usage
func (h *GatewayHandler) Usage(c *gin.Context) {
apiKey, ok := middleware2.GetApiKeyFromContext(c)
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
if !ok {
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
return
@@ -628,7 +628,7 @@ func (h *GatewayHandler) errorResponse(c *gin.Context, status int, errType, mess
// 特点:校验订阅/余额,但不计算并发、不记录使用量
func (h *GatewayHandler) CountTokens(c *gin.Context) {
// 从context获取apiKey和userApiKeyAuth中间件已设置
apiKey, ok := middleware2.GetApiKeyFromContext(c)
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
if !ok {
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
return

View File

@@ -21,7 +21,7 @@ import (
// GeminiV1BetaListModels proxies:
// GET /v1beta/models
func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
apiKey, ok := middleware.GetApiKeyFromContext(c)
apiKey, ok := middleware.GetAPIKeyFromContext(c)
if !ok || apiKey == nil {
googleError(c, http.StatusUnauthorized, "Invalid API key")
return
@@ -67,7 +67,7 @@ func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
// GeminiV1BetaGetModel proxies:
// GET /v1beta/models/{model}
func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
apiKey, ok := middleware.GetApiKeyFromContext(c)
apiKey, ok := middleware.GetAPIKeyFromContext(c)
if !ok || apiKey == nil {
googleError(c, http.StatusUnauthorized, "Invalid API key")
return
@@ -120,7 +120,7 @@ func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
// POST /v1beta/models/{model}:generateContent
// POST /v1beta/models/{model}:streamGenerateContent?alt=sse
func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
apiKey, ok := middleware.GetApiKeyFromContext(c)
apiKey, ok := middleware.GetAPIKeyFromContext(c)
if !ok || apiKey == nil {
googleError(c, http.StatusUnauthorized, "Invalid API key")
return
@@ -299,7 +299,7 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
defer cancel()
if err := h.gatewayService.RecordUsage(ctx, &service.RecordUsageInput{
Result: result,
ApiKey: apiKey,
APIKey: apiKey,
User: apiKey.User,
Account: usedAccount,
Subscription: subscription,

View File

@@ -41,7 +41,7 @@ func NewOpenAIGatewayHandler(
// POST /openai/v1/responses
func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
// Get apiKey and user from context (set by ApiKeyAuth middleware)
apiKey, ok := middleware2.GetApiKeyFromContext(c)
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
if !ok {
h.errorResponse(c, http.StatusUnauthorized, "authentication_error", "Invalid API key")
return
@@ -235,7 +235,7 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
defer cancel()
if err := h.gatewayService.RecordUsage(ctx, &service.OpenAIRecordUsageInput{
Result: result,
ApiKey: apiKey,
APIKey: apiKey,
User: apiKey.User,
Account: usedAccount,
Subscription: subscription,

View File

@@ -39,9 +39,9 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
SiteName: settings.SiteName,
SiteLogo: settings.SiteLogo,
SiteSubtitle: settings.SiteSubtitle,
ApiBaseUrl: settings.ApiBaseUrl,
APIBaseURL: settings.APIBaseURL,
ContactInfo: settings.ContactInfo,
DocUrl: settings.DocUrl,
DocURL: settings.DocURL,
Version: h.version,
})
}

View File

@@ -18,11 +18,11 @@ import (
// UsageHandler handles usage-related requests
type UsageHandler struct {
usageService *service.UsageService
apiKeyService *service.ApiKeyService
apiKeyService *service.APIKeyService
}
// NewUsageHandler creates a new UsageHandler
func NewUsageHandler(usageService *service.UsageService, apiKeyService *service.ApiKeyService) *UsageHandler {
func NewUsageHandler(usageService *service.UsageService, apiKeyService *service.APIKeyService) *UsageHandler {
return &UsageHandler{
usageService: usageService,
apiKeyService: apiKeyService,
@@ -111,7 +111,7 @@ func (h *UsageHandler) List(c *gin.Context) {
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
filters := usagestats.UsageLogFilters{
UserID: subject.UserID, // Always filter by current user for security
ApiKeyID: apiKeyID,
APIKeyID: apiKeyID,
Model: model,
Stream: stream,
BillingType: billingType,
@@ -235,7 +235,7 @@ func (h *UsageHandler) Stats(c *gin.Context) {
var stats *service.UsageStats
var err error
if apiKeyID > 0 {
stats, err = h.usageService.GetStatsByApiKey(c.Request.Context(), apiKeyID, startTime, endTime)
stats, err = h.usageService.GetStatsByAPIKey(c.Request.Context(), apiKeyID, startTime, endTime)
} else {
stats, err = h.usageService.GetStatsByUser(c.Request.Context(), subject.UserID, startTime, endTime)
}
@@ -346,49 +346,49 @@ func (h *UsageHandler) DashboardModels(c *gin.Context) {
})
}
// BatchApiKeysUsageRequest represents the request for batch API keys usage
type BatchApiKeysUsageRequest struct {
ApiKeyIDs []int64 `json:"api_key_ids" binding:"required"`
// BatchAPIKeysUsageRequest represents the request for batch API keys usage
type BatchAPIKeysUsageRequest struct {
APIKeyIDs []int64 `json:"api_key_ids" binding:"required"`
}
// DashboardApiKeysUsage handles getting usage stats for user's own API keys
// DashboardAPIKeysUsage handles getting usage stats for user's own API keys
// POST /api/v1/usage/dashboard/api-keys-usage
func (h *UsageHandler) DashboardApiKeysUsage(c *gin.Context) {
func (h *UsageHandler) DashboardAPIKeysUsage(c *gin.Context) {
subject, ok := middleware2.GetAuthSubjectFromContext(c)
if !ok {
response.Unauthorized(c, "User not authenticated")
return
}
var req BatchApiKeysUsageRequest
var req BatchAPIKeysUsageRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
if len(req.ApiKeyIDs) == 0 {
if len(req.APIKeyIDs) == 0 {
response.Success(c, gin.H{"stats": map[string]any{}})
return
}
// Limit the number of API key IDs to prevent SQL parameter overflow
if len(req.ApiKeyIDs) > 100 {
if len(req.APIKeyIDs) > 100 {
response.BadRequest(c, "Too many API key IDs (maximum 100 allowed)")
return
}
validApiKeyIDs, err := h.apiKeyService.VerifyOwnership(c.Request.Context(), subject.UserID, req.ApiKeyIDs)
validAPIKeyIDs, err := h.apiKeyService.VerifyOwnership(c.Request.Context(), subject.UserID, req.APIKeyIDs)
if err != nil {
response.ErrorFrom(c, err)
return
}
if len(validApiKeyIDs) == 0 {
if len(validAPIKeyIDs) == 0 {
response.Success(c, gin.H{"stats": map[string]any{}})
return
}
stats, err := h.usageService.GetBatchApiKeyUsageStats(c.Request.Context(), validApiKeyIDs)
stats, err := h.usageService.GetBatchAPIKeyUsageStats(c.Request.Context(), validAPIKeyIDs)
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -1,3 +1,4 @@
// Package antigravity provides a client for the Antigravity API.
package antigravity
import (
@@ -57,6 +58,29 @@ type TierInfo struct {
Description string `json:"description"` // 描述
}
// UnmarshalJSON supports both legacy string tiers and object tiers.
func (t *TierInfo) UnmarshalJSON(data []byte) error {
data = bytes.TrimSpace(data)
if len(data) == 0 || string(data) == "null" {
return nil
}
if data[0] == '"' {
var id string
if err := json.Unmarshal(data, &id); err != nil {
return err
}
t.ID = id
return nil
}
type alias TierInfo
var decoded alias
if err := json.Unmarshal(data, &decoded); err != nil {
return err
}
*t = TierInfo(decoded)
return nil
}
// IneligibleTier 不符合条件的层级信息
type IneligibleTier struct {
Tier *TierInfo `json:"tier,omitempty"`

View File

@@ -240,10 +240,13 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu
ID: block.ID,
},
}
// 只有 Gemini 模型使用 dummy signature
// Claude 模型不设置 signature避免验证问题
// tool_use 的 signature 处理:
// - Gemini 模型:使用 dummy signature跳过 thought_signature 校验
// - Claude 模型:透传上游返回的真实 signatureVertex/Google 需要完整签名链路)
if allowDummyThought {
part.ThoughtSignature = dummyThoughtSignature
} else if block.Signature != "" && block.Signature != dummyThoughtSignature {
part.ThoughtSignature = block.Signature
}
parts = append(parts, part)

View File

@@ -15,26 +15,26 @@ func TestBuildParts_ThinkingBlockWithoutSignature(t *testing.T) {
description string
}{
{
name: "Claude model - skip thinking block without signature",
name: "Claude model - drop thinking without signature",
content: `[
{"type": "text", "text": "Hello"},
{"type": "thinking", "thinking": "Let me think...", "signature": ""},
{"type": "text", "text": "World"}
]`,
allowDummyThought: false,
expectedParts: 2, // 只有两个text block
description: "Claude模型应该跳过无signature的thinking block",
expectedParts: 2, // thinking 内容被丢弃
description: "Claude模型应丢弃无signature的thinking block内容",
},
{
name: "Claude model - keep thinking block with signature",
name: "Claude model - preserve thinking block with signature",
content: `[
{"type": "text", "text": "Hello"},
{"type": "thinking", "thinking": "Let me think...", "signature": "valid_sig"},
{"type": "thinking", "thinking": "Let me think...", "signature": "sig_real_123"},
{"type": "text", "text": "World"}
]`,
allowDummyThought: false,
expectedParts: 3, // 三个block都保留
description: "Claude模型应该保留有signaturethinking block",
expectedParts: 3,
description: "Claude模型应透传带 signaturethinking block(用于 Vertex 签名链路)",
},
{
name: "Gemini model - use dummy signature",
@@ -61,10 +61,64 @@ func TestBuildParts_ThinkingBlockWithoutSignature(t *testing.T) {
if len(parts) != tt.expectedParts {
t.Errorf("%s: got %d parts, want %d parts", tt.description, len(parts), tt.expectedParts)
}
switch tt.name {
case "Claude model - preserve thinking block with signature":
if len(parts) != 3 {
t.Fatalf("expected 3 parts, got %d", len(parts))
}
if !parts[1].Thought || parts[1].ThoughtSignature != "sig_real_123" {
t.Fatalf("expected thought part with signature sig_real_123, got thought=%v signature=%q",
parts[1].Thought, parts[1].ThoughtSignature)
}
case "Gemini model - use dummy signature":
if len(parts) != 3 {
t.Fatalf("expected 3 parts, got %d", len(parts))
}
if !parts[1].Thought || parts[1].ThoughtSignature != dummyThoughtSignature {
t.Fatalf("expected dummy thought signature, got thought=%v signature=%q",
parts[1].Thought, parts[1].ThoughtSignature)
}
}
})
}
}
func TestBuildParts_ToolUseSignatureHandling(t *testing.T) {
content := `[
{"type": "tool_use", "id": "t1", "name": "Bash", "input": {"command": "ls"}, "signature": "sig_tool_abc"}
]`
t.Run("Gemini uses dummy tool_use signature", func(t *testing.T) {
toolIDToName := make(map[string]string)
parts, err := buildParts(json.RawMessage(content), toolIDToName, true)
if err != nil {
t.Fatalf("buildParts() error = %v", err)
}
if len(parts) != 1 || parts[0].FunctionCall == nil {
t.Fatalf("expected 1 functionCall part, got %+v", parts)
}
if parts[0].ThoughtSignature != dummyThoughtSignature {
t.Fatalf("expected dummy tool signature %q, got %q", dummyThoughtSignature, parts[0].ThoughtSignature)
}
})
t.Run("Claude model - preserve valid signature for tool_use", func(t *testing.T) {
toolIDToName := make(map[string]string)
parts, err := buildParts(json.RawMessage(content), toolIDToName, false)
if err != nil {
t.Fatalf("buildParts() error = %v", err)
}
if len(parts) != 1 || parts[0].FunctionCall == nil {
t.Fatalf("expected 1 functionCall part, got %+v", parts)
}
// Claude 模型应透传有效的 signatureVertex/Google 需要完整签名链路)
if parts[0].ThoughtSignature != "sig_tool_abc" {
t.Fatalf("expected preserved tool signature %q, got %q", "sig_tool_abc", parts[0].ThoughtSignature)
}
})
}
// TestBuildTools_CustomTypeTools 测试custom类型工具转换
func TestBuildTools_CustomTypeTools(t *testing.T) {
tests := []struct {

View File

@@ -1,3 +1,4 @@
// Package claude provides constants and helpers for Claude API integration.
package claude
// Claude Code 客户端相关常量
@@ -16,13 +17,13 @@ const DefaultBetaHeader = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleav
// HaikuBetaHeader Haiku 模型使用的 anthropic-beta header不需要 claude-code beta
const HaikuBetaHeader = BetaOAuth + "," + BetaInterleavedThinking
// ApiKeyBetaHeader API-key 账号建议使用的 anthropic-beta header不包含 oauth
const ApiKeyBetaHeader = BetaClaudeCode + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
// APIKeyBetaHeader API-key 账号建议使用的 anthropic-beta header不包含 oauth
const APIKeyBetaHeader = BetaClaudeCode + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
// ApiKeyHaikuBetaHeader Haiku 模型在 API-key 账号下使用的 anthropic-beta header不包含 oauth / claude-code
const ApiKeyHaikuBetaHeader = BetaInterleavedThinking
// APIKeyHaikuBetaHeader Haiku 模型在 API-key 账号下使用的 anthropic-beta header不包含 oauth / claude-code
const APIKeyHaikuBetaHeader = BetaInterleavedThinking
// Claude Code 客户端默认请求头
// DefaultHeaders 是 Claude Code 客户端默认请求头
var DefaultHeaders = map[string]string{
"User-Agent": "claude-cli/2.0.62 (external, cli)",
"X-Stainless-Lang": "js",

View File

@@ -1,3 +1,4 @@
// Package errors provides application error types and helpers.
// nolint:mnd
package errors

View File

@@ -1,7 +1,6 @@
package gemini
// This package provides minimal fallback model metadata for Gemini native endpoints.
// Package gemini provides minimal fallback model metadata for Gemini native endpoints.
// It is used when upstream model listing is unavailable (e.g. OAuth token missing AI Studio scopes).
package gemini
type Model struct {
Name string `json:"name"`

View File

@@ -1,5 +1,10 @@
package geminicli
import (
"bytes"
"encoding/json"
)
// LoadCodeAssistRequest matches done-hub's internal Code Assist call.
type LoadCodeAssistRequest struct {
Metadata LoadCodeAssistMetadata `json:"metadata"`
@@ -11,12 +16,51 @@ type LoadCodeAssistMetadata struct {
PluginType string `json:"pluginType"`
}
type TierInfo struct {
ID string `json:"id"`
}
// UnmarshalJSON supports both legacy string tiers and object tiers.
func (t *TierInfo) UnmarshalJSON(data []byte) error {
data = bytes.TrimSpace(data)
if len(data) == 0 || string(data) == "null" {
return nil
}
if data[0] == '"' {
var id string
if err := json.Unmarshal(data, &id); err != nil {
return err
}
t.ID = id
return nil
}
type alias TierInfo
var decoded alias
if err := json.Unmarshal(data, &decoded); err != nil {
return err
}
*t = TierInfo(decoded)
return nil
}
type LoadCodeAssistResponse struct {
CurrentTier string `json:"currentTier,omitempty"`
CurrentTier *TierInfo `json:"currentTier,omitempty"`
PaidTier *TierInfo `json:"paidTier,omitempty"`
CloudAICompanionProject string `json:"cloudaicompanionProject,omitempty"`
AllowedTiers []AllowedTier `json:"allowedTiers,omitempty"`
}
// GetTier extracts tier ID, prioritizing paidTier over currentTier
func (r *LoadCodeAssistResponse) GetTier() string {
if r.PaidTier != nil && r.PaidTier.ID != "" {
return r.PaidTier.ID
}
if r.CurrentTier != nil {
return r.CurrentTier.ID
}
return ""
}
type AllowedTier struct {
ID string `json:"id"`
IsDefault bool `json:"isDefault,omitempty"`

View File

@@ -1,3 +1,4 @@
// Package geminicli provides helpers for interacting with Gemini CLI tools.
package geminicli
import "time"
@@ -26,6 +27,12 @@ const (
// https://www.googleapis.com/auth/generative-language.retriever (often with cloud-platform).
DefaultAIStudioScopes = "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever"
// DefaultScopes for Google One (personal Google accounts with Gemini access)
// Only used when a custom OAuth client is configured. When using the built-in Gemini CLI client,
// Google One uses DefaultCodeAssistScopes (same as code_assist) because the built-in client
// cannot request restricted scopes like generative-language.retriever or drive.readonly.
DefaultGoogleOneScopes = "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
// GeminiCLIRedirectURI is the redirect URI used by Gemini CLI for Code Assist OAuth.
GeminiCLIRedirectURI = "https://codeassist.google.com/authcode"

View File

@@ -11,11 +11,12 @@ type Model struct {
// DefaultModels is the curated Gemini model list used by the admin UI "test account" flow.
var DefaultModels = []Model{
{ID: "gemini-3-pro-preview", Type: "model", DisplayName: "Gemini 3 Pro Preview", CreatedAt: ""},
{ID: "gemini-3-flash-preview", Type: "model", DisplayName: "Gemini 3 Flash Preview", CreatedAt: ""},
{ID: "gemini-2.0-flash", Type: "model", DisplayName: "Gemini 2.0 Flash", CreatedAt: ""},
{ID: "gemini-2.5-pro", Type: "model", DisplayName: "Gemini 2.5 Pro", CreatedAt: ""},
{ID: "gemini-2.5-flash", Type: "model", DisplayName: "Gemini 2.5 Flash", CreatedAt: ""},
{ID: "gemini-3-pro-preview", Type: "model", DisplayName: "Gemini 3 Pro Preview", CreatedAt: ""},
{ID: "gemini-3-flash-preview", Type: "model", DisplayName: "Gemini 3 Flash Preview", CreatedAt: ""},
}
// DefaultTestModel is the default model to preselect in test flows.
const DefaultTestModel = "gemini-3-pro-preview"
const DefaultTestModel = "gemini-2.0-flash"

View File

@@ -19,13 +19,17 @@ type OAuthConfig struct {
}
type OAuthSession struct {
State string `json:"state"`
CodeVerifier string `json:"code_verifier"`
ProxyURL string `json:"proxy_url,omitempty"`
RedirectURI string `json:"redirect_uri"`
ProjectID string `json:"project_id,omitempty"`
OAuthType string `json:"oauth_type"` // "code_assist" 或 "ai_studio"
CreatedAt time.Time `json:"created_at"`
State string `json:"state"`
CodeVerifier string `json:"code_verifier"`
ProxyURL string `json:"proxy_url,omitempty"`
RedirectURI string `json:"redirect_uri"`
ProjectID string `json:"project_id,omitempty"`
// TierID is a user-selected fallback tier.
// For oauth types that support auto detection (google_one/code_assist), the server will prefer
// the detected tier and fall back to TierID when detection fails.
TierID string `json:"tier_id,omitempty"`
OAuthType string `json:"oauth_type"` // "code_assist" 或 "ai_studio"
CreatedAt time.Time `json:"created_at"`
}
type SessionStore struct {
@@ -172,23 +176,32 @@ func EffectiveOAuthConfig(cfg OAuthConfig, oauthType string) (OAuthConfig, error
if effective.Scopes == "" {
// Use different default scopes based on OAuth type
if oauthType == "ai_studio" {
switch oauthType {
case "ai_studio":
// Built-in client can't request some AI Studio scopes (notably generative-language).
if isBuiltinClient {
effective.Scopes = DefaultCodeAssistScopes
} else {
effective.Scopes = DefaultAIStudioScopes
}
} else {
case "google_one":
// Google One uses built-in Gemini CLI client (same as code_assist)
// Built-in client can't request restricted scopes like generative-language.retriever
if isBuiltinClient {
effective.Scopes = DefaultCodeAssistScopes
} else {
effective.Scopes = DefaultGoogleOneScopes
}
default:
// Default to Code Assist scopes
effective.Scopes = DefaultCodeAssistScopes
}
} else if oauthType == "ai_studio" && isBuiltinClient {
} else if (oauthType == "ai_studio" || oauthType == "google_one") && isBuiltinClient {
// If user overrides scopes while still using the built-in client, strip restricted scopes.
parts := strings.Fields(effective.Scopes)
filtered := make([]string, 0, len(parts))
for _, s := range parts {
if strings.Contains(s, "generative-language") {
if hasRestrictedScope(s) {
continue
}
filtered = append(filtered, s)
@@ -214,6 +227,11 @@ func EffectiveOAuthConfig(cfg OAuthConfig, oauthType string) (OAuthConfig, error
return effective, nil
}
func hasRestrictedScope(scope string) bool {
return strings.HasPrefix(scope, "https://www.googleapis.com/auth/generative-language") ||
strings.HasPrefix(scope, "https://www.googleapis.com/auth/drive")
}
func BuildAuthorizationURL(cfg OAuthConfig, state, codeChallenge, redirectURI, projectID, oauthType string) (string, error) {
effectiveCfg, err := EffectiveOAuthConfig(cfg, oauthType)
if err != nil {

View File

@@ -0,0 +1,113 @@
package geminicli
import (
"strings"
"testing"
)
func TestEffectiveOAuthConfig_GoogleOne(t *testing.T) {
tests := []struct {
name string
input OAuthConfig
oauthType string
wantClientID string
wantScopes string
wantErr bool
}{
{
name: "Google One with built-in client (empty config)",
input: OAuthConfig{},
oauthType: "google_one",
wantClientID: GeminiCLIOAuthClientID,
wantScopes: DefaultCodeAssistScopes,
wantErr: false,
},
{
name: "Google One with custom client",
input: OAuthConfig{
ClientID: "custom-client-id",
ClientSecret: "custom-client-secret",
},
oauthType: "google_one",
wantClientID: "custom-client-id",
wantScopes: DefaultGoogleOneScopes,
wantErr: false,
},
{
name: "Google One with built-in client and custom scopes (should filter restricted scopes)",
input: OAuthConfig{
Scopes: "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly",
},
oauthType: "google_one",
wantClientID: GeminiCLIOAuthClientID,
wantScopes: "https://www.googleapis.com/auth/cloud-platform",
wantErr: false,
},
{
name: "Google One with built-in client and only restricted scopes (should fallback to default)",
input: OAuthConfig{
Scopes: "https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly",
},
oauthType: "google_one",
wantClientID: GeminiCLIOAuthClientID,
wantScopes: DefaultCodeAssistScopes,
wantErr: false,
},
{
name: "Code Assist with built-in client",
input: OAuthConfig{},
oauthType: "code_assist",
wantClientID: GeminiCLIOAuthClientID,
wantScopes: DefaultCodeAssistScopes,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := EffectiveOAuthConfig(tt.input, tt.oauthType)
if (err != nil) != tt.wantErr {
t.Errorf("EffectiveOAuthConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil {
return
}
if got.ClientID != tt.wantClientID {
t.Errorf("EffectiveOAuthConfig() ClientID = %v, want %v", got.ClientID, tt.wantClientID)
}
if got.Scopes != tt.wantScopes {
t.Errorf("EffectiveOAuthConfig() Scopes = %v, want %v", got.Scopes, tt.wantScopes)
}
})
}
}
func TestEffectiveOAuthConfig_ScopeFiltering(t *testing.T) {
// Test that Google One with built-in client filters out restricted scopes
cfg, err := EffectiveOAuthConfig(OAuthConfig{
Scopes: "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/generative-language.retriever https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.profile",
}, "google_one")
if err != nil {
t.Fatalf("EffectiveOAuthConfig() error = %v", err)
}
// Should only contain cloud-platform, userinfo.email, and userinfo.profile
// Should NOT contain generative-language or drive scopes
if strings.Contains(cfg.Scopes, "generative-language") {
t.Errorf("Scopes should not contain generative-language when using built-in client, got: %v", cfg.Scopes)
}
if strings.Contains(cfg.Scopes, "drive") {
t.Errorf("Scopes should not contain drive when using built-in client, got: %v", cfg.Scopes)
}
if !strings.Contains(cfg.Scopes, "cloud-platform") {
t.Errorf("Scopes should contain cloud-platform, got: %v", cfg.Scopes)
}
if !strings.Contains(cfg.Scopes, "userinfo.email") {
t.Errorf("Scopes should contain userinfo.email, got: %v", cfg.Scopes)
}
if !strings.Contains(cfg.Scopes, "userinfo.profile") {
t.Errorf("Scopes should contain userinfo.profile, got: %v", cfg.Scopes)
}
}

View File

@@ -1,3 +1,4 @@
// Package googleapi provides helpers for Google-style API responses.
package googleapi
import "net/http"

View File

@@ -1,3 +1,4 @@
// Package oauth provides helpers for OAuth flows used by this service.
package oauth
import (

View File

@@ -1,3 +1,4 @@
// Package openai provides helpers and types for OpenAI API integration.
package openai
import _ "embed"

View File

@@ -327,7 +327,7 @@ func ParseIDToken(idToken string) (*IDTokenClaims, error) {
return &claims, nil
}
// ExtractUserInfo extracts user information from ID Token claims
// UserInfo represents user information extracted from ID Token claims.
type UserInfo struct {
Email string
ChatGPTAccountID string

View File

@@ -1,3 +1,4 @@
// Package pagination provides types and helpers for paginated responses.
package pagination
// PaginationParams 分页参数

View File

@@ -1,3 +1,4 @@
// Package response provides standardized HTTP response helpers.
package response
import (

View File

@@ -1,3 +1,4 @@
// Package sysutil provides system-level utilities for process management.
package sysutil
import (

View File

@@ -1,3 +1,4 @@
// Package usagestats provides types for usage statistics and reporting.
package usagestats
import "time"
@@ -10,8 +11,8 @@ type DashboardStats struct {
ActiveUsers int64 `json:"active_users"` // 今日有请求的用户数
// API Key 统计
TotalApiKeys int64 `json:"total_api_keys"`
ActiveApiKeys int64 `json:"active_api_keys"` // 状态为 active 的 API Key 数
TotalAPIKeys int64 `json:"total_api_keys"`
ActiveAPIKeys int64 `json:"active_api_keys"` // 状态为 active 的 API Key 数
// 账户统计
TotalAccounts int64 `json:"total_accounts"`
@@ -82,10 +83,10 @@ type UserUsageTrendPoint struct {
ActualCost float64 `json:"actual_cost"` // 实际扣除
}
// ApiKeyUsageTrendPoint represents API key usage trend data point
type ApiKeyUsageTrendPoint struct {
// APIKeyUsageTrendPoint represents API key usage trend data point
type APIKeyUsageTrendPoint struct {
Date string `json:"date"`
ApiKeyID int64 `json:"api_key_id"`
APIKeyID int64 `json:"api_key_id"`
KeyName string `json:"key_name"`
Requests int64 `json:"requests"`
Tokens int64 `json:"tokens"`
@@ -94,8 +95,8 @@ type ApiKeyUsageTrendPoint struct {
// UserDashboardStats 用户仪表盘统计
type UserDashboardStats struct {
// API Key 统计
TotalApiKeys int64 `json:"total_api_keys"`
ActiveApiKeys int64 `json:"active_api_keys"`
TotalAPIKeys int64 `json:"total_api_keys"`
ActiveAPIKeys int64 `json:"active_api_keys"`
// 累计 Token 使用统计
TotalRequests int64 `json:"total_requests"`
@@ -128,7 +129,7 @@ type UserDashboardStats struct {
// UsageLogFilters represents filters for usage log queries
type UsageLogFilters struct {
UserID int64
ApiKeyID int64
APIKeyID int64
AccountID int64
GroupID int64
Model string
@@ -157,9 +158,9 @@ type BatchUserUsageStats struct {
TotalActualCost float64 `json:"total_actual_cost"`
}
// BatchApiKeyUsageStats represents usage stats for a single API key
type BatchApiKeyUsageStats struct {
ApiKeyID int64 `json:"api_key_id"`
// BatchAPIKeyUsageStats represents usage stats for a single API key
type BatchAPIKeyUsageStats struct {
APIKeyID int64 `json:"api_key_id"`
TodayActualCost float64 `json:"today_actual_cost"`
TotalActualCost float64 `json:"total_actual_cost"`
}

View File

@@ -43,6 +43,11 @@ type accountRepository struct {
sql sqlExecutor // 原生 SQL 执行接口
}
type tempUnschedSnapshot struct {
until *time.Time
reason string
}
// NewAccountRepository 创建账户仓储实例。
// 这是对外暴露的构造函数,返回接口类型以便于依赖注入。
func NewAccountRepository(client *dbent.Client, sqlDB *sql.DB) service.AccountRepository {
@@ -165,6 +170,11 @@ func (r *accountRepository) GetByIDs(ctx context.Context, ids []int64) ([]*servi
accountIDs = append(accountIDs, acc.ID)
}
tempUnschedMap, err := r.loadTempUnschedStates(ctx, accountIDs)
if err != nil {
return nil, err
}
groupsByAccount, groupIDsByAccount, accountGroupsByAccount, err := r.loadAccountGroups(ctx, accountIDs)
if err != nil {
return nil, err
@@ -191,6 +201,10 @@ func (r *accountRepository) GetByIDs(ctx context.Context, ids []int64) ([]*servi
if ags, ok := accountGroupsByAccount[entAcc.ID]; ok {
out.AccountGroups = ags
}
if snap, ok := tempUnschedMap[entAcc.ID]; ok {
out.TempUnschedulableUntil = snap.until
out.TempUnschedulableReason = snap.reason
}
outByID[entAcc.ID] = out
}
@@ -550,6 +564,7 @@ func (r *accountRepository) ListSchedulable(ctx context.Context) ([]service.Acco
Where(
dbaccount.StatusEQ(service.StatusActive),
dbaccount.SchedulableEQ(true),
tempUnschedulablePredicate(),
dbaccount.Or(dbaccount.OverloadUntilIsNil(), dbaccount.OverloadUntilLTE(now)),
dbaccount.Or(dbaccount.RateLimitResetAtIsNil(), dbaccount.RateLimitResetAtLTE(now)),
).
@@ -575,6 +590,7 @@ func (r *accountRepository) ListSchedulableByPlatform(ctx context.Context, platf
dbaccount.PlatformEQ(platform),
dbaccount.StatusEQ(service.StatusActive),
dbaccount.SchedulableEQ(true),
tempUnschedulablePredicate(),
dbaccount.Or(dbaccount.OverloadUntilIsNil(), dbaccount.OverloadUntilLTE(now)),
dbaccount.Or(dbaccount.RateLimitResetAtIsNil(), dbaccount.RateLimitResetAtLTE(now)),
).
@@ -607,6 +623,7 @@ func (r *accountRepository) ListSchedulableByPlatforms(ctx context.Context, plat
dbaccount.PlatformIn(platforms...),
dbaccount.StatusEQ(service.StatusActive),
dbaccount.SchedulableEQ(true),
tempUnschedulablePredicate(),
dbaccount.Or(dbaccount.OverloadUntilIsNil(), dbaccount.OverloadUntilLTE(now)),
dbaccount.Or(dbaccount.RateLimitResetAtIsNil(), dbaccount.RateLimitResetAtLTE(now)),
).
@@ -648,6 +665,31 @@ func (r *accountRepository) SetOverloaded(ctx context.Context, id int64, until t
return err
}
func (r *accountRepository) SetTempUnschedulable(ctx context.Context, id int64, until time.Time, reason string) error {
_, err := r.sql.ExecContext(ctx, `
UPDATE accounts
SET temp_unschedulable_until = $1,
temp_unschedulable_reason = $2,
updated_at = NOW()
WHERE id = $3
AND deleted_at IS NULL
AND (temp_unschedulable_until IS NULL OR temp_unschedulable_until < $1)
`, until, reason, id)
return err
}
func (r *accountRepository) ClearTempUnschedulable(ctx context.Context, id int64) error {
_, err := r.sql.ExecContext(ctx, `
UPDATE accounts
SET temp_unschedulable_until = NULL,
temp_unschedulable_reason = NULL,
updated_at = NOW()
WHERE id = $1
AND deleted_at IS NULL
`, id)
return err
}
func (r *accountRepository) ClearRateLimit(ctx context.Context, id int64) error {
_, err := r.client.Account.Update().
Where(dbaccount.IDEQ(id)).
@@ -808,6 +850,7 @@ func (r *accountRepository) queryAccountsByGroup(ctx context.Context, groupID in
now := time.Now()
preds = append(preds,
dbaccount.SchedulableEQ(true),
tempUnschedulablePredicate(),
dbaccount.Or(dbaccount.OverloadUntilIsNil(), dbaccount.OverloadUntilLTE(now)),
dbaccount.Or(dbaccount.RateLimitResetAtIsNil(), dbaccount.RateLimitResetAtLTE(now)),
)
@@ -869,6 +912,10 @@ func (r *accountRepository) accountsToService(ctx context.Context, accounts []*d
if err != nil {
return nil, err
}
tempUnschedMap, err := r.loadTempUnschedStates(ctx, accountIDs)
if err != nil {
return nil, err
}
groupsByAccount, groupIDsByAccount, accountGroupsByAccount, err := r.loadAccountGroups(ctx, accountIDs)
if err != nil {
return nil, err
@@ -894,12 +941,68 @@ func (r *accountRepository) accountsToService(ctx context.Context, accounts []*d
if ags, ok := accountGroupsByAccount[acc.ID]; ok {
out.AccountGroups = ags
}
if snap, ok := tempUnschedMap[acc.ID]; ok {
out.TempUnschedulableUntil = snap.until
out.TempUnschedulableReason = snap.reason
}
outAccounts = append(outAccounts, *out)
}
return outAccounts, nil
}
func tempUnschedulablePredicate() dbpredicate.Account {
return dbpredicate.Account(func(s *entsql.Selector) {
col := s.C("temp_unschedulable_until")
s.Where(entsql.Or(
entsql.IsNull(col),
entsql.LTE(col, entsql.Expr("NOW()")),
))
})
}
func (r *accountRepository) loadTempUnschedStates(ctx context.Context, accountIDs []int64) (map[int64]tempUnschedSnapshot, error) {
out := make(map[int64]tempUnschedSnapshot)
if len(accountIDs) == 0 {
return out, nil
}
rows, err := r.sql.QueryContext(ctx, `
SELECT id, temp_unschedulable_until, temp_unschedulable_reason
FROM accounts
WHERE id = ANY($1)
`, pq.Array(accountIDs))
if err != nil {
return nil, err
}
defer func() { _ = rows.Close() }()
for rows.Next() {
var id int64
var until sql.NullTime
var reason sql.NullString
if err := rows.Scan(&id, &until, &reason); err != nil {
return nil, err
}
var untilPtr *time.Time
if until.Valid {
tmp := until.Time
untilPtr = &tmp
}
if reason.Valid {
out[id] = tempUnschedSnapshot{until: untilPtr, reason: reason.String}
} else {
out[id] = tempUnschedSnapshot{until: untilPtr, reason: ""}
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return out, nil
}
func (r *accountRepository) loadProxies(ctx context.Context, proxyIDs []int64) (map[int64]*service.Proxy, error) {
proxyMap := make(map[int64]*service.Proxy)
if len(proxyIDs) == 0 {

View File

@@ -135,12 +135,12 @@ func (s *AccountRepoSuite) TestListWithFilters() {
name: "filter_by_type",
setup: func(client *dbent.Client) {
mustCreateAccount(s.T(), client, &service.Account{Name: "t1", Type: service.AccountTypeOAuth})
mustCreateAccount(s.T(), client, &service.Account{Name: "t2", Type: service.AccountTypeApiKey})
mustCreateAccount(s.T(), client, &service.Account{Name: "t2", Type: service.AccountTypeAPIKey})
},
accType: service.AccountTypeApiKey,
accType: service.AccountTypeAPIKey,
wantCount: 1,
validate: func(accounts []service.Account) {
s.Require().Equal(service.AccountTypeApiKey, accounts[0].Type)
s.Require().Equal(service.AccountTypeAPIKey, accounts[0].Type)
},
},
{

View File

@@ -98,7 +98,7 @@ func TestGroupRepository_DeleteCascade_RemovesAllowedGroupsAndClearsApiKeys(t *t
userRepo := newUserRepositoryWithSQL(entClient, tx)
groupRepo := newGroupRepositoryWithSQL(entClient, tx)
apiKeyRepo := NewApiKeyRepository(entClient)
apiKeyRepo := NewAPIKeyRepository(entClient)
u := &service.User{
Email: uniqueTestValue(t, "cascade-user") + "@example.com",
@@ -110,7 +110,7 @@ func TestGroupRepository_DeleteCascade_RemovesAllowedGroupsAndClearsApiKeys(t *t
}
require.NoError(t, userRepo.Create(ctx, u))
key := &service.ApiKey{
key := &service.APIKey{
UserID: u.ID,
Key: uniqueTestValue(t, "sk-test-delete-cascade"),
Name: "test key",

View File

@@ -24,7 +24,7 @@ type apiKeyCache struct {
rdb *redis.Client
}
func NewApiKeyCache(rdb *redis.Client) service.ApiKeyCache {
func NewAPIKeyCache(rdb *redis.Client) service.APIKeyCache {
return &apiKeyCache{rdb: rdb}
}

View File

@@ -16,17 +16,17 @@ type apiKeyRepository struct {
client *dbent.Client
}
func NewApiKeyRepository(client *dbent.Client) service.ApiKeyRepository {
func NewAPIKeyRepository(client *dbent.Client) service.APIKeyRepository {
return &apiKeyRepository{client: client}
}
func (r *apiKeyRepository) activeQuery() *dbent.ApiKeyQuery {
func (r *apiKeyRepository) activeQuery() *dbent.APIKeyQuery {
// 默认过滤已软删除记录,避免删除后仍被查询到。
return r.client.ApiKey.Query().Where(apikey.DeletedAtIsNil())
return r.client.APIKey.Query().Where(apikey.DeletedAtIsNil())
}
func (r *apiKeyRepository) Create(ctx context.Context, key *service.ApiKey) error {
created, err := r.client.ApiKey.Create().
func (r *apiKeyRepository) Create(ctx context.Context, key *service.APIKey) error {
created, err := r.client.APIKey.Create().
SetUserID(key.UserID).
SetKey(key.Key).
SetName(key.Name).
@@ -38,10 +38,10 @@ func (r *apiKeyRepository) Create(ctx context.Context, key *service.ApiKey) erro
key.CreatedAt = created.CreatedAt
key.UpdatedAt = created.UpdatedAt
}
return translatePersistenceError(err, nil, service.ErrApiKeyExists)
return translatePersistenceError(err, nil, service.ErrAPIKeyExists)
}
func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.ApiKey, error) {
func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.APIKey, error) {
m, err := r.activeQuery().
Where(apikey.IDEQ(id)).
WithUser().
@@ -49,7 +49,7 @@ func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.ApiK
Only(ctx)
if err != nil {
if dbent.IsNotFound(err) {
return nil, service.ErrApiKeyNotFound
return nil, service.ErrAPIKeyNotFound
}
return nil, err
}
@@ -59,7 +59,7 @@ func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.ApiK
// GetOwnerID 根据 API Key ID 获取其所有者(用户)的 ID。
// 相比 GetByID此方法性能更优因为
// - 使用 Select() 只查询 user_id 字段,减少数据传输量
// - 不加载完整的 ApiKey 实体及其关联数据User、Group 等)
// - 不加载完整的 API Key 实体及其关联数据User、Group 等)
// - 适用于权限验证等只需用户 ID 的场景(如删除前的所有权检查)
func (r *apiKeyRepository) GetOwnerID(ctx context.Context, id int64) (int64, error) {
m, err := r.activeQuery().
@@ -68,14 +68,14 @@ func (r *apiKeyRepository) GetOwnerID(ctx context.Context, id int64) (int64, err
Only(ctx)
if err != nil {
if dbent.IsNotFound(err) {
return 0, service.ErrApiKeyNotFound
return 0, service.ErrAPIKeyNotFound
}
return 0, err
}
return m.UserID, nil
}
func (r *apiKeyRepository) GetByKey(ctx context.Context, key string) (*service.ApiKey, error) {
func (r *apiKeyRepository) GetByKey(ctx context.Context, key string) (*service.APIKey, error) {
m, err := r.activeQuery().
Where(apikey.KeyEQ(key)).
WithUser().
@@ -83,21 +83,21 @@ func (r *apiKeyRepository) GetByKey(ctx context.Context, key string) (*service.A
Only(ctx)
if err != nil {
if dbent.IsNotFound(err) {
return nil, service.ErrApiKeyNotFound
return nil, service.ErrAPIKeyNotFound
}
return nil, err
}
return apiKeyEntityToService(m), nil
}
func (r *apiKeyRepository) Update(ctx context.Context, key *service.ApiKey) error {
func (r *apiKeyRepository) Update(ctx context.Context, key *service.APIKey) error {
// 使用原子操作:将软删除检查与更新合并到同一语句,避免竞态条件。
// 之前的实现先检查 Exist 再 UpdateOneID若在两步之间发生软删除
// 则会更新已删除的记录。
// 这里选择 Update().Where(),确保只有未软删除记录能被更新。
// 同时显式设置 updated_at避免二次查询带来的并发可见性问题。
now := time.Now()
builder := r.client.ApiKey.Update().
builder := r.client.APIKey.Update().
Where(apikey.IDEQ(key.ID), apikey.DeletedAtIsNil()).
SetName(key.Name).
SetStatus(key.Status).
@@ -114,7 +114,7 @@ func (r *apiKeyRepository) Update(ctx context.Context, key *service.ApiKey) erro
}
if affected == 0 {
// 更新影响行数为 0说明记录不存在或已被软删除。
return service.ErrApiKeyNotFound
return service.ErrAPIKeyNotFound
}
// 使用同一时间戳回填,避免并发删除导致二次查询失败。
@@ -124,18 +124,18 @@ func (r *apiKeyRepository) Update(ctx context.Context, key *service.ApiKey) erro
func (r *apiKeyRepository) Delete(ctx context.Context, id int64) error {
// 显式软删除:避免依赖 Hook 行为,确保 deleted_at 一定被设置。
affected, err := r.client.ApiKey.Update().
affected, err := r.client.APIKey.Update().
Where(apikey.IDEQ(id), apikey.DeletedAtIsNil()).
SetDeletedAt(time.Now()).
Save(ctx)
if err != nil {
if dbent.IsNotFound(err) {
return service.ErrApiKeyNotFound
return service.ErrAPIKeyNotFound
}
return err
}
if affected == 0 {
exists, err := r.client.ApiKey.Query().
exists, err := r.client.APIKey.Query().
Where(apikey.IDEQ(id)).
Exist(mixins.SkipSoftDelete(ctx))
if err != nil {
@@ -144,12 +144,12 @@ func (r *apiKeyRepository) Delete(ctx context.Context, id int64) error {
if exists {
return nil
}
return service.ErrApiKeyNotFound
return service.ErrAPIKeyNotFound
}
return nil
}
func (r *apiKeyRepository) ListByUserID(ctx context.Context, userID int64, params pagination.PaginationParams) ([]service.ApiKey, *pagination.PaginationResult, error) {
func (r *apiKeyRepository) ListByUserID(ctx context.Context, userID int64, params pagination.PaginationParams) ([]service.APIKey, *pagination.PaginationResult, error) {
q := r.activeQuery().Where(apikey.UserIDEQ(userID))
total, err := q.Count(ctx)
@@ -167,7 +167,7 @@ func (r *apiKeyRepository) ListByUserID(ctx context.Context, userID int64, param
return nil, nil, err
}
outKeys := make([]service.ApiKey, 0, len(keys))
outKeys := make([]service.APIKey, 0, len(keys))
for i := range keys {
outKeys = append(outKeys, *apiKeyEntityToService(keys[i]))
}
@@ -180,7 +180,7 @@ func (r *apiKeyRepository) VerifyOwnership(ctx context.Context, userID int64, ap
return []int64{}, nil
}
ids, err := r.client.ApiKey.Query().
ids, err := r.client.APIKey.Query().
Where(apikey.UserIDEQ(userID), apikey.IDIn(apiKeyIDs...), apikey.DeletedAtIsNil()).
IDs(ctx)
if err != nil {
@@ -199,7 +199,7 @@ func (r *apiKeyRepository) ExistsByKey(ctx context.Context, key string) (bool, e
return count > 0, err
}
func (r *apiKeyRepository) ListByGroupID(ctx context.Context, groupID int64, params pagination.PaginationParams) ([]service.ApiKey, *pagination.PaginationResult, error) {
func (r *apiKeyRepository) ListByGroupID(ctx context.Context, groupID int64, params pagination.PaginationParams) ([]service.APIKey, *pagination.PaginationResult, error) {
q := r.activeQuery().Where(apikey.GroupIDEQ(groupID))
total, err := q.Count(ctx)
@@ -217,7 +217,7 @@ func (r *apiKeyRepository) ListByGroupID(ctx context.Context, groupID int64, par
return nil, nil, err
}
outKeys := make([]service.ApiKey, 0, len(keys))
outKeys := make([]service.APIKey, 0, len(keys))
for i := range keys {
outKeys = append(outKeys, *apiKeyEntityToService(keys[i]))
}
@@ -225,8 +225,8 @@ func (r *apiKeyRepository) ListByGroupID(ctx context.Context, groupID int64, par
return outKeys, paginationResultFromTotal(int64(total), params), nil
}
// SearchApiKeys searches API keys by user ID and/or keyword (name)
func (r *apiKeyRepository) SearchApiKeys(ctx context.Context, userID int64, keyword string, limit int) ([]service.ApiKey, error) {
// SearchAPIKeys searches API keys by user ID and/or keyword (name)
func (r *apiKeyRepository) SearchAPIKeys(ctx context.Context, userID int64, keyword string, limit int) ([]service.APIKey, error) {
q := r.activeQuery()
if userID > 0 {
q = q.Where(apikey.UserIDEQ(userID))
@@ -241,7 +241,7 @@ func (r *apiKeyRepository) SearchApiKeys(ctx context.Context, userID int64, keyw
return nil, err
}
outKeys := make([]service.ApiKey, 0, len(keys))
outKeys := make([]service.APIKey, 0, len(keys))
for i := range keys {
outKeys = append(outKeys, *apiKeyEntityToService(keys[i]))
}
@@ -250,7 +250,7 @@ func (r *apiKeyRepository) SearchApiKeys(ctx context.Context, userID int64, keyw
// ClearGroupIDByGroupID 将指定分组的所有 API Key 的 group_id 设为 nil
func (r *apiKeyRepository) ClearGroupIDByGroupID(ctx context.Context, groupID int64) (int64, error) {
n, err := r.client.ApiKey.Update().
n, err := r.client.APIKey.Update().
Where(apikey.GroupIDEQ(groupID), apikey.DeletedAtIsNil()).
ClearGroupID().
Save(ctx)
@@ -263,11 +263,11 @@ func (r *apiKeyRepository) CountByGroupID(ctx context.Context, groupID int64) (i
return int64(count), err
}
func apiKeyEntityToService(m *dbent.ApiKey) *service.ApiKey {
func apiKeyEntityToService(m *dbent.APIKey) *service.APIKey {
if m == nil {
return nil
}
out := &service.ApiKey{
out := &service.APIKey{
ID: m.ID,
UserID: m.UserID,
Key: m.Key,

View File

@@ -12,30 +12,30 @@ import (
"github.com/stretchr/testify/suite"
)
type ApiKeyRepoSuite struct {
type APIKeyRepoSuite struct {
suite.Suite
ctx context.Context
client *dbent.Client
repo *apiKeyRepository
}
func (s *ApiKeyRepoSuite) SetupTest() {
func (s *APIKeyRepoSuite) SetupTest() {
s.ctx = context.Background()
tx := testEntTx(s.T())
s.client = tx.Client()
s.repo = NewApiKeyRepository(s.client).(*apiKeyRepository)
s.repo = NewAPIKeyRepository(s.client).(*apiKeyRepository)
}
func TestApiKeyRepoSuite(t *testing.T) {
suite.Run(t, new(ApiKeyRepoSuite))
func TestAPIKeyRepoSuite(t *testing.T) {
suite.Run(t, new(APIKeyRepoSuite))
}
// --- Create / GetByID / GetByKey ---
func (s *ApiKeyRepoSuite) TestCreate() {
func (s *APIKeyRepoSuite) TestCreate() {
user := s.mustCreateUser("create@test.com")
key := &service.ApiKey{
key := &service.APIKey{
UserID: user.ID,
Key: "sk-create-test",
Name: "Test Key",
@@ -51,16 +51,16 @@ func (s *ApiKeyRepoSuite) TestCreate() {
s.Require().Equal("sk-create-test", got.Key)
}
func (s *ApiKeyRepoSuite) TestGetByID_NotFound() {
func (s *APIKeyRepoSuite) TestGetByID_NotFound() {
_, err := s.repo.GetByID(s.ctx, 999999)
s.Require().Error(err, "expected error for non-existent ID")
}
func (s *ApiKeyRepoSuite) TestGetByKey() {
func (s *APIKeyRepoSuite) TestGetByKey() {
user := s.mustCreateUser("getbykey@test.com")
group := s.mustCreateGroup("g-key")
key := &service.ApiKey{
key := &service.APIKey{
UserID: user.ID,
Key: "sk-getbykey",
Name: "My Key",
@@ -78,16 +78,16 @@ func (s *ApiKeyRepoSuite) TestGetByKey() {
s.Require().Equal(group.ID, got.Group.ID)
}
func (s *ApiKeyRepoSuite) TestGetByKey_NotFound() {
func (s *APIKeyRepoSuite) TestGetByKey_NotFound() {
_, err := s.repo.GetByKey(s.ctx, "non-existent-key")
s.Require().Error(err, "expected error for non-existent key")
}
// --- Update ---
func (s *ApiKeyRepoSuite) TestUpdate() {
func (s *APIKeyRepoSuite) TestUpdate() {
user := s.mustCreateUser("update@test.com")
key := &service.ApiKey{
key := &service.APIKey{
UserID: user.ID,
Key: "sk-update",
Name: "Original",
@@ -108,10 +108,10 @@ func (s *ApiKeyRepoSuite) TestUpdate() {
s.Require().Equal(service.StatusDisabled, got.Status)
}
func (s *ApiKeyRepoSuite) TestUpdate_ClearGroupID() {
func (s *APIKeyRepoSuite) TestUpdate_ClearGroupID() {
user := s.mustCreateUser("cleargroup@test.com")
group := s.mustCreateGroup("g-clear")
key := &service.ApiKey{
key := &service.APIKey{
UserID: user.ID,
Key: "sk-clear-group",
Name: "Group Key",
@@ -131,9 +131,9 @@ func (s *ApiKeyRepoSuite) TestUpdate_ClearGroupID() {
// --- Delete ---
func (s *ApiKeyRepoSuite) TestDelete() {
func (s *APIKeyRepoSuite) TestDelete() {
user := s.mustCreateUser("delete@test.com")
key := &service.ApiKey{
key := &service.APIKey{
UserID: user.ID,
Key: "sk-delete",
Name: "Delete Me",
@@ -150,7 +150,7 @@ func (s *ApiKeyRepoSuite) TestDelete() {
// --- ListByUserID / CountByUserID ---
func (s *ApiKeyRepoSuite) TestListByUserID() {
func (s *APIKeyRepoSuite) TestListByUserID() {
user := s.mustCreateUser("listbyuser@test.com")
s.mustCreateApiKey(user.ID, "sk-list-1", "Key 1", nil)
s.mustCreateApiKey(user.ID, "sk-list-2", "Key 2", nil)
@@ -161,7 +161,7 @@ func (s *ApiKeyRepoSuite) TestListByUserID() {
s.Require().Equal(int64(2), page.Total)
}
func (s *ApiKeyRepoSuite) TestListByUserID_Pagination() {
func (s *APIKeyRepoSuite) TestListByUserID_Pagination() {
user := s.mustCreateUser("paging@test.com")
for i := 0; i < 5; i++ {
s.mustCreateApiKey(user.ID, "sk-page-"+string(rune('a'+i)), "Key", nil)
@@ -174,7 +174,7 @@ func (s *ApiKeyRepoSuite) TestListByUserID_Pagination() {
s.Require().Equal(3, page.Pages)
}
func (s *ApiKeyRepoSuite) TestCountByUserID() {
func (s *APIKeyRepoSuite) TestCountByUserID() {
user := s.mustCreateUser("count@test.com")
s.mustCreateApiKey(user.ID, "sk-count-1", "K1", nil)
s.mustCreateApiKey(user.ID, "sk-count-2", "K2", nil)
@@ -186,7 +186,7 @@ func (s *ApiKeyRepoSuite) TestCountByUserID() {
// --- ListByGroupID / CountByGroupID ---
func (s *ApiKeyRepoSuite) TestListByGroupID() {
func (s *APIKeyRepoSuite) TestListByGroupID() {
user := s.mustCreateUser("listbygroup@test.com")
group := s.mustCreateGroup("g-list")
@@ -202,7 +202,7 @@ func (s *ApiKeyRepoSuite) TestListByGroupID() {
s.Require().NotNil(keys[0].User)
}
func (s *ApiKeyRepoSuite) TestCountByGroupID() {
func (s *APIKeyRepoSuite) TestCountByGroupID() {
user := s.mustCreateUser("countgroup@test.com")
group := s.mustCreateGroup("g-count")
s.mustCreateApiKey(user.ID, "sk-gc-1", "K1", &group.ID)
@@ -214,7 +214,7 @@ func (s *ApiKeyRepoSuite) TestCountByGroupID() {
// --- ExistsByKey ---
func (s *ApiKeyRepoSuite) TestExistsByKey() {
func (s *APIKeyRepoSuite) TestExistsByKey() {
user := s.mustCreateUser("exists@test.com")
s.mustCreateApiKey(user.ID, "sk-exists", "K", nil)
@@ -227,41 +227,41 @@ func (s *ApiKeyRepoSuite) TestExistsByKey() {
s.Require().False(notExists)
}
// --- SearchApiKeys ---
// --- SearchAPIKeys ---
func (s *ApiKeyRepoSuite) TestSearchApiKeys() {
func (s *APIKeyRepoSuite) TestSearchAPIKeys() {
user := s.mustCreateUser("search@test.com")
s.mustCreateApiKey(user.ID, "sk-search-1", "Production Key", nil)
s.mustCreateApiKey(user.ID, "sk-search-2", "Development Key", nil)
found, err := s.repo.SearchApiKeys(s.ctx, user.ID, "prod", 10)
s.Require().NoError(err, "SearchApiKeys")
found, err := s.repo.SearchAPIKeys(s.ctx, user.ID, "prod", 10)
s.Require().NoError(err, "SearchAPIKeys")
s.Require().Len(found, 1)
s.Require().Contains(found[0].Name, "Production")
}
func (s *ApiKeyRepoSuite) TestSearchApiKeys_NoKeyword() {
func (s *APIKeyRepoSuite) TestSearchAPIKeys_NoKeyword() {
user := s.mustCreateUser("searchnokw@test.com")
s.mustCreateApiKey(user.ID, "sk-nk-1", "K1", nil)
s.mustCreateApiKey(user.ID, "sk-nk-2", "K2", nil)
found, err := s.repo.SearchApiKeys(s.ctx, user.ID, "", 10)
found, err := s.repo.SearchAPIKeys(s.ctx, user.ID, "", 10)
s.Require().NoError(err)
s.Require().Len(found, 2)
}
func (s *ApiKeyRepoSuite) TestSearchApiKeys_NoUserID() {
func (s *APIKeyRepoSuite) TestSearchAPIKeys_NoUserID() {
user := s.mustCreateUser("searchnouid@test.com")
s.mustCreateApiKey(user.ID, "sk-nu-1", "TestKey", nil)
found, err := s.repo.SearchApiKeys(s.ctx, 0, "testkey", 10)
found, err := s.repo.SearchAPIKeys(s.ctx, 0, "testkey", 10)
s.Require().NoError(err)
s.Require().Len(found, 1)
}
// --- ClearGroupIDByGroupID ---
func (s *ApiKeyRepoSuite) TestClearGroupIDByGroupID() {
func (s *APIKeyRepoSuite) TestClearGroupIDByGroupID() {
user := s.mustCreateUser("cleargrp@test.com")
group := s.mustCreateGroup("g-clear-bulk")
@@ -284,7 +284,7 @@ func (s *ApiKeyRepoSuite) TestClearGroupIDByGroupID() {
// --- Combined CRUD/Search/ClearGroupID (original test preserved as integration) ---
func (s *ApiKeyRepoSuite) TestCRUD_Search_ClearGroupID() {
func (s *APIKeyRepoSuite) TestCRUD_Search_ClearGroupID() {
user := s.mustCreateUser("k@example.com")
group := s.mustCreateGroup("g-k")
key := s.mustCreateApiKey(user.ID, "sk-test-1", "My Key", &group.ID)
@@ -320,8 +320,8 @@ func (s *ApiKeyRepoSuite) TestCRUD_Search_ClearGroupID() {
s.Require().NoError(err, "ExistsByKey")
s.Require().True(exists, "expected key to exist")
found, err := s.repo.SearchApiKeys(s.ctx, user.ID, "renam", 10)
s.Require().NoError(err, "SearchApiKeys")
found, err := s.repo.SearchAPIKeys(s.ctx, user.ID, "renam", 10)
s.Require().NoError(err, "SearchAPIKeys")
s.Require().Len(found, 1)
s.Require().Equal(key.ID, found[0].ID)
@@ -346,7 +346,7 @@ func (s *ApiKeyRepoSuite) TestCRUD_Search_ClearGroupID() {
s.Require().Equal(int64(0), countAfter, "expected 0 keys in group after clear")
}
func (s *ApiKeyRepoSuite) mustCreateUser(email string) *service.User {
func (s *APIKeyRepoSuite) mustCreateUser(email string) *service.User {
s.T().Helper()
u, err := s.client.User.Create().
@@ -359,7 +359,7 @@ func (s *ApiKeyRepoSuite) mustCreateUser(email string) *service.User {
return userEntityToService(u)
}
func (s *ApiKeyRepoSuite) mustCreateGroup(name string) *service.Group {
func (s *APIKeyRepoSuite) mustCreateGroup(name string) *service.Group {
s.T().Helper()
g, err := s.client.Group.Create().
@@ -370,10 +370,10 @@ func (s *ApiKeyRepoSuite) mustCreateGroup(name string) *service.Group {
return groupEntityToService(g)
}
func (s *ApiKeyRepoSuite) mustCreateApiKey(userID int64, key, name string, groupID *int64) *service.ApiKey {
func (s *APIKeyRepoSuite) mustCreateApiKey(userID int64, key, name string, groupID *int64) *service.APIKey {
s.T().Helper()
k := &service.ApiKey{
k := &service.APIKey{
UserID: userID,
Key: key,
Name: name,

View File

@@ -5,28 +5,20 @@ import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/Wei-Shaw/sub2api/internal/pkg/oauth"
"github.com/imroc/req/v3"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
type ClaudeOAuthServiceSuite struct {
suite.Suite
srv *httptest.Server
client *claudeOAuthService
}
func (s *ClaudeOAuthServiceSuite) TearDownTest() {
if s.srv != nil {
s.srv.Close()
s.srv = nil
}
}
// requestCapture holds captured request data for assertions in the main goroutine.
type requestCapture struct {
path string
@@ -37,6 +29,12 @@ type requestCapture struct {
contentType string
}
func newTestReqClient(rt http.RoundTripper) *req.Client {
c := req.C()
c.GetClient().Transport = rt
return c
}
func (s *ClaudeOAuthServiceSuite) TestGetOrganizationUUID() {
tests := []struct {
name string
@@ -83,17 +81,17 @@ func (s *ClaudeOAuthServiceSuite) TestGetOrganizationUUID() {
s.Run(tt.name, func() {
var captured requestCapture
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rt := newInProcessTransport(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
captured.path = r.URL.Path
captured.cookies = r.Cookies()
tt.handler(w, r)
}))
defer s.srv.Close()
}), nil)
client, ok := NewClaudeOAuthClient().(*claudeOAuthService)
require.True(s.T(), ok, "type assertion failed")
s.client = client
s.client.baseURL = s.srv.URL
s.client.baseURL = "http://in-process"
s.client.clientFactory = func(string) *req.Client { return newTestReqClient(rt) }
got, err := s.client.GetOrganizationUUID(context.Background(), "sess", "")
@@ -158,20 +156,20 @@ func (s *ClaudeOAuthServiceSuite) TestGetAuthorizationCode() {
s.Run(tt.name, func() {
var captured requestCapture
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rt := newInProcessTransport(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
captured.path = r.URL.Path
captured.method = r.Method
captured.cookies = r.Cookies()
captured.body, _ = io.ReadAll(r.Body)
_ = json.Unmarshal(captured.body, &captured.bodyJSON)
tt.handler(w, r)
}))
defer s.srv.Close()
}), nil)
client, ok := NewClaudeOAuthClient().(*claudeOAuthService)
require.True(s.T(), ok, "type assertion failed")
s.client = client
s.client.baseURL = s.srv.URL
s.client.baseURL = "http://in-process"
s.client.clientFactory = func(string) *req.Client { return newTestReqClient(rt) }
code, err := s.client.GetAuthorizationCode(context.Background(), "sess", "org-1", oauth.ScopeProfile, "cc", "st", "")
@@ -266,19 +264,19 @@ func (s *ClaudeOAuthServiceSuite) TestExchangeCodeForToken() {
s.Run(tt.name, func() {
var captured requestCapture
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rt := newInProcessTransport(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
captured.method = r.Method
captured.contentType = r.Header.Get("Content-Type")
captured.body, _ = io.ReadAll(r.Body)
_ = json.Unmarshal(captured.body, &captured.bodyJSON)
tt.handler(w, r)
}))
defer s.srv.Close()
}), nil)
client, ok := NewClaudeOAuthClient().(*claudeOAuthService)
require.True(s.T(), ok, "type assertion failed")
s.client = client
s.client.tokenURL = s.srv.URL
s.client.tokenURL = "http://in-process/token"
s.client.clientFactory = func(string) *req.Client { return newTestReqClient(rt) }
resp, err := s.client.ExchangeCodeForToken(context.Background(), tt.code, "ver", "", "", tt.isSetupToken)
@@ -362,19 +360,19 @@ func (s *ClaudeOAuthServiceSuite) TestRefreshToken() {
s.Run(tt.name, func() {
var captured requestCapture
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rt := newInProcessTransport(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
captured.method = r.Method
captured.contentType = r.Header.Get("Content-Type")
captured.body, _ = io.ReadAll(r.Body)
_ = json.Unmarshal(captured.body, &captured.bodyJSON)
tt.handler(w, r)
}))
defer s.srv.Close()
}), nil)
client, ok := NewClaudeOAuthClient().(*claudeOAuthService)
require.True(s.T(), ok, "type assertion failed")
s.client = client
s.client.tokenURL = s.srv.URL
s.client.tokenURL = "http://in-process/token"
s.client.clientFactory = func(string) *req.Client { return newTestReqClient(rt) }
resp, err := s.client.RefreshToken(context.Background(), "rt", "")

View File

@@ -33,7 +33,7 @@ type usageRequestCapture struct {
func (s *ClaudeUsageServiceSuite) TestFetchUsage_Success() {
var captured usageRequestCapture
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
captured.authorization = r.Header.Get("Authorization")
captured.anthropicBeta = r.Header.Get("anthropic-beta")
@@ -59,7 +59,7 @@ func (s *ClaudeUsageServiceSuite) TestFetchUsage_Success() {
}
func (s *ClaudeUsageServiceSuite) TestFetchUsage_NonOK() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
_, _ = io.WriteString(w, "nope")
}))
@@ -73,7 +73,7 @@ func (s *ClaudeUsageServiceSuite) TestFetchUsage_NonOK() {
}
func (s *ClaudeUsageServiceSuite) TestFetchUsage_BadJSON() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = io.WriteString(w, "not-json")
}))
@@ -86,7 +86,7 @@ func (s *ClaudeUsageServiceSuite) TestFetchUsage_BadJSON() {
}
func (s *ClaudeUsageServiceSuite) TestFetchUsage_ContextCancel() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Never respond - simulate slow server
<-r.Context().Done()
}))

View File

@@ -309,7 +309,7 @@ func (c *concurrencyCache) GetUserConcurrency(ctx context.Context, userID int64)
func (c *concurrencyCache) IncrementWaitCount(ctx context.Context, userID int64, maxWait int) (bool, error) {
key := waitQueueKey(userID)
result, err := incrementWaitScript.Run(ctx, c.rdb, []string{key}, maxWait, c.slotTTLSeconds).Int()
result, err := incrementWaitScript.Run(ctx, c.rdb, []string{key}, maxWait, c.waitQueueTTLSeconds).Int()
if err != nil {
return false, err
}

View File

@@ -1,4 +1,4 @@
// Package infrastructure 提供应用程序的基础设施层组件。
// Package repository 提供应用程序的基础设施层组件。
// 包括数据库连接初始化、ORM 客户端管理、Redis 连接、数据库迁移等核心功能。
package repository

View File

@@ -243,7 +243,7 @@ func mustCreateAccount(t *testing.T, client *dbent.Client, a *service.Account) *
return a
}
func mustCreateApiKey(t *testing.T, client *dbent.Client, k *service.ApiKey) *service.ApiKey {
func mustCreateApiKey(t *testing.T, client *dbent.Client, k *service.APIKey) *service.APIKey {
t.Helper()
ctx := context.Background()
@@ -257,7 +257,7 @@ func mustCreateApiKey(t *testing.T, client *dbent.Client, k *service.ApiKey) *se
k.Name = "default"
}
create := client.ApiKey.Create().
create := client.APIKey.Create().
SetUserID(k.UserID).
SetKey(k.Key).
SetName(k.Name).

View File

@@ -30,6 +30,7 @@ func (c *geminiOAuthClient) ExchangeCode(ctx context.Context, oauthType, code, c
// Use different OAuth clients based on oauthType:
// - code_assist: always use built-in Gemini CLI OAuth client (public)
// - google_one: uses configured OAuth client when provided; otherwise falls back to built-in client
// - ai_studio: requires a user-provided OAuth client
oauthCfgInput := geminicli.OAuthConfig{
ClientID: c.cfg.Gemini.OAuth.ClientID,

View File

@@ -49,7 +49,7 @@ func (s *GitHubReleaseServiceSuite) TearDownTest() {
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_EnforcesMaxSize_ContentLength() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", "100")
w.WriteHeader(http.StatusOK)
_, _ = w.Write(bytes.Repeat([]byte("a"), 100))
@@ -68,7 +68,7 @@ func (s *GitHubReleaseServiceSuite) TestDownloadFile_EnforcesMaxSize_ContentLeng
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_EnforcesMaxSize_Chunked() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Force chunked encoding (unknown Content-Length) by flushing headers before writing.
w.WriteHeader(http.StatusOK)
if fl, ok := w.(http.Flusher); ok {
@@ -95,7 +95,7 @@ func (s *GitHubReleaseServiceSuite) TestDownloadFile_EnforcesMaxSize_Chunked() {
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_Success() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
if fl, ok := w.(http.Flusher); ok {
fl.Flush()
@@ -123,7 +123,7 @@ func (s *GitHubReleaseServiceSuite) TestDownloadFile_Success() {
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_404() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
@@ -140,7 +140,7 @@ func (s *GitHubReleaseServiceSuite) TestDownloadFile_404() {
}
func (s *GitHubReleaseServiceSuite) TestFetchChecksumFile_Success() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("sum"))
}))
@@ -155,7 +155,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchChecksumFile_Success() {
}
func (s *GitHubReleaseServiceSuite) TestFetchChecksumFile_Non200() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
@@ -168,7 +168,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchChecksumFile_Non200() {
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_ContextCancel() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-r.Context().Done()
}))
@@ -195,7 +195,7 @@ func (s *GitHubReleaseServiceSuite) TestDownloadFile_InvalidURL() {
}
func (s *GitHubReleaseServiceSuite) TestDownloadFile_InvalidDestPath() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("content"))
}))
@@ -233,7 +233,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Success() {
]
}`
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(s.T(), "/repos/test/repo/releases/latest", r.URL.Path)
require.Equal(s.T(), "application/vnd.github.v3+json", r.Header.Get("Accept"))
require.Equal(s.T(), "Sub2API-Updater", r.Header.Get("User-Agent"))
@@ -258,7 +258,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Success() {
}
func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Non200() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
@@ -274,7 +274,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Non200() {
}
func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_InvalidJSON() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("not valid json"))
}))
@@ -290,7 +290,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_InvalidJSON() {
}
func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_ContextCancel() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-r.Context().Done()
}))
@@ -308,7 +308,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_ContextCancel() {
}
func (s *GitHubReleaseServiceSuite) TestFetchChecksumFile_ContextCancel() {
s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-r.Context().Done()
}))

View File

@@ -293,8 +293,8 @@ func (r *groupRepository) DeleteCascade(ctx context.Context, id int64) ([]int64,
// 2. Clear group_id for api keys bound to this group.
// 仅更新未软删除的记录,避免修改已删除数据,保证审计与历史回溯一致性。
// 与 ApiKeyRepository 的软删除语义保持一致,减少跨模块行为差异。
if _, err := txClient.ApiKey.Update().
// 与 APIKeyRepository 的软删除语义保持一致,减少跨模块行为差异。
if _, err := txClient.APIKey.Update().
Where(apikey.GroupIDEQ(id), apikey.DeletedAtIsNil()).
ClearGroupID().
Save(ctx); err != nil {

View File

@@ -3,7 +3,6 @@ package repository
import (
"io"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
@@ -93,7 +92,7 @@ func (s *HTTPUpstreamSuite) TestAcquireClient_OverLimitReturnsError() {
// 验证空代理 URL 时请求直接发送到目标服务器
func (s *HTTPUpstreamSuite) TestDo_WithoutProxy_GoesDirect() {
// 创建模拟上游服务器
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
upstream := newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "direct")
}))
s.T().Cleanup(upstream.Close)
@@ -115,7 +114,7 @@ func (s *HTTPUpstreamSuite) TestDo_WithHTTPProxy_UsesProxy() {
// 用于接收代理请求的通道
seen := make(chan string, 1)
// 创建模拟代理服务器
proxySrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
proxySrv := newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
seen <- r.RequestURI // 记录请求 URI
_, _ = io.WriteString(w, "proxied")
}))
@@ -145,7 +144,7 @@ func (s *HTTPUpstreamSuite) TestDo_WithHTTPProxy_UsesProxy() {
// TestDo_EmptyProxy_UsesDirect 测试空代理字符串
// 验证空字符串代理等同于直连
func (s *HTTPUpstreamSuite) TestDo_EmptyProxy_UsesDirect() {
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
upstream := newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "direct-empty")
}))
s.T().Cleanup(upstream.Close)

View File

@@ -0,0 +1,63 @@
package repository
import (
"bytes"
"io"
"net"
"net/http"
"net/http/httptest"
"sync"
"testing"
)
type roundTripFunc func(*http.Request) (*http.Response, error)
func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
// newInProcessTransport adapts an http.HandlerFunc into an http.RoundTripper without opening sockets.
// It captures the request body (if any) and then rewinds it before invoking the handler.
func newInProcessTransport(handler http.HandlerFunc, capture func(r *http.Request, body []byte)) http.RoundTripper {
return roundTripFunc(func(r *http.Request) (*http.Response, error) {
var body []byte
if r.Body != nil {
body, _ = io.ReadAll(r.Body)
_ = r.Body.Close()
r.Body = io.NopCloser(bytes.NewReader(body))
}
if capture != nil {
capture(r, body)
}
rec := httptest.NewRecorder()
handler(rec, r)
return rec.Result(), nil
})
}
var (
canListenOnce sync.Once
canListen bool
canListenErr error
)
func localListenerAvailable() bool {
canListenOnce.Do(func() {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
canListenErr = err
canListen = false
return
}
_ = ln.Close()
canListen = true
})
return canListen
}
func newLocalTestServer(tb testing.TB, handler http.Handler) *httptest.Server {
tb.Helper()
if !localListenerAvailable() {
tb.Skipf("local listeners are not permitted in this environment: %v", canListenErr)
}
return httptest.NewServer(handler)
}

View File

@@ -34,7 +34,7 @@ func (s *OpenAIOAuthServiceSuite) TearDownTest() {
}
func (s *OpenAIOAuthServiceSuite) setupServer(handler http.HandlerFunc) {
s.srv = httptest.NewServer(handler)
s.srv = newLocalTestServer(s.T(), handler)
s.svc = &openaiOAuthService{tokenURL: s.srv.URL}
}

View File

@@ -32,7 +32,7 @@ func (s *PricingServiceSuite) TearDownTest() {
}
func (s *PricingServiceSuite) setupServer(handler http.HandlerFunc) {
s.srv = httptest.NewServer(handler)
s.srv = newLocalTestServer(s.T(), handler)
}
func (s *PricingServiceSuite) TestFetchPricingJSON_Success() {

View File

@@ -31,7 +31,7 @@ func (s *ProxyProbeServiceSuite) TearDownTest() {
}
func (s *ProxyProbeServiceSuite) setupProxyServer(handler http.HandlerFunc) {
s.proxySrv = httptest.NewServer(handler)
s.proxySrv = newLocalTestServer(s.T(), handler)
}
func (s *ProxyProbeServiceSuite) TestProbeProxy_InvalidProxyURL() {

View File

@@ -41,8 +41,8 @@ func TestEntSoftDelete_ApiKey_DefaultFilterAndSkip(t *testing.T) {
u := createEntUser(t, ctx, client, uniqueSoftDeleteValue(t, "sd-user")+"@example.com")
repo := NewApiKeyRepository(client)
key := &service.ApiKey{
repo := NewAPIKeyRepository(client)
key := &service.APIKey{
UserID: u.ID,
Key: uniqueSoftDeleteValue(t, "sk-soft-delete"),
Name: "soft-delete",
@@ -53,13 +53,13 @@ func TestEntSoftDelete_ApiKey_DefaultFilterAndSkip(t *testing.T) {
require.NoError(t, repo.Delete(ctx, key.ID), "soft delete api key")
_, err := repo.GetByID(ctx, key.ID)
require.ErrorIs(t, err, service.ErrApiKeyNotFound, "deleted rows should be hidden by default")
require.ErrorIs(t, err, service.ErrAPIKeyNotFound, "deleted rows should be hidden by default")
_, err = client.ApiKey.Query().Where(apikey.IDEQ(key.ID)).Only(ctx)
_, err = client.APIKey.Query().Where(apikey.IDEQ(key.ID)).Only(ctx)
require.Error(t, err, "default ent query should not see soft-deleted rows")
require.True(t, dbent.IsNotFound(err), "expected ent not-found after default soft delete filter")
got, err := client.ApiKey.Query().
got, err := client.APIKey.Query().
Where(apikey.IDEQ(key.ID)).
Only(mixins.SkipSoftDelete(ctx))
require.NoError(t, err, "SkipSoftDelete should include soft-deleted rows")
@@ -73,8 +73,8 @@ func TestEntSoftDelete_ApiKey_DeleteIdempotent(t *testing.T) {
u := createEntUser(t, ctx, client, uniqueSoftDeleteValue(t, "sd-user2")+"@example.com")
repo := NewApiKeyRepository(client)
key := &service.ApiKey{
repo := NewAPIKeyRepository(client)
key := &service.APIKey{
UserID: u.ID,
Key: uniqueSoftDeleteValue(t, "sk-soft-delete2"),
Name: "soft-delete2",
@@ -93,8 +93,8 @@ func TestEntSoftDelete_ApiKey_HardDeleteViaSkipSoftDelete(t *testing.T) {
u := createEntUser(t, ctx, client, uniqueSoftDeleteValue(t, "sd-user3")+"@example.com")
repo := NewApiKeyRepository(client)
key := &service.ApiKey{
repo := NewAPIKeyRepository(client)
key := &service.APIKey{
UserID: u.ID,
Key: uniqueSoftDeleteValue(t, "sk-soft-delete3"),
Name: "soft-delete3",
@@ -105,10 +105,10 @@ func TestEntSoftDelete_ApiKey_HardDeleteViaSkipSoftDelete(t *testing.T) {
require.NoError(t, repo.Delete(ctx, key.ID), "soft delete api key")
// Hard delete using SkipSoftDelete so the hook doesn't convert it to update-deleted_at.
_, err := client.ApiKey.Delete().Where(apikey.IDEQ(key.ID)).Exec(mixins.SkipSoftDelete(ctx))
_, err := client.APIKey.Delete().Where(apikey.IDEQ(key.ID)).Exec(mixins.SkipSoftDelete(ctx))
require.NoError(t, err, "hard delete")
_, err = client.ApiKey.Query().
_, err = client.APIKey.Query().
Where(apikey.IDEQ(key.ID)).
Only(mixins.SkipSoftDelete(ctx))
require.True(t, dbent.IsNotFound(err), "expected row to be hard deleted")

View File

@@ -0,0 +1,91 @@
package repository
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9"
)
const tempUnschedPrefix = "temp_unsched:account:"
var tempUnschedSetScript = redis.NewScript(`
local key = KEYS[1]
local new_until = tonumber(ARGV[1])
local new_value = ARGV[2]
local new_ttl = tonumber(ARGV[3])
local existing = redis.call('GET', key)
if existing then
local ok, existing_data = pcall(cjson.decode, existing)
if ok and existing_data and existing_data.until_unix then
local existing_until = tonumber(existing_data.until_unix)
if existing_until and new_until <= existing_until then
return 0
end
end
end
redis.call('SET', key, new_value, 'EX', new_ttl)
return 1
`)
type tempUnschedCache struct {
rdb *redis.Client
}
func NewTempUnschedCache(rdb *redis.Client) service.TempUnschedCache {
return &tempUnschedCache{rdb: rdb}
}
// SetTempUnsched 设置临时不可调度状态(只延长不缩短)
func (c *tempUnschedCache) SetTempUnsched(ctx context.Context, accountID int64, state *service.TempUnschedState) error {
key := fmt.Sprintf("%s%d", tempUnschedPrefix, accountID)
stateJSON, err := json.Marshal(state)
if err != nil {
return fmt.Errorf("marshal state: %w", err)
}
ttl := time.Until(time.Unix(state.UntilUnix, 0))
if ttl <= 0 {
return nil // 已过期,不设置
}
ttlSeconds := int(ttl.Seconds())
if ttlSeconds < 1 {
ttlSeconds = 1
}
_, err = tempUnschedSetScript.Run(ctx, c.rdb, []string{key}, state.UntilUnix, string(stateJSON), ttlSeconds).Result()
return err
}
// GetTempUnsched 获取临时不可调度状态
func (c *tempUnschedCache) GetTempUnsched(ctx context.Context, accountID int64) (*service.TempUnschedState, error) {
key := fmt.Sprintf("%s%d", tempUnschedPrefix, accountID)
val, err := c.rdb.Get(ctx, key).Result()
if err == redis.Nil {
return nil, nil
}
if err != nil {
return nil, err
}
var state service.TempUnschedState
if err := json.Unmarshal([]byte(val), &state); err != nil {
return nil, fmt.Errorf("unmarshal state: %w", err)
}
return &state, nil
}
// DeleteTempUnsched 删除临时不可调度状态
func (c *tempUnschedCache) DeleteTempUnsched(ctx context.Context, accountID int64) error {
key := fmt.Sprintf("%s%d", tempUnschedPrefix, accountID)
return c.rdb.Del(ctx, key).Err()
}

Some files were not shown because too many files have changed in this diff Show More