diff --git a/backend/cmd/server/plugins.go b/backend/cmd/server/plugins.go new file mode 100644 index 000000000..028f144ba --- /dev/null +++ b/backend/cmd/server/plugins.go @@ -0,0 +1,8 @@ +// plugins.go 是 LDAP 插件的唯一注册点。 +// 删除此文件(或移除空白导入)即可完全禁用 LDAP 功能,主线代码无需任何改动。 +package main + +import ( + // 引入 LDAP 插件,通过 init() 注册到全局插件系统 + _ "github.com/Wei-Shaw/sub2api/internal/plugins/ldap" +) diff --git a/backend/cmd/server/wire_gen.go b/backend/cmd/server/wire_gen.go index 2e9afc26d..00e5d3153 100644 --- a/backend/cmd/server/wire_gen.go +++ b/backend/cmd/server/wire_gen.go @@ -26,6 +26,7 @@ import ( import ( _ "embed" _ "github.com/Wei-Shaw/sub2api/ent/runtime" + _ "github.com/Wei-Shaw/sub2api/internal/plugins/ldap" ) // Injectors from wire.go: @@ -168,10 +169,6 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) { opsSystemLogSink := service.ProvideOpsSystemLogSink(opsRepository) opsService := service.NewOpsService(opsRepository, settingRepository, configConfig, accountRepository, userRepository, concurrencyService, gatewayService, openAIGatewayService, geminiMessagesCompatService, antigravityGatewayService, opsSystemLogSink) soraS3Storage := service.NewSoraS3Storage(settingService) - settingService.SetOnS3UpdateCallback(soraS3Storage.RefreshClient) - soraGenerationRepository := repository.NewSoraGenerationRepository(db) - soraQuotaService := service.NewSoraQuotaService(userRepository, groupRepository, settingService) - soraGenerationService := service.NewSoraGenerationService(soraGenerationRepository, soraS3Storage, soraQuotaService) settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService, opsService, soraS3Storage) opsHandler := admin.NewOpsHandler(opsService) updateCache := repository.NewUpdateCache(redisClient) @@ -201,10 +198,13 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) { gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, usageService, apiKeyService, usageRecordWorkerPool, errorPassthroughService, userMessageQueueService, configConfig, settingService) openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, apiKeyService, usageRecordWorkerPool, errorPassthroughService, configConfig) soraSDKClient := service.ProvideSoraSDKClient(configConfig, httpUpstream, openAITokenProvider, accountRepository, soraAccountRepository) - soraMediaStorage := service.ProvideSoraMediaStorage(configConfig) soraGatewayService := service.NewSoraGatewayService(soraSDKClient, rateLimitService, httpUpstream, configConfig) - soraClientHandler := handler.NewSoraClientHandler(soraGenerationService, soraQuotaService, soraS3Storage, soraGatewayService, gatewayService, soraMediaStorage, apiKeyService) soraGatewayHandler := handler.NewSoraGatewayHandler(gatewayService, soraGatewayService, concurrencyService, billingCacheService, usageRecordWorkerPool, configConfig) + soraGenerationRepository := repository.NewSoraGenerationRepository(db) + soraQuotaService := service.NewSoraQuotaService(userRepository, groupRepository, settingService) + soraGenerationService := service.NewSoraGenerationService(soraGenerationRepository, soraS3Storage, soraQuotaService) + soraMediaStorage := service.ProvideSoraMediaStorage(configConfig) + soraClientHandler := handler.NewSoraClientHandler(soraGenerationService, soraQuotaService, soraS3Storage, soraGatewayService, gatewayService, soraMediaStorage, apiKeyService) handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo) totpHandler := handler.NewTotpHandler(totpService) idempotencyCoordinator := service.ProvideIdempotencyCoordinator(idempotencyRepository, configConfig) @@ -213,7 +213,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) { jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService) adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService) apiKeyAuthMiddleware := middleware.NewAPIKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig) - engine := server.ProvideRouter(configConfig, handlers, jwtAuthMiddleware, adminAuthMiddleware, apiKeyAuthMiddleware, apiKeyService, subscriptionService, opsService, settingService, redisClient) + engine := server.ProvideRouter(configConfig, handlers, jwtAuthMiddleware, adminAuthMiddleware, apiKeyAuthMiddleware, apiKeyService, subscriptionService, opsService, settingService, redisClient, client, authService, totpService, userRepository) httpServer := server.ProvideHTTPServer(configConfig, engine) opsMetricsCollector := service.ProvideOpsMetricsCollector(opsRepository, settingRepository, accountRepository, concurrencyService, db, redisClient, configConfig) opsAggregationService := service.ProvideOpsAggregationService(opsRepository, settingRepository, db, redisClient, configConfig) diff --git a/backend/ent/client.go b/backend/ent/client.go index 7ebbaa322..b0f1b9f83 100644 --- a/backend/ent/client.go +++ b/backend/ent/client.go @@ -23,6 +23,8 @@ import ( "github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule" "github.com/Wei-Shaw/sub2api/ent/group" "github.com/Wei-Shaw/sub2api/ent/idempotencyrecord" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" "github.com/Wei-Shaw/sub2api/ent/promocode" "github.com/Wei-Shaw/sub2api/ent/promocodeusage" "github.com/Wei-Shaw/sub2api/ent/proxy" @@ -61,6 +63,10 @@ type Client struct { Group *GroupClient // IdempotencyRecord is the client for interacting with the IdempotencyRecord builders. IdempotencyRecord *IdempotencyRecordClient + // LdapConfig is the client for interacting with the LdapConfig builders. + LdapConfig *LdapConfigClient + // LdapUser is the client for interacting with the LdapUser builders. + LdapUser *LdapUserClient // PromoCode is the client for interacting with the PromoCode builders. PromoCode *PromoCodeClient // PromoCodeUsage is the client for interacting with the PromoCodeUsage builders. @@ -106,6 +112,8 @@ func (c *Client) init() { c.ErrorPassthroughRule = NewErrorPassthroughRuleClient(c.config) c.Group = NewGroupClient(c.config) c.IdempotencyRecord = NewIdempotencyRecordClient(c.config) + c.LdapConfig = NewLdapConfigClient(c.config) + c.LdapUser = NewLdapUserClient(c.config) c.PromoCode = NewPromoCodeClient(c.config) c.PromoCodeUsage = NewPromoCodeUsageClient(c.config) c.Proxy = NewProxyClient(c.config) @@ -219,6 +227,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg), Group: NewGroupClient(cfg), IdempotencyRecord: NewIdempotencyRecordClient(cfg), + LdapConfig: NewLdapConfigClient(cfg), + LdapUser: NewLdapUserClient(cfg), PromoCode: NewPromoCodeClient(cfg), PromoCodeUsage: NewPromoCodeUsageClient(cfg), Proxy: NewProxyClient(cfg), @@ -259,6 +269,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg), Group: NewGroupClient(cfg), IdempotencyRecord: NewIdempotencyRecordClient(cfg), + LdapConfig: NewLdapConfigClient(cfg), + LdapUser: NewLdapUserClient(cfg), PromoCode: NewPromoCodeClient(cfg), PromoCodeUsage: NewPromoCodeUsageClient(cfg), Proxy: NewProxyClient(cfg), @@ -302,9 +314,9 @@ func (c *Client) Close() error { func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead, - c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PromoCode, - c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, - c.UsageCleanupTask, c.UsageLog, c.User, c.UserAllowedGroup, + c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.LdapConfig, c.LdapUser, + c.PromoCode, c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, + c.Setting, c.UsageCleanupTask, c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue, c.UserSubscription, } { n.Use(hooks...) @@ -316,9 +328,9 @@ func (c *Client) Use(hooks ...Hook) { func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead, - c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PromoCode, - c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, - c.UsageCleanupTask, c.UsageLog, c.User, c.UserAllowedGroup, + c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.LdapConfig, c.LdapUser, + c.PromoCode, c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, + c.Setting, c.UsageCleanupTask, c.UsageLog, c.User, c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue, c.UserSubscription, } { n.Intercept(interceptors...) @@ -344,6 +356,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.Group.mutate(ctx, m) case *IdempotencyRecordMutation: return c.IdempotencyRecord.mutate(ctx, m) + case *LdapConfigMutation: + return c.LdapConfig.mutate(ctx, m) + case *LdapUserMutation: + return c.LdapUser.mutate(ctx, m) case *PromoCodeMutation: return c.PromoCode.mutate(ctx, m) case *PromoCodeUsageMutation: @@ -1716,6 +1732,288 @@ func (c *IdempotencyRecordClient) mutate(ctx context.Context, m *IdempotencyReco } } +// LdapConfigClient is a client for the LdapConfig schema. +type LdapConfigClient struct { + config +} + +// NewLdapConfigClient returns a client for the LdapConfig from the given config. +func NewLdapConfigClient(c config) *LdapConfigClient { + return &LdapConfigClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `ldapconfig.Hooks(f(g(h())))`. +func (c *LdapConfigClient) Use(hooks ...Hook) { + c.hooks.LdapConfig = append(c.hooks.LdapConfig, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `ldapconfig.Intercept(f(g(h())))`. +func (c *LdapConfigClient) Intercept(interceptors ...Interceptor) { + c.inters.LdapConfig = append(c.inters.LdapConfig, interceptors...) +} + +// Create returns a builder for creating a LdapConfig entity. +func (c *LdapConfigClient) Create() *LdapConfigCreate { + mutation := newLdapConfigMutation(c.config, OpCreate) + return &LdapConfigCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of LdapConfig entities. +func (c *LdapConfigClient) CreateBulk(builders ...*LdapConfigCreate) *LdapConfigCreateBulk { + return &LdapConfigCreateBulk{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 *LdapConfigClient) MapCreateBulk(slice any, setFunc func(*LdapConfigCreate, int)) *LdapConfigCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &LdapConfigCreateBulk{err: fmt.Errorf("calling to LdapConfigClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*LdapConfigCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &LdapConfigCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for LdapConfig. +func (c *LdapConfigClient) Update() *LdapConfigUpdate { + mutation := newLdapConfigMutation(c.config, OpUpdate) + return &LdapConfigUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *LdapConfigClient) UpdateOne(_m *LdapConfig) *LdapConfigUpdateOne { + mutation := newLdapConfigMutation(c.config, OpUpdateOne, withLdapConfig(_m)) + return &LdapConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *LdapConfigClient) UpdateOneID(id int64) *LdapConfigUpdateOne { + mutation := newLdapConfigMutation(c.config, OpUpdateOne, withLdapConfigID(id)) + return &LdapConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for LdapConfig. +func (c *LdapConfigClient) Delete() *LdapConfigDelete { + mutation := newLdapConfigMutation(c.config, OpDelete) + return &LdapConfigDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *LdapConfigClient) DeleteOne(_m *LdapConfig) *LdapConfigDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *LdapConfigClient) DeleteOneID(id int64) *LdapConfigDeleteOne { + builder := c.Delete().Where(ldapconfig.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &LdapConfigDeleteOne{builder} +} + +// Query returns a query builder for LdapConfig. +func (c *LdapConfigClient) Query() *LdapConfigQuery { + return &LdapConfigQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeLdapConfig}, + inters: c.Interceptors(), + } +} + +// Get returns a LdapConfig entity by its id. +func (c *LdapConfigClient) Get(ctx context.Context, id int64) (*LdapConfig, error) { + return c.Query().Where(ldapconfig.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *LdapConfigClient) GetX(ctx context.Context, id int64) *LdapConfig { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *LdapConfigClient) Hooks() []Hook { + return c.hooks.LdapConfig +} + +// Interceptors returns the client interceptors. +func (c *LdapConfigClient) Interceptors() []Interceptor { + return c.inters.LdapConfig +} + +func (c *LdapConfigClient) mutate(ctx context.Context, m *LdapConfigMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&LdapConfigCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&LdapConfigUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&LdapConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&LdapConfigDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown LdapConfig mutation op: %q", m.Op()) + } +} + +// LdapUserClient is a client for the LdapUser schema. +type LdapUserClient struct { + config +} + +// NewLdapUserClient returns a client for the LdapUser from the given config. +func NewLdapUserClient(c config) *LdapUserClient { + return &LdapUserClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `ldapuser.Hooks(f(g(h())))`. +func (c *LdapUserClient) Use(hooks ...Hook) { + c.hooks.LdapUser = append(c.hooks.LdapUser, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `ldapuser.Intercept(f(g(h())))`. +func (c *LdapUserClient) Intercept(interceptors ...Interceptor) { + c.inters.LdapUser = append(c.inters.LdapUser, interceptors...) +} + +// Create returns a builder for creating a LdapUser entity. +func (c *LdapUserClient) Create() *LdapUserCreate { + mutation := newLdapUserMutation(c.config, OpCreate) + return &LdapUserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of LdapUser entities. +func (c *LdapUserClient) CreateBulk(builders ...*LdapUserCreate) *LdapUserCreateBulk { + return &LdapUserCreateBulk{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 *LdapUserClient) MapCreateBulk(slice any, setFunc func(*LdapUserCreate, int)) *LdapUserCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &LdapUserCreateBulk{err: fmt.Errorf("calling to LdapUserClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*LdapUserCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &LdapUserCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for LdapUser. +func (c *LdapUserClient) Update() *LdapUserUpdate { + mutation := newLdapUserMutation(c.config, OpUpdate) + return &LdapUserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *LdapUserClient) UpdateOne(_m *LdapUser) *LdapUserUpdateOne { + mutation := newLdapUserMutation(c.config, OpUpdateOne, withLdapUser(_m)) + return &LdapUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *LdapUserClient) UpdateOneID(id int64) *LdapUserUpdateOne { + mutation := newLdapUserMutation(c.config, OpUpdateOne, withLdapUserID(id)) + return &LdapUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for LdapUser. +func (c *LdapUserClient) Delete() *LdapUserDelete { + mutation := newLdapUserMutation(c.config, OpDelete) + return &LdapUserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *LdapUserClient) DeleteOne(_m *LdapUser) *LdapUserDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *LdapUserClient) DeleteOneID(id int64) *LdapUserDeleteOne { + builder := c.Delete().Where(ldapuser.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &LdapUserDeleteOne{builder} +} + +// Query returns a query builder for LdapUser. +func (c *LdapUserClient) Query() *LdapUserQuery { + return &LdapUserQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeLdapUser}, + inters: c.Interceptors(), + } +} + +// Get returns a LdapUser entity by its id. +func (c *LdapUserClient) Get(ctx context.Context, id int64) (*LdapUser, error) { + return c.Query().Where(ldapuser.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *LdapUserClient) GetX(ctx context.Context, id int64) *LdapUser { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryUser queries the user edge of a LdapUser. +func (c *LdapUserClient) QueryUser(_m *LdapUser) *UserQuery { + query := (&UserClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(ldapuser.Table, ldapuser.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ldapuser.UserTable, ldapuser.UserColumn), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *LdapUserClient) Hooks() []Hook { + return c.hooks.LdapUser +} + +// Interceptors returns the client interceptors. +func (c *LdapUserClient) Interceptors() []Interceptor { + return c.inters.LdapUser +} + +func (c *LdapUserClient) mutate(ctx context.Context, m *LdapUserMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&LdapUserCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&LdapUserUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&LdapUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&LdapUserDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown LdapUser mutation op: %q", m.Op()) + } +} + // PromoCodeClient is a client for the PromoCode schema. type PromoCodeClient struct { config @@ -3888,17 +4186,17 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription type ( hooks struct { APIKey, Account, AccountGroup, Announcement, AnnouncementRead, - ErrorPassthroughRule, Group, IdempotencyRecord, PromoCode, PromoCodeUsage, - Proxy, RedeemCode, SecuritySecret, Setting, UsageCleanupTask, UsageLog, User, - UserAllowedGroup, UserAttributeDefinition, UserAttributeValue, - UserSubscription []ent.Hook + ErrorPassthroughRule, Group, IdempotencyRecord, LdapConfig, LdapUser, + PromoCode, PromoCodeUsage, Proxy, RedeemCode, SecuritySecret, Setting, + UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition, + UserAttributeValue, UserSubscription []ent.Hook } inters struct { APIKey, Account, AccountGroup, Announcement, AnnouncementRead, - ErrorPassthroughRule, Group, IdempotencyRecord, PromoCode, PromoCodeUsage, - Proxy, RedeemCode, SecuritySecret, Setting, UsageCleanupTask, UsageLog, User, - UserAllowedGroup, UserAttributeDefinition, UserAttributeValue, - UserSubscription []ent.Interceptor + ErrorPassthroughRule, Group, IdempotencyRecord, LdapConfig, LdapUser, + PromoCode, PromoCodeUsage, Proxy, RedeemCode, SecuritySecret, Setting, + UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition, + UserAttributeValue, UserSubscription []ent.Interceptor } ) diff --git a/backend/ent/ent.go b/backend/ent/ent.go index 5197e4d84..75086a1c2 100644 --- a/backend/ent/ent.go +++ b/backend/ent/ent.go @@ -20,6 +20,8 @@ import ( "github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule" "github.com/Wei-Shaw/sub2api/ent/group" "github.com/Wei-Shaw/sub2api/ent/idempotencyrecord" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" "github.com/Wei-Shaw/sub2api/ent/promocode" "github.com/Wei-Shaw/sub2api/ent/promocodeusage" "github.com/Wei-Shaw/sub2api/ent/proxy" @@ -101,6 +103,8 @@ func checkColumn(t, c string) error { errorpassthroughrule.Table: errorpassthroughrule.ValidColumn, group.Table: group.ValidColumn, idempotencyrecord.Table: idempotencyrecord.ValidColumn, + ldapconfig.Table: ldapconfig.ValidColumn, + ldapuser.Table: ldapuser.ValidColumn, promocode.Table: promocode.ValidColumn, promocodeusage.Table: promocodeusage.ValidColumn, proxy.Table: proxy.ValidColumn, diff --git a/backend/ent/hook/hook.go b/backend/ent/hook/hook.go index 49d7f3c55..c165e6912 100644 --- a/backend/ent/hook/hook.go +++ b/backend/ent/hook/hook.go @@ -105,6 +105,30 @@ func (f IdempotencyRecordFunc) Mutate(ctx context.Context, m ent.Mutation) (ent. return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IdempotencyRecordMutation", m) } +// The LdapConfigFunc type is an adapter to allow the use of ordinary +// function as LdapConfig mutator. +type LdapConfigFunc func(context.Context, *ent.LdapConfigMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f LdapConfigFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.LdapConfigMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.LdapConfigMutation", m) +} + +// The LdapUserFunc type is an adapter to allow the use of ordinary +// function as LdapUser mutator. +type LdapUserFunc func(context.Context, *ent.LdapUserMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f LdapUserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.LdapUserMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.LdapUserMutation", m) +} + // The PromoCodeFunc type is an adapter to allow the use of ordinary // function as PromoCode mutator. type PromoCodeFunc func(context.Context, *ent.PromoCodeMutation) (ent.Value, error) diff --git a/backend/ent/intercept/intercept.go b/backend/ent/intercept/intercept.go index e77464026..d73018a4c 100644 --- a/backend/ent/intercept/intercept.go +++ b/backend/ent/intercept/intercept.go @@ -16,6 +16,8 @@ import ( "github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule" "github.com/Wei-Shaw/sub2api/ent/group" "github.com/Wei-Shaw/sub2api/ent/idempotencyrecord" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" "github.com/Wei-Shaw/sub2api/ent/predicate" "github.com/Wei-Shaw/sub2api/ent/promocode" "github.com/Wei-Shaw/sub2api/ent/promocodeusage" @@ -304,6 +306,60 @@ func (f TraverseIdempotencyRecord) Traverse(ctx context.Context, q ent.Query) er return fmt.Errorf("unexpected query type %T. expect *ent.IdempotencyRecordQuery", q) } +// The LdapConfigFunc type is an adapter to allow the use of ordinary function as a Querier. +type LdapConfigFunc func(context.Context, *ent.LdapConfigQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f LdapConfigFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.LdapConfigQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.LdapConfigQuery", q) +} + +// The TraverseLdapConfig type is an adapter to allow the use of ordinary function as Traverser. +type TraverseLdapConfig func(context.Context, *ent.LdapConfigQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseLdapConfig) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseLdapConfig) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.LdapConfigQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.LdapConfigQuery", q) +} + +// The LdapUserFunc type is an adapter to allow the use of ordinary function as a Querier. +type LdapUserFunc func(context.Context, *ent.LdapUserQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f LdapUserFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.LdapUserQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.LdapUserQuery", q) +} + +// The TraverseLdapUser type is an adapter to allow the use of ordinary function as Traverser. +type TraverseLdapUser func(context.Context, *ent.LdapUserQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseLdapUser) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseLdapUser) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.LdapUserQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.LdapUserQuery", q) +} + // The PromoCodeFunc type is an adapter to allow the use of ordinary function as a Querier. type PromoCodeFunc func(context.Context, *ent.PromoCodeQuery) (ent.Value, error) @@ -674,6 +730,10 @@ func NewQuery(q ent.Query) (Query, error) { return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil case *ent.IdempotencyRecordQuery: return &query[*ent.IdempotencyRecordQuery, predicate.IdempotencyRecord, idempotencyrecord.OrderOption]{typ: ent.TypeIdempotencyRecord, tq: q}, nil + case *ent.LdapConfigQuery: + return &query[*ent.LdapConfigQuery, predicate.LdapConfig, ldapconfig.OrderOption]{typ: ent.TypeLdapConfig, tq: q}, nil + case *ent.LdapUserQuery: + return &query[*ent.LdapUserQuery, predicate.LdapUser, ldapuser.OrderOption]{typ: ent.TypeLdapUser, tq: q}, nil case *ent.PromoCodeQuery: return &query[*ent.PromoCodeQuery, predicate.PromoCode, promocode.OrderOption]{typ: ent.TypePromoCode, tq: q}, nil case *ent.PromoCodeUsageQuery: diff --git a/backend/ent/ldapconfig.go b/backend/ent/ldapconfig.go new file mode 100644 index 000000000..b5916d2c3 --- /dev/null +++ b/backend/ent/ldapconfig.go @@ -0,0 +1,217 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" +) + +// LdapConfig is the model entity for the LdapConfig schema. +type LdapConfig struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // LDAP server URL (e.g., ldap://ldap.example.com:389) + ServerURL string `json:"server_url,omitempty"` + // Bind DN for LDAP authentication + BindDn string `json:"bind_dn,omitempty"` + // Encrypted bind password (AES-256-GCM) + BindPasswordEncrypted string `json:"-"` + // Base DN for user search + BaseDn string `json:"base_dn,omitempty"` + // LDAP user filter template + UserFilter string `json:"user_filter,omitempty"` + // Whether this LDAP config is enabled + Enabled bool `json:"enabled,omitempty"` + // Whether to use LDAP over TLS (ldaps://) + TLSEnabled bool `json:"tls_enabled,omitempty"` + // Whether to skip TLS certificate verification + TLSSkipVerify bool `json:"tls_skip_verify,omitempty"` + // Configuration source: 'env' or 'database' + ConfigSource string `json:"config_source,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*LdapConfig) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case ldapconfig.FieldEnabled, ldapconfig.FieldTLSEnabled, ldapconfig.FieldTLSSkipVerify: + values[i] = new(sql.NullBool) + case ldapconfig.FieldID: + values[i] = new(sql.NullInt64) + case ldapconfig.FieldServerURL, ldapconfig.FieldBindDn, ldapconfig.FieldBindPasswordEncrypted, ldapconfig.FieldBaseDn, ldapconfig.FieldUserFilter, ldapconfig.FieldConfigSource: + values[i] = new(sql.NullString) + case ldapconfig.FieldCreatedAt, ldapconfig.FieldUpdatedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the LdapConfig fields. +func (_m *LdapConfig) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case ldapconfig.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int64(value.Int64) + case ldapconfig.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case ldapconfig.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + _m.UpdatedAt = value.Time + } + case ldapconfig.FieldServerURL: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field server_url", values[i]) + } else if value.Valid { + _m.ServerURL = value.String + } + case ldapconfig.FieldBindDn: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field bind_dn", values[i]) + } else if value.Valid { + _m.BindDn = value.String + } + case ldapconfig.FieldBindPasswordEncrypted: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field bind_password_encrypted", values[i]) + } else if value.Valid { + _m.BindPasswordEncrypted = value.String + } + case ldapconfig.FieldBaseDn: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field base_dn", values[i]) + } else if value.Valid { + _m.BaseDn = value.String + } + case ldapconfig.FieldUserFilter: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field user_filter", values[i]) + } else if value.Valid { + _m.UserFilter = value.String + } + case ldapconfig.FieldEnabled: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field enabled", values[i]) + } else if value.Valid { + _m.Enabled = value.Bool + } + case ldapconfig.FieldTLSEnabled: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field tls_enabled", values[i]) + } else if value.Valid { + _m.TLSEnabled = value.Bool + } + case ldapconfig.FieldTLSSkipVerify: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field tls_skip_verify", values[i]) + } else if value.Valid { + _m.TLSSkipVerify = value.Bool + } + case ldapconfig.FieldConfigSource: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field config_source", values[i]) + } else if value.Valid { + _m.ConfigSource = value.String + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the LdapConfig. +// This includes values selected through modifiers, order, etc. +func (_m *LdapConfig) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// Update returns a builder for updating this LdapConfig. +// Note that you need to call LdapConfig.Unwrap() before calling this method if this LdapConfig +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *LdapConfig) Update() *LdapConfigUpdateOne { + return NewLdapConfigClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the LdapConfig 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 *LdapConfig) Unwrap() *LdapConfig { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: LdapConfig is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *LdapConfig) String() string { + var builder strings.Builder + builder.WriteString("LdapConfig(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(_m.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("server_url=") + builder.WriteString(_m.ServerURL) + builder.WriteString(", ") + builder.WriteString("bind_dn=") + builder.WriteString(_m.BindDn) + builder.WriteString(", ") + builder.WriteString("bind_password_encrypted=") + builder.WriteString(", ") + builder.WriteString("base_dn=") + builder.WriteString(_m.BaseDn) + builder.WriteString(", ") + builder.WriteString("user_filter=") + builder.WriteString(_m.UserFilter) + builder.WriteString(", ") + builder.WriteString("enabled=") + builder.WriteString(fmt.Sprintf("%v", _m.Enabled)) + builder.WriteString(", ") + builder.WriteString("tls_enabled=") + builder.WriteString(fmt.Sprintf("%v", _m.TLSEnabled)) + builder.WriteString(", ") + builder.WriteString("tls_skip_verify=") + builder.WriteString(fmt.Sprintf("%v", _m.TLSSkipVerify)) + builder.WriteString(", ") + builder.WriteString("config_source=") + builder.WriteString(_m.ConfigSource) + builder.WriteByte(')') + return builder.String() +} + +// LdapConfigs is a parsable slice of LdapConfig. +type LdapConfigs []*LdapConfig diff --git a/backend/ent/ldapconfig/ldapconfig.go b/backend/ent/ldapconfig/ldapconfig.go new file mode 100644 index 000000000..6d5ae363d --- /dev/null +++ b/backend/ent/ldapconfig/ldapconfig.go @@ -0,0 +1,160 @@ +// Code generated by ent, DO NOT EDIT. + +package ldapconfig + +import ( + "time" + + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the ldapconfig type in the database. + Label = "ldap_config" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldServerURL holds the string denoting the server_url field in the database. + FieldServerURL = "server_url" + // FieldBindDn holds the string denoting the bind_dn field in the database. + FieldBindDn = "bind_dn" + // FieldBindPasswordEncrypted holds the string denoting the bind_password_encrypted field in the database. + FieldBindPasswordEncrypted = "bind_password_encrypted" + // FieldBaseDn holds the string denoting the base_dn field in the database. + FieldBaseDn = "base_dn" + // FieldUserFilter holds the string denoting the user_filter field in the database. + FieldUserFilter = "user_filter" + // FieldEnabled holds the string denoting the enabled field in the database. + FieldEnabled = "enabled" + // FieldTLSEnabled holds the string denoting the tls_enabled field in the database. + FieldTLSEnabled = "tls_enabled" + // FieldTLSSkipVerify holds the string denoting the tls_skip_verify field in the database. + FieldTLSSkipVerify = "tls_skip_verify" + // FieldConfigSource holds the string denoting the config_source field in the database. + FieldConfigSource = "config_source" + // Table holds the table name of the ldapconfig in the database. + Table = "ldap_configs" +) + +// Columns holds all SQL columns for ldapconfig fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldServerURL, + FieldBindDn, + FieldBindPasswordEncrypted, + FieldBaseDn, + FieldUserFilter, + FieldEnabled, + FieldTLSEnabled, + FieldTLSSkipVerify, + FieldConfigSource, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() time.Time + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() time.Time + // ServerURLValidator is a validator for the "server_url" field. It is called by the builders before save. + ServerURLValidator func(string) error + // BindDnValidator is a validator for the "bind_dn" field. It is called by the builders before save. + BindDnValidator func(string) error + // BindPasswordEncryptedValidator is a validator for the "bind_password_encrypted" field. It is called by the builders before save. + BindPasswordEncryptedValidator func(string) error + // BaseDnValidator is a validator for the "base_dn" field. It is called by the builders before save. + BaseDnValidator func(string) error + // DefaultUserFilter holds the default value on creation for the "user_filter" field. + DefaultUserFilter string + // UserFilterValidator is a validator for the "user_filter" field. It is called by the builders before save. + UserFilterValidator func(string) error + // DefaultEnabled holds the default value on creation for the "enabled" field. + DefaultEnabled bool + // DefaultTLSEnabled holds the default value on creation for the "tls_enabled" field. + DefaultTLSEnabled bool + // DefaultTLSSkipVerify holds the default value on creation for the "tls_skip_verify" field. + DefaultTLSSkipVerify bool + // DefaultConfigSource holds the default value on creation for the "config_source" field. + DefaultConfigSource string + // ConfigSourceValidator is a validator for the "config_source" field. It is called by the builders before save. + ConfigSourceValidator func(string) error +) + +// OrderOption defines the ordering options for the LdapConfig queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByServerURL orders the results by the server_url field. +func ByServerURL(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldServerURL, opts...).ToFunc() +} + +// ByBindDn orders the results by the bind_dn field. +func ByBindDn(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldBindDn, opts...).ToFunc() +} + +// ByBindPasswordEncrypted orders the results by the bind_password_encrypted field. +func ByBindPasswordEncrypted(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldBindPasswordEncrypted, opts...).ToFunc() +} + +// ByBaseDn orders the results by the base_dn field. +func ByBaseDn(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldBaseDn, opts...).ToFunc() +} + +// ByUserFilter orders the results by the user_filter field. +func ByUserFilter(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUserFilter, opts...).ToFunc() +} + +// ByEnabled orders the results by the enabled field. +func ByEnabled(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldEnabled, opts...).ToFunc() +} + +// ByTLSEnabled orders the results by the tls_enabled field. +func ByTLSEnabled(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTLSEnabled, opts...).ToFunc() +} + +// ByTLSSkipVerify orders the results by the tls_skip_verify field. +func ByTLSSkipVerify(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTLSSkipVerify, opts...).ToFunc() +} + +// ByConfigSource orders the results by the config_source field. +func ByConfigSource(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldConfigSource, opts...).ToFunc() +} diff --git a/backend/ent/ldapconfig/where.go b/backend/ent/ldapconfig/where.go new file mode 100644 index 000000000..5e7a50c0e --- /dev/null +++ b/backend/ent/ldapconfig/where.go @@ -0,0 +1,625 @@ +// Code generated by ent, DO NOT EDIT. + +package ldapconfig + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.LdapConfig { + return predicate.LdapConfig(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.LdapConfig { + return predicate.LdapConfig(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.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// ServerURL applies equality check predicate on the "server_url" field. It's identical to ServerURLEQ. +func ServerURL(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldServerURL, v)) +} + +// BindDn applies equality check predicate on the "bind_dn" field. It's identical to BindDnEQ. +func BindDn(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBindDn, v)) +} + +// BindPasswordEncrypted applies equality check predicate on the "bind_password_encrypted" field. It's identical to BindPasswordEncryptedEQ. +func BindPasswordEncrypted(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBindPasswordEncrypted, v)) +} + +// BaseDn applies equality check predicate on the "base_dn" field. It's identical to BaseDnEQ. +func BaseDn(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBaseDn, v)) +} + +// UserFilter applies equality check predicate on the "user_filter" field. It's identical to UserFilterEQ. +func UserFilter(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldUserFilter, v)) +} + +// Enabled applies equality check predicate on the "enabled" field. It's identical to EnabledEQ. +func Enabled(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldEnabled, v)) +} + +// TLSEnabled applies equality check predicate on the "tls_enabled" field. It's identical to TLSEnabledEQ. +func TLSEnabled(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldTLSEnabled, v)) +} + +// TLSSkipVerify applies equality check predicate on the "tls_skip_verify" field. It's identical to TLSSkipVerifyEQ. +func TLSSkipVerify(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldTLSSkipVerify, v)) +} + +// ConfigSource applies equality check predicate on the "config_source" field. It's identical to ConfigSourceEQ. +func ConfigSource(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldConfigSource, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// ServerURLEQ applies the EQ predicate on the "server_url" field. +func ServerURLEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldServerURL, v)) +} + +// ServerURLNEQ applies the NEQ predicate on the "server_url" field. +func ServerURLNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldServerURL, v)) +} + +// ServerURLIn applies the In predicate on the "server_url" field. +func ServerURLIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldServerURL, vs...)) +} + +// ServerURLNotIn applies the NotIn predicate on the "server_url" field. +func ServerURLNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldServerURL, vs...)) +} + +// ServerURLGT applies the GT predicate on the "server_url" field. +func ServerURLGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldServerURL, v)) +} + +// ServerURLGTE applies the GTE predicate on the "server_url" field. +func ServerURLGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldServerURL, v)) +} + +// ServerURLLT applies the LT predicate on the "server_url" field. +func ServerURLLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldServerURL, v)) +} + +// ServerURLLTE applies the LTE predicate on the "server_url" field. +func ServerURLLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldServerURL, v)) +} + +// ServerURLContains applies the Contains predicate on the "server_url" field. +func ServerURLContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldServerURL, v)) +} + +// ServerURLHasPrefix applies the HasPrefix predicate on the "server_url" field. +func ServerURLHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldServerURL, v)) +} + +// ServerURLHasSuffix applies the HasSuffix predicate on the "server_url" field. +func ServerURLHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldServerURL, v)) +} + +// ServerURLEqualFold applies the EqualFold predicate on the "server_url" field. +func ServerURLEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldServerURL, v)) +} + +// ServerURLContainsFold applies the ContainsFold predicate on the "server_url" field. +func ServerURLContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldServerURL, v)) +} + +// BindDnEQ applies the EQ predicate on the "bind_dn" field. +func BindDnEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBindDn, v)) +} + +// BindDnNEQ applies the NEQ predicate on the "bind_dn" field. +func BindDnNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldBindDn, v)) +} + +// BindDnIn applies the In predicate on the "bind_dn" field. +func BindDnIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldBindDn, vs...)) +} + +// BindDnNotIn applies the NotIn predicate on the "bind_dn" field. +func BindDnNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldBindDn, vs...)) +} + +// BindDnGT applies the GT predicate on the "bind_dn" field. +func BindDnGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldBindDn, v)) +} + +// BindDnGTE applies the GTE predicate on the "bind_dn" field. +func BindDnGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldBindDn, v)) +} + +// BindDnLT applies the LT predicate on the "bind_dn" field. +func BindDnLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldBindDn, v)) +} + +// BindDnLTE applies the LTE predicate on the "bind_dn" field. +func BindDnLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldBindDn, v)) +} + +// BindDnContains applies the Contains predicate on the "bind_dn" field. +func BindDnContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldBindDn, v)) +} + +// BindDnHasPrefix applies the HasPrefix predicate on the "bind_dn" field. +func BindDnHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldBindDn, v)) +} + +// BindDnHasSuffix applies the HasSuffix predicate on the "bind_dn" field. +func BindDnHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldBindDn, v)) +} + +// BindDnEqualFold applies the EqualFold predicate on the "bind_dn" field. +func BindDnEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldBindDn, v)) +} + +// BindDnContainsFold applies the ContainsFold predicate on the "bind_dn" field. +func BindDnContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldBindDn, v)) +} + +// BindPasswordEncryptedEQ applies the EQ predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedNEQ applies the NEQ predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedIn applies the In predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldBindPasswordEncrypted, vs...)) +} + +// BindPasswordEncryptedNotIn applies the NotIn predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldBindPasswordEncrypted, vs...)) +} + +// BindPasswordEncryptedGT applies the GT predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedGTE applies the GTE predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedLT applies the LT predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedLTE applies the LTE predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedContains applies the Contains predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedHasPrefix applies the HasPrefix predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedHasSuffix applies the HasSuffix predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedEqualFold applies the EqualFold predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldBindPasswordEncrypted, v)) +} + +// BindPasswordEncryptedContainsFold applies the ContainsFold predicate on the "bind_password_encrypted" field. +func BindPasswordEncryptedContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldBindPasswordEncrypted, v)) +} + +// BaseDnEQ applies the EQ predicate on the "base_dn" field. +func BaseDnEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldBaseDn, v)) +} + +// BaseDnNEQ applies the NEQ predicate on the "base_dn" field. +func BaseDnNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldBaseDn, v)) +} + +// BaseDnIn applies the In predicate on the "base_dn" field. +func BaseDnIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldBaseDn, vs...)) +} + +// BaseDnNotIn applies the NotIn predicate on the "base_dn" field. +func BaseDnNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldBaseDn, vs...)) +} + +// BaseDnGT applies the GT predicate on the "base_dn" field. +func BaseDnGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldBaseDn, v)) +} + +// BaseDnGTE applies the GTE predicate on the "base_dn" field. +func BaseDnGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldBaseDn, v)) +} + +// BaseDnLT applies the LT predicate on the "base_dn" field. +func BaseDnLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldBaseDn, v)) +} + +// BaseDnLTE applies the LTE predicate on the "base_dn" field. +func BaseDnLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldBaseDn, v)) +} + +// BaseDnContains applies the Contains predicate on the "base_dn" field. +func BaseDnContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldBaseDn, v)) +} + +// BaseDnHasPrefix applies the HasPrefix predicate on the "base_dn" field. +func BaseDnHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldBaseDn, v)) +} + +// BaseDnHasSuffix applies the HasSuffix predicate on the "base_dn" field. +func BaseDnHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldBaseDn, v)) +} + +// BaseDnEqualFold applies the EqualFold predicate on the "base_dn" field. +func BaseDnEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldBaseDn, v)) +} + +// BaseDnContainsFold applies the ContainsFold predicate on the "base_dn" field. +func BaseDnContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldBaseDn, v)) +} + +// UserFilterEQ applies the EQ predicate on the "user_filter" field. +func UserFilterEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldUserFilter, v)) +} + +// UserFilterNEQ applies the NEQ predicate on the "user_filter" field. +func UserFilterNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldUserFilter, v)) +} + +// UserFilterIn applies the In predicate on the "user_filter" field. +func UserFilterIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldUserFilter, vs...)) +} + +// UserFilterNotIn applies the NotIn predicate on the "user_filter" field. +func UserFilterNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldUserFilter, vs...)) +} + +// UserFilterGT applies the GT predicate on the "user_filter" field. +func UserFilterGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldUserFilter, v)) +} + +// UserFilterGTE applies the GTE predicate on the "user_filter" field. +func UserFilterGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldUserFilter, v)) +} + +// UserFilterLT applies the LT predicate on the "user_filter" field. +func UserFilterLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldUserFilter, v)) +} + +// UserFilterLTE applies the LTE predicate on the "user_filter" field. +func UserFilterLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldUserFilter, v)) +} + +// UserFilterContains applies the Contains predicate on the "user_filter" field. +func UserFilterContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldUserFilter, v)) +} + +// UserFilterHasPrefix applies the HasPrefix predicate on the "user_filter" field. +func UserFilterHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldUserFilter, v)) +} + +// UserFilterHasSuffix applies the HasSuffix predicate on the "user_filter" field. +func UserFilterHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldUserFilter, v)) +} + +// UserFilterEqualFold applies the EqualFold predicate on the "user_filter" field. +func UserFilterEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldUserFilter, v)) +} + +// UserFilterContainsFold applies the ContainsFold predicate on the "user_filter" field. +func UserFilterContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldUserFilter, v)) +} + +// EnabledEQ applies the EQ predicate on the "enabled" field. +func EnabledEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldEnabled, v)) +} + +// EnabledNEQ applies the NEQ predicate on the "enabled" field. +func EnabledNEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldEnabled, v)) +} + +// TLSEnabledEQ applies the EQ predicate on the "tls_enabled" field. +func TLSEnabledEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldTLSEnabled, v)) +} + +// TLSEnabledNEQ applies the NEQ predicate on the "tls_enabled" field. +func TLSEnabledNEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldTLSEnabled, v)) +} + +// TLSSkipVerifyEQ applies the EQ predicate on the "tls_skip_verify" field. +func TLSSkipVerifyEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldTLSSkipVerify, v)) +} + +// TLSSkipVerifyNEQ applies the NEQ predicate on the "tls_skip_verify" field. +func TLSSkipVerifyNEQ(v bool) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldTLSSkipVerify, v)) +} + +// ConfigSourceEQ applies the EQ predicate on the "config_source" field. +func ConfigSourceEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEQ(FieldConfigSource, v)) +} + +// ConfigSourceNEQ applies the NEQ predicate on the "config_source" field. +func ConfigSourceNEQ(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNEQ(FieldConfigSource, v)) +} + +// ConfigSourceIn applies the In predicate on the "config_source" field. +func ConfigSourceIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldIn(FieldConfigSource, vs...)) +} + +// ConfigSourceNotIn applies the NotIn predicate on the "config_source" field. +func ConfigSourceNotIn(vs ...string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldNotIn(FieldConfigSource, vs...)) +} + +// ConfigSourceGT applies the GT predicate on the "config_source" field. +func ConfigSourceGT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGT(FieldConfigSource, v)) +} + +// ConfigSourceGTE applies the GTE predicate on the "config_source" field. +func ConfigSourceGTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldGTE(FieldConfigSource, v)) +} + +// ConfigSourceLT applies the LT predicate on the "config_source" field. +func ConfigSourceLT(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLT(FieldConfigSource, v)) +} + +// ConfigSourceLTE applies the LTE predicate on the "config_source" field. +func ConfigSourceLTE(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldLTE(FieldConfigSource, v)) +} + +// ConfigSourceContains applies the Contains predicate on the "config_source" field. +func ConfigSourceContains(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContains(FieldConfigSource, v)) +} + +// ConfigSourceHasPrefix applies the HasPrefix predicate on the "config_source" field. +func ConfigSourceHasPrefix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasPrefix(FieldConfigSource, v)) +} + +// ConfigSourceHasSuffix applies the HasSuffix predicate on the "config_source" field. +func ConfigSourceHasSuffix(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldHasSuffix(FieldConfigSource, v)) +} + +// ConfigSourceEqualFold applies the EqualFold predicate on the "config_source" field. +func ConfigSourceEqualFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldEqualFold(FieldConfigSource, v)) +} + +// ConfigSourceContainsFold applies the ContainsFold predicate on the "config_source" field. +func ConfigSourceContainsFold(v string) predicate.LdapConfig { + return predicate.LdapConfig(sql.FieldContainsFold(FieldConfigSource, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.LdapConfig) predicate.LdapConfig { + return predicate.LdapConfig(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.LdapConfig) predicate.LdapConfig { + return predicate.LdapConfig(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.LdapConfig) predicate.LdapConfig { + return predicate.LdapConfig(sql.NotPredicates(p)) +} diff --git a/backend/ent/ldapconfig_create.go b/backend/ent/ldapconfig_create.go new file mode 100644 index 000000000..04afa3baa --- /dev/null +++ b/backend/ent/ldapconfig_create.go @@ -0,0 +1,1077 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" +) + +// LdapConfigCreate is the builder for creating a LdapConfig entity. +type LdapConfigCreate struct { + config + mutation *LdapConfigMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (_c *LdapConfigCreate) SetCreatedAt(v time.Time) *LdapConfigCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableCreatedAt(v *time.Time) *LdapConfigCreate { + if v != nil { + _c.SetCreatedAt(*v) + } + return _c +} + +// SetUpdatedAt sets the "updated_at" field. +func (_c *LdapConfigCreate) SetUpdatedAt(v time.Time) *LdapConfigCreate { + _c.mutation.SetUpdatedAt(v) + return _c +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableUpdatedAt(v *time.Time) *LdapConfigCreate { + if v != nil { + _c.SetUpdatedAt(*v) + } + return _c +} + +// SetServerURL sets the "server_url" field. +func (_c *LdapConfigCreate) SetServerURL(v string) *LdapConfigCreate { + _c.mutation.SetServerURL(v) + return _c +} + +// SetBindDn sets the "bind_dn" field. +func (_c *LdapConfigCreate) SetBindDn(v string) *LdapConfigCreate { + _c.mutation.SetBindDn(v) + return _c +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (_c *LdapConfigCreate) SetBindPasswordEncrypted(v string) *LdapConfigCreate { + _c.mutation.SetBindPasswordEncrypted(v) + return _c +} + +// SetBaseDn sets the "base_dn" field. +func (_c *LdapConfigCreate) SetBaseDn(v string) *LdapConfigCreate { + _c.mutation.SetBaseDn(v) + return _c +} + +// SetUserFilter sets the "user_filter" field. +func (_c *LdapConfigCreate) SetUserFilter(v string) *LdapConfigCreate { + _c.mutation.SetUserFilter(v) + return _c +} + +// SetNillableUserFilter sets the "user_filter" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableUserFilter(v *string) *LdapConfigCreate { + if v != nil { + _c.SetUserFilter(*v) + } + return _c +} + +// SetEnabled sets the "enabled" field. +func (_c *LdapConfigCreate) SetEnabled(v bool) *LdapConfigCreate { + _c.mutation.SetEnabled(v) + return _c +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableEnabled(v *bool) *LdapConfigCreate { + if v != nil { + _c.SetEnabled(*v) + } + return _c +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (_c *LdapConfigCreate) SetTLSEnabled(v bool) *LdapConfigCreate { + _c.mutation.SetTLSEnabled(v) + return _c +} + +// SetNillableTLSEnabled sets the "tls_enabled" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableTLSEnabled(v *bool) *LdapConfigCreate { + if v != nil { + _c.SetTLSEnabled(*v) + } + return _c +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (_c *LdapConfigCreate) SetTLSSkipVerify(v bool) *LdapConfigCreate { + _c.mutation.SetTLSSkipVerify(v) + return _c +} + +// SetNillableTLSSkipVerify sets the "tls_skip_verify" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableTLSSkipVerify(v *bool) *LdapConfigCreate { + if v != nil { + _c.SetTLSSkipVerify(*v) + } + return _c +} + +// SetConfigSource sets the "config_source" field. +func (_c *LdapConfigCreate) SetConfigSource(v string) *LdapConfigCreate { + _c.mutation.SetConfigSource(v) + return _c +} + +// SetNillableConfigSource sets the "config_source" field if the given value is not nil. +func (_c *LdapConfigCreate) SetNillableConfigSource(v *string) *LdapConfigCreate { + if v != nil { + _c.SetConfigSource(*v) + } + return _c +} + +// Mutation returns the LdapConfigMutation object of the builder. +func (_c *LdapConfigCreate) Mutation() *LdapConfigMutation { + return _c.mutation +} + +// Save creates the LdapConfig in the database. +func (_c *LdapConfigCreate) Save(ctx context.Context) (*LdapConfig, error) { + _c.defaults() + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *LdapConfigCreate) SaveX(ctx context.Context) *LdapConfig { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *LdapConfigCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *LdapConfigCreate) 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 *LdapConfigCreate) defaults() { + if _, ok := _c.mutation.CreatedAt(); !ok { + v := ldapconfig.DefaultCreatedAt() + _c.mutation.SetCreatedAt(v) + } + if _, ok := _c.mutation.UpdatedAt(); !ok { + v := ldapconfig.DefaultUpdatedAt() + _c.mutation.SetUpdatedAt(v) + } + if _, ok := _c.mutation.UserFilter(); !ok { + v := ldapconfig.DefaultUserFilter + _c.mutation.SetUserFilter(v) + } + if _, ok := _c.mutation.Enabled(); !ok { + v := ldapconfig.DefaultEnabled + _c.mutation.SetEnabled(v) + } + if _, ok := _c.mutation.TLSEnabled(); !ok { + v := ldapconfig.DefaultTLSEnabled + _c.mutation.SetTLSEnabled(v) + } + if _, ok := _c.mutation.TLSSkipVerify(); !ok { + v := ldapconfig.DefaultTLSSkipVerify + _c.mutation.SetTLSSkipVerify(v) + } + if _, ok := _c.mutation.ConfigSource(); !ok { + v := ldapconfig.DefaultConfigSource + _c.mutation.SetConfigSource(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *LdapConfigCreate) check() error { + if _, ok := _c.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "LdapConfig.created_at"`)} + } + if _, ok := _c.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "LdapConfig.updated_at"`)} + } + if _, ok := _c.mutation.ServerURL(); !ok { + return &ValidationError{Name: "server_url", err: errors.New(`ent: missing required field "LdapConfig.server_url"`)} + } + if v, ok := _c.mutation.ServerURL(); ok { + if err := ldapconfig.ServerURLValidator(v); err != nil { + return &ValidationError{Name: "server_url", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.server_url": %w`, err)} + } + } + if _, ok := _c.mutation.BindDn(); !ok { + return &ValidationError{Name: "bind_dn", err: errors.New(`ent: missing required field "LdapConfig.bind_dn"`)} + } + if v, ok := _c.mutation.BindDn(); ok { + if err := ldapconfig.BindDnValidator(v); err != nil { + return &ValidationError{Name: "bind_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_dn": %w`, err)} + } + } + if _, ok := _c.mutation.BindPasswordEncrypted(); !ok { + return &ValidationError{Name: "bind_password_encrypted", err: errors.New(`ent: missing required field "LdapConfig.bind_password_encrypted"`)} + } + if v, ok := _c.mutation.BindPasswordEncrypted(); ok { + if err := ldapconfig.BindPasswordEncryptedValidator(v); err != nil { + return &ValidationError{Name: "bind_password_encrypted", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_password_encrypted": %w`, err)} + } + } + if _, ok := _c.mutation.BaseDn(); !ok { + return &ValidationError{Name: "base_dn", err: errors.New(`ent: missing required field "LdapConfig.base_dn"`)} + } + if v, ok := _c.mutation.BaseDn(); ok { + if err := ldapconfig.BaseDnValidator(v); err != nil { + return &ValidationError{Name: "base_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.base_dn": %w`, err)} + } + } + if _, ok := _c.mutation.UserFilter(); !ok { + return &ValidationError{Name: "user_filter", err: errors.New(`ent: missing required field "LdapConfig.user_filter"`)} + } + if v, ok := _c.mutation.UserFilter(); ok { + if err := ldapconfig.UserFilterValidator(v); err != nil { + return &ValidationError{Name: "user_filter", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.user_filter": %w`, err)} + } + } + if _, ok := _c.mutation.Enabled(); !ok { + return &ValidationError{Name: "enabled", err: errors.New(`ent: missing required field "LdapConfig.enabled"`)} + } + if _, ok := _c.mutation.TLSEnabled(); !ok { + return &ValidationError{Name: "tls_enabled", err: errors.New(`ent: missing required field "LdapConfig.tls_enabled"`)} + } + if _, ok := _c.mutation.TLSSkipVerify(); !ok { + return &ValidationError{Name: "tls_skip_verify", err: errors.New(`ent: missing required field "LdapConfig.tls_skip_verify"`)} + } + if _, ok := _c.mutation.ConfigSource(); !ok { + return &ValidationError{Name: "config_source", err: errors.New(`ent: missing required field "LdapConfig.config_source"`)} + } + if v, ok := _c.mutation.ConfigSource(); ok { + if err := ldapconfig.ConfigSourceValidator(v); err != nil { + return &ValidationError{Name: "config_source", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.config_source": %w`, err)} + } + } + return nil +} + +func (_c *LdapConfigCreate) sqlSave(ctx context.Context) (*LdapConfig, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *LdapConfigCreate) createSpec() (*LdapConfig, *sqlgraph.CreateSpec) { + var ( + _node = &LdapConfig{config: _c.config} + _spec = sqlgraph.NewCreateSpec(ldapconfig.Table, sqlgraph.NewFieldSpec(ldapconfig.FieldID, field.TypeInt64)) + ) + _spec.OnConflict = _c.conflict + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(ldapconfig.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.UpdatedAt(); ok { + _spec.SetField(ldapconfig.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := _c.mutation.ServerURL(); ok { + _spec.SetField(ldapconfig.FieldServerURL, field.TypeString, value) + _node.ServerURL = value + } + if value, ok := _c.mutation.BindDn(); ok { + _spec.SetField(ldapconfig.FieldBindDn, field.TypeString, value) + _node.BindDn = value + } + if value, ok := _c.mutation.BindPasswordEncrypted(); ok { + _spec.SetField(ldapconfig.FieldBindPasswordEncrypted, field.TypeString, value) + _node.BindPasswordEncrypted = value + } + if value, ok := _c.mutation.BaseDn(); ok { + _spec.SetField(ldapconfig.FieldBaseDn, field.TypeString, value) + _node.BaseDn = value + } + if value, ok := _c.mutation.UserFilter(); ok { + _spec.SetField(ldapconfig.FieldUserFilter, field.TypeString, value) + _node.UserFilter = value + } + if value, ok := _c.mutation.Enabled(); ok { + _spec.SetField(ldapconfig.FieldEnabled, field.TypeBool, value) + _node.Enabled = value + } + if value, ok := _c.mutation.TLSEnabled(); ok { + _spec.SetField(ldapconfig.FieldTLSEnabled, field.TypeBool, value) + _node.TLSEnabled = value + } + if value, ok := _c.mutation.TLSSkipVerify(); ok { + _spec.SetField(ldapconfig.FieldTLSSkipVerify, field.TypeBool, value) + _node.TLSSkipVerify = value + } + if value, ok := _c.mutation.ConfigSource(); ok { + _spec.SetField(ldapconfig.FieldConfigSource, field.TypeString, value) + _node.ConfigSource = value + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.LdapConfig.Create(). +// SetCreatedAt(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.LdapConfigUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (_c *LdapConfigCreate) OnConflict(opts ...sql.ConflictOption) *LdapConfigUpsertOne { + _c.conflict = opts + return &LdapConfigUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *LdapConfigCreate) OnConflictColumns(columns ...string) *LdapConfigUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &LdapConfigUpsertOne{ + create: _c, + } +} + +type ( + // LdapConfigUpsertOne is the builder for "upsert"-ing + // one LdapConfig node. + LdapConfigUpsertOne struct { + create *LdapConfigCreate + } + + // LdapConfigUpsert is the "OnConflict" setter. + LdapConfigUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapConfigUpsert) SetUpdatedAt(v time.Time) *LdapConfigUpsert { + u.Set(ldapconfig.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateUpdatedAt() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldUpdatedAt) + return u +} + +// SetServerURL sets the "server_url" field. +func (u *LdapConfigUpsert) SetServerURL(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldServerURL, v) + return u +} + +// UpdateServerURL sets the "server_url" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateServerURL() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldServerURL) + return u +} + +// SetBindDn sets the "bind_dn" field. +func (u *LdapConfigUpsert) SetBindDn(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldBindDn, v) + return u +} + +// UpdateBindDn sets the "bind_dn" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateBindDn() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldBindDn) + return u +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (u *LdapConfigUpsert) SetBindPasswordEncrypted(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldBindPasswordEncrypted, v) + return u +} + +// UpdateBindPasswordEncrypted sets the "bind_password_encrypted" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateBindPasswordEncrypted() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldBindPasswordEncrypted) + return u +} + +// SetBaseDn sets the "base_dn" field. +func (u *LdapConfigUpsert) SetBaseDn(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldBaseDn, v) + return u +} + +// UpdateBaseDn sets the "base_dn" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateBaseDn() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldBaseDn) + return u +} + +// SetUserFilter sets the "user_filter" field. +func (u *LdapConfigUpsert) SetUserFilter(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldUserFilter, v) + return u +} + +// UpdateUserFilter sets the "user_filter" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateUserFilter() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldUserFilter) + return u +} + +// SetEnabled sets the "enabled" field. +func (u *LdapConfigUpsert) SetEnabled(v bool) *LdapConfigUpsert { + u.Set(ldapconfig.FieldEnabled, v) + return u +} + +// UpdateEnabled sets the "enabled" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateEnabled() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldEnabled) + return u +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (u *LdapConfigUpsert) SetTLSEnabled(v bool) *LdapConfigUpsert { + u.Set(ldapconfig.FieldTLSEnabled, v) + return u +} + +// UpdateTLSEnabled sets the "tls_enabled" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateTLSEnabled() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldTLSEnabled) + return u +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (u *LdapConfigUpsert) SetTLSSkipVerify(v bool) *LdapConfigUpsert { + u.Set(ldapconfig.FieldTLSSkipVerify, v) + return u +} + +// UpdateTLSSkipVerify sets the "tls_skip_verify" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateTLSSkipVerify() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldTLSSkipVerify) + return u +} + +// SetConfigSource sets the "config_source" field. +func (u *LdapConfigUpsert) SetConfigSource(v string) *LdapConfigUpsert { + u.Set(ldapconfig.FieldConfigSource, v) + return u +} + +// UpdateConfigSource sets the "config_source" field to the value that was provided on create. +func (u *LdapConfigUpsert) UpdateConfigSource() *LdapConfigUpsert { + u.SetExcluded(ldapconfig.FieldConfigSource) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *LdapConfigUpsertOne) UpdateNewValues() *LdapConfigUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.CreatedAt(); exists { + s.SetIgnore(ldapconfig.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *LdapConfigUpsertOne) Ignore() *LdapConfigUpsertOne { + 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 *LdapConfigUpsertOne) DoNothing() *LdapConfigUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the LdapConfigCreate.OnConflict +// documentation for more info. +func (u *LdapConfigUpsertOne) Update(set func(*LdapConfigUpsert)) *LdapConfigUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&LdapConfigUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapConfigUpsertOne) SetUpdatedAt(v time.Time) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateUpdatedAt() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetServerURL sets the "server_url" field. +func (u *LdapConfigUpsertOne) SetServerURL(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetServerURL(v) + }) +} + +// UpdateServerURL sets the "server_url" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateServerURL() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateServerURL() + }) +} + +// SetBindDn sets the "bind_dn" field. +func (u *LdapConfigUpsertOne) SetBindDn(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBindDn(v) + }) +} + +// UpdateBindDn sets the "bind_dn" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateBindDn() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBindDn() + }) +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (u *LdapConfigUpsertOne) SetBindPasswordEncrypted(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBindPasswordEncrypted(v) + }) +} + +// UpdateBindPasswordEncrypted sets the "bind_password_encrypted" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateBindPasswordEncrypted() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBindPasswordEncrypted() + }) +} + +// SetBaseDn sets the "base_dn" field. +func (u *LdapConfigUpsertOne) SetBaseDn(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBaseDn(v) + }) +} + +// UpdateBaseDn sets the "base_dn" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateBaseDn() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBaseDn() + }) +} + +// SetUserFilter sets the "user_filter" field. +func (u *LdapConfigUpsertOne) SetUserFilter(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetUserFilter(v) + }) +} + +// UpdateUserFilter sets the "user_filter" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateUserFilter() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateUserFilter() + }) +} + +// SetEnabled sets the "enabled" field. +func (u *LdapConfigUpsertOne) SetEnabled(v bool) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetEnabled(v) + }) +} + +// UpdateEnabled sets the "enabled" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateEnabled() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateEnabled() + }) +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (u *LdapConfigUpsertOne) SetTLSEnabled(v bool) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetTLSEnabled(v) + }) +} + +// UpdateTLSEnabled sets the "tls_enabled" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateTLSEnabled() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateTLSEnabled() + }) +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (u *LdapConfigUpsertOne) SetTLSSkipVerify(v bool) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetTLSSkipVerify(v) + }) +} + +// UpdateTLSSkipVerify sets the "tls_skip_verify" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateTLSSkipVerify() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateTLSSkipVerify() + }) +} + +// SetConfigSource sets the "config_source" field. +func (u *LdapConfigUpsertOne) SetConfigSource(v string) *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.SetConfigSource(v) + }) +} + +// UpdateConfigSource sets the "config_source" field to the value that was provided on create. +func (u *LdapConfigUpsertOne) UpdateConfigSource() *LdapConfigUpsertOne { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateConfigSource() + }) +} + +// Exec executes the query. +func (u *LdapConfigUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for LdapConfigCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *LdapConfigUpsertOne) 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 *LdapConfigUpsertOne) ID(ctx context.Context) (id int64, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *LdapConfigUpsertOne) IDX(ctx context.Context) int64 { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// LdapConfigCreateBulk is the builder for creating many LdapConfig entities in bulk. +type LdapConfigCreateBulk struct { + config + err error + builders []*LdapConfigCreate + conflict []sql.ConflictOption +} + +// Save creates the LdapConfig entities in the database. +func (_c *LdapConfigCreateBulk) Save(ctx context.Context) ([]*LdapConfig, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*LdapConfig, 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.(*LdapConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *LdapConfigCreateBulk) SaveX(ctx context.Context) []*LdapConfig { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *LdapConfigCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *LdapConfigCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.LdapConfig.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.LdapConfigUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (_c *LdapConfigCreateBulk) OnConflict(opts ...sql.ConflictOption) *LdapConfigUpsertBulk { + _c.conflict = opts + return &LdapConfigUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *LdapConfigCreateBulk) OnConflictColumns(columns ...string) *LdapConfigUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &LdapConfigUpsertBulk{ + create: _c, + } +} + +// LdapConfigUpsertBulk is the builder for "upsert"-ing +// a bulk of LdapConfig nodes. +type LdapConfigUpsertBulk struct { + create *LdapConfigCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *LdapConfigUpsertBulk) UpdateNewValues() *LdapConfigUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.CreatedAt(); exists { + s.SetIgnore(ldapconfig.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.LdapConfig.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *LdapConfigUpsertBulk) Ignore() *LdapConfigUpsertBulk { + 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 *LdapConfigUpsertBulk) DoNothing() *LdapConfigUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the LdapConfigCreateBulk.OnConflict +// documentation for more info. +func (u *LdapConfigUpsertBulk) Update(set func(*LdapConfigUpsert)) *LdapConfigUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&LdapConfigUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapConfigUpsertBulk) SetUpdatedAt(v time.Time) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateUpdatedAt() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetServerURL sets the "server_url" field. +func (u *LdapConfigUpsertBulk) SetServerURL(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetServerURL(v) + }) +} + +// UpdateServerURL sets the "server_url" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateServerURL() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateServerURL() + }) +} + +// SetBindDn sets the "bind_dn" field. +func (u *LdapConfigUpsertBulk) SetBindDn(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBindDn(v) + }) +} + +// UpdateBindDn sets the "bind_dn" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateBindDn() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBindDn() + }) +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (u *LdapConfigUpsertBulk) SetBindPasswordEncrypted(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBindPasswordEncrypted(v) + }) +} + +// UpdateBindPasswordEncrypted sets the "bind_password_encrypted" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateBindPasswordEncrypted() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBindPasswordEncrypted() + }) +} + +// SetBaseDn sets the "base_dn" field. +func (u *LdapConfigUpsertBulk) SetBaseDn(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetBaseDn(v) + }) +} + +// UpdateBaseDn sets the "base_dn" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateBaseDn() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateBaseDn() + }) +} + +// SetUserFilter sets the "user_filter" field. +func (u *LdapConfigUpsertBulk) SetUserFilter(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetUserFilter(v) + }) +} + +// UpdateUserFilter sets the "user_filter" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateUserFilter() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateUserFilter() + }) +} + +// SetEnabled sets the "enabled" field. +func (u *LdapConfigUpsertBulk) SetEnabled(v bool) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetEnabled(v) + }) +} + +// UpdateEnabled sets the "enabled" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateEnabled() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateEnabled() + }) +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (u *LdapConfigUpsertBulk) SetTLSEnabled(v bool) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetTLSEnabled(v) + }) +} + +// UpdateTLSEnabled sets the "tls_enabled" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateTLSEnabled() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateTLSEnabled() + }) +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (u *LdapConfigUpsertBulk) SetTLSSkipVerify(v bool) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetTLSSkipVerify(v) + }) +} + +// UpdateTLSSkipVerify sets the "tls_skip_verify" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateTLSSkipVerify() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateTLSSkipVerify() + }) +} + +// SetConfigSource sets the "config_source" field. +func (u *LdapConfigUpsertBulk) SetConfigSource(v string) *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.SetConfigSource(v) + }) +} + +// UpdateConfigSource sets the "config_source" field to the value that was provided on create. +func (u *LdapConfigUpsertBulk) UpdateConfigSource() *LdapConfigUpsertBulk { + return u.Update(func(s *LdapConfigUpsert) { + s.UpdateConfigSource() + }) +} + +// Exec executes the query. +func (u *LdapConfigUpsertBulk) 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 LdapConfigCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for LdapConfigCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *LdapConfigUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/backend/ent/ldapconfig_delete.go b/backend/ent/ldapconfig_delete.go new file mode 100644 index 000000000..961d9fca7 --- /dev/null +++ b/backend/ent/ldapconfig_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// LdapConfigDelete is the builder for deleting a LdapConfig entity. +type LdapConfigDelete struct { + config + hooks []Hook + mutation *LdapConfigMutation +} + +// Where appends a list predicates to the LdapConfigDelete builder. +func (_d *LdapConfigDelete) Where(ps ...predicate.LdapConfig) *LdapConfigDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *LdapConfigDelete) 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 *LdapConfigDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *LdapConfigDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(ldapconfig.Table, sqlgraph.NewFieldSpec(ldapconfig.FieldID, field.TypeInt64)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// LdapConfigDeleteOne is the builder for deleting a single LdapConfig entity. +type LdapConfigDeleteOne struct { + _d *LdapConfigDelete +} + +// Where appends a list predicates to the LdapConfigDelete builder. +func (_d *LdapConfigDeleteOne) Where(ps ...predicate.LdapConfig) *LdapConfigDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *LdapConfigDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{ldapconfig.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *LdapConfigDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/backend/ent/ldapconfig_query.go b/backend/ent/ldapconfig_query.go new file mode 100644 index 000000000..d347304e2 --- /dev/null +++ b/backend/ent/ldapconfig_query.go @@ -0,0 +1,564 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// LdapConfigQuery is the builder for querying LdapConfig entities. +type LdapConfigQuery struct { + config + ctx *QueryContext + order []ldapconfig.OrderOption + inters []Interceptor + predicates []predicate.LdapConfig + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the LdapConfigQuery builder. +func (_q *LdapConfigQuery) Where(ps ...predicate.LdapConfig) *LdapConfigQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *LdapConfigQuery) Limit(limit int) *LdapConfigQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *LdapConfigQuery) Offset(offset int) *LdapConfigQuery { + _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 *LdapConfigQuery) Unique(unique bool) *LdapConfigQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *LdapConfigQuery) Order(o ...ldapconfig.OrderOption) *LdapConfigQuery { + _q.order = append(_q.order, o...) + return _q +} + +// First returns the first LdapConfig entity from the query. +// Returns a *NotFoundError when no LdapConfig was found. +func (_q *LdapConfigQuery) First(ctx context.Context) (*LdapConfig, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{ldapconfig.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *LdapConfigQuery) FirstX(ctx context.Context) *LdapConfig { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first LdapConfig ID from the query. +// Returns a *NotFoundError when no LdapConfig ID was found. +func (_q *LdapConfigQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{ldapconfig.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *LdapConfigQuery) FirstIDX(ctx context.Context) int64 { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single LdapConfig entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one LdapConfig entity is found. +// Returns a *NotFoundError when no LdapConfig entities are found. +func (_q *LdapConfigQuery) Only(ctx context.Context) (*LdapConfig, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{ldapconfig.Label} + default: + return nil, &NotSingularError{ldapconfig.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *LdapConfigQuery) OnlyX(ctx context.Context) *LdapConfig { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only LdapConfig ID in the query. +// Returns a *NotSingularError when more than one LdapConfig ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *LdapConfigQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{ldapconfig.Label} + default: + err = &NotSingularError{ldapconfig.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *LdapConfigQuery) OnlyIDX(ctx context.Context) int64 { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of LdapConfigs. +func (_q *LdapConfigQuery) All(ctx context.Context) ([]*LdapConfig, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*LdapConfig, *LdapConfigQuery]() + return withInterceptors[[]*LdapConfig](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *LdapConfigQuery) AllX(ctx context.Context) []*LdapConfig { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of LdapConfig IDs. +func (_q *LdapConfigQuery) IDs(ctx context.Context) (ids []int64, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(ldapconfig.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *LdapConfigQuery) IDsX(ctx context.Context) []int64 { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *LdapConfigQuery) 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[*LdapConfigQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *LdapConfigQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *LdapConfigQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *LdapConfigQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the LdapConfigQuery 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 *LdapConfigQuery) Clone() *LdapConfigQuery { + if _q == nil { + return nil + } + return &LdapConfigQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]ldapconfig.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.LdapConfig{}, _q.predicates...), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.LdapConfig.Query(). +// GroupBy(ldapconfig.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *LdapConfigQuery) GroupBy(field string, fields ...string) *LdapConfigGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &LdapConfigGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = ldapconfig.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.LdapConfig.Query(). +// Select(ldapconfig.FieldCreatedAt). +// Scan(ctx, &v) +func (_q *LdapConfigQuery) Select(fields ...string) *LdapConfigSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &LdapConfigSelect{LdapConfigQuery: _q} + sbuild.label = ldapconfig.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a LdapConfigSelect configured with the given aggregations. +func (_q *LdapConfigQuery) Aggregate(fns ...AggregateFunc) *LdapConfigSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *LdapConfigQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !ldapconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *LdapConfigQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*LdapConfig, error) { + var ( + nodes = []*LdapConfig{} + _spec = _q.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*LdapConfig).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &LdapConfig{config: _q.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + if len(_q.modifiers) > 0 { + _spec.Modifiers = _q.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (_q *LdapConfigQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + if len(_q.modifiers) > 0 { + _spec.Modifiers = _q.modifiers + } + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *LdapConfigQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(ldapconfig.Table, ldapconfig.Columns, sqlgraph.NewFieldSpec(ldapconfig.FieldID, field.TypeInt64)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, ldapconfig.FieldID) + for i := range fields { + if fields[i] != ldapconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *LdapConfigQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(ldapconfig.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = ldapconfig.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, m := range _q.modifiers { + m(selector) + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ForUpdate locks the selected rows against concurrent updates, and prevent them from being +// updated, deleted or "selected ... for update" by other sessions, until the transaction is +// either committed or rolled-back. +func (_q *LdapConfigQuery) ForUpdate(opts ...sql.LockOption) *LdapConfigQuery { + if _q.driver.Dialect() == dialect.Postgres { + _q.Unique(false) + } + _q.modifiers = append(_q.modifiers, func(s *sql.Selector) { + s.ForUpdate(opts...) + }) + return _q +} + +// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock +// on any rows that are read. Other sessions can read the rows, but cannot modify them +// until your transaction commits. +func (_q *LdapConfigQuery) ForShare(opts ...sql.LockOption) *LdapConfigQuery { + if _q.driver.Dialect() == dialect.Postgres { + _q.Unique(false) + } + _q.modifiers = append(_q.modifiers, func(s *sql.Selector) { + s.ForShare(opts...) + }) + return _q +} + +// LdapConfigGroupBy is the group-by builder for LdapConfig entities. +type LdapConfigGroupBy struct { + selector + build *LdapConfigQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *LdapConfigGroupBy) Aggregate(fns ...AggregateFunc) *LdapConfigGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *LdapConfigGroupBy) 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[*LdapConfigQuery, *LdapConfigGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *LdapConfigGroupBy) sqlScan(ctx context.Context, root *LdapConfigQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// LdapConfigSelect is the builder for selecting fields of LdapConfig entities. +type LdapConfigSelect struct { + *LdapConfigQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *LdapConfigSelect) Aggregate(fns ...AggregateFunc) *LdapConfigSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *LdapConfigSelect) 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[*LdapConfigQuery, *LdapConfigSelect](ctx, _s.LdapConfigQuery, _s, _s.inters, v) +} + +func (_s *LdapConfigSelect) sqlScan(ctx context.Context, root *LdapConfigQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/backend/ent/ldapconfig_update.go b/backend/ent/ldapconfig_update.go new file mode 100644 index 000000000..045016a5e --- /dev/null +++ b/backend/ent/ldapconfig_update.go @@ -0,0 +1,594 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// LdapConfigUpdate is the builder for updating LdapConfig entities. +type LdapConfigUpdate struct { + config + hooks []Hook + mutation *LdapConfigMutation +} + +// Where appends a list predicates to the LdapConfigUpdate builder. +func (_u *LdapConfigUpdate) Where(ps ...predicate.LdapConfig) *LdapConfigUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *LdapConfigUpdate) SetUpdatedAt(v time.Time) *LdapConfigUpdate { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetServerURL sets the "server_url" field. +func (_u *LdapConfigUpdate) SetServerURL(v string) *LdapConfigUpdate { + _u.mutation.SetServerURL(v) + return _u +} + +// SetNillableServerURL sets the "server_url" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableServerURL(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetServerURL(*v) + } + return _u +} + +// SetBindDn sets the "bind_dn" field. +func (_u *LdapConfigUpdate) SetBindDn(v string) *LdapConfigUpdate { + _u.mutation.SetBindDn(v) + return _u +} + +// SetNillableBindDn sets the "bind_dn" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableBindDn(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetBindDn(*v) + } + return _u +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (_u *LdapConfigUpdate) SetBindPasswordEncrypted(v string) *LdapConfigUpdate { + _u.mutation.SetBindPasswordEncrypted(v) + return _u +} + +// SetNillableBindPasswordEncrypted sets the "bind_password_encrypted" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableBindPasswordEncrypted(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetBindPasswordEncrypted(*v) + } + return _u +} + +// SetBaseDn sets the "base_dn" field. +func (_u *LdapConfigUpdate) SetBaseDn(v string) *LdapConfigUpdate { + _u.mutation.SetBaseDn(v) + return _u +} + +// SetNillableBaseDn sets the "base_dn" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableBaseDn(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetBaseDn(*v) + } + return _u +} + +// SetUserFilter sets the "user_filter" field. +func (_u *LdapConfigUpdate) SetUserFilter(v string) *LdapConfigUpdate { + _u.mutation.SetUserFilter(v) + return _u +} + +// SetNillableUserFilter sets the "user_filter" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableUserFilter(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetUserFilter(*v) + } + return _u +} + +// SetEnabled sets the "enabled" field. +func (_u *LdapConfigUpdate) SetEnabled(v bool) *LdapConfigUpdate { + _u.mutation.SetEnabled(v) + return _u +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableEnabled(v *bool) *LdapConfigUpdate { + if v != nil { + _u.SetEnabled(*v) + } + return _u +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (_u *LdapConfigUpdate) SetTLSEnabled(v bool) *LdapConfigUpdate { + _u.mutation.SetTLSEnabled(v) + return _u +} + +// SetNillableTLSEnabled sets the "tls_enabled" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableTLSEnabled(v *bool) *LdapConfigUpdate { + if v != nil { + _u.SetTLSEnabled(*v) + } + return _u +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (_u *LdapConfigUpdate) SetTLSSkipVerify(v bool) *LdapConfigUpdate { + _u.mutation.SetTLSSkipVerify(v) + return _u +} + +// SetNillableTLSSkipVerify sets the "tls_skip_verify" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableTLSSkipVerify(v *bool) *LdapConfigUpdate { + if v != nil { + _u.SetTLSSkipVerify(*v) + } + return _u +} + +// SetConfigSource sets the "config_source" field. +func (_u *LdapConfigUpdate) SetConfigSource(v string) *LdapConfigUpdate { + _u.mutation.SetConfigSource(v) + return _u +} + +// SetNillableConfigSource sets the "config_source" field if the given value is not nil. +func (_u *LdapConfigUpdate) SetNillableConfigSource(v *string) *LdapConfigUpdate { + if v != nil { + _u.SetConfigSource(*v) + } + return _u +} + +// Mutation returns the LdapConfigMutation object of the builder. +func (_u *LdapConfigUpdate) Mutation() *LdapConfigMutation { + return _u.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *LdapConfigUpdate) Save(ctx context.Context) (int, error) { + _u.defaults() + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *LdapConfigUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *LdapConfigUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *LdapConfigUpdate) 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 *LdapConfigUpdate) defaults() { + if _, ok := _u.mutation.UpdatedAt(); !ok { + v := ldapconfig.UpdateDefaultUpdatedAt() + _u.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *LdapConfigUpdate) check() error { + if v, ok := _u.mutation.ServerURL(); ok { + if err := ldapconfig.ServerURLValidator(v); err != nil { + return &ValidationError{Name: "server_url", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.server_url": %w`, err)} + } + } + if v, ok := _u.mutation.BindDn(); ok { + if err := ldapconfig.BindDnValidator(v); err != nil { + return &ValidationError{Name: "bind_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_dn": %w`, err)} + } + } + if v, ok := _u.mutation.BindPasswordEncrypted(); ok { + if err := ldapconfig.BindPasswordEncryptedValidator(v); err != nil { + return &ValidationError{Name: "bind_password_encrypted", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_password_encrypted": %w`, err)} + } + } + if v, ok := _u.mutation.BaseDn(); ok { + if err := ldapconfig.BaseDnValidator(v); err != nil { + return &ValidationError{Name: "base_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.base_dn": %w`, err)} + } + } + if v, ok := _u.mutation.UserFilter(); ok { + if err := ldapconfig.UserFilterValidator(v); err != nil { + return &ValidationError{Name: "user_filter", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.user_filter": %w`, err)} + } + } + if v, ok := _u.mutation.ConfigSource(); ok { + if err := ldapconfig.ConfigSourceValidator(v); err != nil { + return &ValidationError{Name: "config_source", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.config_source": %w`, err)} + } + } + return nil +} + +func (_u *LdapConfigUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(ldapconfig.Table, ldapconfig.Columns, sqlgraph.NewFieldSpec(ldapconfig.FieldID, field.TypeInt64)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(ldapconfig.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.ServerURL(); ok { + _spec.SetField(ldapconfig.FieldServerURL, field.TypeString, value) + } + if value, ok := _u.mutation.BindDn(); ok { + _spec.SetField(ldapconfig.FieldBindDn, field.TypeString, value) + } + if value, ok := _u.mutation.BindPasswordEncrypted(); ok { + _spec.SetField(ldapconfig.FieldBindPasswordEncrypted, field.TypeString, value) + } + if value, ok := _u.mutation.BaseDn(); ok { + _spec.SetField(ldapconfig.FieldBaseDn, field.TypeString, value) + } + if value, ok := _u.mutation.UserFilter(); ok { + _spec.SetField(ldapconfig.FieldUserFilter, field.TypeString, value) + } + if value, ok := _u.mutation.Enabled(); ok { + _spec.SetField(ldapconfig.FieldEnabled, field.TypeBool, value) + } + if value, ok := _u.mutation.TLSEnabled(); ok { + _spec.SetField(ldapconfig.FieldTLSEnabled, field.TypeBool, value) + } + if value, ok := _u.mutation.TLSSkipVerify(); ok { + _spec.SetField(ldapconfig.FieldTLSSkipVerify, field.TypeBool, value) + } + if value, ok := _u.mutation.ConfigSource(); ok { + _spec.SetField(ldapconfig.FieldConfigSource, field.TypeString, value) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{ldapconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// LdapConfigUpdateOne is the builder for updating a single LdapConfig entity. +type LdapConfigUpdateOne struct { + config + fields []string + hooks []Hook + mutation *LdapConfigMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *LdapConfigUpdateOne) SetUpdatedAt(v time.Time) *LdapConfigUpdateOne { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetServerURL sets the "server_url" field. +func (_u *LdapConfigUpdateOne) SetServerURL(v string) *LdapConfigUpdateOne { + _u.mutation.SetServerURL(v) + return _u +} + +// SetNillableServerURL sets the "server_url" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableServerURL(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetServerURL(*v) + } + return _u +} + +// SetBindDn sets the "bind_dn" field. +func (_u *LdapConfigUpdateOne) SetBindDn(v string) *LdapConfigUpdateOne { + _u.mutation.SetBindDn(v) + return _u +} + +// SetNillableBindDn sets the "bind_dn" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableBindDn(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetBindDn(*v) + } + return _u +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (_u *LdapConfigUpdateOne) SetBindPasswordEncrypted(v string) *LdapConfigUpdateOne { + _u.mutation.SetBindPasswordEncrypted(v) + return _u +} + +// SetNillableBindPasswordEncrypted sets the "bind_password_encrypted" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableBindPasswordEncrypted(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetBindPasswordEncrypted(*v) + } + return _u +} + +// SetBaseDn sets the "base_dn" field. +func (_u *LdapConfigUpdateOne) SetBaseDn(v string) *LdapConfigUpdateOne { + _u.mutation.SetBaseDn(v) + return _u +} + +// SetNillableBaseDn sets the "base_dn" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableBaseDn(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetBaseDn(*v) + } + return _u +} + +// SetUserFilter sets the "user_filter" field. +func (_u *LdapConfigUpdateOne) SetUserFilter(v string) *LdapConfigUpdateOne { + _u.mutation.SetUserFilter(v) + return _u +} + +// SetNillableUserFilter sets the "user_filter" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableUserFilter(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetUserFilter(*v) + } + return _u +} + +// SetEnabled sets the "enabled" field. +func (_u *LdapConfigUpdateOne) SetEnabled(v bool) *LdapConfigUpdateOne { + _u.mutation.SetEnabled(v) + return _u +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableEnabled(v *bool) *LdapConfigUpdateOne { + if v != nil { + _u.SetEnabled(*v) + } + return _u +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (_u *LdapConfigUpdateOne) SetTLSEnabled(v bool) *LdapConfigUpdateOne { + _u.mutation.SetTLSEnabled(v) + return _u +} + +// SetNillableTLSEnabled sets the "tls_enabled" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableTLSEnabled(v *bool) *LdapConfigUpdateOne { + if v != nil { + _u.SetTLSEnabled(*v) + } + return _u +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (_u *LdapConfigUpdateOne) SetTLSSkipVerify(v bool) *LdapConfigUpdateOne { + _u.mutation.SetTLSSkipVerify(v) + return _u +} + +// SetNillableTLSSkipVerify sets the "tls_skip_verify" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableTLSSkipVerify(v *bool) *LdapConfigUpdateOne { + if v != nil { + _u.SetTLSSkipVerify(*v) + } + return _u +} + +// SetConfigSource sets the "config_source" field. +func (_u *LdapConfigUpdateOne) SetConfigSource(v string) *LdapConfigUpdateOne { + _u.mutation.SetConfigSource(v) + return _u +} + +// SetNillableConfigSource sets the "config_source" field if the given value is not nil. +func (_u *LdapConfigUpdateOne) SetNillableConfigSource(v *string) *LdapConfigUpdateOne { + if v != nil { + _u.SetConfigSource(*v) + } + return _u +} + +// Mutation returns the LdapConfigMutation object of the builder. +func (_u *LdapConfigUpdateOne) Mutation() *LdapConfigMutation { + return _u.mutation +} + +// Where appends a list predicates to the LdapConfigUpdate builder. +func (_u *LdapConfigUpdateOne) Where(ps ...predicate.LdapConfig) *LdapConfigUpdateOne { + _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 *LdapConfigUpdateOne) Select(field string, fields ...string) *LdapConfigUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated LdapConfig entity. +func (_u *LdapConfigUpdateOne) Save(ctx context.Context) (*LdapConfig, error) { + _u.defaults() + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *LdapConfigUpdateOne) SaveX(ctx context.Context) *LdapConfig { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *LdapConfigUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *LdapConfigUpdateOne) 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 *LdapConfigUpdateOne) defaults() { + if _, ok := _u.mutation.UpdatedAt(); !ok { + v := ldapconfig.UpdateDefaultUpdatedAt() + _u.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *LdapConfigUpdateOne) check() error { + if v, ok := _u.mutation.ServerURL(); ok { + if err := ldapconfig.ServerURLValidator(v); err != nil { + return &ValidationError{Name: "server_url", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.server_url": %w`, err)} + } + } + if v, ok := _u.mutation.BindDn(); ok { + if err := ldapconfig.BindDnValidator(v); err != nil { + return &ValidationError{Name: "bind_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_dn": %w`, err)} + } + } + if v, ok := _u.mutation.BindPasswordEncrypted(); ok { + if err := ldapconfig.BindPasswordEncryptedValidator(v); err != nil { + return &ValidationError{Name: "bind_password_encrypted", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.bind_password_encrypted": %w`, err)} + } + } + if v, ok := _u.mutation.BaseDn(); ok { + if err := ldapconfig.BaseDnValidator(v); err != nil { + return &ValidationError{Name: "base_dn", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.base_dn": %w`, err)} + } + } + if v, ok := _u.mutation.UserFilter(); ok { + if err := ldapconfig.UserFilterValidator(v); err != nil { + return &ValidationError{Name: "user_filter", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.user_filter": %w`, err)} + } + } + if v, ok := _u.mutation.ConfigSource(); ok { + if err := ldapconfig.ConfigSourceValidator(v); err != nil { + return &ValidationError{Name: "config_source", err: fmt.Errorf(`ent: validator failed for field "LdapConfig.config_source": %w`, err)} + } + } + return nil +} + +func (_u *LdapConfigUpdateOne) sqlSave(ctx context.Context) (_node *LdapConfig, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(ldapconfig.Table, ldapconfig.Columns, sqlgraph.NewFieldSpec(ldapconfig.FieldID, field.TypeInt64)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "LdapConfig.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, ldapconfig.FieldID) + for _, f := range fields { + if !ldapconfig.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != ldapconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(ldapconfig.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.ServerURL(); ok { + _spec.SetField(ldapconfig.FieldServerURL, field.TypeString, value) + } + if value, ok := _u.mutation.BindDn(); ok { + _spec.SetField(ldapconfig.FieldBindDn, field.TypeString, value) + } + if value, ok := _u.mutation.BindPasswordEncrypted(); ok { + _spec.SetField(ldapconfig.FieldBindPasswordEncrypted, field.TypeString, value) + } + if value, ok := _u.mutation.BaseDn(); ok { + _spec.SetField(ldapconfig.FieldBaseDn, field.TypeString, value) + } + if value, ok := _u.mutation.UserFilter(); ok { + _spec.SetField(ldapconfig.FieldUserFilter, field.TypeString, value) + } + if value, ok := _u.mutation.Enabled(); ok { + _spec.SetField(ldapconfig.FieldEnabled, field.TypeBool, value) + } + if value, ok := _u.mutation.TLSEnabled(); ok { + _spec.SetField(ldapconfig.FieldTLSEnabled, field.TypeBool, value) + } + if value, ok := _u.mutation.TLSSkipVerify(); ok { + _spec.SetField(ldapconfig.FieldTLSSkipVerify, field.TypeBool, value) + } + if value, ok := _u.mutation.ConfigSource(); ok { + _spec.SetField(ldapconfig.FieldConfigSource, field.TypeString, value) + } + _node = &LdapConfig{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{ldapconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/backend/ent/ldapuser.go b/backend/ent/ldapuser.go new file mode 100644 index 000000000..61cf8d59e --- /dev/null +++ b/backend/ent/ldapuser.go @@ -0,0 +1,190 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/user" +) + +// LdapUser is the model entity for the LdapUser schema. +type LdapUser struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // Foreign key to users table + UserID int64 `json:"user_id,omitempty"` + // LDAP username (uid) + LdapUsername string `json:"ldap_username,omitempty"` + // LDAP Distinguished Name + LdapDn string `json:"ldap_dn,omitempty"` + // Last synchronization time + LastSyncAt time.Time `json:"last_sync_at,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the LdapUserQuery when eager-loading is set. + Edges LdapUserEdges `json:"edges"` + selectValues sql.SelectValues +} + +// LdapUserEdges holds the relations/edges for other nodes in the graph. +type LdapUserEdges struct { + // User holds the value of the user edge. + User *User `json:"user,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// UserOrErr returns the User value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e LdapUserEdges) UserOrErr() (*User, error) { + if e.User != nil { + return e.User, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: user.Label} + } + return nil, &NotLoadedError{edge: "user"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*LdapUser) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case ldapuser.FieldID, ldapuser.FieldUserID: + values[i] = new(sql.NullInt64) + case ldapuser.FieldLdapUsername, ldapuser.FieldLdapDn: + values[i] = new(sql.NullString) + case ldapuser.FieldCreatedAt, ldapuser.FieldUpdatedAt, ldapuser.FieldLastSyncAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the LdapUser fields. +func (_m *LdapUser) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case ldapuser.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int64(value.Int64) + case ldapuser.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case ldapuser.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + _m.UpdatedAt = value.Time + } + case ldapuser.FieldUserID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field user_id", values[i]) + } else if value.Valid { + _m.UserID = value.Int64 + } + case ldapuser.FieldLdapUsername: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field ldap_username", values[i]) + } else if value.Valid { + _m.LdapUsername = value.String + } + case ldapuser.FieldLdapDn: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field ldap_dn", values[i]) + } else if value.Valid { + _m.LdapDn = value.String + } + case ldapuser.FieldLastSyncAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field last_sync_at", values[i]) + } else if value.Valid { + _m.LastSyncAt = value.Time + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the LdapUser. +// This includes values selected through modifiers, order, etc. +func (_m *LdapUser) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// QueryUser queries the "user" edge of the LdapUser entity. +func (_m *LdapUser) QueryUser() *UserQuery { + return NewLdapUserClient(_m.config).QueryUser(_m) +} + +// Update returns a builder for updating this LdapUser. +// Note that you need to call LdapUser.Unwrap() before calling this method if this LdapUser +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *LdapUser) Update() *LdapUserUpdateOne { + return NewLdapUserClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the LdapUser 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 *LdapUser) Unwrap() *LdapUser { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: LdapUser is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *LdapUser) String() string { + var builder strings.Builder + builder.WriteString("LdapUser(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(_m.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("user_id=") + builder.WriteString(fmt.Sprintf("%v", _m.UserID)) + builder.WriteString(", ") + builder.WriteString("ldap_username=") + builder.WriteString(_m.LdapUsername) + builder.WriteString(", ") + builder.WriteString("ldap_dn=") + builder.WriteString(_m.LdapDn) + builder.WriteString(", ") + builder.WriteString("last_sync_at=") + builder.WriteString(_m.LastSyncAt.Format(time.ANSIC)) + builder.WriteByte(')') + return builder.String() +} + +// LdapUsers is a parsable slice of LdapUser. +type LdapUsers []*LdapUser diff --git a/backend/ent/ldapuser/ldapuser.go b/backend/ent/ldapuser/ldapuser.go new file mode 100644 index 000000000..f1e0ef3dc --- /dev/null +++ b/backend/ent/ldapuser/ldapuser.go @@ -0,0 +1,128 @@ +// Code generated by ent, DO NOT EDIT. + +package ldapuser + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the ldapuser type in the database. + Label = "ldap_user" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldUserID holds the string denoting the user_id field in the database. + FieldUserID = "user_id" + // FieldLdapUsername holds the string denoting the ldap_username field in the database. + FieldLdapUsername = "ldap_username" + // FieldLdapDn holds the string denoting the ldap_dn field in the database. + FieldLdapDn = "ldap_dn" + // FieldLastSyncAt holds the string denoting the last_sync_at field in the database. + FieldLastSyncAt = "last_sync_at" + // EdgeUser holds the string denoting the user edge name in mutations. + EdgeUser = "user" + // Table holds the table name of the ldapuser in the database. + Table = "ldap_users" + // UserTable is the table that holds the user relation/edge. + UserTable = "ldap_users" + // UserInverseTable is the table name for the User entity. + // It exists in this package in order to avoid circular dependency with the "user" package. + UserInverseTable = "users" + // UserColumn is the table column denoting the user relation/edge. + UserColumn = "user_id" +) + +// Columns holds all SQL columns for ldapuser fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldUserID, + FieldLdapUsername, + FieldLdapDn, + FieldLastSyncAt, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() time.Time + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() time.Time + // LdapUsernameValidator is a validator for the "ldap_username" field. It is called by the builders before save. + LdapUsernameValidator func(string) error + // LdapDnValidator is a validator for the "ldap_dn" field. It is called by the builders before save. + LdapDnValidator func(string) error + // DefaultLastSyncAt holds the default value on creation for the "last_sync_at" field. + DefaultLastSyncAt func() time.Time +) + +// OrderOption defines the ordering options for the LdapUser queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByUserID orders the results by the user_id field. +func ByUserID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUserID, opts...).ToFunc() +} + +// ByLdapUsername orders the results by the ldap_username field. +func ByLdapUsername(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLdapUsername, opts...).ToFunc() +} + +// ByLdapDn orders the results by the ldap_dn field. +func ByLdapDn(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLdapDn, opts...).ToFunc() +} + +// ByLastSyncAt orders the results by the last_sync_at field. +func ByLastSyncAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLastSyncAt, opts...).ToFunc() +} + +// ByUserField orders the results by user field. +func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...)) + } +} +func newUserStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(UserInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn), + ) +} diff --git a/backend/ent/ldapuser/where.go b/backend/ent/ldapuser/where.go new file mode 100644 index 000000000..3f914bc49 --- /dev/null +++ b/backend/ent/ldapuser/where.go @@ -0,0 +1,394 @@ +// Code generated by ent, DO NOT EDIT. + +package ldapuser + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.LdapUser { + return predicate.LdapUser(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.LdapUser { + return predicate.LdapUser(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.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ. +func UserID(v int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldUserID, v)) +} + +// LdapUsername applies equality check predicate on the "ldap_username" field. It's identical to LdapUsernameEQ. +func LdapUsername(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLdapUsername, v)) +} + +// LdapDn applies equality check predicate on the "ldap_dn" field. It's identical to LdapDnEQ. +func LdapDn(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLdapDn, v)) +} + +// LastSyncAt applies equality check predicate on the "last_sync_at" field. It's identical to LastSyncAtEQ. +func LastSyncAt(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLastSyncAt, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// UserIDEQ applies the EQ predicate on the "user_id" field. +func UserIDEQ(v int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldUserID, v)) +} + +// UserIDNEQ applies the NEQ predicate on the "user_id" field. +func UserIDNEQ(v int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldUserID, v)) +} + +// UserIDIn applies the In predicate on the "user_id" field. +func UserIDIn(vs ...int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldUserID, vs...)) +} + +// UserIDNotIn applies the NotIn predicate on the "user_id" field. +func UserIDNotIn(vs ...int64) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldUserID, vs...)) +} + +// LdapUsernameEQ applies the EQ predicate on the "ldap_username" field. +func LdapUsernameEQ(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLdapUsername, v)) +} + +// LdapUsernameNEQ applies the NEQ predicate on the "ldap_username" field. +func LdapUsernameNEQ(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldLdapUsername, v)) +} + +// LdapUsernameIn applies the In predicate on the "ldap_username" field. +func LdapUsernameIn(vs ...string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldLdapUsername, vs...)) +} + +// LdapUsernameNotIn applies the NotIn predicate on the "ldap_username" field. +func LdapUsernameNotIn(vs ...string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldLdapUsername, vs...)) +} + +// LdapUsernameGT applies the GT predicate on the "ldap_username" field. +func LdapUsernameGT(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldLdapUsername, v)) +} + +// LdapUsernameGTE applies the GTE predicate on the "ldap_username" field. +func LdapUsernameGTE(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldLdapUsername, v)) +} + +// LdapUsernameLT applies the LT predicate on the "ldap_username" field. +func LdapUsernameLT(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldLdapUsername, v)) +} + +// LdapUsernameLTE applies the LTE predicate on the "ldap_username" field. +func LdapUsernameLTE(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLTE(FieldLdapUsername, v)) +} + +// LdapUsernameContains applies the Contains predicate on the "ldap_username" field. +func LdapUsernameContains(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldContains(FieldLdapUsername, v)) +} + +// LdapUsernameHasPrefix applies the HasPrefix predicate on the "ldap_username" field. +func LdapUsernameHasPrefix(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldHasPrefix(FieldLdapUsername, v)) +} + +// LdapUsernameHasSuffix applies the HasSuffix predicate on the "ldap_username" field. +func LdapUsernameHasSuffix(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldHasSuffix(FieldLdapUsername, v)) +} + +// LdapUsernameEqualFold applies the EqualFold predicate on the "ldap_username" field. +func LdapUsernameEqualFold(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEqualFold(FieldLdapUsername, v)) +} + +// LdapUsernameContainsFold applies the ContainsFold predicate on the "ldap_username" field. +func LdapUsernameContainsFold(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldContainsFold(FieldLdapUsername, v)) +} + +// LdapDnEQ applies the EQ predicate on the "ldap_dn" field. +func LdapDnEQ(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLdapDn, v)) +} + +// LdapDnNEQ applies the NEQ predicate on the "ldap_dn" field. +func LdapDnNEQ(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldLdapDn, v)) +} + +// LdapDnIn applies the In predicate on the "ldap_dn" field. +func LdapDnIn(vs ...string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldLdapDn, vs...)) +} + +// LdapDnNotIn applies the NotIn predicate on the "ldap_dn" field. +func LdapDnNotIn(vs ...string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldLdapDn, vs...)) +} + +// LdapDnGT applies the GT predicate on the "ldap_dn" field. +func LdapDnGT(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldLdapDn, v)) +} + +// LdapDnGTE applies the GTE predicate on the "ldap_dn" field. +func LdapDnGTE(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldLdapDn, v)) +} + +// LdapDnLT applies the LT predicate on the "ldap_dn" field. +func LdapDnLT(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldLdapDn, v)) +} + +// LdapDnLTE applies the LTE predicate on the "ldap_dn" field. +func LdapDnLTE(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLTE(FieldLdapDn, v)) +} + +// LdapDnContains applies the Contains predicate on the "ldap_dn" field. +func LdapDnContains(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldContains(FieldLdapDn, v)) +} + +// LdapDnHasPrefix applies the HasPrefix predicate on the "ldap_dn" field. +func LdapDnHasPrefix(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldHasPrefix(FieldLdapDn, v)) +} + +// LdapDnHasSuffix applies the HasSuffix predicate on the "ldap_dn" field. +func LdapDnHasSuffix(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldHasSuffix(FieldLdapDn, v)) +} + +// LdapDnEqualFold applies the EqualFold predicate on the "ldap_dn" field. +func LdapDnEqualFold(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEqualFold(FieldLdapDn, v)) +} + +// LdapDnContainsFold applies the ContainsFold predicate on the "ldap_dn" field. +func LdapDnContainsFold(v string) predicate.LdapUser { + return predicate.LdapUser(sql.FieldContainsFold(FieldLdapDn, v)) +} + +// LastSyncAtEQ applies the EQ predicate on the "last_sync_at" field. +func LastSyncAtEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldEQ(FieldLastSyncAt, v)) +} + +// LastSyncAtNEQ applies the NEQ predicate on the "last_sync_at" field. +func LastSyncAtNEQ(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNEQ(FieldLastSyncAt, v)) +} + +// LastSyncAtIn applies the In predicate on the "last_sync_at" field. +func LastSyncAtIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldIn(FieldLastSyncAt, vs...)) +} + +// LastSyncAtNotIn applies the NotIn predicate on the "last_sync_at" field. +func LastSyncAtNotIn(vs ...time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldNotIn(FieldLastSyncAt, vs...)) +} + +// LastSyncAtGT applies the GT predicate on the "last_sync_at" field. +func LastSyncAtGT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGT(FieldLastSyncAt, v)) +} + +// LastSyncAtGTE applies the GTE predicate on the "last_sync_at" field. +func LastSyncAtGTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldGTE(FieldLastSyncAt, v)) +} + +// LastSyncAtLT applies the LT predicate on the "last_sync_at" field. +func LastSyncAtLT(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLT(FieldLastSyncAt, v)) +} + +// LastSyncAtLTE applies the LTE predicate on the "last_sync_at" field. +func LastSyncAtLTE(v time.Time) predicate.LdapUser { + return predicate.LdapUser(sql.FieldLTE(FieldLastSyncAt, v)) +} + +// HasUser applies the HasEdge predicate on the "user" edge. +func HasUser() predicate.LdapUser { + return predicate.LdapUser(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates). +func HasUserWith(preds ...predicate.User) predicate.LdapUser { + return predicate.LdapUser(func(s *sql.Selector) { + step := newUserStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.LdapUser) predicate.LdapUser { + return predicate.LdapUser(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.LdapUser) predicate.LdapUser { + return predicate.LdapUser(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.LdapUser) predicate.LdapUser { + return predicate.LdapUser(sql.NotPredicates(p)) +} diff --git a/backend/ent/ldapuser_create.go b/backend/ent/ldapuser_create.go new file mode 100644 index 000000000..41f526d89 --- /dev/null +++ b/backend/ent/ldapuser_create.go @@ -0,0 +1,766 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/user" +) + +// LdapUserCreate is the builder for creating a LdapUser entity. +type LdapUserCreate struct { + config + mutation *LdapUserMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (_c *LdapUserCreate) SetCreatedAt(v time.Time) *LdapUserCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_c *LdapUserCreate) SetNillableCreatedAt(v *time.Time) *LdapUserCreate { + if v != nil { + _c.SetCreatedAt(*v) + } + return _c +} + +// SetUpdatedAt sets the "updated_at" field. +func (_c *LdapUserCreate) SetUpdatedAt(v time.Time) *LdapUserCreate { + _c.mutation.SetUpdatedAt(v) + return _c +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (_c *LdapUserCreate) SetNillableUpdatedAt(v *time.Time) *LdapUserCreate { + if v != nil { + _c.SetUpdatedAt(*v) + } + return _c +} + +// SetUserID sets the "user_id" field. +func (_c *LdapUserCreate) SetUserID(v int64) *LdapUserCreate { + _c.mutation.SetUserID(v) + return _c +} + +// SetLdapUsername sets the "ldap_username" field. +func (_c *LdapUserCreate) SetLdapUsername(v string) *LdapUserCreate { + _c.mutation.SetLdapUsername(v) + return _c +} + +// SetLdapDn sets the "ldap_dn" field. +func (_c *LdapUserCreate) SetLdapDn(v string) *LdapUserCreate { + _c.mutation.SetLdapDn(v) + return _c +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (_c *LdapUserCreate) SetLastSyncAt(v time.Time) *LdapUserCreate { + _c.mutation.SetLastSyncAt(v) + return _c +} + +// SetNillableLastSyncAt sets the "last_sync_at" field if the given value is not nil. +func (_c *LdapUserCreate) SetNillableLastSyncAt(v *time.Time) *LdapUserCreate { + if v != nil { + _c.SetLastSyncAt(*v) + } + return _c +} + +// SetUser sets the "user" edge to the User entity. +func (_c *LdapUserCreate) SetUser(v *User) *LdapUserCreate { + return _c.SetUserID(v.ID) +} + +// Mutation returns the LdapUserMutation object of the builder. +func (_c *LdapUserCreate) Mutation() *LdapUserMutation { + return _c.mutation +} + +// Save creates the LdapUser in the database. +func (_c *LdapUserCreate) Save(ctx context.Context) (*LdapUser, error) { + _c.defaults() + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *LdapUserCreate) SaveX(ctx context.Context) *LdapUser { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *LdapUserCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *LdapUserCreate) 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 *LdapUserCreate) defaults() { + if _, ok := _c.mutation.CreatedAt(); !ok { + v := ldapuser.DefaultCreatedAt() + _c.mutation.SetCreatedAt(v) + } + if _, ok := _c.mutation.UpdatedAt(); !ok { + v := ldapuser.DefaultUpdatedAt() + _c.mutation.SetUpdatedAt(v) + } + if _, ok := _c.mutation.LastSyncAt(); !ok { + v := ldapuser.DefaultLastSyncAt() + _c.mutation.SetLastSyncAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *LdapUserCreate) check() error { + if _, ok := _c.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "LdapUser.created_at"`)} + } + if _, ok := _c.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "LdapUser.updated_at"`)} + } + if _, ok := _c.mutation.UserID(); !ok { + return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "LdapUser.user_id"`)} + } + if _, ok := _c.mutation.LdapUsername(); !ok { + return &ValidationError{Name: "ldap_username", err: errors.New(`ent: missing required field "LdapUser.ldap_username"`)} + } + if v, ok := _c.mutation.LdapUsername(); ok { + if err := ldapuser.LdapUsernameValidator(v); err != nil { + return &ValidationError{Name: "ldap_username", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_username": %w`, err)} + } + } + if _, ok := _c.mutation.LdapDn(); !ok { + return &ValidationError{Name: "ldap_dn", err: errors.New(`ent: missing required field "LdapUser.ldap_dn"`)} + } + if v, ok := _c.mutation.LdapDn(); ok { + if err := ldapuser.LdapDnValidator(v); err != nil { + return &ValidationError{Name: "ldap_dn", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_dn": %w`, err)} + } + } + if _, ok := _c.mutation.LastSyncAt(); !ok { + return &ValidationError{Name: "last_sync_at", err: errors.New(`ent: missing required field "LdapUser.last_sync_at"`)} + } + if len(_c.mutation.UserIDs()) == 0 { + return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "LdapUser.user"`)} + } + return nil +} + +func (_c *LdapUserCreate) sqlSave(ctx context.Context) (*LdapUser, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *LdapUserCreate) createSpec() (*LdapUser, *sqlgraph.CreateSpec) { + var ( + _node = &LdapUser{config: _c.config} + _spec = sqlgraph.NewCreateSpec(ldapuser.Table, sqlgraph.NewFieldSpec(ldapuser.FieldID, field.TypeInt64)) + ) + _spec.OnConflict = _c.conflict + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(ldapuser.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.UpdatedAt(); ok { + _spec.SetField(ldapuser.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := _c.mutation.LdapUsername(); ok { + _spec.SetField(ldapuser.FieldLdapUsername, field.TypeString, value) + _node.LdapUsername = value + } + if value, ok := _c.mutation.LdapDn(); ok { + _spec.SetField(ldapuser.FieldLdapDn, field.TypeString, value) + _node.LdapDn = value + } + if value, ok := _c.mutation.LastSyncAt(); ok { + _spec.SetField(ldapuser.FieldLastSyncAt, field.TypeTime, value) + _node.LastSyncAt = value + } + if nodes := _c.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: ldapuser.UserTable, + Columns: []string{ldapuser.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.UserID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.LdapUser.Create(). +// SetCreatedAt(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.LdapUserUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (_c *LdapUserCreate) OnConflict(opts ...sql.ConflictOption) *LdapUserUpsertOne { + _c.conflict = opts + return &LdapUserUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *LdapUserCreate) OnConflictColumns(columns ...string) *LdapUserUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &LdapUserUpsertOne{ + create: _c, + } +} + +type ( + // LdapUserUpsertOne is the builder for "upsert"-ing + // one LdapUser node. + LdapUserUpsertOne struct { + create *LdapUserCreate + } + + // LdapUserUpsert is the "OnConflict" setter. + LdapUserUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapUserUpsert) SetUpdatedAt(v time.Time) *LdapUserUpsert { + u.Set(ldapuser.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapUserUpsert) UpdateUpdatedAt() *LdapUserUpsert { + u.SetExcluded(ldapuser.FieldUpdatedAt) + return u +} + +// SetUserID sets the "user_id" field. +func (u *LdapUserUpsert) SetUserID(v int64) *LdapUserUpsert { + u.Set(ldapuser.FieldUserID, v) + return u +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *LdapUserUpsert) UpdateUserID() *LdapUserUpsert { + u.SetExcluded(ldapuser.FieldUserID) + return u +} + +// SetLdapUsername sets the "ldap_username" field. +func (u *LdapUserUpsert) SetLdapUsername(v string) *LdapUserUpsert { + u.Set(ldapuser.FieldLdapUsername, v) + return u +} + +// UpdateLdapUsername sets the "ldap_username" field to the value that was provided on create. +func (u *LdapUserUpsert) UpdateLdapUsername() *LdapUserUpsert { + u.SetExcluded(ldapuser.FieldLdapUsername) + return u +} + +// SetLdapDn sets the "ldap_dn" field. +func (u *LdapUserUpsert) SetLdapDn(v string) *LdapUserUpsert { + u.Set(ldapuser.FieldLdapDn, v) + return u +} + +// UpdateLdapDn sets the "ldap_dn" field to the value that was provided on create. +func (u *LdapUserUpsert) UpdateLdapDn() *LdapUserUpsert { + u.SetExcluded(ldapuser.FieldLdapDn) + return u +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (u *LdapUserUpsert) SetLastSyncAt(v time.Time) *LdapUserUpsert { + u.Set(ldapuser.FieldLastSyncAt, v) + return u +} + +// UpdateLastSyncAt sets the "last_sync_at" field to the value that was provided on create. +func (u *LdapUserUpsert) UpdateLastSyncAt() *LdapUserUpsert { + u.SetExcluded(ldapuser.FieldLastSyncAt) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *LdapUserUpsertOne) UpdateNewValues() *LdapUserUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.CreatedAt(); exists { + s.SetIgnore(ldapuser.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *LdapUserUpsertOne) Ignore() *LdapUserUpsertOne { + 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 *LdapUserUpsertOne) DoNothing() *LdapUserUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the LdapUserCreate.OnConflict +// documentation for more info. +func (u *LdapUserUpsertOne) Update(set func(*LdapUserUpsert)) *LdapUserUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&LdapUserUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapUserUpsertOne) SetUpdatedAt(v time.Time) *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapUserUpsertOne) UpdateUpdatedAt() *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetUserID sets the "user_id" field. +func (u *LdapUserUpsertOne) SetUserID(v int64) *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.SetUserID(v) + }) +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *LdapUserUpsertOne) UpdateUserID() *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateUserID() + }) +} + +// SetLdapUsername sets the "ldap_username" field. +func (u *LdapUserUpsertOne) SetLdapUsername(v string) *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.SetLdapUsername(v) + }) +} + +// UpdateLdapUsername sets the "ldap_username" field to the value that was provided on create. +func (u *LdapUserUpsertOne) UpdateLdapUsername() *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLdapUsername() + }) +} + +// SetLdapDn sets the "ldap_dn" field. +func (u *LdapUserUpsertOne) SetLdapDn(v string) *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.SetLdapDn(v) + }) +} + +// UpdateLdapDn sets the "ldap_dn" field to the value that was provided on create. +func (u *LdapUserUpsertOne) UpdateLdapDn() *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLdapDn() + }) +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (u *LdapUserUpsertOne) SetLastSyncAt(v time.Time) *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.SetLastSyncAt(v) + }) +} + +// UpdateLastSyncAt sets the "last_sync_at" field to the value that was provided on create. +func (u *LdapUserUpsertOne) UpdateLastSyncAt() *LdapUserUpsertOne { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLastSyncAt() + }) +} + +// Exec executes the query. +func (u *LdapUserUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for LdapUserCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *LdapUserUpsertOne) 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 *LdapUserUpsertOne) ID(ctx context.Context) (id int64, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *LdapUserUpsertOne) IDX(ctx context.Context) int64 { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// LdapUserCreateBulk is the builder for creating many LdapUser entities in bulk. +type LdapUserCreateBulk struct { + config + err error + builders []*LdapUserCreate + conflict []sql.ConflictOption +} + +// Save creates the LdapUser entities in the database. +func (_c *LdapUserCreateBulk) Save(ctx context.Context) ([]*LdapUser, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*LdapUser, 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.(*LdapUserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *LdapUserCreateBulk) SaveX(ctx context.Context) []*LdapUser { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *LdapUserCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *LdapUserCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.LdapUser.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.LdapUserUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (_c *LdapUserCreateBulk) OnConflict(opts ...sql.ConflictOption) *LdapUserUpsertBulk { + _c.conflict = opts + return &LdapUserUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *LdapUserCreateBulk) OnConflictColumns(columns ...string) *LdapUserUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &LdapUserUpsertBulk{ + create: _c, + } +} + +// LdapUserUpsertBulk is the builder for "upsert"-ing +// a bulk of LdapUser nodes. +type LdapUserUpsertBulk struct { + create *LdapUserCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *LdapUserUpsertBulk) UpdateNewValues() *LdapUserUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.CreatedAt(); exists { + s.SetIgnore(ldapuser.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.LdapUser.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *LdapUserUpsertBulk) Ignore() *LdapUserUpsertBulk { + 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 *LdapUserUpsertBulk) DoNothing() *LdapUserUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the LdapUserCreateBulk.OnConflict +// documentation for more info. +func (u *LdapUserUpsertBulk) Update(set func(*LdapUserUpsert)) *LdapUserUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&LdapUserUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *LdapUserUpsertBulk) SetUpdatedAt(v time.Time) *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *LdapUserUpsertBulk) UpdateUpdatedAt() *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetUserID sets the "user_id" field. +func (u *LdapUserUpsertBulk) SetUserID(v int64) *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.SetUserID(v) + }) +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *LdapUserUpsertBulk) UpdateUserID() *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateUserID() + }) +} + +// SetLdapUsername sets the "ldap_username" field. +func (u *LdapUserUpsertBulk) SetLdapUsername(v string) *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.SetLdapUsername(v) + }) +} + +// UpdateLdapUsername sets the "ldap_username" field to the value that was provided on create. +func (u *LdapUserUpsertBulk) UpdateLdapUsername() *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLdapUsername() + }) +} + +// SetLdapDn sets the "ldap_dn" field. +func (u *LdapUserUpsertBulk) SetLdapDn(v string) *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.SetLdapDn(v) + }) +} + +// UpdateLdapDn sets the "ldap_dn" field to the value that was provided on create. +func (u *LdapUserUpsertBulk) UpdateLdapDn() *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLdapDn() + }) +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (u *LdapUserUpsertBulk) SetLastSyncAt(v time.Time) *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.SetLastSyncAt(v) + }) +} + +// UpdateLastSyncAt sets the "last_sync_at" field to the value that was provided on create. +func (u *LdapUserUpsertBulk) UpdateLastSyncAt() *LdapUserUpsertBulk { + return u.Update(func(s *LdapUserUpsert) { + s.UpdateLastSyncAt() + }) +} + +// Exec executes the query. +func (u *LdapUserUpsertBulk) 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 LdapUserCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for LdapUserCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *LdapUserUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/backend/ent/ldapuser_delete.go b/backend/ent/ldapuser_delete.go new file mode 100644 index 000000000..3301a616e --- /dev/null +++ b/backend/ent/ldapuser_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/predicate" +) + +// LdapUserDelete is the builder for deleting a LdapUser entity. +type LdapUserDelete struct { + config + hooks []Hook + mutation *LdapUserMutation +} + +// Where appends a list predicates to the LdapUserDelete builder. +func (_d *LdapUserDelete) Where(ps ...predicate.LdapUser) *LdapUserDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *LdapUserDelete) 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 *LdapUserDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *LdapUserDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(ldapuser.Table, sqlgraph.NewFieldSpec(ldapuser.FieldID, field.TypeInt64)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// LdapUserDeleteOne is the builder for deleting a single LdapUser entity. +type LdapUserDeleteOne struct { + _d *LdapUserDelete +} + +// Where appends a list predicates to the LdapUserDelete builder. +func (_d *LdapUserDeleteOne) Where(ps ...predicate.LdapUser) *LdapUserDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *LdapUserDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{ldapuser.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *LdapUserDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/backend/ent/ldapuser_query.go b/backend/ent/ldapuser_query.go new file mode 100644 index 000000000..9cbffa0c6 --- /dev/null +++ b/backend/ent/ldapuser_query.go @@ -0,0 +1,643 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/predicate" + "github.com/Wei-Shaw/sub2api/ent/user" +) + +// LdapUserQuery is the builder for querying LdapUser entities. +type LdapUserQuery struct { + config + ctx *QueryContext + order []ldapuser.OrderOption + inters []Interceptor + predicates []predicate.LdapUser + withUser *UserQuery + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the LdapUserQuery builder. +func (_q *LdapUserQuery) Where(ps ...predicate.LdapUser) *LdapUserQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *LdapUserQuery) Limit(limit int) *LdapUserQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *LdapUserQuery) Offset(offset int) *LdapUserQuery { + _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 *LdapUserQuery) Unique(unique bool) *LdapUserQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *LdapUserQuery) Order(o ...ldapuser.OrderOption) *LdapUserQuery { + _q.order = append(_q.order, o...) + return _q +} + +// QueryUser chains the current query on the "user" edge. +func (_q *LdapUserQuery) QueryUser() *UserQuery { + query := (&UserClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(ldapuser.Table, ldapuser.FieldID, selector), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ldapuser.UserTable, ldapuser.UserColumn), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first LdapUser entity from the query. +// Returns a *NotFoundError when no LdapUser was found. +func (_q *LdapUserQuery) First(ctx context.Context) (*LdapUser, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{ldapuser.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *LdapUserQuery) FirstX(ctx context.Context) *LdapUser { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first LdapUser ID from the query. +// Returns a *NotFoundError when no LdapUser ID was found. +func (_q *LdapUserQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{ldapuser.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *LdapUserQuery) FirstIDX(ctx context.Context) int64 { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single LdapUser entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one LdapUser entity is found. +// Returns a *NotFoundError when no LdapUser entities are found. +func (_q *LdapUserQuery) Only(ctx context.Context) (*LdapUser, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{ldapuser.Label} + default: + return nil, &NotSingularError{ldapuser.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *LdapUserQuery) OnlyX(ctx context.Context) *LdapUser { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only LdapUser ID in the query. +// Returns a *NotSingularError when more than one LdapUser ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *LdapUserQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{ldapuser.Label} + default: + err = &NotSingularError{ldapuser.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *LdapUserQuery) OnlyIDX(ctx context.Context) int64 { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of LdapUsers. +func (_q *LdapUserQuery) All(ctx context.Context) ([]*LdapUser, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*LdapUser, *LdapUserQuery]() + return withInterceptors[[]*LdapUser](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *LdapUserQuery) AllX(ctx context.Context) []*LdapUser { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of LdapUser IDs. +func (_q *LdapUserQuery) IDs(ctx context.Context) (ids []int64, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(ldapuser.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *LdapUserQuery) IDsX(ctx context.Context) []int64 { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *LdapUserQuery) 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[*LdapUserQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *LdapUserQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *LdapUserQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *LdapUserQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the LdapUserQuery 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 *LdapUserQuery) Clone() *LdapUserQuery { + if _q == nil { + return nil + } + return &LdapUserQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]ldapuser.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.LdapUser{}, _q.predicates...), + withUser: _q.withUser.Clone(), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// WithUser tells the query-builder to eager-load the nodes that are connected to +// the "user" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *LdapUserQuery) WithUser(opts ...func(*UserQuery)) *LdapUserQuery { + query := (&UserClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withUser = query + return _q +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.LdapUser.Query(). +// GroupBy(ldapuser.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *LdapUserQuery) GroupBy(field string, fields ...string) *LdapUserGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &LdapUserGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = ldapuser.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.LdapUser.Query(). +// Select(ldapuser.FieldCreatedAt). +// Scan(ctx, &v) +func (_q *LdapUserQuery) Select(fields ...string) *LdapUserSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &LdapUserSelect{LdapUserQuery: _q} + sbuild.label = ldapuser.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a LdapUserSelect configured with the given aggregations. +func (_q *LdapUserQuery) Aggregate(fns ...AggregateFunc) *LdapUserSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *LdapUserQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !ldapuser.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *LdapUserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*LdapUser, error) { + var ( + nodes = []*LdapUser{} + _spec = _q.querySpec() + loadedTypes = [1]bool{ + _q.withUser != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*LdapUser).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &LdapUser{config: _q.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if len(_q.modifiers) > 0 { + _spec.Modifiers = _q.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := _q.withUser; query != nil { + if err := _q.loadUser(ctx, query, nodes, nil, + func(n *LdapUser, e *User) { n.Edges.User = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (_q *LdapUserQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*LdapUser, init func(*LdapUser), assign func(*LdapUser, *User)) error { + ids := make([]int64, 0, len(nodes)) + nodeids := make(map[int64][]*LdapUser) + for i := range nodes { + fk := nodes[i].UserID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(user.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "user_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (_q *LdapUserQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + if len(_q.modifiers) > 0 { + _spec.Modifiers = _q.modifiers + } + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *LdapUserQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(ldapuser.Table, ldapuser.Columns, sqlgraph.NewFieldSpec(ldapuser.FieldID, field.TypeInt64)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, ldapuser.FieldID) + for i := range fields { + if fields[i] != ldapuser.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if _q.withUser != nil { + _spec.Node.AddColumnOnce(ldapuser.FieldUserID) + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *LdapUserQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(ldapuser.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = ldapuser.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, m := range _q.modifiers { + m(selector) + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ForUpdate locks the selected rows against concurrent updates, and prevent them from being +// updated, deleted or "selected ... for update" by other sessions, until the transaction is +// either committed or rolled-back. +func (_q *LdapUserQuery) ForUpdate(opts ...sql.LockOption) *LdapUserQuery { + if _q.driver.Dialect() == dialect.Postgres { + _q.Unique(false) + } + _q.modifiers = append(_q.modifiers, func(s *sql.Selector) { + s.ForUpdate(opts...) + }) + return _q +} + +// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock +// on any rows that are read. Other sessions can read the rows, but cannot modify them +// until your transaction commits. +func (_q *LdapUserQuery) ForShare(opts ...sql.LockOption) *LdapUserQuery { + if _q.driver.Dialect() == dialect.Postgres { + _q.Unique(false) + } + _q.modifiers = append(_q.modifiers, func(s *sql.Selector) { + s.ForShare(opts...) + }) + return _q +} + +// LdapUserGroupBy is the group-by builder for LdapUser entities. +type LdapUserGroupBy struct { + selector + build *LdapUserQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *LdapUserGroupBy) Aggregate(fns ...AggregateFunc) *LdapUserGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *LdapUserGroupBy) 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[*LdapUserQuery, *LdapUserGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *LdapUserGroupBy) sqlScan(ctx context.Context, root *LdapUserQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// LdapUserSelect is the builder for selecting fields of LdapUser entities. +type LdapUserSelect struct { + *LdapUserQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *LdapUserSelect) Aggregate(fns ...AggregateFunc) *LdapUserSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *LdapUserSelect) 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[*LdapUserQuery, *LdapUserSelect](ctx, _s.LdapUserQuery, _s, _s.inters, v) +} + +func (_s *LdapUserSelect) sqlScan(ctx context.Context, root *LdapUserQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/backend/ent/ldapuser_update.go b/backend/ent/ldapuser_update.go new file mode 100644 index 000000000..e8d6d590f --- /dev/null +++ b/backend/ent/ldapuser_update.go @@ -0,0 +1,465 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/predicate" + "github.com/Wei-Shaw/sub2api/ent/user" +) + +// LdapUserUpdate is the builder for updating LdapUser entities. +type LdapUserUpdate struct { + config + hooks []Hook + mutation *LdapUserMutation +} + +// Where appends a list predicates to the LdapUserUpdate builder. +func (_u *LdapUserUpdate) Where(ps ...predicate.LdapUser) *LdapUserUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *LdapUserUpdate) SetUpdatedAt(v time.Time) *LdapUserUpdate { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetUserID sets the "user_id" field. +func (_u *LdapUserUpdate) SetUserID(v int64) *LdapUserUpdate { + _u.mutation.SetUserID(v) + return _u +} + +// SetNillableUserID sets the "user_id" field if the given value is not nil. +func (_u *LdapUserUpdate) SetNillableUserID(v *int64) *LdapUserUpdate { + if v != nil { + _u.SetUserID(*v) + } + return _u +} + +// SetLdapUsername sets the "ldap_username" field. +func (_u *LdapUserUpdate) SetLdapUsername(v string) *LdapUserUpdate { + _u.mutation.SetLdapUsername(v) + return _u +} + +// SetNillableLdapUsername sets the "ldap_username" field if the given value is not nil. +func (_u *LdapUserUpdate) SetNillableLdapUsername(v *string) *LdapUserUpdate { + if v != nil { + _u.SetLdapUsername(*v) + } + return _u +} + +// SetLdapDn sets the "ldap_dn" field. +func (_u *LdapUserUpdate) SetLdapDn(v string) *LdapUserUpdate { + _u.mutation.SetLdapDn(v) + return _u +} + +// SetNillableLdapDn sets the "ldap_dn" field if the given value is not nil. +func (_u *LdapUserUpdate) SetNillableLdapDn(v *string) *LdapUserUpdate { + if v != nil { + _u.SetLdapDn(*v) + } + return _u +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (_u *LdapUserUpdate) SetLastSyncAt(v time.Time) *LdapUserUpdate { + _u.mutation.SetLastSyncAt(v) + return _u +} + +// SetNillableLastSyncAt sets the "last_sync_at" field if the given value is not nil. +func (_u *LdapUserUpdate) SetNillableLastSyncAt(v *time.Time) *LdapUserUpdate { + if v != nil { + _u.SetLastSyncAt(*v) + } + return _u +} + +// SetUser sets the "user" edge to the User entity. +func (_u *LdapUserUpdate) SetUser(v *User) *LdapUserUpdate { + return _u.SetUserID(v.ID) +} + +// Mutation returns the LdapUserMutation object of the builder. +func (_u *LdapUserUpdate) Mutation() *LdapUserMutation { + return _u.mutation +} + +// ClearUser clears the "user" edge to the User entity. +func (_u *LdapUserUpdate) ClearUser() *LdapUserUpdate { + _u.mutation.ClearUser() + return _u +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *LdapUserUpdate) Save(ctx context.Context) (int, error) { + _u.defaults() + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *LdapUserUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *LdapUserUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *LdapUserUpdate) 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 *LdapUserUpdate) defaults() { + if _, ok := _u.mutation.UpdatedAt(); !ok { + v := ldapuser.UpdateDefaultUpdatedAt() + _u.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *LdapUserUpdate) check() error { + if v, ok := _u.mutation.LdapUsername(); ok { + if err := ldapuser.LdapUsernameValidator(v); err != nil { + return &ValidationError{Name: "ldap_username", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_username": %w`, err)} + } + } + if v, ok := _u.mutation.LdapDn(); ok { + if err := ldapuser.LdapDnValidator(v); err != nil { + return &ValidationError{Name: "ldap_dn", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_dn": %w`, err)} + } + } + if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "LdapUser.user"`) + } + return nil +} + +func (_u *LdapUserUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(ldapuser.Table, ldapuser.Columns, sqlgraph.NewFieldSpec(ldapuser.FieldID, field.TypeInt64)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(ldapuser.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.LdapUsername(); ok { + _spec.SetField(ldapuser.FieldLdapUsername, field.TypeString, value) + } + if value, ok := _u.mutation.LdapDn(); ok { + _spec.SetField(ldapuser.FieldLdapDn, field.TypeString, value) + } + if value, ok := _u.mutation.LastSyncAt(); ok { + _spec.SetField(ldapuser.FieldLastSyncAt, field.TypeTime, value) + } + if _u.mutation.UserCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: ldapuser.UserTable, + Columns: []string{ldapuser.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: ldapuser.UserTable, + Columns: []string{ldapuser.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{ldapuser.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// LdapUserUpdateOne is the builder for updating a single LdapUser entity. +type LdapUserUpdateOne struct { + config + fields []string + hooks []Hook + mutation *LdapUserMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *LdapUserUpdateOne) SetUpdatedAt(v time.Time) *LdapUserUpdateOne { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetUserID sets the "user_id" field. +func (_u *LdapUserUpdateOne) SetUserID(v int64) *LdapUserUpdateOne { + _u.mutation.SetUserID(v) + return _u +} + +// SetNillableUserID sets the "user_id" field if the given value is not nil. +func (_u *LdapUserUpdateOne) SetNillableUserID(v *int64) *LdapUserUpdateOne { + if v != nil { + _u.SetUserID(*v) + } + return _u +} + +// SetLdapUsername sets the "ldap_username" field. +func (_u *LdapUserUpdateOne) SetLdapUsername(v string) *LdapUserUpdateOne { + _u.mutation.SetLdapUsername(v) + return _u +} + +// SetNillableLdapUsername sets the "ldap_username" field if the given value is not nil. +func (_u *LdapUserUpdateOne) SetNillableLdapUsername(v *string) *LdapUserUpdateOne { + if v != nil { + _u.SetLdapUsername(*v) + } + return _u +} + +// SetLdapDn sets the "ldap_dn" field. +func (_u *LdapUserUpdateOne) SetLdapDn(v string) *LdapUserUpdateOne { + _u.mutation.SetLdapDn(v) + return _u +} + +// SetNillableLdapDn sets the "ldap_dn" field if the given value is not nil. +func (_u *LdapUserUpdateOne) SetNillableLdapDn(v *string) *LdapUserUpdateOne { + if v != nil { + _u.SetLdapDn(*v) + } + return _u +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (_u *LdapUserUpdateOne) SetLastSyncAt(v time.Time) *LdapUserUpdateOne { + _u.mutation.SetLastSyncAt(v) + return _u +} + +// SetNillableLastSyncAt sets the "last_sync_at" field if the given value is not nil. +func (_u *LdapUserUpdateOne) SetNillableLastSyncAt(v *time.Time) *LdapUserUpdateOne { + if v != nil { + _u.SetLastSyncAt(*v) + } + return _u +} + +// SetUser sets the "user" edge to the User entity. +func (_u *LdapUserUpdateOne) SetUser(v *User) *LdapUserUpdateOne { + return _u.SetUserID(v.ID) +} + +// Mutation returns the LdapUserMutation object of the builder. +func (_u *LdapUserUpdateOne) Mutation() *LdapUserMutation { + return _u.mutation +} + +// ClearUser clears the "user" edge to the User entity. +func (_u *LdapUserUpdateOne) ClearUser() *LdapUserUpdateOne { + _u.mutation.ClearUser() + return _u +} + +// Where appends a list predicates to the LdapUserUpdate builder. +func (_u *LdapUserUpdateOne) Where(ps ...predicate.LdapUser) *LdapUserUpdateOne { + _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 *LdapUserUpdateOne) Select(field string, fields ...string) *LdapUserUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated LdapUser entity. +func (_u *LdapUserUpdateOne) Save(ctx context.Context) (*LdapUser, error) { + _u.defaults() + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *LdapUserUpdateOne) SaveX(ctx context.Context) *LdapUser { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *LdapUserUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *LdapUserUpdateOne) 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 *LdapUserUpdateOne) defaults() { + if _, ok := _u.mutation.UpdatedAt(); !ok { + v := ldapuser.UpdateDefaultUpdatedAt() + _u.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *LdapUserUpdateOne) check() error { + if v, ok := _u.mutation.LdapUsername(); ok { + if err := ldapuser.LdapUsernameValidator(v); err != nil { + return &ValidationError{Name: "ldap_username", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_username": %w`, err)} + } + } + if v, ok := _u.mutation.LdapDn(); ok { + if err := ldapuser.LdapDnValidator(v); err != nil { + return &ValidationError{Name: "ldap_dn", err: fmt.Errorf(`ent: validator failed for field "LdapUser.ldap_dn": %w`, err)} + } + } + if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "LdapUser.user"`) + } + return nil +} + +func (_u *LdapUserUpdateOne) sqlSave(ctx context.Context) (_node *LdapUser, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(ldapuser.Table, ldapuser.Columns, sqlgraph.NewFieldSpec(ldapuser.FieldID, field.TypeInt64)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "LdapUser.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, ldapuser.FieldID) + for _, f := range fields { + if !ldapuser.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != ldapuser.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(ldapuser.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.LdapUsername(); ok { + _spec.SetField(ldapuser.FieldLdapUsername, field.TypeString, value) + } + if value, ok := _u.mutation.LdapDn(); ok { + _spec.SetField(ldapuser.FieldLdapDn, field.TypeString, value) + } + if value, ok := _u.mutation.LastSyncAt(); ok { + _spec.SetField(ldapuser.FieldLastSyncAt, field.TypeTime, value) + } + if _u.mutation.UserCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: ldapuser.UserTable, + Columns: []string{ldapuser.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: ldapuser.UserTable, + Columns: []string{ldapuser.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &LdapUser{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{ldapuser.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/backend/ent/migrate/schema.go b/backend/ent/migrate/schema.go index 769dddce9..ce5438662 100644 --- a/backend/ent/migrate/schema.go +++ b/backend/ent/migrate/schema.go @@ -474,6 +474,70 @@ var ( }, }, } + // LdapConfigsColumns holds the columns for the "ldap_configs" table. + LdapConfigsColumns = []*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: "server_url", Type: field.TypeString, Size: 255}, + {Name: "bind_dn", Type: field.TypeString, Size: 255}, + {Name: "bind_password_encrypted", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}}, + {Name: "base_dn", Type: field.TypeString, Size: 255}, + {Name: "user_filter", Type: field.TypeString, Size: 255, Default: "(uid=%s)"}, + {Name: "enabled", Type: field.TypeBool, Default: false}, + {Name: "tls_enabled", Type: field.TypeBool, Default: false}, + {Name: "tls_skip_verify", Type: field.TypeBool, Default: false}, + {Name: "config_source", Type: field.TypeString, Size: 50, Default: "database"}, + } + // LdapConfigsTable holds the schema information for the "ldap_configs" table. + LdapConfigsTable = &schema.Table{ + Name: "ldap_configs", + Columns: LdapConfigsColumns, + PrimaryKey: []*schema.Column{LdapConfigsColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "ldapconfig_enabled", + Unique: false, + Columns: []*schema.Column{LdapConfigsColumns[8]}, + }, + }, + } + // LdapUsersColumns holds the columns for the "ldap_users" table. + LdapUsersColumns = []*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: "ldap_username", Type: field.TypeString, Unique: true, Size: 255}, + {Name: "ldap_dn", Type: field.TypeString, Size: 500}, + {Name: "last_sync_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}}, + {Name: "user_id", Type: field.TypeInt64}, + } + // LdapUsersTable holds the schema information for the "ldap_users" table. + LdapUsersTable = &schema.Table{ + Name: "ldap_users", + Columns: LdapUsersColumns, + PrimaryKey: []*schema.Column{LdapUsersColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "ldap_users_users_user", + Columns: []*schema.Column{LdapUsersColumns[6]}, + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + Indexes: []*schema.Index{ + { + Name: "ldapuser_user_id", + Unique: false, + Columns: []*schema.Column{LdapUsersColumns[6]}, + }, + { + Name: "ldapuser_ldap_username", + Unique: false, + Columns: []*schema.Column{LdapUsersColumns[3]}, + }, + }, + } // PromoCodesColumns holds the columns for the "promo_codes" table. PromoCodesColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt64, Increment: true}, @@ -1085,6 +1149,8 @@ var ( ErrorPassthroughRulesTable, GroupsTable, IdempotencyRecordsTable, + LdapConfigsTable, + LdapUsersTable, PromoCodesTable, PromoCodeUsagesTable, ProxiesTable, @@ -1133,6 +1199,13 @@ func init() { IdempotencyRecordsTable.Annotation = &entsql.Annotation{ Table: "idempotency_records", } + LdapConfigsTable.Annotation = &entsql.Annotation{ + Table: "ldap_configs", + } + LdapUsersTable.ForeignKeys[0].RefTable = UsersTable + LdapUsersTable.Annotation = &entsql.Annotation{ + Table: "ldap_users", + } PromoCodesTable.Annotation = &entsql.Annotation{ Table: "promo_codes", } diff --git a/backend/ent/mutation.go b/backend/ent/mutation.go index 823cd3894..b8d90e077 100644 --- a/backend/ent/mutation.go +++ b/backend/ent/mutation.go @@ -20,6 +20,8 @@ import ( "github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule" "github.com/Wei-Shaw/sub2api/ent/group" "github.com/Wei-Shaw/sub2api/ent/idempotencyrecord" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" "github.com/Wei-Shaw/sub2api/ent/predicate" "github.com/Wei-Shaw/sub2api/ent/promocode" "github.com/Wei-Shaw/sub2api/ent/promocodeusage" @@ -54,6 +56,8 @@ const ( TypeErrorPassthroughRule = "ErrorPassthroughRule" TypeGroup = "Group" TypeIdempotencyRecord = "IdempotencyRecord" + TypeLdapConfig = "LdapConfig" + TypeLdapUser = "LdapUser" TypePromoCode = "PromoCode" TypePromoCodeUsage = "PromoCodeUsage" TypeProxy = "Proxy" @@ -11524,6 +11528,1525 @@ func (m *IdempotencyRecordMutation) ResetEdge(name string) error { return fmt.Errorf("unknown IdempotencyRecord edge %s", name) } +// LdapConfigMutation represents an operation that mutates the LdapConfig nodes in the graph. +type LdapConfigMutation struct { + config + op Op + typ string + id *int64 + created_at *time.Time + updated_at *time.Time + server_url *string + bind_dn *string + bind_password_encrypted *string + base_dn *string + user_filter *string + enabled *bool + tls_enabled *bool + tls_skip_verify *bool + config_source *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*LdapConfig, error) + predicates []predicate.LdapConfig +} + +var _ ent.Mutation = (*LdapConfigMutation)(nil) + +// ldapconfigOption allows management of the mutation configuration using functional options. +type ldapconfigOption func(*LdapConfigMutation) + +// newLdapConfigMutation creates new mutation for the LdapConfig entity. +func newLdapConfigMutation(c config, op Op, opts ...ldapconfigOption) *LdapConfigMutation { + m := &LdapConfigMutation{ + config: c, + op: op, + typ: TypeLdapConfig, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withLdapConfigID sets the ID field of the mutation. +func withLdapConfigID(id int64) ldapconfigOption { + return func(m *LdapConfigMutation) { + var ( + err error + once sync.Once + value *LdapConfig + ) + m.oldValue = func(ctx context.Context) (*LdapConfig, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().LdapConfig.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withLdapConfig sets the old LdapConfig of the mutation. +func withLdapConfig(node *LdapConfig) ldapconfigOption { + return func(m *LdapConfigMutation) { + m.oldValue = func(context.Context) (*LdapConfig, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m LdapConfigMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m LdapConfigMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *LdapConfigMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *LdapConfigMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().LdapConfig.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *LdapConfigMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *LdapConfigMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *LdapConfigMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *LdapConfigMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *LdapConfigMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *LdapConfigMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetServerURL sets the "server_url" field. +func (m *LdapConfigMutation) SetServerURL(s string) { + m.server_url = &s +} + +// ServerURL returns the value of the "server_url" field in the mutation. +func (m *LdapConfigMutation) ServerURL() (r string, exists bool) { + v := m.server_url + if v == nil { + return + } + return *v, true +} + +// OldServerURL returns the old "server_url" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldServerURL(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldServerURL is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldServerURL requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldServerURL: %w", err) + } + return oldValue.ServerURL, nil +} + +// ResetServerURL resets all changes to the "server_url" field. +func (m *LdapConfigMutation) ResetServerURL() { + m.server_url = nil +} + +// SetBindDn sets the "bind_dn" field. +func (m *LdapConfigMutation) SetBindDn(s string) { + m.bind_dn = &s +} + +// BindDn returns the value of the "bind_dn" field in the mutation. +func (m *LdapConfigMutation) BindDn() (r string, exists bool) { + v := m.bind_dn + if v == nil { + return + } + return *v, true +} + +// OldBindDn returns the old "bind_dn" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldBindDn(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldBindDn is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldBindDn requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldBindDn: %w", err) + } + return oldValue.BindDn, nil +} + +// ResetBindDn resets all changes to the "bind_dn" field. +func (m *LdapConfigMutation) ResetBindDn() { + m.bind_dn = nil +} + +// SetBindPasswordEncrypted sets the "bind_password_encrypted" field. +func (m *LdapConfigMutation) SetBindPasswordEncrypted(s string) { + m.bind_password_encrypted = &s +} + +// BindPasswordEncrypted returns the value of the "bind_password_encrypted" field in the mutation. +func (m *LdapConfigMutation) BindPasswordEncrypted() (r string, exists bool) { + v := m.bind_password_encrypted + if v == nil { + return + } + return *v, true +} + +// OldBindPasswordEncrypted returns the old "bind_password_encrypted" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldBindPasswordEncrypted(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldBindPasswordEncrypted is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldBindPasswordEncrypted requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldBindPasswordEncrypted: %w", err) + } + return oldValue.BindPasswordEncrypted, nil +} + +// ResetBindPasswordEncrypted resets all changes to the "bind_password_encrypted" field. +func (m *LdapConfigMutation) ResetBindPasswordEncrypted() { + m.bind_password_encrypted = nil +} + +// SetBaseDn sets the "base_dn" field. +func (m *LdapConfigMutation) SetBaseDn(s string) { + m.base_dn = &s +} + +// BaseDn returns the value of the "base_dn" field in the mutation. +func (m *LdapConfigMutation) BaseDn() (r string, exists bool) { + v := m.base_dn + if v == nil { + return + } + return *v, true +} + +// OldBaseDn returns the old "base_dn" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldBaseDn(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldBaseDn is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldBaseDn requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldBaseDn: %w", err) + } + return oldValue.BaseDn, nil +} + +// ResetBaseDn resets all changes to the "base_dn" field. +func (m *LdapConfigMutation) ResetBaseDn() { + m.base_dn = nil +} + +// SetUserFilter sets the "user_filter" field. +func (m *LdapConfigMutation) SetUserFilter(s string) { + m.user_filter = &s +} + +// UserFilter returns the value of the "user_filter" field in the mutation. +func (m *LdapConfigMutation) UserFilter() (r string, exists bool) { + v := m.user_filter + if v == nil { + return + } + return *v, true +} + +// OldUserFilter returns the old "user_filter" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldUserFilter(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUserFilter is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUserFilter requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUserFilter: %w", err) + } + return oldValue.UserFilter, nil +} + +// ResetUserFilter resets all changes to the "user_filter" field. +func (m *LdapConfigMutation) ResetUserFilter() { + m.user_filter = nil +} + +// SetEnabled sets the "enabled" field. +func (m *LdapConfigMutation) SetEnabled(b bool) { + m.enabled = &b +} + +// Enabled returns the value of the "enabled" field in the mutation. +func (m *LdapConfigMutation) Enabled() (r bool, exists bool) { + v := m.enabled + if v == nil { + return + } + return *v, true +} + +// OldEnabled returns the old "enabled" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldEnabled(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldEnabled is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldEnabled requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEnabled: %w", err) + } + return oldValue.Enabled, nil +} + +// ResetEnabled resets all changes to the "enabled" field. +func (m *LdapConfigMutation) ResetEnabled() { + m.enabled = nil +} + +// SetTLSEnabled sets the "tls_enabled" field. +func (m *LdapConfigMutation) SetTLSEnabled(b bool) { + m.tls_enabled = &b +} + +// TLSEnabled returns the value of the "tls_enabled" field in the mutation. +func (m *LdapConfigMutation) TLSEnabled() (r bool, exists bool) { + v := m.tls_enabled + if v == nil { + return + } + return *v, true +} + +// OldTLSEnabled returns the old "tls_enabled" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldTLSEnabled(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTLSEnabled is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTLSEnabled requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTLSEnabled: %w", err) + } + return oldValue.TLSEnabled, nil +} + +// ResetTLSEnabled resets all changes to the "tls_enabled" field. +func (m *LdapConfigMutation) ResetTLSEnabled() { + m.tls_enabled = nil +} + +// SetTLSSkipVerify sets the "tls_skip_verify" field. +func (m *LdapConfigMutation) SetTLSSkipVerify(b bool) { + m.tls_skip_verify = &b +} + +// TLSSkipVerify returns the value of the "tls_skip_verify" field in the mutation. +func (m *LdapConfigMutation) TLSSkipVerify() (r bool, exists bool) { + v := m.tls_skip_verify + if v == nil { + return + } + return *v, true +} + +// OldTLSSkipVerify returns the old "tls_skip_verify" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldTLSSkipVerify(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTLSSkipVerify is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTLSSkipVerify requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTLSSkipVerify: %w", err) + } + return oldValue.TLSSkipVerify, nil +} + +// ResetTLSSkipVerify resets all changes to the "tls_skip_verify" field. +func (m *LdapConfigMutation) ResetTLSSkipVerify() { + m.tls_skip_verify = nil +} + +// SetConfigSource sets the "config_source" field. +func (m *LdapConfigMutation) SetConfigSource(s string) { + m.config_source = &s +} + +// ConfigSource returns the value of the "config_source" field in the mutation. +func (m *LdapConfigMutation) ConfigSource() (r string, exists bool) { + v := m.config_source + if v == nil { + return + } + return *v, true +} + +// OldConfigSource returns the old "config_source" field's value of the LdapConfig entity. +// If the LdapConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapConfigMutation) OldConfigSource(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldConfigSource is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldConfigSource requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldConfigSource: %w", err) + } + return oldValue.ConfigSource, nil +} + +// ResetConfigSource resets all changes to the "config_source" field. +func (m *LdapConfigMutation) ResetConfigSource() { + m.config_source = nil +} + +// Where appends a list predicates to the LdapConfigMutation builder. +func (m *LdapConfigMutation) Where(ps ...predicate.LdapConfig) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the LdapConfigMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *LdapConfigMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.LdapConfig, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *LdapConfigMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *LdapConfigMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (LdapConfig). +func (m *LdapConfigMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *LdapConfigMutation) Fields() []string { + fields := make([]string, 0, 11) + if m.created_at != nil { + fields = append(fields, ldapconfig.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, ldapconfig.FieldUpdatedAt) + } + if m.server_url != nil { + fields = append(fields, ldapconfig.FieldServerURL) + } + if m.bind_dn != nil { + fields = append(fields, ldapconfig.FieldBindDn) + } + if m.bind_password_encrypted != nil { + fields = append(fields, ldapconfig.FieldBindPasswordEncrypted) + } + if m.base_dn != nil { + fields = append(fields, ldapconfig.FieldBaseDn) + } + if m.user_filter != nil { + fields = append(fields, ldapconfig.FieldUserFilter) + } + if m.enabled != nil { + fields = append(fields, ldapconfig.FieldEnabled) + } + if m.tls_enabled != nil { + fields = append(fields, ldapconfig.FieldTLSEnabled) + } + if m.tls_skip_verify != nil { + fields = append(fields, ldapconfig.FieldTLSSkipVerify) + } + if m.config_source != nil { + fields = append(fields, ldapconfig.FieldConfigSource) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *LdapConfigMutation) Field(name string) (ent.Value, bool) { + switch name { + case ldapconfig.FieldCreatedAt: + return m.CreatedAt() + case ldapconfig.FieldUpdatedAt: + return m.UpdatedAt() + case ldapconfig.FieldServerURL: + return m.ServerURL() + case ldapconfig.FieldBindDn: + return m.BindDn() + case ldapconfig.FieldBindPasswordEncrypted: + return m.BindPasswordEncrypted() + case ldapconfig.FieldBaseDn: + return m.BaseDn() + case ldapconfig.FieldUserFilter: + return m.UserFilter() + case ldapconfig.FieldEnabled: + return m.Enabled() + case ldapconfig.FieldTLSEnabled: + return m.TLSEnabled() + case ldapconfig.FieldTLSSkipVerify: + return m.TLSSkipVerify() + case ldapconfig.FieldConfigSource: + return m.ConfigSource() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *LdapConfigMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case ldapconfig.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case ldapconfig.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case ldapconfig.FieldServerURL: + return m.OldServerURL(ctx) + case ldapconfig.FieldBindDn: + return m.OldBindDn(ctx) + case ldapconfig.FieldBindPasswordEncrypted: + return m.OldBindPasswordEncrypted(ctx) + case ldapconfig.FieldBaseDn: + return m.OldBaseDn(ctx) + case ldapconfig.FieldUserFilter: + return m.OldUserFilter(ctx) + case ldapconfig.FieldEnabled: + return m.OldEnabled(ctx) + case ldapconfig.FieldTLSEnabled: + return m.OldTLSEnabled(ctx) + case ldapconfig.FieldTLSSkipVerify: + return m.OldTLSSkipVerify(ctx) + case ldapconfig.FieldConfigSource: + return m.OldConfigSource(ctx) + } + return nil, fmt.Errorf("unknown LdapConfig field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *LdapConfigMutation) SetField(name string, value ent.Value) error { + switch name { + case ldapconfig.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case ldapconfig.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case ldapconfig.FieldServerURL: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetServerURL(v) + return nil + case ldapconfig.FieldBindDn: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBindDn(v) + return nil + case ldapconfig.FieldBindPasswordEncrypted: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBindPasswordEncrypted(v) + return nil + case ldapconfig.FieldBaseDn: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBaseDn(v) + return nil + case ldapconfig.FieldUserFilter: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUserFilter(v) + return nil + case ldapconfig.FieldEnabled: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEnabled(v) + return nil + case ldapconfig.FieldTLSEnabled: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTLSEnabled(v) + return nil + case ldapconfig.FieldTLSSkipVerify: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTLSSkipVerify(v) + return nil + case ldapconfig.FieldConfigSource: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetConfigSource(v) + return nil + } + return fmt.Errorf("unknown LdapConfig field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *LdapConfigMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *LdapConfigMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *LdapConfigMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown LdapConfig numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *LdapConfigMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *LdapConfigMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *LdapConfigMutation) ClearField(name string) error { + return fmt.Errorf("unknown LdapConfig nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *LdapConfigMutation) ResetField(name string) error { + switch name { + case ldapconfig.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case ldapconfig.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case ldapconfig.FieldServerURL: + m.ResetServerURL() + return nil + case ldapconfig.FieldBindDn: + m.ResetBindDn() + return nil + case ldapconfig.FieldBindPasswordEncrypted: + m.ResetBindPasswordEncrypted() + return nil + case ldapconfig.FieldBaseDn: + m.ResetBaseDn() + return nil + case ldapconfig.FieldUserFilter: + m.ResetUserFilter() + return nil + case ldapconfig.FieldEnabled: + m.ResetEnabled() + return nil + case ldapconfig.FieldTLSEnabled: + m.ResetTLSEnabled() + return nil + case ldapconfig.FieldTLSSkipVerify: + m.ResetTLSSkipVerify() + return nil + case ldapconfig.FieldConfigSource: + m.ResetConfigSource() + return nil + } + return fmt.Errorf("unknown LdapConfig field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *LdapConfigMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *LdapConfigMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *LdapConfigMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *LdapConfigMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *LdapConfigMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *LdapConfigMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *LdapConfigMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown LdapConfig unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *LdapConfigMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown LdapConfig edge %s", name) +} + +// LdapUserMutation represents an operation that mutates the LdapUser nodes in the graph. +type LdapUserMutation struct { + config + op Op + typ string + id *int64 + created_at *time.Time + updated_at *time.Time + ldap_username *string + ldap_dn *string + last_sync_at *time.Time + clearedFields map[string]struct{} + user *int64 + cleareduser bool + done bool + oldValue func(context.Context) (*LdapUser, error) + predicates []predicate.LdapUser +} + +var _ ent.Mutation = (*LdapUserMutation)(nil) + +// ldapuserOption allows management of the mutation configuration using functional options. +type ldapuserOption func(*LdapUserMutation) + +// newLdapUserMutation creates new mutation for the LdapUser entity. +func newLdapUserMutation(c config, op Op, opts ...ldapuserOption) *LdapUserMutation { + m := &LdapUserMutation{ + config: c, + op: op, + typ: TypeLdapUser, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withLdapUserID sets the ID field of the mutation. +func withLdapUserID(id int64) ldapuserOption { + return func(m *LdapUserMutation) { + var ( + err error + once sync.Once + value *LdapUser + ) + m.oldValue = func(ctx context.Context) (*LdapUser, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().LdapUser.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withLdapUser sets the old LdapUser of the mutation. +func withLdapUser(node *LdapUser) ldapuserOption { + return func(m *LdapUserMutation) { + m.oldValue = func(context.Context) (*LdapUser, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m LdapUserMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m LdapUserMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *LdapUserMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *LdapUserMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().LdapUser.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *LdapUserMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *LdapUserMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *LdapUserMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *LdapUserMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *LdapUserMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *LdapUserMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetUserID sets the "user_id" field. +func (m *LdapUserMutation) SetUserID(i int64) { + m.user = &i +} + +// UserID returns the value of the "user_id" field in the mutation. +func (m *LdapUserMutation) UserID() (r int64, exists bool) { + v := m.user + if v == nil { + return + } + return *v, true +} + +// OldUserID returns the old "user_id" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldUserID(ctx context.Context) (v int64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUserID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUserID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUserID: %w", err) + } + return oldValue.UserID, nil +} + +// ResetUserID resets all changes to the "user_id" field. +func (m *LdapUserMutation) ResetUserID() { + m.user = nil +} + +// SetLdapUsername sets the "ldap_username" field. +func (m *LdapUserMutation) SetLdapUsername(s string) { + m.ldap_username = &s +} + +// LdapUsername returns the value of the "ldap_username" field in the mutation. +func (m *LdapUserMutation) LdapUsername() (r string, exists bool) { + v := m.ldap_username + if v == nil { + return + } + return *v, true +} + +// OldLdapUsername returns the old "ldap_username" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldLdapUsername(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLdapUsername is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLdapUsername requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLdapUsername: %w", err) + } + return oldValue.LdapUsername, nil +} + +// ResetLdapUsername resets all changes to the "ldap_username" field. +func (m *LdapUserMutation) ResetLdapUsername() { + m.ldap_username = nil +} + +// SetLdapDn sets the "ldap_dn" field. +func (m *LdapUserMutation) SetLdapDn(s string) { + m.ldap_dn = &s +} + +// LdapDn returns the value of the "ldap_dn" field in the mutation. +func (m *LdapUserMutation) LdapDn() (r string, exists bool) { + v := m.ldap_dn + if v == nil { + return + } + return *v, true +} + +// OldLdapDn returns the old "ldap_dn" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldLdapDn(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLdapDn is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLdapDn requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLdapDn: %w", err) + } + return oldValue.LdapDn, nil +} + +// ResetLdapDn resets all changes to the "ldap_dn" field. +func (m *LdapUserMutation) ResetLdapDn() { + m.ldap_dn = nil +} + +// SetLastSyncAt sets the "last_sync_at" field. +func (m *LdapUserMutation) SetLastSyncAt(t time.Time) { + m.last_sync_at = &t +} + +// LastSyncAt returns the value of the "last_sync_at" field in the mutation. +func (m *LdapUserMutation) LastSyncAt() (r time.Time, exists bool) { + v := m.last_sync_at + if v == nil { + return + } + return *v, true +} + +// OldLastSyncAt returns the old "last_sync_at" field's value of the LdapUser entity. +// If the LdapUser object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *LdapUserMutation) OldLastSyncAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLastSyncAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLastSyncAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLastSyncAt: %w", err) + } + return oldValue.LastSyncAt, nil +} + +// ResetLastSyncAt resets all changes to the "last_sync_at" field. +func (m *LdapUserMutation) ResetLastSyncAt() { + m.last_sync_at = nil +} + +// ClearUser clears the "user" edge to the User entity. +func (m *LdapUserMutation) ClearUser() { + m.cleareduser = true + m.clearedFields[ldapuser.FieldUserID] = struct{}{} +} + +// UserCleared reports if the "user" edge to the User entity was cleared. +func (m *LdapUserMutation) UserCleared() bool { + return m.cleareduser +} + +// UserIDs returns the "user" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// UserID instead. It exists only for internal usage by the builders. +func (m *LdapUserMutation) UserIDs() (ids []int64) { + if id := m.user; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetUser resets all changes to the "user" edge. +func (m *LdapUserMutation) ResetUser() { + m.user = nil + m.cleareduser = false +} + +// Where appends a list predicates to the LdapUserMutation builder. +func (m *LdapUserMutation) Where(ps ...predicate.LdapUser) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the LdapUserMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *LdapUserMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.LdapUser, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *LdapUserMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *LdapUserMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (LdapUser). +func (m *LdapUserMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *LdapUserMutation) Fields() []string { + fields := make([]string, 0, 6) + if m.created_at != nil { + fields = append(fields, ldapuser.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, ldapuser.FieldUpdatedAt) + } + if m.user != nil { + fields = append(fields, ldapuser.FieldUserID) + } + if m.ldap_username != nil { + fields = append(fields, ldapuser.FieldLdapUsername) + } + if m.ldap_dn != nil { + fields = append(fields, ldapuser.FieldLdapDn) + } + if m.last_sync_at != nil { + fields = append(fields, ldapuser.FieldLastSyncAt) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *LdapUserMutation) Field(name string) (ent.Value, bool) { + switch name { + case ldapuser.FieldCreatedAt: + return m.CreatedAt() + case ldapuser.FieldUpdatedAt: + return m.UpdatedAt() + case ldapuser.FieldUserID: + return m.UserID() + case ldapuser.FieldLdapUsername: + return m.LdapUsername() + case ldapuser.FieldLdapDn: + return m.LdapDn() + case ldapuser.FieldLastSyncAt: + return m.LastSyncAt() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *LdapUserMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case ldapuser.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case ldapuser.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case ldapuser.FieldUserID: + return m.OldUserID(ctx) + case ldapuser.FieldLdapUsername: + return m.OldLdapUsername(ctx) + case ldapuser.FieldLdapDn: + return m.OldLdapDn(ctx) + case ldapuser.FieldLastSyncAt: + return m.OldLastSyncAt(ctx) + } + return nil, fmt.Errorf("unknown LdapUser field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *LdapUserMutation) SetField(name string, value ent.Value) error { + switch name { + case ldapuser.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case ldapuser.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case ldapuser.FieldUserID: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUserID(v) + return nil + case ldapuser.FieldLdapUsername: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLdapUsername(v) + return nil + case ldapuser.FieldLdapDn: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLdapDn(v) + return nil + case ldapuser.FieldLastSyncAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLastSyncAt(v) + return nil + } + return fmt.Errorf("unknown LdapUser field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *LdapUserMutation) AddedFields() []string { + var fields []string + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *LdapUserMutation) AddedField(name string) (ent.Value, bool) { + switch name { + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *LdapUserMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown LdapUser numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *LdapUserMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *LdapUserMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *LdapUserMutation) ClearField(name string) error { + return fmt.Errorf("unknown LdapUser nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *LdapUserMutation) ResetField(name string) error { + switch name { + case ldapuser.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case ldapuser.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case ldapuser.FieldUserID: + m.ResetUserID() + return nil + case ldapuser.FieldLdapUsername: + m.ResetLdapUsername() + return nil + case ldapuser.FieldLdapDn: + m.ResetLdapDn() + return nil + case ldapuser.FieldLastSyncAt: + m.ResetLastSyncAt() + return nil + } + return fmt.Errorf("unknown LdapUser field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *LdapUserMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.user != nil { + edges = append(edges, ldapuser.EdgeUser) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *LdapUserMutation) AddedIDs(name string) []ent.Value { + switch name { + case ldapuser.EdgeUser: + if id := m.user; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *LdapUserMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *LdapUserMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *LdapUserMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.cleareduser { + edges = append(edges, ldapuser.EdgeUser) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *LdapUserMutation) EdgeCleared(name string) bool { + switch name { + case ldapuser.EdgeUser: + return m.cleareduser + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *LdapUserMutation) ClearEdge(name string) error { + switch name { + case ldapuser.EdgeUser: + m.ClearUser() + return nil + } + return fmt.Errorf("unknown LdapUser unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *LdapUserMutation) ResetEdge(name string) error { + switch name { + case ldapuser.EdgeUser: + m.ResetUser() + return nil + } + return fmt.Errorf("unknown LdapUser edge %s", name) +} + // PromoCodeMutation represents an operation that mutates the PromoCode nodes in the graph. type PromoCodeMutation struct { config diff --git a/backend/ent/predicate/predicate.go b/backend/ent/predicate/predicate.go index 89d933fcd..8b746fc5b 100644 --- a/backend/ent/predicate/predicate.go +++ b/backend/ent/predicate/predicate.go @@ -30,6 +30,12 @@ type Group func(*sql.Selector) // IdempotencyRecord is the predicate function for idempotencyrecord builders. type IdempotencyRecord func(*sql.Selector) +// LdapConfig is the predicate function for ldapconfig builders. +type LdapConfig func(*sql.Selector) + +// LdapUser is the predicate function for ldapuser builders. +type LdapUser func(*sql.Selector) + // PromoCode is the predicate function for promocode builders. type PromoCode func(*sql.Selector) diff --git a/backend/ent/runtime/runtime.go b/backend/ent/runtime/runtime.go index 65531aae4..ab5995058 100644 --- a/backend/ent/runtime/runtime.go +++ b/backend/ent/runtime/runtime.go @@ -13,6 +13,8 @@ import ( "github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule" "github.com/Wei-Shaw/sub2api/ent/group" "github.com/Wei-Shaw/sub2api/ent/idempotencyrecord" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" "github.com/Wei-Shaw/sub2api/ent/promocode" "github.com/Wei-Shaw/sub2api/ent/promocodeusage" "github.com/Wei-Shaw/sub2api/ent/proxy" @@ -458,6 +460,158 @@ func init() { idempotencyrecordDescErrorReason := idempotencyrecordFields[6].Descriptor() // idempotencyrecord.ErrorReasonValidator is a validator for the "error_reason" field. It is called by the builders before save. idempotencyrecord.ErrorReasonValidator = idempotencyrecordDescErrorReason.Validators[0].(func(string) error) + ldapconfigMixin := schema.LdapConfig{}.Mixin() + ldapconfigMixinFields0 := ldapconfigMixin[0].Fields() + _ = ldapconfigMixinFields0 + ldapconfigFields := schema.LdapConfig{}.Fields() + _ = ldapconfigFields + // ldapconfigDescCreatedAt is the schema descriptor for created_at field. + ldapconfigDescCreatedAt := ldapconfigMixinFields0[0].Descriptor() + // ldapconfig.DefaultCreatedAt holds the default value on creation for the created_at field. + ldapconfig.DefaultCreatedAt = ldapconfigDescCreatedAt.Default.(func() time.Time) + // ldapconfigDescUpdatedAt is the schema descriptor for updated_at field. + ldapconfigDescUpdatedAt := ldapconfigMixinFields0[1].Descriptor() + // ldapconfig.DefaultUpdatedAt holds the default value on creation for the updated_at field. + ldapconfig.DefaultUpdatedAt = ldapconfigDescUpdatedAt.Default.(func() time.Time) + // ldapconfig.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + ldapconfig.UpdateDefaultUpdatedAt = ldapconfigDescUpdatedAt.UpdateDefault.(func() time.Time) + // ldapconfigDescServerURL is the schema descriptor for server_url field. + ldapconfigDescServerURL := ldapconfigFields[0].Descriptor() + // ldapconfig.ServerURLValidator is a validator for the "server_url" field. It is called by the builders before save. + ldapconfig.ServerURLValidator = func() func(string) error { + validators := ldapconfigDescServerURL.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(server_url string) error { + for _, fn := range fns { + if err := fn(server_url); err != nil { + return err + } + } + return nil + } + }() + // ldapconfigDescBindDn is the schema descriptor for bind_dn field. + ldapconfigDescBindDn := ldapconfigFields[1].Descriptor() + // ldapconfig.BindDnValidator is a validator for the "bind_dn" field. It is called by the builders before save. + ldapconfig.BindDnValidator = func() func(string) error { + validators := ldapconfigDescBindDn.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(bind_dn string) error { + for _, fn := range fns { + if err := fn(bind_dn); err != nil { + return err + } + } + return nil + } + }() + // ldapconfigDescBindPasswordEncrypted is the schema descriptor for bind_password_encrypted field. + ldapconfigDescBindPasswordEncrypted := ldapconfigFields[2].Descriptor() + // ldapconfig.BindPasswordEncryptedValidator is a validator for the "bind_password_encrypted" field. It is called by the builders before save. + ldapconfig.BindPasswordEncryptedValidator = ldapconfigDescBindPasswordEncrypted.Validators[0].(func(string) error) + // ldapconfigDescBaseDn is the schema descriptor for base_dn field. + ldapconfigDescBaseDn := ldapconfigFields[3].Descriptor() + // ldapconfig.BaseDnValidator is a validator for the "base_dn" field. It is called by the builders before save. + ldapconfig.BaseDnValidator = func() func(string) error { + validators := ldapconfigDescBaseDn.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(base_dn string) error { + for _, fn := range fns { + if err := fn(base_dn); err != nil { + return err + } + } + return nil + } + }() + // ldapconfigDescUserFilter is the schema descriptor for user_filter field. + ldapconfigDescUserFilter := ldapconfigFields[4].Descriptor() + // ldapconfig.DefaultUserFilter holds the default value on creation for the user_filter field. + ldapconfig.DefaultUserFilter = ldapconfigDescUserFilter.Default.(string) + // ldapconfig.UserFilterValidator is a validator for the "user_filter" field. It is called by the builders before save. + ldapconfig.UserFilterValidator = ldapconfigDescUserFilter.Validators[0].(func(string) error) + // ldapconfigDescEnabled is the schema descriptor for enabled field. + ldapconfigDescEnabled := ldapconfigFields[5].Descriptor() + // ldapconfig.DefaultEnabled holds the default value on creation for the enabled field. + ldapconfig.DefaultEnabled = ldapconfigDescEnabled.Default.(bool) + // ldapconfigDescTLSEnabled is the schema descriptor for tls_enabled field. + ldapconfigDescTLSEnabled := ldapconfigFields[6].Descriptor() + // ldapconfig.DefaultTLSEnabled holds the default value on creation for the tls_enabled field. + ldapconfig.DefaultTLSEnabled = ldapconfigDescTLSEnabled.Default.(bool) + // ldapconfigDescTLSSkipVerify is the schema descriptor for tls_skip_verify field. + ldapconfigDescTLSSkipVerify := ldapconfigFields[7].Descriptor() + // ldapconfig.DefaultTLSSkipVerify holds the default value on creation for the tls_skip_verify field. + ldapconfig.DefaultTLSSkipVerify = ldapconfigDescTLSSkipVerify.Default.(bool) + // ldapconfigDescConfigSource is the schema descriptor for config_source field. + ldapconfigDescConfigSource := ldapconfigFields[8].Descriptor() + // ldapconfig.DefaultConfigSource holds the default value on creation for the config_source field. + ldapconfig.DefaultConfigSource = ldapconfigDescConfigSource.Default.(string) + // ldapconfig.ConfigSourceValidator is a validator for the "config_source" field. It is called by the builders before save. + ldapconfig.ConfigSourceValidator = ldapconfigDescConfigSource.Validators[0].(func(string) error) + ldapuserMixin := schema.LdapUser{}.Mixin() + ldapuserMixinFields0 := ldapuserMixin[0].Fields() + _ = ldapuserMixinFields0 + ldapuserFields := schema.LdapUser{}.Fields() + _ = ldapuserFields + // ldapuserDescCreatedAt is the schema descriptor for created_at field. + ldapuserDescCreatedAt := ldapuserMixinFields0[0].Descriptor() + // ldapuser.DefaultCreatedAt holds the default value on creation for the created_at field. + ldapuser.DefaultCreatedAt = ldapuserDescCreatedAt.Default.(func() time.Time) + // ldapuserDescUpdatedAt is the schema descriptor for updated_at field. + ldapuserDescUpdatedAt := ldapuserMixinFields0[1].Descriptor() + // ldapuser.DefaultUpdatedAt holds the default value on creation for the updated_at field. + ldapuser.DefaultUpdatedAt = ldapuserDescUpdatedAt.Default.(func() time.Time) + // ldapuser.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + ldapuser.UpdateDefaultUpdatedAt = ldapuserDescUpdatedAt.UpdateDefault.(func() time.Time) + // ldapuserDescLdapUsername is the schema descriptor for ldap_username field. + ldapuserDescLdapUsername := ldapuserFields[1].Descriptor() + // ldapuser.LdapUsernameValidator is a validator for the "ldap_username" field. It is called by the builders before save. + ldapuser.LdapUsernameValidator = func() func(string) error { + validators := ldapuserDescLdapUsername.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(ldap_username string) error { + for _, fn := range fns { + if err := fn(ldap_username); err != nil { + return err + } + } + return nil + } + }() + // ldapuserDescLdapDn is the schema descriptor for ldap_dn field. + ldapuserDescLdapDn := ldapuserFields[2].Descriptor() + // ldapuser.LdapDnValidator is a validator for the "ldap_dn" field. It is called by the builders before save. + ldapuser.LdapDnValidator = func() func(string) error { + validators := ldapuserDescLdapDn.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + } + return func(ldap_dn string) error { + for _, fn := range fns { + if err := fn(ldap_dn); err != nil { + return err + } + } + return nil + } + }() + // ldapuserDescLastSyncAt is the schema descriptor for last_sync_at field. + ldapuserDescLastSyncAt := ldapuserFields[3].Descriptor() + // ldapuser.DefaultLastSyncAt holds the default value on creation for the last_sync_at field. + ldapuser.DefaultLastSyncAt = ldapuserDescLastSyncAt.Default.(func() time.Time) promocodeFields := schema.PromoCode{}.Fields() _ = promocodeFields // promocodeDescCode is the schema descriptor for code field. diff --git a/backend/ent/schema/ldap_config.go b/backend/ent/schema/ldap_config.go new file mode 100644 index 000000000..6179fdfd0 --- /dev/null +++ b/backend/ent/schema/ldap_config.go @@ -0,0 +1,87 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" + "github.com/Wei-Shaw/sub2api/ent/schema/mixins" +) + +// LdapConfig holds the schema definition for the LdapConfig entity. +type LdapConfig struct { + ent.Schema +} + +// Annotations of the LdapConfig. +func (LdapConfig) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "ldap_configs"}, + } +} + +// Mixin of the LdapConfig. +func (LdapConfig) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixins.TimeMixin{}, + } +} + +// Fields of the LdapConfig. +func (LdapConfig) Fields() []ent.Field { + return []ent.Field{ + field.String("server_url"). + MaxLen(255). + NotEmpty(). + Comment("LDAP server URL (e.g., ldap://ldap.example.com:389)"), + + field.String("bind_dn"). + MaxLen(255). + NotEmpty(). + Comment("Bind DN for LDAP authentication"), + + field.String("bind_password_encrypted"). + SchemaType(map[string]string{ + dialect.Postgres: "text", + }). + NotEmpty(). + Sensitive(). + Comment("Encrypted bind password (AES-256-GCM)"), + + field.String("base_dn"). + MaxLen(255). + NotEmpty(). + Comment("Base DN for user search"), + + field.String("user_filter"). + MaxLen(255). + Default("(uid=%s)"). + Comment("LDAP user filter template"), + + field.Bool("enabled"). + Default(false). + Comment("Whether this LDAP config is enabled"), + + field.Bool("tls_enabled"). + Default(false). + Comment("Whether to use LDAP over TLS (ldaps://)"), + + field.Bool("tls_skip_verify"). + Default(false). + Comment("Whether to skip TLS certificate verification"), + + field.String("config_source"). + MaxLen(50). + Default("database"). + Comment("Configuration source: 'env' or 'database'"), + } +} + +// Indexes of the LdapConfig. +func (LdapConfig) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("enabled"), + } +} diff --git a/backend/ent/schema/ldap_user.go b/backend/ent/schema/ldap_user.go new file mode 100644 index 000000000..55befff28 --- /dev/null +++ b/backend/ent/schema/ldap_user.go @@ -0,0 +1,79 @@ +package schema + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" + "github.com/Wei-Shaw/sub2api/ent/schema/mixins" +) + +// LdapUser holds the schema definition for the LdapUser entity. +type LdapUser struct { + ent.Schema +} + +// Annotations of the LdapUser. +func (LdapUser) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "ldap_users"}, + } +} + +// Mixin of the LdapUser. +func (LdapUser) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixins.TimeMixin{}, + } +} + +// Fields of the LdapUser. +func (LdapUser) Fields() []ent.Field { + return []ent.Field{ + field.Int64("user_id"). + Unique(). + Comment("Foreign key to users table"), + + field.String("ldap_username"). + MaxLen(255). + NotEmpty(). + Unique(). + Comment("LDAP username (uid)"), + + field.String("ldap_dn"). + MaxLen(500). + NotEmpty(). + Comment("LDAP Distinguished Name"), + + field.Time("last_sync_at"). + SchemaType(map[string]string{ + dialect.Postgres: "timestamptz", + }). + Default(time.Now). + Comment("Last synchronization time"), + } +} + +// Edges of the LdapUser. +func (LdapUser) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("user", User.Type). + Required(). + Unique(). + Field("user_id"). + Annotations(entsql.OnDelete(entsql.Cascade)), + } +} + +// Indexes of the LdapUser. +func (LdapUser) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("user_id"), + index.Fields("ldap_username"), + } +} diff --git a/backend/ent/tx.go b/backend/ent/tx.go index cd3b2296c..1d7e4adb0 100644 --- a/backend/ent/tx.go +++ b/backend/ent/tx.go @@ -30,6 +30,10 @@ type Tx struct { Group *GroupClient // IdempotencyRecord is the client for interacting with the IdempotencyRecord builders. IdempotencyRecord *IdempotencyRecordClient + // LdapConfig is the client for interacting with the LdapConfig builders. + LdapConfig *LdapConfigClient + // LdapUser is the client for interacting with the LdapUser builders. + LdapUser *LdapUserClient // PromoCode is the client for interacting with the PromoCode builders. PromoCode *PromoCodeClient // PromoCodeUsage is the client for interacting with the PromoCodeUsage builders. @@ -195,6 +199,8 @@ func (tx *Tx) init() { tx.ErrorPassthroughRule = NewErrorPassthroughRuleClient(tx.config) tx.Group = NewGroupClient(tx.config) tx.IdempotencyRecord = NewIdempotencyRecordClient(tx.config) + tx.LdapConfig = NewLdapConfigClient(tx.config) + tx.LdapUser = NewLdapUserClient(tx.config) tx.PromoCode = NewPromoCodeClient(tx.config) tx.PromoCodeUsage = NewPromoCodeUsageClient(tx.config) tx.Proxy = NewProxyClient(tx.config) diff --git a/backend/go.mod b/backend/go.mod index a34c9fff9..ef80cc6a0 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -49,6 +49,7 @@ require ( ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect dario.cat/mergo v1.0.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/andybalholm/brotli v1.2.0 // indirect @@ -99,6 +100,8 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect + github.com/go-ldap/ldap/v3 v3.4.12 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -180,8 +183,6 @@ require ( golang.org/x/text v0.34.0 // indirect golang.org/x/tools v0.41.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.10 // indirect gopkg.in/ini.v1 v1.67.0 // indirect modernc.org/libc v1.67.6 // indirect modernc.org/mathutil v1.7.1 // indirect diff --git a/backend/go.sum b/backend/go.sum index 32e389a76..54f7634c7 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -8,6 +8,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8af github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DouDOU-start/go-sora2api v1.1.0 h1:PxWiukK77StiHxEngOFwT1rKUn9oTAJJTl07wQUXwiU= @@ -148,6 +150,10 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4= +github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= diff --git a/backend/internal/handler/ldap_auth_handler.go b/backend/internal/handler/ldap_auth_handler.go new file mode 100644 index 000000000..8dbff536e --- /dev/null +++ b/backend/internal/handler/ldap_auth_handler.go @@ -0,0 +1,110 @@ +package handler + +import ( + "log/slog" + + "github.com/Wei-Shaw/sub2api/internal/handler/dto" + infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors" + "github.com/Wei-Shaw/sub2api/internal/pkg/ip" + "github.com/Wei-Shaw/sub2api/internal/pkg/response" + "github.com/Wei-Shaw/sub2api/internal/service" + + "github.com/gin-gonic/gin" +) + +// LdapLoginRequest represents the LDAP login request payload +type LdapLoginRequest struct { + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` + TurnstileToken string `json:"turnstile_token"` +} + +// LdapAuthHandler 处理 LDAP 登录请求 +type LdapAuthHandler struct { + ldapService *service.LdapService + authService *service.AuthService + totpService *service.TotpService + settingService *service.SettingService +} + +// NewLdapAuthHandler 创建 LDAP 认证 Handler +func NewLdapAuthHandler( + ldapService *service.LdapService, + authService *service.AuthService, + totpService *service.TotpService, + settingService *service.SettingService, +) *LdapAuthHandler { + return &LdapAuthHandler{ + ldapService: ldapService, + authService: authService, + totpService: totpService, + settingService: settingService, + } +} + +// Login handles LDAP login requests +func (h *LdapAuthHandler) Login(c *gin.Context) { + var req LdapLoginRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.ErrorFrom(c, infraerrors.BadRequest("INVALID_REQUEST", err.Error())) + return + } + + if err := h.authService.VerifyTurnstile(c.Request.Context(), req.TurnstileToken, ip.GetClientIP(c)); err != nil { + response.ErrorFrom(c, err) + return + } + + user, err := h.ldapService.Authenticate(c.Request.Context(), req.Username, req.Password) + if err != nil { + response.ErrorFrom(c, err) + return + } + + if !user.IsActive() { + response.ErrorFrom(c, service.ErrUserNotActive) + return + } + + // Check if TOTP 2FA is enabled for this user + if h.totpService != nil && h.settingService.IsTotpEnabled(c.Request.Context()) && user.TotpEnabled { + // Create a temporary login session for 2FA + tempToken, err := h.totpService.CreateLoginSession(c.Request.Context(), user.ID, user.Email) + if err != nil { + response.ErrorFrom(c, infraerrors.InternalServer("2FA_SESSION_FAILED", "failed to create 2FA session")) + return + } + + response.Success(c, TotpLoginResponse{ + Requires2FA: true, + TempToken: tempToken, + UserEmailMasked: service.MaskEmail(user.Email), + }) + return + } + + tokenPair, err := h.authService.GenerateTokenPair(c.Request.Context(), user, "") + if err != nil { + slog.Error("ldap_generate_token_pair_failed", "error", err, "user_id", user.ID) + accessToken, tokenErr := h.authService.GenerateToken(user) + if tokenErr != nil { + response.ErrorFrom(c, tokenErr) + return + } + + response.Success(c, AuthResponse{ + AccessToken: accessToken, + TokenType: "Bearer", + User: dto.UserFromService(user), + }) + return + } + + response.Success(c, AuthResponse{ + AccessToken: tokenPair.AccessToken, + RefreshToken: tokenPair.RefreshToken, + ExpiresIn: tokenPair.ExpiresIn, + TokenType: "Bearer", + User: dto.UserFromService(user), + }) +} diff --git a/backend/internal/handler/wire.go b/backend/internal/handler/wire.go index 76f5a9796..ca1d29d52 100644 --- a/backend/internal/handler/wire.go +++ b/backend/internal/handler/wire.go @@ -116,6 +116,7 @@ var ProviderSet = wire.NewSet( NewGatewayHandler, NewOpenAIGatewayHandler, NewSoraGatewayHandler, + NewSoraClientHandler, NewTotpHandler, ProvideSettingHandler, diff --git a/backend/internal/plugin/registry.go b/backend/internal/plugin/registry.go new file mode 100644 index 000000000..2280214f9 --- /dev/null +++ b/backend/internal/plugin/registry.go @@ -0,0 +1,40 @@ +// Package plugin 提供插件注册与初始化机制。 +// 插件通过 init() 调用 Register() 注册自身, +// 主程序在 Wire 初始化完成后调用 SetupAll() 一次性初始化所有插件。 +package plugin + +import ( + "github.com/Wei-Shaw/sub2api/ent" + "github.com/Wei-Shaw/sub2api/internal/config" + "github.com/Wei-Shaw/sub2api/internal/service" +) + +// AppContext 插件初始化所需的核心依赖上下文,由 Wire 注入并传递给每个插件的 Setup 方法 +type AppContext struct { + EntClient *ent.Client + Config *config.Config + SettingService *service.SettingService + TotpService *service.TotpService + AuthService *service.AuthService + UserRepo service.UserRepository +} + +// Plugin 定义插件接口,所有插件必须实现此接口 +type Plugin interface { + Setup(ctx *AppContext) +} + +// registeredPlugins 存储所有已注册的插件 +var registeredPlugins []Plugin + +// Register 注册一个插件,通常在插件包的 init() 函数中调用 +func Register(p Plugin) { + registeredPlugins = append(registeredPlugins, p) +} + +// SetupAll 初始化所有已注册的插件,在服务器启动前调用 +func SetupAll(ctx *AppContext) { + for _, p := range registeredPlugins { + p.Setup(ctx) + } +} diff --git a/backend/internal/plugins/ldap/plugin.go b/backend/internal/plugins/ldap/plugin.go new file mode 100644 index 000000000..1382e22ab --- /dev/null +++ b/backend/internal/plugins/ldap/plugin.go @@ -0,0 +1,47 @@ +// Package ldap 提供 LDAP 认证功能的插件实现。 +// 通过 init() 注册到全局插件系统,在 Wire 完成依赖注入后由 plugin.SetupAll() 调用 Setup()。 +// 删除 cmd/server/plugins.go 中的空白导入即可完全禁用此插件,主线代码无需任何改动。 +package ldap + +import ( + "context" + "log" + + "github.com/Wei-Shaw/sub2api/internal/handler" + "github.com/Wei-Shaw/sub2api/internal/plugin" + "github.com/Wei-Shaw/sub2api/internal/repository" + "github.com/Wei-Shaw/sub2api/internal/server/routes" + "github.com/Wei-Shaw/sub2api/internal/service" +) + +func init() { + // 在 main() 执行前通过 init() 注册插件 + plugin.Register(&ldapPlugin{}) +} + +// ldapPlugin 实现 plugin.Plugin 接口 +type ldapPlugin struct{} + +// Setup 在 Wire 依赖注入完成后由主程序调用,初始化 LDAP 相关组件并注册到主线系统 +func (p *ldapPlugin) Setup(ctx *plugin.AppContext) { + // 构建 LDAP 专属仓库(直接使用 EntClient,不进入 Wire 图) + ldapConfigRepo := repository.NewLdapConfigRepository(ctx.EntClient) + ldapUserRepo := repository.NewLdapUserRepository(ctx.EntClient) + + // 构建 LDAP 服务 + ldapSvc := service.NewLdapService(ldapConfigRepo, ldapUserRepo, ctx.UserRepo, ctx.Config) + + // 从环境变量加载 LDAP 配置(替代原来在 provideCleanup 中的逻辑) + bgCtx := context.Background() + if err := ldapSvc.LoadConfigFromEnv(bgCtx); err != nil { + log.Printf("[LDAP] 从环境变量加载配置失败: %v", err) + } else { + log.Println("[LDAP] 已从环境变量加载配置") + } + + // 构建 LDAP 认证 Handler 并注册路由处理器 + ldapHandler := handler.NewLdapAuthHandler(ldapSvc, ctx.AuthService, ctx.TotpService, ctx.SettingService) + routes.RegisterLdapLoginHandler(ldapHandler.Login) + + log.Println("[LDAP] 插件初始化完成") +} diff --git a/backend/internal/repository/ldap_config_repo.go b/backend/internal/repository/ldap_config_repo.go new file mode 100644 index 000000000..8c28a82aa --- /dev/null +++ b/backend/internal/repository/ldap_config_repo.go @@ -0,0 +1,119 @@ +package repository + +import ( + "context" + "fmt" + + "github.com/Wei-Shaw/sub2api/ent" + "github.com/Wei-Shaw/sub2api/ent/ldapconfig" + "github.com/Wei-Shaw/sub2api/internal/service" +) + +type ldapConfigRepository struct { + client *ent.Client +} + +// NewLdapConfigRepository creates a new LDAP config repository. +func NewLdapConfigRepository(client *ent.Client) service.LdapConfigRepository { + return &ldapConfigRepository{client: client} +} + +func (r *ldapConfigRepository) Get(ctx context.Context) (*service.LdapConfig, error) { + client := clientFromContext(ctx, r.client) + m, err := client.LdapConfig. + Query(). + Order(ent.Asc(ldapconfig.FieldID)). + First(ctx) + if err != nil { + return nil, translatePersistenceError(err, service.ErrLdapConfigNotFound, nil) + } + return ldapConfigEntityToService(m), nil +} + +func (r *ldapConfigRepository) GetEnabled(ctx context.Context) (*service.LdapConfig, error) { + client := clientFromContext(ctx, r.client) + m, err := client.LdapConfig. + Query(). + Where(ldapconfig.EnabledEQ(true)). + Order(ent.Asc(ldapconfig.FieldID)). + First(ctx) + if err != nil { + return nil, translatePersistenceError(err, service.ErrLdapConfigNotFound, nil) + } + return ldapConfigEntityToService(m), nil +} + +func (r *ldapConfigRepository) Create(ctx context.Context, config *service.LdapConfig) error { + if config == nil { + return fmt.Errorf("config cannot be nil") + } + client := clientFromContext(ctx, r.client) + created, err := client.LdapConfig. + Create(). + SetServerURL(config.ServerURL). + SetBindDn(config.BindDn). + SetBindPasswordEncrypted(config.BindPasswordEncrypted). + SetBaseDn(config.BaseDn). + SetUserFilter(config.UserFilter). + SetEnabled(config.Enabled). + SetTLSEnabled(config.TLSEnabled). + SetTLSSkipVerify(config.TLSSkipVerify). + SetConfigSource(config.ConfigSource). + Save(ctx) + if err != nil { + return err + } + config.ID = created.ID + config.CreatedAt = created.CreatedAt + config.UpdatedAt = created.UpdatedAt + return nil +} + +func (r *ldapConfigRepository) Update(ctx context.Context, config *service.LdapConfig) error { + if config == nil { + return fmt.Errorf("config cannot be nil") + } + client := clientFromContext(ctx, r.client) + updated, err := client.LdapConfig. + UpdateOneID(config.ID). + SetServerURL(config.ServerURL). + SetBindDn(config.BindDn). + SetBindPasswordEncrypted(config.BindPasswordEncrypted). + SetBaseDn(config.BaseDn). + SetUserFilter(config.UserFilter). + SetEnabled(config.Enabled). + SetTLSEnabled(config.TLSEnabled). + SetTLSSkipVerify(config.TLSSkipVerify). + SetConfigSource(config.ConfigSource). + Save(ctx) + if err != nil { + return err + } + config.UpdatedAt = updated.UpdatedAt + return nil +} + +func (r *ldapConfigRepository) Exists(ctx context.Context) (bool, error) { + client := clientFromContext(ctx, r.client) + return client.LdapConfig.Query().Exist(ctx) +} + +func ldapConfigEntityToService(m *ent.LdapConfig) *service.LdapConfig { + if m == nil { + return nil + } + return &service.LdapConfig{ + ID: m.ID, + ServerURL: m.ServerURL, + BindDn: m.BindDn, + BindPasswordEncrypted: m.BindPasswordEncrypted, + BaseDn: m.BaseDn, + UserFilter: m.UserFilter, + Enabled: m.Enabled, + TLSEnabled: m.TLSEnabled, + TLSSkipVerify: m.TLSSkipVerify, + ConfigSource: m.ConfigSource, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, + } +} diff --git a/backend/internal/repository/ldap_user_repo.go b/backend/internal/repository/ldap_user_repo.go new file mode 100644 index 000000000..5e2c6eff1 --- /dev/null +++ b/backend/internal/repository/ldap_user_repo.go @@ -0,0 +1,131 @@ +package repository + +import ( + "context" + "fmt" + "time" + + "github.com/Wei-Shaw/sub2api/ent" + "github.com/Wei-Shaw/sub2api/ent/ldapuser" + "github.com/Wei-Shaw/sub2api/ent/user" + "github.com/Wei-Shaw/sub2api/internal/service" +) + +type ldapUserRepository struct { + client *ent.Client +} + +// NewLdapUserRepository creates a new LDAP user repository. +func NewLdapUserRepository(client *ent.Client) service.LdapUserRepository { + return &ldapUserRepository{client: client} +} + +func (r *ldapUserRepository) Create(ctx context.Context, ldapUser *service.LdapUser) error { + if ldapUser == nil { + return fmt.Errorf("ldapUser cannot be nil") + } + client := clientFromContext(ctx, r.client) + created, err := client.LdapUser. + Create(). + SetUserID(ldapUser.UserID). + SetLdapUsername(ldapUser.LdapUsername). + SetLdapDn(ldapUser.LdapDn). + SetLastSyncAt(ldapUser.LastSyncAt). + Save(ctx) + if err != nil { + return err + } + ldapUser.ID = created.ID + ldapUser.CreatedAt = created.CreatedAt + ldapUser.UpdatedAt = created.UpdatedAt + return nil +} + +func (r *ldapUserRepository) GetByUsername(ctx context.Context, username string) (*service.LdapUser, error) { + client := clientFromContext(ctx, r.client) + m, err := client.LdapUser. + Query(). + Where(ldapuser.LdapUsernameEQ(username)). + WithUser(). + First(ctx) + if err != nil { + return nil, translatePersistenceError(err, service.ErrLdapUserNotFound, nil) + } + return ldapUserEntityToService(m), nil +} + +func (r *ldapUserRepository) GetByUserID(ctx context.Context, userID int64) (*service.LdapUser, error) { + client := clientFromContext(ctx, r.client) + m, err := client.LdapUser. + Query(). + Where(ldapuser.UserIDEQ(userID)). + First(ctx) + if err != nil { + return nil, translatePersistenceError(err, service.ErrLdapUserNotFound, nil) + } + return ldapUserEntityToService(m), nil +} + +func (r *ldapUserRepository) UpdateLastSync(ctx context.Context, id int64) error { + client := clientFromContext(ctx, r.client) + return client.LdapUser. + UpdateOneID(id). + SetLastSyncAt(time.Now()). + Exec(ctx) +} + +func (r *ldapUserRepository) ExistsByUsername(ctx context.Context, username string) (bool, error) { + client := clientFromContext(ctx, r.client) + return client.LdapUser. + Query(). + Where(ldapuser.LdapUsernameEQ(username)). + Exist(ctx) +} + +// GetByEmailWithUser 通过邮箱查询 LDAP 用户关联(包含关联的用户信息) +func (r *ldapUserRepository) GetByEmailWithUser(ctx context.Context, email string) (*service.LdapUser, error) { + client := clientFromContext(ctx, r.client) + m, err := client.LdapUser. + Query(). + Where(ldapuser.HasUserWith(user.EmailEQ(email))). + WithUser(). + Only(ctx) + if err != nil { + return nil, translatePersistenceError(err, service.ErrLdapUserNotFound, nil) + } + return ldapUserEntityToService(m), nil +} + +// UpdateUsernameAndDN 更新 LDAP 用户名和 DN +func (r *ldapUserRepository) UpdateUsernameAndDN(ctx context.Context, id int64, username, dn string) error { + client := clientFromContext(ctx, r.client) + err := client.LdapUser. + UpdateOneID(id). + SetLdapUsername(username). + SetLdapDn(dn). + SetLastSyncAt(time.Now()). + Exec(ctx) + if err != nil { + return translatePersistenceError(err, nil, nil) + } + return nil +} + +func ldapUserEntityToService(m *ent.LdapUser) *service.LdapUser { + if m == nil { + return nil + } + out := &service.LdapUser{ + ID: m.ID, + UserID: m.UserID, + LdapUsername: m.LdapUsername, + LdapDn: m.LdapDn, + LastSyncAt: m.LastSyncAt, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, + } + if m.Edges.User != nil { + out.User = userEntityToService(m.Edges.User) + } + return out +} diff --git a/backend/internal/repository/ldap_user_repo_integration_test.go b/backend/internal/repository/ldap_user_repo_integration_test.go new file mode 100644 index 000000000..f681753e7 --- /dev/null +++ b/backend/internal/repository/ldap_user_repo_integration_test.go @@ -0,0 +1,126 @@ +//go:build integration + +package repository + +import ( + "context" + "testing" + "time" + + dbent "github.com/Wei-Shaw/sub2api/ent" + "github.com/Wei-Shaw/sub2api/internal/service" + "github.com/stretchr/testify/suite" +) + +type LdapUserRepoSuite struct { + suite.Suite + ctx context.Context + client *dbent.Client + repo *ldapUserRepository + userRepo *userRepository +} + +func (s *LdapUserRepoSuite) SetupTest() { + s.ctx = context.Background() + s.client = testEntClient(s.T()) + s.repo = &ldapUserRepository{client: s.client} + s.userRepo = newUserRepositoryWithSQL(s.client, integrationDB) + + // 清理测试数据 + _, _ = integrationDB.ExecContext(s.ctx, "DELETE FROM ldap_users") + _, _ = integrationDB.ExecContext(s.ctx, "DELETE FROM users") +} + +func TestLdapUserRepoSuite(t *testing.T) { + suite.Run(t, new(LdapUserRepoSuite)) +} + +// mustCreateUser 创建测试用户 +func (s *LdapUserRepoSuite) mustCreateUser(email string) *service.User { + s.T().Helper() + + u := &service.User{ + Email: email, + PasswordHash: "test-password-hash", + Role: service.RoleUser, + Status: service.StatusActive, + Concurrency: 5, + } + + s.Require().NoError(s.userRepo.Create(s.ctx, u), "create user") + return u +} + +// mustCreateLdapUser 创建测试 LDAP 用户 +func (s *LdapUserRepoSuite) mustCreateLdapUser(userID int64, username, dn string) *service.LdapUser { + s.T().Helper() + + ldapUser := &service.LdapUser{ + UserID: userID, + LdapUsername: username, + LdapDn: dn, + LastSyncAt: time.Now(), + } + + s.Require().NoError(s.repo.Create(s.ctx, ldapUser), "create ldap user") + return ldapUser +} + +func (s *LdapUserRepoSuite) TestGetByEmailWithUser() { + // 创建测试用户 + email := "test-ldap@example.com" + user := s.mustCreateUser(email) + + // 创建 LDAP 用户关联 + username := "testuser" + dn := "cn=testuser,ou=users,dc=example,dc=com" + ldapUser := s.mustCreateLdapUser(user.ID, username, dn) + + // 测试通过邮箱查询 + result, err := s.repo.GetByEmailWithUser(s.ctx, email) + s.Require().NoError(err, "GetByEmailWithUser should succeed") + s.Require().NotNil(result, "result should not be nil") + + // 验证 LDAP 用户信息 + s.Equal(ldapUser.ID, result.ID) + s.Equal(ldapUser.UserID, result.UserID) + s.Equal(ldapUser.LdapUsername, result.LdapUsername) + s.Equal(ldapUser.LdapDn, result.LdapDn) + + // 验证关联的用户信息 + s.Require().NotNil(result.User, "user should be loaded") + s.Equal(user.ID, result.User.ID) + s.Equal(user.Email, result.User.Email) +} + +func (s *LdapUserRepoSuite) TestGetByEmailWithUser_NotFound() { + // 测试不存在的邮箱 + result, err := s.repo.GetByEmailWithUser(s.ctx, "nonexistent@example.com") + s.Error(err, "should return error for nonexistent email") + s.Nil(result, "result should be nil") + s.ErrorIs(err, service.ErrLdapUserNotFound, "should return ErrLdapUserNotFound") +} + +func (s *LdapUserRepoSuite) TestUpdateUsernameAndDN() { + // 创建测试用户和 LDAP 用户 + user := s.mustCreateUser("test-update@example.com") + ldapUser := s.mustCreateLdapUser(user.ID, "olduser", "cn=olduser,ou=users,dc=example,dc=com") + + // 更新用户名和 DN + newUsername := "newuser" + newDN := "cn=newuser,ou=users,dc=example,dc=com" + err := s.repo.UpdateUsernameAndDN(s.ctx, ldapUser.ID, newUsername, newDN) + s.Require().NoError(err, "UpdateUsernameAndDN should succeed") + + // 验证更新结果 + updated, err := s.repo.GetByUsername(s.ctx, newUsername) + s.Require().NoError(err, "should find updated user") + s.Equal(ldapUser.ID, updated.ID) + s.Equal(newUsername, updated.LdapUsername) + s.Equal(newDN, updated.LdapDn) + + // 验证旧用户名不存在 + exists, err := s.repo.ExistsByUsername(s.ctx, "olduser") + s.Require().NoError(err) + s.False(exists, "old username should not exist") +} diff --git a/backend/internal/repository/wire.go b/backend/internal/repository/wire.go index 2e35e0a00..f741f7d72 100644 --- a/backend/internal/repository/wire.go +++ b/backend/internal/repository/wire.go @@ -54,6 +54,7 @@ var ProviderSet = wire.NewSet( NewGroupRepository, NewAccountRepository, NewSoraAccountRepository, // Sora 账号扩展表仓储 + NewSoraGenerationRepository, NewProxyRepository, NewRedeemCodeRepository, NewPromoCodeRepository, diff --git a/backend/internal/server/http.go b/backend/internal/server/http.go index a8034e981..9cb54036a 100644 --- a/backend/internal/server/http.go +++ b/backend/internal/server/http.go @@ -6,8 +6,10 @@ import ( "net/http" "time" + "github.com/Wei-Shaw/sub2api/ent" "github.com/Wei-Shaw/sub2api/internal/config" "github.com/Wei-Shaw/sub2api/internal/handler" + "github.com/Wei-Shaw/sub2api/internal/plugin" middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware" "github.com/Wei-Shaw/sub2api/internal/service" @@ -36,6 +38,10 @@ func ProvideRouter( opsService *service.OpsService, settingService *service.SettingService, redisClient *redis.Client, + entClient *ent.Client, + authService *service.AuthService, + totpService *service.TotpService, + userRepo service.UserRepository, ) *gin.Engine { if cfg.Server.Mode == "release" { gin.SetMode(gin.ReleaseMode) @@ -56,6 +62,17 @@ func ProvideRouter( } } + // 初始化插件系统 + pluginCtx := &plugin.AppContext{ + EntClient: entClient, + Config: cfg, + SettingService: settingService, + TotpService: totpService, + AuthService: authService, + UserRepo: userRepo, + } + plugin.SetupAll(pluginCtx) + return SetupRouter(r, handlers, jwtAuth, adminAuth, apiKeyAuth, apiKeyService, subscriptionService, opsService, settingService, cfg, redisClient) } diff --git a/backend/internal/server/routes/auth.go b/backend/internal/server/routes/auth.go index c168820c9..b05a08c46 100644 --- a/backend/internal/server/routes/auth.go +++ b/backend/internal/server/routes/auth.go @@ -31,6 +31,10 @@ func RegisterAuthRoutes( auth.POST("/login", rateLimiter.LimitWithOptions("auth-login", 20, time.Minute, middleware.RateLimitOptions{ FailureMode: middleware.RateLimitFailClose, }), h.Auth.Login) + // LDAP 登录路由(插件懒绑定,未启用时返回 404) + auth.POST("/ldap/login", rateLimiter.LimitWithOptions("auth-ldap-login", 20, time.Minute, middleware.RateLimitOptions{ + FailureMode: middleware.RateLimitFailClose, + }), getLdapLoginHandler()) auth.POST("/login/2fa", rateLimiter.LimitWithOptions("auth-login-2fa", 20, time.Minute, middleware.RateLimitOptions{ FailureMode: middleware.RateLimitFailClose, }), h.Auth.Login2FA) diff --git a/backend/internal/server/routes/ldap_plugin.go b/backend/internal/server/routes/ldap_plugin.go new file mode 100644 index 000000000..f05472fe2 --- /dev/null +++ b/backend/internal/server/routes/ldap_plugin.go @@ -0,0 +1,33 @@ +// ldap_plugin.go 提供 LDAP 登录路由的懒绑定机制。 +// 路由在服务器初始化时注册(指向此处的代理函数), +// LDAP 插件在 Setup() 中调用 RegisterLdapLoginHandler 注册实际处理器。 +// 未注册处理器时,路由返回 404,从而实现插件可选加载。 +package routes + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +// ldapLoginHandler 运行时注册的 LDAP 登录处理器,未注册时为 nil +var ldapLoginHandler gin.HandlerFunc + +// RegisterLdapLoginHandler 供 LDAP 插件在 Setup() 中注册登录处理器 +func RegisterLdapLoginHandler(h gin.HandlerFunc) { + ldapLoginHandler = h +} + +// getLdapLoginHandler 返回已注册的 LDAP 登录处理器, +// 若未注册则返回一个 404 响应处理器(LDAP 未启用) +func getLdapLoginHandler() gin.HandlerFunc { + if ldapLoginHandler == nil { + return func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": "LDAP_NOT_ENABLED", + "message": "LDAP 认证未启用", + }) + } + } + return ldapLoginHandler +} diff --git a/backend/internal/service/ldap.go b/backend/internal/service/ldap.go new file mode 100644 index 000000000..76b2d5de1 --- /dev/null +++ b/backend/internal/service/ldap.go @@ -0,0 +1,670 @@ +package service + +import ( + "context" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/tls" + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "io" + "log/slog" + "net" + "os" + "strings" + "time" + + "github.com/Wei-Shaw/sub2api/ent" + "github.com/Wei-Shaw/sub2api/internal/config" + infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors" + "github.com/go-ldap/ldap/v3" + "golang.org/x/crypto/bcrypt" +) + +var ( + ErrLdapConfigNotFound = infraerrors.InternalServer("LDAP_CONFIG_NOT_FOUND", "ldap configuration not found") + ErrLdapUserNotFound = infraerrors.Unauthorized("LDAP_USER_NOT_FOUND", "invalid ldap credentials") + ErrLdapDisabled = infraerrors.Forbidden("LDAP_DISABLED", "ldap authentication is disabled") + ErrLdapConnectionFailed = infraerrors.ServiceUnavailable("LDAP_CONNECTION_FAILED", "failed to connect to ldap server") + ErrLdapBindFailed = infraerrors.Unauthorized("LDAP_BIND_FAILED", "invalid ldap credentials") + ErrLdapInvalidCredentials = infraerrors.Unauthorized("LDAP_INVALID_CREDENTIALS", "invalid ldap credentials") + ErrLdapEncryptionKeyNotSet = infraerrors.InternalServer("LDAP_ENCRYPTION_KEY_NOT_SET", "ldap encryption key not configured") + ErrLdapInvalidEncryptionKey = infraerrors.InternalServer("LDAP_INVALID_ENCRYPTION_KEY", "invalid ldap encryption key format") + ErrLdapMultipleUsersFound = infraerrors.BadRequest("LDAP_MULTIPLE_USERS_FOUND", "LDAP search returned multiple users. Please contact administrator to fix LDAP filter configuration.") + ErrLdapUserEmailRequired = infraerrors.BadRequest("LDAP_USER_EMAIL_REQUIRED", "LDAP user must have email attribute (mail or userPrincipalName). Please contact administrator.") + ErrConcurrentConflict = errors.New("concurrent conflict detected") +) + +type LdapConfig struct { + ID int64 + ServerURL string + BindDn string + BindPasswordEncrypted string + BaseDn string + UserFilter string + Enabled bool + TLSEnabled bool + TLSSkipVerify bool + ConfigSource string + CreatedAt time.Time + UpdatedAt time.Time +} + +type LdapUser struct { + ID int64 + UserID int64 + LdapUsername string + LdapDn string + LastSyncAt time.Time + CreatedAt time.Time + UpdatedAt time.Time + User *User +} + +type LdapConfigRepository interface { + Get(ctx context.Context) (*LdapConfig, error) + GetEnabled(ctx context.Context) (*LdapConfig, error) + Create(ctx context.Context, config *LdapConfig) error + Update(ctx context.Context, config *LdapConfig) error + Exists(ctx context.Context) (bool, error) +} + +type LdapUserRepository interface { + Create(ctx context.Context, ldapUser *LdapUser) error + GetByUsername(ctx context.Context, username string) (*LdapUser, error) + GetByUserID(ctx context.Context, userID int64) (*LdapUser, error) + UpdateLastSync(ctx context.Context, id int64) error + ExistsByUsername(ctx context.Context, username string) (bool, error) + GetByEmailWithUser(ctx context.Context, email string) (*LdapUser, error) + UpdateUsernameAndDN(ctx context.Context, id int64, username, dn string) error +} + +// LdapService 处理 LDAP 认证操作 +type LdapService struct { + ldapConfigRepo LdapConfigRepository + ldapUserRepo LdapUserRepository + userRepo UserRepository + cfg *config.Config +} + +// NewLdapService 创建新的 LDAP 服务实例 +func NewLdapService( + ldapConfigRepo LdapConfigRepository, + ldapUserRepo LdapUserRepository, + userRepo UserRepository, + cfg *config.Config, +) *LdapService { + return &LdapService{ + ldapConfigRepo: ldapConfigRepo, + ldapUserRepo: ldapUserRepo, + userRepo: userRepo, + cfg: cfg, + } +} + +// getEncryptionKeyBytes 获取并验证加密密钥 +func getEncryptionKeyBytes() ([]byte, error) { + key := os.Getenv("LDAP_ENCRYPTION_KEY") + if key == "" { + return nil, ErrLdapEncryptionKeyNotSet + } + + keyBytes, err := hex.DecodeString(key) + if err != nil || len(keyBytes) != 32 { + return nil, ErrLdapInvalidEncryptionKey + } + + return keyBytes, nil +} + +// encryptPassword 使用 AES-256-GCM 加密密码 +func (s *LdapService) encryptPassword(plaintext string) (string, error) { + keyBytes, err := getEncryptionKeyBytes() + if err != nil { + return "", err + } + + block, err := aes.NewCipher(keyBytes) + if err != nil { + return "", fmt.Errorf("failed to create cipher: %w", err) + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", fmt.Errorf("failed to create GCM: %w", err) + } + + nonce := make([]byte, gcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return "", fmt.Errorf("failed to generate nonce: %w", err) + } + + ciphertext := gcm.Seal(nonce, nonce, []byte(plaintext), nil) + return base64.StdEncoding.EncodeToString(ciphertext), nil +} + +// decryptPassword 使用 AES-256-GCM 解密密码 +func (s *LdapService) decryptPassword(ciphertext string) (string, error) { + keyBytes, err := getEncryptionKeyBytes() + if err != nil { + return "", err + } + + data, err := base64.StdEncoding.DecodeString(ciphertext) + if err != nil { + return "", fmt.Errorf("failed to decode base64: %w", err) + } + + block, err := aes.NewCipher(keyBytes) + if err != nil { + return "", fmt.Errorf("failed to create cipher: %w", err) + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", fmt.Errorf("failed to create GCM: %w", err) + } + + nonceSize := gcm.NonceSize() + if len(data) < nonceSize { + return "", fmt.Errorf("ciphertext too short") + } + + nonce, ciphertextBytes := data[:nonceSize], data[nonceSize:] + plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil) + if err != nil { + return "", fmt.Errorf("failed to decrypt: %w", err) + } + + return string(plaintext), nil +} + +// connectLdap 建立 LDAP 连接(带 3 秒超时) +func (s *LdapService) connectLdap(config *LdapConfig) (*ldap.Conn, error) { + var conn *ldap.Conn + var err error + + // 创建带超时的 dialer(遵循规范要求的 3 秒超时) + dialer := &net.Dialer{Timeout: 3 * time.Second} + + if config.TLSEnabled { + // LDAPS 连接 + tlsConfig := &tls.Config{ + InsecureSkipVerify: config.TLSSkipVerify, + } + conn, err = ldap.DialURL(config.ServerURL, + ldap.DialWithDialer(dialer), + ldap.DialWithTLSConfig(tlsConfig)) + } else { + // 普通 LDAP 连接 + conn, err = ldap.DialURL(config.ServerURL, + ldap.DialWithDialer(dialer)) + } + + if err != nil { + slog.Error("ldap_connection_failed", + "server", maskServerURL(config.ServerURL), + "error", err) + return nil, ErrLdapConnectionFailed + } + + slog.Debug("ldap_connection_established", + "server", maskServerURL(config.ServerURL), + "tls_enabled", config.TLSEnabled) + + return conn, nil +} + +// searchUser 搜索 LDAP 用户并获取 DN 和邮箱 +func (s *LdapService) searchUser( + conn *ldap.Conn, + config *LdapConfig, + username, bindPassword string, +) (string, string, error) { + // 1. 使用 bind DN 进行绑定 + if err := conn.Bind(config.BindDn, bindPassword); err != nil { + slog.Error("ldap_bind_failed", + "bind_dn", maskDN(config.BindDn), + "error", err) + return "", "", ErrLdapBindFailed + } + + // 2. 构造搜索过滤器(转义用户输入防止 LDAP 注入) + safeUsername := ldap.EscapeFilter(username) + filter := fmt.Sprintf(config.UserFilter, safeUsername) + + // 3. 执行搜索 + searchRequest := ldap.NewSearchRequest( + config.BaseDn, + ldap.ScopeWholeSubtree, + ldap.NeverDerefAliases, + 0, + 5, // 5 秒超时 + false, + filter, + []string{"dn", "mail", "userPrincipalName"}, + nil, + ) + + result, err := conn.Search(searchRequest) + if err != nil { + slog.Error("ldap_search_failed", + "filter", filter, + "error", err) + return "", "", ErrLdapUserNotFound + } + + if len(result.Entries) == 0 { + slog.Warn("ldap_user_not_found", "username", username) + return "", "", ErrLdapUserNotFound + } + + if len(result.Entries) > 1 { + slog.Warn("ldap_multiple_users_found", + "username", username, + "count", len(result.Entries), + "filter", filter) + return "", "", ErrLdapMultipleUsersFound + } + + entry := result.Entries[0] + userDN := entry.DN + userEmail := entry.GetAttributeValue("mail") + if userEmail == "" { + userEmail = entry.GetAttributeValue("userPrincipalName") + } + + if userEmail == "" { + slog.Warn("ldap_user_email_required", + "username", username, + "dn", maskDN(userDN)) + return "", "", ErrLdapUserEmailRequired + } + + slog.Debug("ldap_user_found", + "username", username, + "dn", maskDN(userDN), + "email", userEmail) + + return userDN, userEmail, nil +} + +// bindUser 验证用户密码 +func (s *LdapService) bindUser(conn *ldap.Conn, userDN, password string) error { + if err := conn.Bind(userDN, password); err != nil { + slog.Warn("ldap_user_bind_failed", + "dn", maskDN(userDN), + "error", err) + return ErrLdapInvalidCredentials + } + + slog.Info("ldap_authentication_success", "dn", maskDN(userDN)) + return nil +} + +// maskServerURL 掩码服务器 URL 中的敏感信息 +func maskServerURL(url string) string { + if url == "" { + return "" + } + // 保留协议和主机,隐藏端口和路径 + parts := strings.SplitN(url, "://", 2) + if len(parts) != 2 { + return "***" + } + protocol := parts[0] + rest := parts[1] + + // 提取主机部分 + hostParts := strings.SplitN(rest, ":", 2) + host := hostParts[0] + + // 只显示主机的前几个字符 + if len(host) > 10 { + return fmt.Sprintf("%s://%s***", protocol, host[:10]) + } + return fmt.Sprintf("%s://%s***", protocol, host) +} + +// maskDN 掩码 DN 中的敏感信息 +func maskDN(dn string) string { + if dn == "" { + return "" + } + // 只显示 DN 的第一个组件 + parts := strings.SplitN(dn, ",", 2) + if len(parts) > 1 { + return parts[0] + ",***" + } + return dn +} + +// Authenticate 执行 LDAP 认证并返回本地用户 +func (s *LdapService) Authenticate(ctx context.Context, username, password string) (*User, error) { + // 1. 获取 LDAP 配置 + config, err := s.ldapConfigRepo.GetEnabled(ctx) + if err != nil { + if errors.Is(err, ErrLdapConfigNotFound) { + return nil, ErrLdapDisabled + } + return nil, err + } + + // 2. 解密 bind password + bindPassword, err := s.decryptPassword(config.BindPasswordEncrypted) + if err != nil { + slog.Error("ldap_decrypt_password_failed", "error", err) + return nil, ErrLdapConfigNotFound + } + + // 3. 连接 LDAP 服务器 + conn, err := s.connectLdap(config) + if err != nil { + return nil, err + } + defer func() { + if closeErr := conn.Close(); closeErr != nil { + // 记录关闭错误,但不影响主流程 + _ = closeErr + } + }() + + // 4. 搜索用户 DN + userDN, userEmail, err := s.searchUser(conn, config, username, bindPassword) + if err != nil { + return nil, err + } + + // 5. 验证用户密码(Bind) + if err := s.bindUser(conn, userDN, password); err != nil { + return nil, err + } + + // 6. 查找或创建本地用户 + user, err := s.findOrCreateUser(ctx, username, userDN, userEmail) + if err != nil { + return nil, err + } + + return user, nil +} + +// findOrCreateUser 查找或创建本地用户(支持用户名变更和并发冲突重试) +func (s *LdapService) findOrCreateUser( + ctx context.Context, + username, userDN, userEmail string, +) (*User, error) { + return withRetry(ctx, 3, func(ctx context.Context) (*User, error) { + // 1. 尝试通过 LDAP username 查找 + ldapUser, err := s.ldapUserRepo.GetByUsername(ctx, username) + if err == nil { + // 找到关联,返回本地用户 + return ldapUser.User, nil + } + + if !errors.Is(err, ErrLdapUserNotFound) { + return nil, err + } + + // 2. 尝试通过邮箱查找 LDAP 关联(用户名可能变更) + ldapUser, err = s.ldapUserRepo.GetByEmailWithUser(ctx, userEmail) + if err == nil { + // 找到关联,检测用户名变更 + if ldapUser.LdapUsername != username { + // 用户名变更,更新 + slog.Info("ldap_username_changed", + "user_id", ldapUser.UserID, + "old_username", ldapUser.LdapUsername, + "new_username", username, + "email", userEmail) + + // 更新用户名和 DN + err = s.ldapUserRepo.UpdateUsernameAndDN(ctx, ldapUser.ID, username, userDN) + if err != nil { + // 检查是否是唯一约束冲突 + if ent.IsConstraintError(err) { + return nil, ErrConcurrentConflict + } + return nil, err + } + + // 同时更新本地用户的 username + ldapUser.User.Username = username + err = s.userRepo.Update(ctx, ldapUser.User) + if err != nil { + return nil, fmt.Errorf("failed to update user username: %w", err) + } + } + return ldapUser.User, nil + } + + if !errors.Is(err, ErrLdapUserNotFound) { + return nil, err + } + + // 3. 都找不到,尝试通过邮箱查找本地用户 + user, err := s.userRepo.GetByEmail(ctx, userEmail) + if err != nil && !errors.Is(err, ErrUserNotFound) { + return nil, err + } + + // 4. 如果用户不存在,创建新用户 + if user == nil { + user, err = s.createLdapUser(ctx, username, userEmail) + if err != nil { + return nil, err + } + } + + // 5. 创建 LDAP 关联 + ldapUserEntity := &LdapUser{ + UserID: user.ID, + LdapUsername: username, + LdapDn: userDN, + LastSyncAt: time.Now(), + } + + if err := s.ldapUserRepo.Create(ctx, ldapUserEntity); err != nil { + // 检查是否是唯一约束冲突 + if ent.IsConstraintError(err) { + return nil, ErrConcurrentConflict + } + + slog.Error("ldap_user_association_failed", + "user_id", user.ID, + "username", username, + "error", err) + return nil, err + } + + slog.Info("ldap_user_associated", + "user_id", user.ID, + "username", username) + + return user, nil + }) +} + +// createLdapUser 创建 LDAP 用户(遵循 C14) +func (s *LdapService) createLdapUser( + ctx context.Context, + username, email string, +) (*User, error) { + // 1. 生成随机密码(禁止本地密码登录) + randomPassword, err := generateRandomHex(32) + if err != nil { + return nil, err + } + + hashedPassword, err := hashPassword(randomPassword) + if err != nil { + return nil, err + } + + // 2. 获取默认配置 + defaultBalance := s.cfg.Default.UserBalance + defaultConcurrency := s.cfg.Default.UserConcurrency + + // 3. 创建用户 + user := &User{ + Email: email, + PasswordHash: hashedPassword, + Role: "user", + Balance: defaultBalance, + Concurrency: defaultConcurrency, + Status: "active", + Username: username, + } + + if err := s.userRepo.Create(ctx, user); err != nil { + // 处理并发创建冲突(遵循 C14 约束) + if errors.Is(err, ErrEmailExists) { + // 重新加载已存在的用户 + existingUser, getErr := s.userRepo.GetByEmail(ctx, email) + if getErr != nil { + slog.Error("ldap_user_reload_failed", + "username", username, + "email", email, + "error", getErr) + return nil, getErr + } + slog.Info("ldap_user_already_exists", + "user_id", existingUser.ID, + "username", username, + "email", email) + return existingUser, nil + } + // 其他错误正常返回 + slog.Error("ldap_user_creation_failed", + "username", username, + "email", email, + "error", err) + return nil, err + } + + slog.Info("ldap_user_created", + "user_id", user.ID, + "username", username, + "email", email) + + return user, nil +} + +// generateRandomHex 生成随机 hex 字符串 +func generateRandomHex(byteLength int) (string, error) { + b := make([]byte, byteLength) + if _, err := rand.Read(b); err != nil { + return "", err + } + return hex.EncodeToString(b), nil +} + +// hashPassword 使用 bcrypt 哈希密码 +func hashPassword(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", err + } + return string(hash), nil +} + +// LoadConfigFromEnv 从环境变量加载配置 +func (s *LdapService) LoadConfigFromEnv(ctx context.Context) error { + // 检查环境变量是否存在 + serverURL := os.Getenv("LDAP_SERVER_URL") + if serverURL == "" { + return nil // 无环境变量配置 + } + + bindDN := os.Getenv("LDAP_BIND_DN") + bindPassword := os.Getenv("LDAP_BIND_PASSWORD") + baseDN := os.Getenv("LDAP_BASE_DN") + + if bindDN == "" || bindPassword == "" || baseDN == "" { + return fmt.Errorf("incomplete LDAP environment variables") + } + + // 加密密码 + encryptedPassword, err := s.encryptPassword(bindPassword) + if err != nil { + return err + } + + // 构造配置对象 + config := &LdapConfig{ + ServerURL: serverURL, + BindDn: bindDN, + BindPasswordEncrypted: encryptedPassword, + BaseDn: baseDN, + UserFilter: getEnvOrDefault("LDAP_USER_FILTER", "(uid=%s)"), + Enabled: getEnvBool("LDAP_ENABLED", false), + TLSEnabled: getEnvBool("LDAP_TLS_ENABLED", false), + TLSSkipVerify: getEnvBool("LDAP_TLS_SKIP_VERIFY", false), + ConfigSource: "env", + } + + // 检查是否已存在配置 + exists, err := s.ldapConfigRepo.Exists(ctx) + if err != nil { + return err + } + + if exists { + // 更新现有配置 + existingConfig, err := s.ldapConfigRepo.Get(ctx) + if err != nil { + return err + } + config.ID = existingConfig.ID + return s.ldapConfigRepo.Update(ctx, config) + } + + // 创建新配置 + return s.ldapConfigRepo.Create(ctx, config) +} + +// getEnvOrDefault 获取环境变量或返回默认值 +func getEnvOrDefault(key, defaultValue string) string { + if value := os.Getenv(key); value != "" { + return value + } + return defaultValue +} + +// getEnvBool 获取布尔类型的环境变量 +func getEnvBool(key string, defaultValue bool) bool { + value := os.Getenv(key) + if value == "" { + return defaultValue + } + return value == "true" || value == "1" || value == "yes" +} + +// withRetry 重试辅助函数 +func withRetry(ctx context.Context, maxRetries int, fn func(context.Context) (*User, error)) (*User, error) { + retryDelays := []time.Duration{10 * time.Millisecond, 50 * time.Millisecond, 100 * time.Millisecond} + + for attempt := 0; attempt <= maxRetries; attempt++ { + user, err := fn(ctx) + if err == nil { + return user, nil + } + + // 只重试并发冲突错误 + if !errors.Is(err, ErrConcurrentConflict) { + return nil, err + } + + if attempt < maxRetries { + slog.Debug("retrying_after_concurrent_conflict", + "attempt", attempt+1, + "delay_ms", retryDelays[attempt].Milliseconds()) + time.Sleep(retryDelays[attempt]) + } + } + + return nil, ErrConcurrentConflict +} diff --git a/backend/internal/service/ldap_test.go b/backend/internal/service/ldap_test.go new file mode 100644 index 000000000..5c674eab1 --- /dev/null +++ b/backend/internal/service/ldap_test.go @@ -0,0 +1,341 @@ +//go:build unit + +package service + +import ( + "context" + "errors" + "testing" + + "github.com/Wei-Shaw/sub2api/ent" + infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// ldapUserRepoStub 用于测试的 LDAP 用户仓库 stub +type ldapUserRepoStub struct { + getByUsernameFunc func(ctx context.Context, username string) (*LdapUser, error) + getByEmailWithUserFunc func(ctx context.Context, email string) (*LdapUser, error) + updateUsernameAndDNFunc func(ctx context.Context, id int64, username, dn string) error + createFunc func(ctx context.Context, ldapUser *LdapUser) error +} + +func (s *ldapUserRepoStub) Create(ctx context.Context, ldapUser *LdapUser) error { + if s.createFunc != nil { + return s.createFunc(ctx, ldapUser) + } + panic("unexpected Create call") +} + +func (s *ldapUserRepoStub) GetByUsername(ctx context.Context, username string) (*LdapUser, error) { + if s.getByUsernameFunc != nil { + return s.getByUsernameFunc(ctx, username) + } + panic("unexpected GetByUsername call") +} + +func (s *ldapUserRepoStub) GetByUserID(ctx context.Context, userID int64) (*LdapUser, error) { + panic("unexpected GetByUserID call") +} + +func (s *ldapUserRepoStub) UpdateLastSync(ctx context.Context, id int64) error { + panic("unexpected UpdateLastSync call") +} + +func (s *ldapUserRepoStub) ExistsByUsername(ctx context.Context, username string) (bool, error) { + panic("unexpected ExistsByUsername call") +} + +func (s *ldapUserRepoStub) GetByEmailWithUser(ctx context.Context, email string) (*LdapUser, error) { + if s.getByEmailWithUserFunc != nil { + return s.getByEmailWithUserFunc(ctx, email) + } + panic("unexpected GetByEmailWithUser call") +} + +func (s *ldapUserRepoStub) UpdateUsernameAndDN(ctx context.Context, id int64, username, dn string) error { + if s.updateUsernameAndDNFunc != nil { + return s.updateUsernameAndDNFunc(ctx, id, username, dn) + } + panic("unexpected UpdateUsernameAndDN call") +} + +// userRepoStubWithUpdate 扩展 userRepoStub 以支持 Update 方法 +type userRepoStubWithUpdate struct { + *userRepoStub + updateFunc func(ctx context.Context, user *User) error +} + +func (s *userRepoStubWithUpdate) Update(ctx context.Context, user *User) error { + if s.updateFunc != nil { + return s.updateFunc(ctx, user) + } + panic("unexpected Update call") +} + +// userRepoStubWithGetByEmail 扩展 userRepoStub 以支持 GetByEmail 方法 +type userRepoStubWithGetByEmail struct { + *userRepoStub + getByEmailFunc func(ctx context.Context, email string) (*User, error) +} + +func (s *userRepoStubWithGetByEmail) GetByEmail(ctx context.Context, email string) (*User, error) { + if s.getByEmailFunc != nil { + return s.getByEmailFunc(ctx, email) + } + panic("unexpected GetByEmail call") +} + + +// TestLdapErrorDefinitions 测试 LDAP 错误定义 +func TestLdapErrorDefinitions(t *testing.T) { + tests := []struct { + name string + err error + expectedCode string + expectedStatus int + expectedMsg string + }{ + { + name: "ErrLdapMultipleUsersFound", + err: ErrLdapMultipleUsersFound, + expectedCode: "LDAP_MULTIPLE_USERS_FOUND", + expectedStatus: 400, + expectedMsg: "LDAP search returned multiple users. Please contact administrator to fix LDAP filter configuration.", + }, + { + name: "ErrLdapUserEmailRequired", + err: ErrLdapUserEmailRequired, + expectedCode: "LDAP_USER_EMAIL_REQUIRED", + expectedStatus: 400, + expectedMsg: "LDAP user must have email attribute (mail or userPrincipalName). Please contact administrator.", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // 验证错误类型 + appErr, ok := tt.err.(*infraerrors.ApplicationError) + assert.True(t, ok, "错误应该是 ApplicationError 类型") + + // 验证错误原因码 + assert.Equal(t, tt.expectedCode, appErr.Reason, "错误原因码应该匹配") + + // 验证 HTTP 状态码 + assert.Equal(t, int32(tt.expectedStatus), appErr.Code, "HTTP 状态码应该是 400") + + // 验证错误消息 + assert.Equal(t, tt.expectedMsg, appErr.Message, "错误消息应该匹配") + }) + } +} + +// TestWithRetry 测试重试逻辑 +func TestWithRetry(t *testing.T) { + ctx := context.Background() + + t.Run("成功无需重试", func(t *testing.T) { + callCount := 0 + fn := func(ctx context.Context) (*User, error) { + callCount++ + return &User{ID: 1, Email: "test@example.com"}, nil + } + + user, err := withRetry(ctx, 3, fn) + require.NoError(t, err) + require.NotNil(t, user) + assert.Equal(t, int64(1), user.ID) + assert.Equal(t, 1, callCount, "应该只调用一次") + }) + + t.Run("并发冲突后重试成功", func(t *testing.T) { + callCount := 0 + fn := func(ctx context.Context) (*User, error) { + callCount++ + if callCount < 3 { + return nil, ErrConcurrentConflict + } + return &User{ID: 2, Email: "test2@example.com"}, nil + } + + user, err := withRetry(ctx, 3, fn) + require.NoError(t, err) + require.NotNil(t, user) + assert.Equal(t, int64(2), user.ID) + assert.Equal(t, 3, callCount, "应该重试2次后成功") + }) + + t.Run("达到最大重试次数", func(t *testing.T) { + callCount := 0 + fn := func(ctx context.Context) (*User, error) { + callCount++ + return nil, ErrConcurrentConflict + } + + user, err := withRetry(ctx, 3, fn) + require.Error(t, err) + assert.Nil(t, user) + assert.ErrorIs(t, err, ErrConcurrentConflict) + assert.Equal(t, 4, callCount, "应该调用4次(初始1次+重试3次)") + }) + + t.Run("非并发冲突错误不重试", func(t *testing.T) { + callCount := 0 + otherErr := errors.New("其他错误") + fn := func(ctx context.Context) (*User, error) { + callCount++ + return nil, otherErr + } + + user, err := withRetry(ctx, 3, fn) + require.Error(t, err) + assert.Nil(t, user) + assert.ErrorIs(t, err, otherErr) + assert.Equal(t, 1, callCount, "不应该重试") + }) +} + +// TestFindOrCreateUser_UsernameChange 测试用户名变更场景 +func TestFindOrCreateUser_UsernameChange(t *testing.T) { + ctx := context.Background() + + t.Run("检测到用户名变更并更新", func(t *testing.T) { + // 准备测试数据 + oldUsername := "olduser" + newUsername := "newuser" + userEmail := "user@example.com" + userDN := "cn=newuser,ou=users,dc=example,dc=com" + + existingUser := &User{ + ID: 1, + Email: userEmail, + } + + existingLdapUser := &LdapUser{ + ID: 10, + UserID: 1, + LdapUsername: oldUsername, + LdapDn: "cn=olduser,ou=users,dc=example,dc=com", + User: existingUser, + } + + // Mock repositories + ldapUserRepo := &ldapUserRepoStub{ + getByUsernameFunc: func(ctx context.Context, username string) (*LdapUser, error) { + // 第一次查询新用户名,找不到 + if username == newUsername { + return nil, ErrLdapUserNotFound + } + panic("unexpected username: " + username) + }, + getByEmailWithUserFunc: func(ctx context.Context, email string) (*LdapUser, error) { + // 通过邮箱找到旧的 LDAP 关联 + if email == userEmail { + return existingLdapUser, nil + } + panic("unexpected email: " + email) + }, + updateUsernameAndDNFunc: func(ctx context.Context, id int64, username, dn string) error { + // 验证更新参数 + assert.Equal(t, existingLdapUser.ID, id) + assert.Equal(t, newUsername, username) + assert.Equal(t, userDN, dn) + return nil + }, + } + + // 创建支持 Update 的 userRepo stub + userRepo := &userRepoStubWithUpdate{ + userRepoStub: &userRepoStub{}, + updateFunc: func(ctx context.Context, user *User) error { + // 验证更新的用户 + assert.Equal(t, existingUser.ID, user.ID) + assert.Equal(t, newUsername, user.Username) + return nil + }, + } + + // 创建 service + service := &LdapService{ + ldapUserRepo: ldapUserRepo, + userRepo: userRepo, + } + + // 执行测试 + user, err := service.findOrCreateUser(ctx, newUsername, userDN, userEmail) + + // 验证结果 + require.NoError(t, err) + require.NotNil(t, user) + assert.Equal(t, existingUser.ID, user.ID) + assert.Equal(t, existingUser.Email, user.Email) + }) +} + +// TestFindOrCreateUser_ConcurrentConflict 测试并发冲突和重试 +func TestFindOrCreateUser_ConcurrentConflict(t *testing.T) { + ctx := context.Background() + + t.Run("创建LDAP关联时遇到并发冲突后重试成功", func(t *testing.T) { + // 准备测试数据 + username := "testuser" + userEmail := "test@example.com" + userDN := "cn=testuser,ou=users,dc=example,dc=com" + + existingUser := &User{ + ID: 1, + Email: userEmail, + } + + createCallCount := 0 + + // Mock repositories + ldapUserRepo := &ldapUserRepoStub{ + getByUsernameFunc: func(ctx context.Context, username string) (*LdapUser, error) { + // 第一次查询找不到 + return nil, ErrLdapUserNotFound + }, + getByEmailWithUserFunc: func(ctx context.Context, email string) (*LdapUser, error) { + // 通过邮箱也找不到 + return nil, ErrLdapUserNotFound + }, + createFunc: func(ctx context.Context, ldapUser *LdapUser) error { + createCallCount++ + if createCallCount == 1 { + // 第一次创建遇到唯一约束冲突,返回 ent.ConstraintError + return &ent.ConstraintError{} + } + // 第二次创建成功 + ldapUser.ID = 10 + return nil + }, + } + + // 创建本地的 userRepo stub,支持 GetByEmail + userRepo := &userRepoStubWithGetByEmail{ + userRepoStub: &userRepoStub{ + user: existingUser, + }, + getByEmailFunc: func(ctx context.Context, email string) (*User, error) { + // 返回已存在的用户 + return existingUser, nil + }, + } + + // 创建 service + service := &LdapService{ + ldapUserRepo: ldapUserRepo, + userRepo: userRepo, + } + + // 执行测试 + user, err := service.findOrCreateUser(ctx, username, userDN, userEmail) + + // 验证结果 + require.NoError(t, err) + require.NotNil(t, user) + assert.Equal(t, existingUser.ID, user.ID) + assert.Equal(t, 2, createCallCount, "应该重试一次后成功") + }) +} diff --git a/backend/internal/service/wire.go b/backend/internal/service/wire.go index c71851901..e8be44986 100644 --- a/backend/internal/service/wire.go +++ b/backend/internal/service/wire.go @@ -321,6 +321,9 @@ var ProviderSet = wire.NewSet( NewAdminService, NewGatewayService, ProvideSoraMediaStorage, + NewSoraS3Storage, + NewSoraGenerationService, + NewSoraQuotaService, ProvideSoraMediaCleanupService, ProvideSoraSDKClient, wire.Bind(new(SoraClient), new(*SoraSDKClient)), diff --git a/backend/migrations/064_add_ldap_tables.sql b/backend/migrations/064_add_ldap_tables.sql new file mode 100644 index 000000000..43f6ad00d --- /dev/null +++ b/backend/migrations/064_add_ldap_tables.sql @@ -0,0 +1,50 @@ +-- 添加 LDAP 配置表 +CREATE TABLE IF NOT EXISTS ldap_configs ( + id BIGSERIAL PRIMARY KEY, + server_url VARCHAR(255) NOT NULL, + bind_dn VARCHAR(255) NOT NULL, + bind_password_encrypted TEXT NOT NULL, + base_dn VARCHAR(255) NOT NULL, + user_filter VARCHAR(255) NOT NULL DEFAULT '(uid=%s)', + enabled BOOLEAN NOT NULL DEFAULT FALSE, + tls_enabled BOOLEAN NOT NULL DEFAULT FALSE, + tls_skip_verify BOOLEAN NOT NULL DEFAULT FALSE, + config_source VARCHAR(50) NOT NULL DEFAULT 'database', + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- 添加 LDAP 用户表 +CREATE TABLE IF NOT EXISTS ldap_users ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL UNIQUE, + ldap_username VARCHAR(255) NOT NULL UNIQUE, + ldap_dn VARCHAR(500) NOT NULL, + last_sync_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); + +-- 创建索引 +CREATE INDEX IF NOT EXISTS idx_ldap_configs_enabled ON ldap_configs(enabled); +CREATE INDEX IF NOT EXISTS idx_ldap_users_user_id ON ldap_users(user_id); +CREATE INDEX IF NOT EXISTS idx_ldap_users_ldap_username ON ldap_users(ldap_username); + +-- 添加注释 +COMMENT ON TABLE ldap_configs IS 'LDAP 服务器配置表'; +COMMENT ON COLUMN ldap_configs.server_url IS 'LDAP 服务器 URL (例如: ldap://ldap.example.com:389)'; +COMMENT ON COLUMN ldap_configs.bind_dn IS 'LDAP 绑定 DN'; +COMMENT ON COLUMN ldap_configs.bind_password_encrypted IS '加密的绑定密码 (AES-256-GCM)'; +COMMENT ON COLUMN ldap_configs.base_dn IS '用户搜索基础 DN'; +COMMENT ON COLUMN ldap_configs.user_filter IS 'LDAP 用户过滤器模板'; +COMMENT ON COLUMN ldap_configs.enabled IS '是否启用此 LDAP 配置'; +COMMENT ON COLUMN ldap_configs.tls_enabled IS '是否使用 LDAP over TLS (ldaps://)'; +COMMENT ON COLUMN ldap_configs.tls_skip_verify IS '是否跳过 TLS 证书验证'; +COMMENT ON COLUMN ldap_configs.config_source IS '配置来源: env 或 database'; + +COMMENT ON TABLE ldap_users IS 'LDAP 用户映射表'; +COMMENT ON COLUMN ldap_users.user_id IS '关联的用户 ID (外键到 users 表)'; +COMMENT ON COLUMN ldap_users.ldap_username IS 'LDAP 用户名 (uid)'; +COMMENT ON COLUMN ldap_users.ldap_dn IS 'LDAP 可分辨名称'; +COMMENT ON COLUMN ldap_users.last_sync_at IS '最后同步时间'; diff --git a/deploy/docker-compose-test.yml b/deploy/docker-compose-test.yml index 4c7ec1441..95208bc92 100644 --- a/deploy/docker-compose-test.yml +++ b/deploy/docker-compose-test.yml @@ -114,6 +114,43 @@ services: # ======================================================================= # Allow private IP addresses for CRS sync (for internal deployments) - SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=${SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS:-true} + # LDAP Authentication Configuration (LDAP 认证配置) + # Enable LDAP authentication for enterprise users +# # 为企业用户启用 LDAP 认证 +# - LDAP_ENABLED=true +# # LDAP server hostname or IP address +# # LDAP 服务器主机名或 IP 地址 +# - LDAP_HOST=10.5.0.4 +# # LDAP server port +# # LDAP 服务器端口 +# # Standard ports: 389 (LDAP), 636 (LDAPS) +# - LDAP_PORT=389 +# # - LDAP_USE_TLS: Use LDAPS (LDAP over SSL/TLS, usually port 636) +# # - LDAP_USE_START_TLS: Use StartTLS to upgrade connection (usually port 389) +# - LDAP_USE_TLS=false +# - LDAP_USE_START_TLS=false +# - LDAP_SKIP_TLS_VERIFY=false +# - LDAP_BIND_DN=cn=root,dc=newlink,dc=com +# - LDAP_BIND_PASSWORD=rEJndg8oj5NmUszAnyKD1qOmMW5nkHf5jlG1PZ68 +# - LDAP_BASE_DN=ou=People,dc=newlink,dc=com +# - LDAP_USER_FILTER=(&(objectClass=inetOrgPerson)(uid=%s)) +# # Map LDAP attributes to application fields +# - LDAP_ATTRIBUTES_USERNAME=uid +# - LDAP_ATTRIBUTES_EMAIL=mail +# - LDAP_ATTRIBUTES_DISPLAY_NAME=cn + # LDAP 认证配置 + - LDAP_ENABLED=true + # 注意:必须是完整的 URL 格式(ldap://host:port 或 ldaps://host:port) + - LDAP_SERVER_URL=ldap://10.5.0.4:389 + - LDAP_BIND_DN=cn=root,dc=newlink,dc=com + - LDAP_BIND_PASSWORD=rEJndg8oj5NmUszAnyKD1qOmMW5nkHf5jlG1PZ68 + - LDAP_BASE_DN=ou=People,dc=newlink,dc=com + - LDAP_USER_FILTER=(&(objectClass=inetOrgPerson)(uid=%s)) + # TLS 配置(可选) + - LDAP_TLS_ENABLED=false + - LDAP_TLS_SKIP_VERIFY=false + # 加密密钥(必需!32字节的十六进制字符串,64个字符) + - LDAP_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef depends_on: postgres: condition: service_healthy @@ -139,13 +176,13 @@ services: nofile: soft: 100000 hard: 100000 - volumes: - - postgres_data:/var/lib/postgresql/data + # volumes: + # - postgres_data:/var/lib/postgresql/data environment: # postgres:18-alpine 默认 PGDATA=/var/lib/postgresql/18/docker(位于镜像声明的匿名卷 /var/lib/postgresql 内)。 # 若不显式设置 PGDATA,则即使挂载了 postgres_data 到 /var/lib/postgresql/data,数据也不会落盘到该命名卷, # docker compose down/up 后会触发 initdb 重新初始化,导致用户/密码等数据丢失。 - - PGDATA=/var/lib/postgresql/data + # - PGDATA=/var/lib/postgresql/data - POSTGRES_USER=${POSTGRES_USER:-sub2api} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - POSTGRES_DB=${POSTGRES_DB:-sub2api} diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 68ace8857..225d809d0 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -4,6 +4,7 @@ import App from './App.vue' import router from './router' import i18n, { initI18n } from './i18n' import { useAppStore } from '@/stores/app' +import ldapPlugin from '@/plugins/ldap' import './style.css' function initThemeClass() { @@ -37,6 +38,10 @@ async function bootstrap() { app.use(router) app.use(i18n) + // LDAP插件必须在router.use之后、router.isReady之前注册 + // 这样才能正确访问router实例并动态添加路由 + app.use(ldapPlugin) + // 等待路由器完成初始导航后再挂载,避免竞态条件导致的空白渲染 await router.isReady() app.mount('#app') diff --git a/frontend/src/plugins/ldap/api.ts b/frontend/src/plugins/ldap/api.ts new file mode 100644 index 000000000..032db7106 --- /dev/null +++ b/frontend/src/plugins/ldap/api.ts @@ -0,0 +1,24 @@ +/** + * LDAP 认证 API — 独立于主线 authAPI,避免污染主线模块。 + * 前端 API 路径 /auth/ldap/login 不变。 + */ + +import { apiClient } from '@/api/client' +import type { LoginResponse } from '@/api/auth' + +/** LDAP 登录请求 */ +export interface LdapLoginRequest { + username: string + password: string + turnstile_token?: string +} + +/** + * LDAP 登录 + * @param credentials - LDAP 用户名和密码 + * @returns 登录响应(可能是完整认证或需要 2FA) + */ +export async function loginLdap(credentials: LdapLoginRequest): Promise { + const { data } = await apiClient.post('/auth/ldap/login', credentials) + return data +} diff --git a/frontend/src/plugins/ldap/index.ts b/frontend/src/plugins/ldap/index.ts new file mode 100644 index 000000000..1d449f3d7 --- /dev/null +++ b/frontend/src/plugins/ldap/index.ts @@ -0,0 +1,32 @@ +/** + * LDAP 前端插件入口。 + * 通过 app.use(ldapPlugin) 动态注册 /auth/ldap 路由,不污染主路由表。 + * 删除 main.ts 中的 app.use(ldapPlugin) 行即可完全禁用前端 LDAP 功能。 + */ + +import type { App } from 'vue' +import type { Router } from 'vue-router' + +const ldapPlugin = { + install(app: App) { + // 从全局获取 router 实例(由 main.ts 在 app.use(router) 后注入) + const router = app.config.globalProperties.$router as Router + if (!router) { + console.warn('[LDAP Plugin] Router not found, route /auth/ldap will not be registered') + return + } + + // 动态注册 LDAP 登录路由,不写死在主路由表 + router.addRoute({ + path: '/auth/ldap', + name: 'LdapLogin', + component: () => import('./views/LdapLoginView.vue'), + meta: { + requiresAuth: false, + title: 'LDAP Login' + } + }) + } +} + +export default ldapPlugin diff --git a/frontend/src/plugins/ldap/store.ts b/frontend/src/plugins/ldap/store.ts new file mode 100644 index 000000000..5aa6291d0 --- /dev/null +++ b/frontend/src/plugins/ldap/store.ts @@ -0,0 +1,56 @@ +/** + * LDAP 认证 composable — 替代 useAuthStore 中已移除的 loginLdap action。 + * 负责调用 LDAP 登录 API 并将认证状态写入全局 authStore。 + */ + +import { useAuthStore } from '@/stores/auth' +import { + isTotp2FARequired, + type LoginResponse, + setAuthToken, + setRefreshToken, + setTokenExpiresAt +} from '@/api/auth' +import { loginLdap } from './api' + +const AUTH_USER_KEY = 'auth_user' + +export function useLdapAuth() { + const authStore = useAuthStore() + + /** + * 执行 LDAP 登录并更新全局认证状态 + * @param username - LDAP 用户名 + * @param password - LDAP 密码 + * @param turnstileToken - 可选的 Turnstile 验证令牌 + */ + async function loginWithLdap( + username: string, + password: string, + turnstileToken?: string + ): Promise { + const response = await loginLdap({ username, password, turnstile_token: turnstileToken }) + + // 如果需要 2FA,直接返回,由视图层处理 + if (isTotp2FARequired(response)) { + return response + } + + // 先将 token 存入 localStorage(setToken 会从 localStorage 读取 refresh token) + setAuthToken(response.access_token) + if (response.refresh_token) { + setRefreshToken(response.refresh_token) + } + if (response.expires_in) { + setTokenExpiresAt(response.expires_in) + } + localStorage.setItem(AUTH_USER_KEY, JSON.stringify(response.user)) + + // 通过 authStore.setToken 完成状态初始化(含 refreshUser + auto-refresh) + await authStore.setToken(response.access_token) + + return response + } + + return { loginWithLdap } +} diff --git a/frontend/src/plugins/ldap/views/LdapLoginView.vue b/frontend/src/plugins/ldap/views/LdapLoginView.vue new file mode 100644 index 000000000..da8302eca --- /dev/null +++ b/frontend/src/plugins/ldap/views/LdapLoginView.vue @@ -0,0 +1,237 @@ + + + diff --git a/frontend/src/views/auth/LoginView.vue b/frontend/src/views/auth/LoginView.vue index 203701081..6918dd29d 100644 --- a/frontend/src/views/auth/LoginView.vue +++ b/frontend/src/views/auth/LoginView.vue @@ -147,6 +147,16 @@ {{ isLoading ? t('auth.signingIn') : t('auth.signIn') }} + + +
+ + 使用 LDAP 登录 + +
diff --git a/ldap_complete_20260302_174855.tar.gz b/ldap_complete_20260302_174855.tar.gz new file mode 100644 index 000000000..f54921956 Binary files /dev/null and b/ldap_complete_20260302_174855.tar.gz differ