From a84c5d8e979714e0c5b013c7c0cfa8c9d946b063 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Fri, 23 Jan 2026 15:22:29 +0800 Subject: [PATCH] feat(oauth): OAuth for 3rd party apps --- application/constants/constants.go | 2 +- application/dependency/dependency.go | 13 +- assets | 2 +- ent/client.go | 366 ++++- ent/ent.go | 4 + ent/hook/hook.go | 24 + ent/intercept/intercept.go | 60 + ent/internal/schema.go | 2 +- ent/migrate/schema.go | 63 + ent/mutation.go | 1935 +++++++++++++++++++++++++- ent/mutationhelper.go | 12 + ent/oauthclient.go | 262 ++++ ent/oauthclient/oauthclient.go | 179 +++ ent/oauthclient/where.go | 544 ++++++++ ent/oauthclient_create.go | 1135 +++++++++++++++ ent/oauthclient_delete.go | 88 ++ ent/oauthclient_query.go | 605 ++++++++ ent/oauthclient_update.go | 783 +++++++++++ ent/oauthgrant.go | 245 ++++ ent/oauthgrant/oauthgrant.go | 158 +++ ent/oauthgrant/where.go | 367 +++++ ent/oauthgrant_create.go | 894 ++++++++++++ ent/oauthgrant_delete.go | 88 ++ ent/oauthgrant_query.go | 680 +++++++++ ent/oauthgrant_update.go | 615 ++++++++ ent/predicate/predicate.go | 6 + ent/runtime/runtime.go | 76 + ent/schema/oauthclient.go | 51 + ent/schema/oauthgrant.go | 60 + ent/schema/user.go | 1 + ent/tx.go | 6 + ent/user.go | 24 +- ent/user/user.go | 30 + ent/user/where.go | 23 + ent/user_create.go | 32 + ent/user_query.go | 76 +- ent/user_update.go | 163 +++ inventory/migration.go | 71 +- inventory/oauth_client.go | 82 ++ inventory/types/types.go | 29 + middleware/auth.go | 16 + pkg/auth/jwt.go | 147 +- pkg/cluster/routes/routes.go | 5 + pkg/serializer/error.go | 2 + routers/controllers/main.go | 14 + routers/controllers/oauth.go | 68 + routers/router.go | 89 +- service/oauth/oauth.go | 281 ++++ service/oauth/response.go | 89 ++ service/user/login.go | 5 +- service/user/setting.go | 9 + 51 files changed, 10542 insertions(+), 39 deletions(-) create mode 100644 ent/oauthclient.go create mode 100644 ent/oauthclient/oauthclient.go create mode 100644 ent/oauthclient/where.go create mode 100644 ent/oauthclient_create.go create mode 100644 ent/oauthclient_delete.go create mode 100644 ent/oauthclient_query.go create mode 100644 ent/oauthclient_update.go create mode 100644 ent/oauthgrant.go create mode 100644 ent/oauthgrant/oauthgrant.go create mode 100644 ent/oauthgrant/where.go create mode 100644 ent/oauthgrant_create.go create mode 100644 ent/oauthgrant_delete.go create mode 100644 ent/oauthgrant_query.go create mode 100644 ent/oauthgrant_update.go create mode 100644 ent/schema/oauthclient.go create mode 100644 ent/schema/oauthgrant.go create mode 100644 inventory/oauth_client.go create mode 100644 routers/controllers/oauth.go create mode 100644 service/oauth/oauth.go create mode 100644 service/oauth/response.go diff --git a/application/constants/constants.go b/application/constants/constants.go index 983d5165..fc2e92c4 100644 --- a/application/constants/constants.go +++ b/application/constants/constants.go @@ -3,7 +3,7 @@ package constants // These values will be injected at build time, DO NOT EDIT. // BackendVersion 当前后端版本号 -var BackendVersion = "4.7.0" +var BackendVersion = "4.12.0" // IsPro 是否为Pro版本 var IsPro = "false" diff --git a/application/dependency/dependency.go b/application/dependency/dependency.go index 06f10dd2..1bbfe8a6 100644 --- a/application/dependency/dependency.go +++ b/application/dependency/dependency.go @@ -87,6 +87,8 @@ type Dep interface { DavAccountClient() inventory.DavAccountClient // DirectLinkClient Creates a new inventory.DirectLinkClient instance for access DB direct link store. DirectLinkClient() inventory.DirectLinkClient + // OAuthClientClient Creates a new inventory.OAuthClientClient instance for access DB OAuth client store. + OAuthClientClient() inventory.OAuthClientClient // HashIDEncoder Get a singleton hashid.Encoder instance for encoding/decoding hashids. HashIDEncoder() hashid.Encoder // TokenAuth Get a singleton auth.TokenAuth instance for token authentication. @@ -160,6 +162,7 @@ type dependency struct { davAccountClient inventory.DavAccountClient directLinkClient inventory.DirectLinkClient fsEventClient inventory.FsEventClient + oAuthClient inventory.OAuthClientClient emailClient email.Driver generalAuth auth.Auth hashidEncoder hashid.Encoder @@ -483,6 +486,14 @@ func (d *dependency) EmailClient(ctx context.Context) email.Driver { return d.emailClient } +func (d *dependency) OAuthClientClient() inventory.OAuthClientClient { + if d.oAuthClient != nil { + return d.oAuthClient + } + + return inventory.NewOAuthClientClient(d.DBClient()) +} + func (d *dependency) MimeDetector(ctx context.Context) mime.MimeDetector { d.mu.Lock() defer d.mu.Unlock() @@ -785,7 +796,7 @@ func (d *dependency) TokenAuth() auth.TokenAuth { } d.tokenAuth = auth.NewTokenAuth(d.HashIDEncoder(), d.SettingProvider(), - []byte(d.SettingProvider().SecretKey(context.Background())), d.UserClient(), d.Logger(), d.KV()) + []byte(d.SettingProvider().SecretKey(context.Background())), d.UserClient(), d.Logger(), d.KV(), d.OAuthClientClient()) return d.tokenAuth } diff --git a/assets b/assets index 49245dc9..ee51bb64 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 49245dc9c19544f1f291fc939f8f00190df7aa00 +Subproject commit ee51bb6483d69f99c86db4c370ca742e486cfad9 diff --git a/ent/client.go b/ent/client.go index 503d2998..ab9d1c4b 100644 --- a/ent/client.go +++ b/ent/client.go @@ -23,6 +23,8 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/setting" "github.com/cloudreve/Cloudreve/v4/ent/share" @@ -54,6 +56,10 @@ type Client struct { Metadata *MetadataClient // Node is the client for interacting with the Node builders. Node *NodeClient + // OAuthClient is the client for interacting with the OAuthClient builders. + OAuthClient *OAuthClientClient + // OAuthGrant is the client for interacting with the OAuthGrant builders. + OAuthGrant *OAuthGrantClient // Passkey is the client for interacting with the Passkey builders. Passkey *PasskeyClient // Setting is the client for interacting with the Setting builders. @@ -85,6 +91,8 @@ func (c *Client) init() { c.Group = NewGroupClient(c.config) c.Metadata = NewMetadataClient(c.config) c.Node = NewNodeClient(c.config) + c.OAuthClient = NewOAuthClientClient(c.config) + c.OAuthGrant = NewOAuthGrantClient(c.config) c.Passkey = NewPasskeyClient(c.config) c.Setting = NewSettingClient(c.config) c.Share = NewShareClient(c.config) @@ -191,6 +199,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { Group: NewGroupClient(cfg), Metadata: NewMetadataClient(cfg), Node: NewNodeClient(cfg), + OAuthClient: NewOAuthClientClient(cfg), + OAuthGrant: NewOAuthGrantClient(cfg), Passkey: NewPasskeyClient(cfg), Setting: NewSettingClient(cfg), Share: NewShareClient(cfg), @@ -224,6 +234,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) Group: NewGroupClient(cfg), Metadata: NewMetadataClient(cfg), Node: NewNodeClient(cfg), + OAuthClient: NewOAuthClientClient(cfg), + OAuthGrant: NewOAuthGrantClient(cfg), Passkey: NewPasskeyClient(cfg), Setting: NewSettingClient(cfg), Share: NewShareClient(cfg), @@ -260,7 +272,8 @@ func (c *Client) Close() error { func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, c.Metadata, - c.Node, c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, + c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, + c.StoragePolicy, c.Task, c.User, } { n.Use(hooks...) } @@ -271,7 +284,8 @@ func (c *Client) Use(hooks ...Hook) { func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, c.Metadata, - c.Node, c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, + c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, + c.StoragePolicy, c.Task, c.User, } { n.Intercept(interceptors...) } @@ -296,6 +310,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.Metadata.mutate(ctx, m) case *NodeMutation: return c.Node.mutate(ctx, m) + case *OAuthClientMutation: + return c.OAuthClient.mutate(ctx, m) + case *OAuthGrantMutation: + return c.OAuthGrant.mutate(ctx, m) case *PasskeyMutation: return c.Passkey.mutate(ctx, m) case *SettingMutation: @@ -1680,6 +1698,324 @@ func (c *NodeClient) mutate(ctx context.Context, m *NodeMutation) (Value, error) } } +// OAuthClientClient is a client for the OAuthClient schema. +type OAuthClientClient struct { + config +} + +// NewOAuthClientClient returns a client for the OAuthClient from the given config. +func NewOAuthClientClient(c config) *OAuthClientClient { + return &OAuthClientClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `oauthclient.Hooks(f(g(h())))`. +func (c *OAuthClientClient) Use(hooks ...Hook) { + c.hooks.OAuthClient = append(c.hooks.OAuthClient, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `oauthclient.Intercept(f(g(h())))`. +func (c *OAuthClientClient) Intercept(interceptors ...Interceptor) { + c.inters.OAuthClient = append(c.inters.OAuthClient, interceptors...) +} + +// Create returns a builder for creating a OAuthClient entity. +func (c *OAuthClientClient) Create() *OAuthClientCreate { + mutation := newOAuthClientMutation(c.config, OpCreate) + return &OAuthClientCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of OAuthClient entities. +func (c *OAuthClientClient) CreateBulk(builders ...*OAuthClientCreate) *OAuthClientCreateBulk { + return &OAuthClientCreateBulk{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 *OAuthClientClient) MapCreateBulk(slice any, setFunc func(*OAuthClientCreate, int)) *OAuthClientCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &OAuthClientCreateBulk{err: fmt.Errorf("calling to OAuthClientClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*OAuthClientCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &OAuthClientCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for OAuthClient. +func (c *OAuthClientClient) Update() *OAuthClientUpdate { + mutation := newOAuthClientMutation(c.config, OpUpdate) + return &OAuthClientUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *OAuthClientClient) UpdateOne(oc *OAuthClient) *OAuthClientUpdateOne { + mutation := newOAuthClientMutation(c.config, OpUpdateOne, withOAuthClient(oc)) + return &OAuthClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *OAuthClientClient) UpdateOneID(id int) *OAuthClientUpdateOne { + mutation := newOAuthClientMutation(c.config, OpUpdateOne, withOAuthClientID(id)) + return &OAuthClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for OAuthClient. +func (c *OAuthClientClient) Delete() *OAuthClientDelete { + mutation := newOAuthClientMutation(c.config, OpDelete) + return &OAuthClientDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *OAuthClientClient) DeleteOne(oc *OAuthClient) *OAuthClientDeleteOne { + return c.DeleteOneID(oc.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *OAuthClientClient) DeleteOneID(id int) *OAuthClientDeleteOne { + builder := c.Delete().Where(oauthclient.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &OAuthClientDeleteOne{builder} +} + +// Query returns a query builder for OAuthClient. +func (c *OAuthClientClient) Query() *OAuthClientQuery { + return &OAuthClientQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeOAuthClient}, + inters: c.Interceptors(), + } +} + +// Get returns a OAuthClient entity by its id. +func (c *OAuthClientClient) Get(ctx context.Context, id int) (*OAuthClient, error) { + return c.Query().Where(oauthclient.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *OAuthClientClient) GetX(ctx context.Context, id int) *OAuthClient { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryGrants queries the grants edge of a OAuthClient. +func (c *OAuthClientClient) QueryGrants(oc *OAuthClient) *OAuthGrantQuery { + query := (&OAuthGrantClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := oc.ID + step := sqlgraph.NewStep( + sqlgraph.From(oauthclient.Table, oauthclient.FieldID, id), + sqlgraph.To(oauthgrant.Table, oauthgrant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, oauthclient.GrantsTable, oauthclient.GrantsColumn), + ) + fromV = sqlgraph.Neighbors(oc.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *OAuthClientClient) Hooks() []Hook { + hooks := c.hooks.OAuthClient + return append(hooks[:len(hooks):len(hooks)], oauthclient.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *OAuthClientClient) Interceptors() []Interceptor { + inters := c.inters.OAuthClient + return append(inters[:len(inters):len(inters)], oauthclient.Interceptors[:]...) +} + +func (c *OAuthClientClient) mutate(ctx context.Context, m *OAuthClientMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&OAuthClientCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&OAuthClientUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&OAuthClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&OAuthClientDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown OAuthClient mutation op: %q", m.Op()) + } +} + +// OAuthGrantClient is a client for the OAuthGrant schema. +type OAuthGrantClient struct { + config +} + +// NewOAuthGrantClient returns a client for the OAuthGrant from the given config. +func NewOAuthGrantClient(c config) *OAuthGrantClient { + return &OAuthGrantClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `oauthgrant.Hooks(f(g(h())))`. +func (c *OAuthGrantClient) Use(hooks ...Hook) { + c.hooks.OAuthGrant = append(c.hooks.OAuthGrant, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `oauthgrant.Intercept(f(g(h())))`. +func (c *OAuthGrantClient) Intercept(interceptors ...Interceptor) { + c.inters.OAuthGrant = append(c.inters.OAuthGrant, interceptors...) +} + +// Create returns a builder for creating a OAuthGrant entity. +func (c *OAuthGrantClient) Create() *OAuthGrantCreate { + mutation := newOAuthGrantMutation(c.config, OpCreate) + return &OAuthGrantCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of OAuthGrant entities. +func (c *OAuthGrantClient) CreateBulk(builders ...*OAuthGrantCreate) *OAuthGrantCreateBulk { + return &OAuthGrantCreateBulk{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 *OAuthGrantClient) MapCreateBulk(slice any, setFunc func(*OAuthGrantCreate, int)) *OAuthGrantCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &OAuthGrantCreateBulk{err: fmt.Errorf("calling to OAuthGrantClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*OAuthGrantCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &OAuthGrantCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for OAuthGrant. +func (c *OAuthGrantClient) Update() *OAuthGrantUpdate { + mutation := newOAuthGrantMutation(c.config, OpUpdate) + return &OAuthGrantUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *OAuthGrantClient) UpdateOne(og *OAuthGrant) *OAuthGrantUpdateOne { + mutation := newOAuthGrantMutation(c.config, OpUpdateOne, withOAuthGrant(og)) + return &OAuthGrantUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *OAuthGrantClient) UpdateOneID(id int) *OAuthGrantUpdateOne { + mutation := newOAuthGrantMutation(c.config, OpUpdateOne, withOAuthGrantID(id)) + return &OAuthGrantUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for OAuthGrant. +func (c *OAuthGrantClient) Delete() *OAuthGrantDelete { + mutation := newOAuthGrantMutation(c.config, OpDelete) + return &OAuthGrantDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *OAuthGrantClient) DeleteOne(og *OAuthGrant) *OAuthGrantDeleteOne { + return c.DeleteOneID(og.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *OAuthGrantClient) DeleteOneID(id int) *OAuthGrantDeleteOne { + builder := c.Delete().Where(oauthgrant.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &OAuthGrantDeleteOne{builder} +} + +// Query returns a query builder for OAuthGrant. +func (c *OAuthGrantClient) Query() *OAuthGrantQuery { + return &OAuthGrantQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeOAuthGrant}, + inters: c.Interceptors(), + } +} + +// Get returns a OAuthGrant entity by its id. +func (c *OAuthGrantClient) Get(ctx context.Context, id int) (*OAuthGrant, error) { + return c.Query().Where(oauthgrant.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *OAuthGrantClient) GetX(ctx context.Context, id int) *OAuthGrant { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryUser queries the user edge of a OAuthGrant. +func (c *OAuthGrantClient) QueryUser(og *OAuthGrant) *UserQuery { + query := (&UserClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := og.ID + step := sqlgraph.NewStep( + sqlgraph.From(oauthgrant.Table, oauthgrant.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, oauthgrant.UserTable, oauthgrant.UserColumn), + ) + fromV = sqlgraph.Neighbors(og.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryClient queries the client edge of a OAuthGrant. +func (c *OAuthGrantClient) QueryClient(og *OAuthGrant) *OAuthClientQuery { + query := (&OAuthClientClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := og.ID + step := sqlgraph.NewStep( + sqlgraph.From(oauthgrant.Table, oauthgrant.FieldID, id), + sqlgraph.To(oauthclient.Table, oauthclient.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, oauthgrant.ClientTable, oauthgrant.ClientColumn), + ) + fromV = sqlgraph.Neighbors(og.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *OAuthGrantClient) Hooks() []Hook { + hooks := c.hooks.OAuthGrant + return append(hooks[:len(hooks):len(hooks)], oauthgrant.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *OAuthGrantClient) Interceptors() []Interceptor { + inters := c.inters.OAuthGrant + return append(inters[:len(inters):len(inters)], oauthgrant.Interceptors[:]...) +} + +func (c *OAuthGrantClient) mutate(ctx context.Context, m *OAuthGrantMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&OAuthGrantCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&OAuthGrantUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&OAuthGrantUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&OAuthGrantDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown OAuthGrant mutation op: %q", m.Op()) + } +} + // PasskeyClient is a client for the Passkey schema. type PasskeyClient struct { config @@ -2719,6 +3055,22 @@ func (c *UserClient) QueryEntities(u *User) *EntityQuery { return query } +// QueryOauthGrants queries the oauth_grants edge of a User. +func (c *UserClient) QueryOauthGrants(u *User) *OAuthGrantQuery { + query := (&OAuthGrantClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(oauthgrant.Table, oauthgrant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.OauthGrantsTable, user.OauthGrantsColumn), + ) + fromV = sqlgraph.Neighbors(u.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *UserClient) Hooks() []Hook { hooks := c.hooks.User @@ -2749,12 +3101,14 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) // hooks and interceptors per client, for fast access. type ( hooks struct { - DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, Passkey, - Setting, Share, StoragePolicy, Task, User []ent.Hook + DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, + OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, + User []ent.Hook } inters struct { - DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, Passkey, - Setting, Share, StoragePolicy, Task, User []ent.Interceptor + DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, + OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, + User []ent.Interceptor } ) diff --git a/ent/ent.go b/ent/ent.go index 3ea446e5..3d92b48c 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -20,6 +20,8 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/setting" "github.com/cloudreve/Cloudreve/v4/ent/share" @@ -94,6 +96,8 @@ func checkColumn(table, column string) error { group.Table: group.ValidColumn, metadata.Table: metadata.ValidColumn, node.Table: node.ValidColumn, + oauthclient.Table: oauthclient.ValidColumn, + oauthgrant.Table: oauthgrant.ValidColumn, passkey.Table: passkey.ValidColumn, setting.Table: setting.ValidColumn, share.Table: share.ValidColumn, diff --git a/ent/hook/hook.go b/ent/hook/hook.go index 5a0f7e64..2bf7e995 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -105,6 +105,30 @@ func (f NodeFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.NodeMutation", m) } +// The OAuthClientFunc type is an adapter to allow the use of ordinary +// function as OAuthClient mutator. +type OAuthClientFunc func(context.Context, *ent.OAuthClientMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f OAuthClientFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.OAuthClientMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.OAuthClientMutation", m) +} + +// The OAuthGrantFunc type is an adapter to allow the use of ordinary +// function as OAuthGrant mutator. +type OAuthGrantFunc func(context.Context, *ent.OAuthGrantMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f OAuthGrantFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.OAuthGrantMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.OAuthGrantMutation", m) +} + // The PasskeyFunc type is an adapter to allow the use of ordinary // function as Passkey mutator. type PasskeyFunc func(context.Context, *ent.PasskeyMutation) (ent.Value, error) diff --git a/ent/intercept/intercept.go b/ent/intercept/intercept.go index cd4ee317..b2efc35b 100644 --- a/ent/intercept/intercept.go +++ b/ent/intercept/intercept.go @@ -16,6 +16,8 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/setting" @@ -297,6 +299,60 @@ func (f TraverseNode) Traverse(ctx context.Context, q ent.Query) error { return fmt.Errorf("unexpected query type %T. expect *ent.NodeQuery", q) } +// The OAuthClientFunc type is an adapter to allow the use of ordinary function as a Querier. +type OAuthClientFunc func(context.Context, *ent.OAuthClientQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f OAuthClientFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.OAuthClientQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.OAuthClientQuery", q) +} + +// The TraverseOAuthClient type is an adapter to allow the use of ordinary function as Traverser. +type TraverseOAuthClient func(context.Context, *ent.OAuthClientQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseOAuthClient) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseOAuthClient) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.OAuthClientQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.OAuthClientQuery", q) +} + +// The OAuthGrantFunc type is an adapter to allow the use of ordinary function as a Querier. +type OAuthGrantFunc func(context.Context, *ent.OAuthGrantQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f OAuthGrantFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.OAuthGrantQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.OAuthGrantQuery", q) +} + +// The TraverseOAuthGrant type is an adapter to allow the use of ordinary function as Traverser. +type TraverseOAuthGrant func(context.Context, *ent.OAuthGrantQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseOAuthGrant) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseOAuthGrant) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.OAuthGrantQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.OAuthGrantQuery", q) +} + // The PasskeyFunc type is an adapter to allow the use of ordinary function as a Querier. type PasskeyFunc func(context.Context, *ent.PasskeyQuery) (ent.Value, error) @@ -478,6 +534,10 @@ func NewQuery(q ent.Query) (Query, error) { return &query[*ent.MetadataQuery, predicate.Metadata, metadata.OrderOption]{typ: ent.TypeMetadata, tq: q}, nil case *ent.NodeQuery: return &query[*ent.NodeQuery, predicate.Node, node.OrderOption]{typ: ent.TypeNode, tq: q}, nil + case *ent.OAuthClientQuery: + return &query[*ent.OAuthClientQuery, predicate.OAuthClient, oauthclient.OrderOption]{typ: ent.TypeOAuthClient, tq: q}, nil + case *ent.OAuthGrantQuery: + return &query[*ent.OAuthGrantQuery, predicate.OAuthGrant, oauthgrant.OrderOption]{typ: ent.TypeOAuthGrant, tq: q}, nil case *ent.PasskeyQuery: return &query[*ent.PasskeyQuery, predicate.Passkey, passkey.OrderOption]{typ: ent.TypePasskey, tq: q}, nil case *ent.SettingQuery: diff --git a/ent/internal/schema.go b/ent/internal/schema.go index c3bb3567..bdee54cc 100644 --- a/ent/internal/schema.go +++ b/ent/internal/schema.go @@ -6,4 +6,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" +const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthClient\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"guid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"homepage_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2048,\"optional\":true,\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"redirect_uris\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.OAuthClientProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"OAuthClientProps\",\"Ident\":\"types.OAuthClientProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_enabled\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":true,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"oauth_grants\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"client\",\"type\":\"OAuthClient\",\"field\":\"client_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"client_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"client_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"oauth_grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 5e35c32f..2e04c739 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -264,6 +264,65 @@ var ( Columns: NodesColumns, PrimaryKey: []*schema.Column{NodesColumns[0]}, } + // OauthClientsColumns holds the columns for the "oauth_clients" table. + OauthClientsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "guid", Type: field.TypeString, Unique: true, Size: 255}, + {Name: "secret", Type: field.TypeString, Size: 255}, + {Name: "name", Type: field.TypeString, Size: 255}, + {Name: "homepage_url", Type: field.TypeString, Nullable: true, Size: 2048}, + {Name: "redirect_uris", Type: field.TypeJSON}, + {Name: "scopes", Type: field.TypeJSON}, + {Name: "props", Type: field.TypeJSON}, + {Name: "is_enabled", Type: field.TypeBool, Default: true}, + } + // OauthClientsTable holds the schema information for the "oauth_clients" table. + OauthClientsTable = &schema.Table{ + Name: "oauth_clients", + Columns: OauthClientsColumns, + PrimaryKey: []*schema.Column{OauthClientsColumns[0]}, + } + // OauthGrantsColumns holds the columns for the "oauth_grants" table. + OauthGrantsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "scopes", Type: field.TypeJSON}, + {Name: "last_used_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "client_id", Type: field.TypeInt}, + {Name: "user_id", Type: field.TypeInt}, + } + // OauthGrantsTable holds the schema information for the "oauth_grants" table. + OauthGrantsTable = &schema.Table{ + Name: "oauth_grants", + Columns: OauthGrantsColumns, + PrimaryKey: []*schema.Column{OauthGrantsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "oauth_grants_oauth_clients_grants", + Columns: []*schema.Column{OauthGrantsColumns[6]}, + RefColumns: []*schema.Column{OauthClientsColumns[0]}, + OnDelete: schema.NoAction, + }, + { + Symbol: "oauth_grants_users_oauth_grants", + Columns: []*schema.Column{OauthGrantsColumns[7]}, + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + Indexes: []*schema.Index{ + { + Name: "oauthgrant_user_id_client_id", + Unique: true, + Columns: []*schema.Column{OauthGrantsColumns[7], OauthGrantsColumns[6]}, + }, + }, + } // PasskeysColumns holds the columns for the "passkeys" table. PasskeysColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -472,6 +531,8 @@ var ( GroupsTable, MetadataTable, NodesTable, + OauthClientsTable, + OauthGrantsTable, PasskeysTable, SettingsTable, SharesTable, @@ -493,6 +554,8 @@ func init() { FsEventsTable.ForeignKeys[0].RefTable = UsersTable GroupsTable.ForeignKeys[0].RefTable = StoragePoliciesTable MetadataTable.ForeignKeys[0].RefTable = FilesTable + OauthGrantsTable.ForeignKeys[0].RefTable = OauthClientsTable + OauthGrantsTable.ForeignKeys[1].RefTable = UsersTable PasskeysTable.ForeignKeys[0].RefTable = UsersTable SharesTable.ForeignKeys[0].RefTable = FilesTable SharesTable.ForeignKeys[1].RefTable = UsersTable diff --git a/ent/mutation.go b/ent/mutation.go index 4a528b6e..0e1fed18 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -19,6 +19,8 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/setting" @@ -49,6 +51,8 @@ const ( TypeGroup = "Group" TypeMetadata = "Metadata" TypeNode = "Node" + TypeOAuthClient = "OAuthClient" + TypeOAuthGrant = "OAuthGrant" TypePasskey = "Passkey" TypeSetting = "Setting" TypeShare = "Share" @@ -8192,6 +8196,1848 @@ func (m *NodeMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Node edge %s", name) } +// OAuthClientMutation represents an operation that mutates the OAuthClient nodes in the graph. +type OAuthClientMutation struct { + config + op Op + typ string + id *int + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + guid *string + secret *string + name *string + homepage_url *string + redirect_uris *[]string + appendredirect_uris []string + scopes *[]string + appendscopes []string + props **types.OAuthClientProps + is_enabled *bool + clearedFields map[string]struct{} + grants map[int]struct{} + removedgrants map[int]struct{} + clearedgrants bool + done bool + oldValue func(context.Context) (*OAuthClient, error) + predicates []predicate.OAuthClient +} + +var _ ent.Mutation = (*OAuthClientMutation)(nil) + +// oauthclientOption allows management of the mutation configuration using functional options. +type oauthclientOption func(*OAuthClientMutation) + +// newOAuthClientMutation creates new mutation for the OAuthClient entity. +func newOAuthClientMutation(c config, op Op, opts ...oauthclientOption) *OAuthClientMutation { + m := &OAuthClientMutation{ + config: c, + op: op, + typ: TypeOAuthClient, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withOAuthClientID sets the ID field of the mutation. +func withOAuthClientID(id int) oauthclientOption { + return func(m *OAuthClientMutation) { + var ( + err error + once sync.Once + value *OAuthClient + ) + m.oldValue = func(ctx context.Context) (*OAuthClient, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().OAuthClient.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withOAuthClient sets the old OAuthClient of the mutation. +func withOAuthClient(node *OAuthClient) oauthclientOption { + return func(m *OAuthClientMutation) { + m.oldValue = func(context.Context) (*OAuthClient, 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 OAuthClientMutation) 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 OAuthClientMutation) 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 *OAuthClientMutation) ID() (id int, 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 *OAuthClientMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().OAuthClient.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 *OAuthClientMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *OAuthClientMutation) 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 OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) 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 *OAuthClientMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *OAuthClientMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *OAuthClientMutation) 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 OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) 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 *OAuthClientMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *OAuthClientMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *OAuthClientMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldDeletedAt(ctx context.Context) (v *time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *OAuthClientMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[oauthclient.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *OAuthClientMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[oauthclient.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *OAuthClientMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, oauthclient.FieldDeletedAt) +} + +// SetGUID sets the "guid" field. +func (m *OAuthClientMutation) SetGUID(s string) { + m.guid = &s +} + +// GUID returns the value of the "guid" field in the mutation. +func (m *OAuthClientMutation) GUID() (r string, exists bool) { + v := m.guid + if v == nil { + return + } + return *v, true +} + +// OldGUID returns the old "guid" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldGUID(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldGUID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldGUID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldGUID: %w", err) + } + return oldValue.GUID, nil +} + +// ResetGUID resets all changes to the "guid" field. +func (m *OAuthClientMutation) ResetGUID() { + m.guid = nil +} + +// SetSecret sets the "secret" field. +func (m *OAuthClientMutation) SetSecret(s string) { + m.secret = &s +} + +// Secret returns the value of the "secret" field in the mutation. +func (m *OAuthClientMutation) Secret() (r string, exists bool) { + v := m.secret + if v == nil { + return + } + return *v, true +} + +// OldSecret returns the old "secret" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldSecret(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSecret is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSecret requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSecret: %w", err) + } + return oldValue.Secret, nil +} + +// ResetSecret resets all changes to the "secret" field. +func (m *OAuthClientMutation) ResetSecret() { + m.secret = nil +} + +// SetName sets the "name" field. +func (m *OAuthClientMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *OAuthClientMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *OAuthClientMutation) ResetName() { + m.name = nil +} + +// SetHomepageURL sets the "homepage_url" field. +func (m *OAuthClientMutation) SetHomepageURL(s string) { + m.homepage_url = &s +} + +// HomepageURL returns the value of the "homepage_url" field in the mutation. +func (m *OAuthClientMutation) HomepageURL() (r string, exists bool) { + v := m.homepage_url + if v == nil { + return + } + return *v, true +} + +// OldHomepageURL returns the old "homepage_url" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldHomepageURL(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldHomepageURL is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldHomepageURL requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldHomepageURL: %w", err) + } + return oldValue.HomepageURL, nil +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (m *OAuthClientMutation) ClearHomepageURL() { + m.homepage_url = nil + m.clearedFields[oauthclient.FieldHomepageURL] = struct{}{} +} + +// HomepageURLCleared returns if the "homepage_url" field was cleared in this mutation. +func (m *OAuthClientMutation) HomepageURLCleared() bool { + _, ok := m.clearedFields[oauthclient.FieldHomepageURL] + return ok +} + +// ResetHomepageURL resets all changes to the "homepage_url" field. +func (m *OAuthClientMutation) ResetHomepageURL() { + m.homepage_url = nil + delete(m.clearedFields, oauthclient.FieldHomepageURL) +} + +// SetRedirectUris sets the "redirect_uris" field. +func (m *OAuthClientMutation) SetRedirectUris(s []string) { + m.redirect_uris = &s + m.appendredirect_uris = nil +} + +// RedirectUris returns the value of the "redirect_uris" field in the mutation. +func (m *OAuthClientMutation) RedirectUris() (r []string, exists bool) { + v := m.redirect_uris + if v == nil { + return + } + return *v, true +} + +// OldRedirectUris returns the old "redirect_uris" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldRedirectUris(ctx context.Context) (v []string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldRedirectUris is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldRedirectUris requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldRedirectUris: %w", err) + } + return oldValue.RedirectUris, nil +} + +// AppendRedirectUris adds s to the "redirect_uris" field. +func (m *OAuthClientMutation) AppendRedirectUris(s []string) { + m.appendredirect_uris = append(m.appendredirect_uris, s...) +} + +// AppendedRedirectUris returns the list of values that were appended to the "redirect_uris" field in this mutation. +func (m *OAuthClientMutation) AppendedRedirectUris() ([]string, bool) { + if len(m.appendredirect_uris) == 0 { + return nil, false + } + return m.appendredirect_uris, true +} + +// ResetRedirectUris resets all changes to the "redirect_uris" field. +func (m *OAuthClientMutation) ResetRedirectUris() { + m.redirect_uris = nil + m.appendredirect_uris = nil +} + +// SetScopes sets the "scopes" field. +func (m *OAuthClientMutation) SetScopes(s []string) { + m.scopes = &s + m.appendscopes = nil +} + +// Scopes returns the value of the "scopes" field in the mutation. +func (m *OAuthClientMutation) Scopes() (r []string, exists bool) { + v := m.scopes + if v == nil { + return + } + return *v, true +} + +// OldScopes returns the old "scopes" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldScopes(ctx context.Context) (v []string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldScopes is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldScopes requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldScopes: %w", err) + } + return oldValue.Scopes, nil +} + +// AppendScopes adds s to the "scopes" field. +func (m *OAuthClientMutation) AppendScopes(s []string) { + m.appendscopes = append(m.appendscopes, s...) +} + +// AppendedScopes returns the list of values that were appended to the "scopes" field in this mutation. +func (m *OAuthClientMutation) AppendedScopes() ([]string, bool) { + if len(m.appendscopes) == 0 { + return nil, false + } + return m.appendscopes, true +} + +// ResetScopes resets all changes to the "scopes" field. +func (m *OAuthClientMutation) ResetScopes() { + m.scopes = nil + m.appendscopes = nil +} + +// SetProps sets the "props" field. +func (m *OAuthClientMutation) SetProps(tacp *types.OAuthClientProps) { + m.props = &tacp +} + +// Props returns the value of the "props" field in the mutation. +func (m *OAuthClientMutation) Props() (r *types.OAuthClientProps, exists bool) { + v := m.props + if v == nil { + return + } + return *v, true +} + +// OldProps returns the old "props" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldProps(ctx context.Context) (v *types.OAuthClientProps, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldProps is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldProps requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldProps: %w", err) + } + return oldValue.Props, nil +} + +// ResetProps resets all changes to the "props" field. +func (m *OAuthClientMutation) ResetProps() { + m.props = nil +} + +// SetIsEnabled sets the "is_enabled" field. +func (m *OAuthClientMutation) SetIsEnabled(b bool) { + m.is_enabled = &b +} + +// IsEnabled returns the value of the "is_enabled" field in the mutation. +func (m *OAuthClientMutation) IsEnabled() (r bool, exists bool) { + v := m.is_enabled + if v == nil { + return + } + return *v, true +} + +// OldIsEnabled returns the old "is_enabled" field's value of the OAuthClient entity. +// If the OAuthClient 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 *OAuthClientMutation) OldIsEnabled(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldIsEnabled is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldIsEnabled requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldIsEnabled: %w", err) + } + return oldValue.IsEnabled, nil +} + +// ResetIsEnabled resets all changes to the "is_enabled" field. +func (m *OAuthClientMutation) ResetIsEnabled() { + m.is_enabled = nil +} + +// AddGrantIDs adds the "grants" edge to the OAuthGrant entity by ids. +func (m *OAuthClientMutation) AddGrantIDs(ids ...int) { + if m.grants == nil { + m.grants = make(map[int]struct{}) + } + for i := range ids { + m.grants[ids[i]] = struct{}{} + } +} + +// ClearGrants clears the "grants" edge to the OAuthGrant entity. +func (m *OAuthClientMutation) ClearGrants() { + m.clearedgrants = true +} + +// GrantsCleared reports if the "grants" edge to the OAuthGrant entity was cleared. +func (m *OAuthClientMutation) GrantsCleared() bool { + return m.clearedgrants +} + +// RemoveGrantIDs removes the "grants" edge to the OAuthGrant entity by IDs. +func (m *OAuthClientMutation) RemoveGrantIDs(ids ...int) { + if m.removedgrants == nil { + m.removedgrants = make(map[int]struct{}) + } + for i := range ids { + delete(m.grants, ids[i]) + m.removedgrants[ids[i]] = struct{}{} + } +} + +// RemovedGrants returns the removed IDs of the "grants" edge to the OAuthGrant entity. +func (m *OAuthClientMutation) RemovedGrantsIDs() (ids []int) { + for id := range m.removedgrants { + ids = append(ids, id) + } + return +} + +// GrantsIDs returns the "grants" edge IDs in the mutation. +func (m *OAuthClientMutation) GrantsIDs() (ids []int) { + for id := range m.grants { + ids = append(ids, id) + } + return +} + +// ResetGrants resets all changes to the "grants" edge. +func (m *OAuthClientMutation) ResetGrants() { + m.grants = nil + m.clearedgrants = false + m.removedgrants = nil +} + +// Where appends a list predicates to the OAuthClientMutation builder. +func (m *OAuthClientMutation) Where(ps ...predicate.OAuthClient) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the OAuthClientMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *OAuthClientMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.OAuthClient, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *OAuthClientMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *OAuthClientMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (OAuthClient). +func (m *OAuthClientMutation) 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 *OAuthClientMutation) Fields() []string { + fields := make([]string, 0, 11) + if m.created_at != nil { + fields = append(fields, oauthclient.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, oauthclient.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, oauthclient.FieldDeletedAt) + } + if m.guid != nil { + fields = append(fields, oauthclient.FieldGUID) + } + if m.secret != nil { + fields = append(fields, oauthclient.FieldSecret) + } + if m.name != nil { + fields = append(fields, oauthclient.FieldName) + } + if m.homepage_url != nil { + fields = append(fields, oauthclient.FieldHomepageURL) + } + if m.redirect_uris != nil { + fields = append(fields, oauthclient.FieldRedirectUris) + } + if m.scopes != nil { + fields = append(fields, oauthclient.FieldScopes) + } + if m.props != nil { + fields = append(fields, oauthclient.FieldProps) + } + if m.is_enabled != nil { + fields = append(fields, oauthclient.FieldIsEnabled) + } + 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 *OAuthClientMutation) Field(name string) (ent.Value, bool) { + switch name { + case oauthclient.FieldCreatedAt: + return m.CreatedAt() + case oauthclient.FieldUpdatedAt: + return m.UpdatedAt() + case oauthclient.FieldDeletedAt: + return m.DeletedAt() + case oauthclient.FieldGUID: + return m.GUID() + case oauthclient.FieldSecret: + return m.Secret() + case oauthclient.FieldName: + return m.Name() + case oauthclient.FieldHomepageURL: + return m.HomepageURL() + case oauthclient.FieldRedirectUris: + return m.RedirectUris() + case oauthclient.FieldScopes: + return m.Scopes() + case oauthclient.FieldProps: + return m.Props() + case oauthclient.FieldIsEnabled: + return m.IsEnabled() + } + 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 *OAuthClientMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case oauthclient.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case oauthclient.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case oauthclient.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case oauthclient.FieldGUID: + return m.OldGUID(ctx) + case oauthclient.FieldSecret: + return m.OldSecret(ctx) + case oauthclient.FieldName: + return m.OldName(ctx) + case oauthclient.FieldHomepageURL: + return m.OldHomepageURL(ctx) + case oauthclient.FieldRedirectUris: + return m.OldRedirectUris(ctx) + case oauthclient.FieldScopes: + return m.OldScopes(ctx) + case oauthclient.FieldProps: + return m.OldProps(ctx) + case oauthclient.FieldIsEnabled: + return m.OldIsEnabled(ctx) + } + return nil, fmt.Errorf("unknown OAuthClient 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 *OAuthClientMutation) SetField(name string, value ent.Value) error { + switch name { + case oauthclient.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 oauthclient.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 oauthclient.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case oauthclient.FieldGUID: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetGUID(v) + return nil + case oauthclient.FieldSecret: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSecret(v) + return nil + case oauthclient.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case oauthclient.FieldHomepageURL: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetHomepageURL(v) + return nil + case oauthclient.FieldRedirectUris: + v, ok := value.([]string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetRedirectUris(v) + return nil + case oauthclient.FieldScopes: + v, ok := value.([]string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetScopes(v) + return nil + case oauthclient.FieldProps: + v, ok := value.(*types.OAuthClientProps) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetProps(v) + return nil + case oauthclient.FieldIsEnabled: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetIsEnabled(v) + return nil + } + return fmt.Errorf("unknown OAuthClient field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *OAuthClientMutation) 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 *OAuthClientMutation) 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 *OAuthClientMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown OAuthClient numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *OAuthClientMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(oauthclient.FieldDeletedAt) { + fields = append(fields, oauthclient.FieldDeletedAt) + } + if m.FieldCleared(oauthclient.FieldHomepageURL) { + fields = append(fields, oauthclient.FieldHomepageURL) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *OAuthClientMutation) 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 *OAuthClientMutation) ClearField(name string) error { + switch name { + case oauthclient.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case oauthclient.FieldHomepageURL: + m.ClearHomepageURL() + return nil + } + return fmt.Errorf("unknown OAuthClient 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 *OAuthClientMutation) ResetField(name string) error { + switch name { + case oauthclient.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case oauthclient.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case oauthclient.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case oauthclient.FieldGUID: + m.ResetGUID() + return nil + case oauthclient.FieldSecret: + m.ResetSecret() + return nil + case oauthclient.FieldName: + m.ResetName() + return nil + case oauthclient.FieldHomepageURL: + m.ResetHomepageURL() + return nil + case oauthclient.FieldRedirectUris: + m.ResetRedirectUris() + return nil + case oauthclient.FieldScopes: + m.ResetScopes() + return nil + case oauthclient.FieldProps: + m.ResetProps() + return nil + case oauthclient.FieldIsEnabled: + m.ResetIsEnabled() + return nil + } + return fmt.Errorf("unknown OAuthClient field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *OAuthClientMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.grants != nil { + edges = append(edges, oauthclient.EdgeGrants) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *OAuthClientMutation) AddedIDs(name string) []ent.Value { + switch name { + case oauthclient.EdgeGrants: + ids := make([]ent.Value, 0, len(m.grants)) + for id := range m.grants { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *OAuthClientMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + if m.removedgrants != nil { + edges = append(edges, oauthclient.EdgeGrants) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *OAuthClientMutation) RemovedIDs(name string) []ent.Value { + switch name { + case oauthclient.EdgeGrants: + ids := make([]ent.Value, 0, len(m.removedgrants)) + for id := range m.removedgrants { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *OAuthClientMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedgrants { + edges = append(edges, oauthclient.EdgeGrants) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *OAuthClientMutation) EdgeCleared(name string) bool { + switch name { + case oauthclient.EdgeGrants: + return m.clearedgrants + } + 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 *OAuthClientMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown OAuthClient 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 *OAuthClientMutation) ResetEdge(name string) error { + switch name { + case oauthclient.EdgeGrants: + m.ResetGrants() + return nil + } + return fmt.Errorf("unknown OAuthClient edge %s", name) +} + +// OAuthGrantMutation represents an operation that mutates the OAuthGrant nodes in the graph. +type OAuthGrantMutation struct { + config + op Op + typ string + id *int + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + scopes *[]string + appendscopes []string + last_used_at *time.Time + clearedFields map[string]struct{} + user *int + cleareduser bool + client *int + clearedclient bool + done bool + oldValue func(context.Context) (*OAuthGrant, error) + predicates []predicate.OAuthGrant +} + +var _ ent.Mutation = (*OAuthGrantMutation)(nil) + +// oauthgrantOption allows management of the mutation configuration using functional options. +type oauthgrantOption func(*OAuthGrantMutation) + +// newOAuthGrantMutation creates new mutation for the OAuthGrant entity. +func newOAuthGrantMutation(c config, op Op, opts ...oauthgrantOption) *OAuthGrantMutation { + m := &OAuthGrantMutation{ + config: c, + op: op, + typ: TypeOAuthGrant, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withOAuthGrantID sets the ID field of the mutation. +func withOAuthGrantID(id int) oauthgrantOption { + return func(m *OAuthGrantMutation) { + var ( + err error + once sync.Once + value *OAuthGrant + ) + m.oldValue = func(ctx context.Context) (*OAuthGrant, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().OAuthGrant.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withOAuthGrant sets the old OAuthGrant of the mutation. +func withOAuthGrant(node *OAuthGrant) oauthgrantOption { + return func(m *OAuthGrantMutation) { + m.oldValue = func(context.Context) (*OAuthGrant, 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 OAuthGrantMutation) 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 OAuthGrantMutation) 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 *OAuthGrantMutation) ID() (id int, 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 *OAuthGrantMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().OAuthGrant.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 *OAuthGrantMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *OAuthGrantMutation) 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 OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) 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 *OAuthGrantMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *OAuthGrantMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *OAuthGrantMutation) 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 OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) 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 *OAuthGrantMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *OAuthGrantMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *OAuthGrantMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) OldDeletedAt(ctx context.Context) (v *time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *OAuthGrantMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[oauthgrant.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *OAuthGrantMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[oauthgrant.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *OAuthGrantMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, oauthgrant.FieldDeletedAt) +} + +// SetUserID sets the "user_id" field. +func (m *OAuthGrantMutation) SetUserID(i int) { + m.user = &i +} + +// UserID returns the value of the "user_id" field in the mutation. +func (m *OAuthGrantMutation) UserID() (r int, exists bool) { + v := m.user + if v == nil { + return + } + return *v, true +} + +// OldUserID returns the old "user_id" field's value of the OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) OldUserID(ctx context.Context) (v int, 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 *OAuthGrantMutation) ResetUserID() { + m.user = nil +} + +// SetClientID sets the "client_id" field. +func (m *OAuthGrantMutation) SetClientID(i int) { + m.client = &i +} + +// ClientID returns the value of the "client_id" field in the mutation. +func (m *OAuthGrantMutation) ClientID() (r int, exists bool) { + v := m.client + if v == nil { + return + } + return *v, true +} + +// OldClientID returns the old "client_id" field's value of the OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) OldClientID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldClientID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldClientID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldClientID: %w", err) + } + return oldValue.ClientID, nil +} + +// ResetClientID resets all changes to the "client_id" field. +func (m *OAuthGrantMutation) ResetClientID() { + m.client = nil +} + +// SetScopes sets the "scopes" field. +func (m *OAuthGrantMutation) SetScopes(s []string) { + m.scopes = &s + m.appendscopes = nil +} + +// Scopes returns the value of the "scopes" field in the mutation. +func (m *OAuthGrantMutation) Scopes() (r []string, exists bool) { + v := m.scopes + if v == nil { + return + } + return *v, true +} + +// OldScopes returns the old "scopes" field's value of the OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) OldScopes(ctx context.Context) (v []string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldScopes is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldScopes requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldScopes: %w", err) + } + return oldValue.Scopes, nil +} + +// AppendScopes adds s to the "scopes" field. +func (m *OAuthGrantMutation) AppendScopes(s []string) { + m.appendscopes = append(m.appendscopes, s...) +} + +// AppendedScopes returns the list of values that were appended to the "scopes" field in this mutation. +func (m *OAuthGrantMutation) AppendedScopes() ([]string, bool) { + if len(m.appendscopes) == 0 { + return nil, false + } + return m.appendscopes, true +} + +// ResetScopes resets all changes to the "scopes" field. +func (m *OAuthGrantMutation) ResetScopes() { + m.scopes = nil + m.appendscopes = nil +} + +// SetLastUsedAt sets the "last_used_at" field. +func (m *OAuthGrantMutation) SetLastUsedAt(t time.Time) { + m.last_used_at = &t +} + +// LastUsedAt returns the value of the "last_used_at" field in the mutation. +func (m *OAuthGrantMutation) LastUsedAt() (r time.Time, exists bool) { + v := m.last_used_at + if v == nil { + return + } + return *v, true +} + +// OldLastUsedAt returns the old "last_used_at" field's value of the OAuthGrant entity. +// If the OAuthGrant 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 *OAuthGrantMutation) OldLastUsedAt(ctx context.Context) (v *time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLastUsedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLastUsedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLastUsedAt: %w", err) + } + return oldValue.LastUsedAt, nil +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (m *OAuthGrantMutation) ClearLastUsedAt() { + m.last_used_at = nil + m.clearedFields[oauthgrant.FieldLastUsedAt] = struct{}{} +} + +// LastUsedAtCleared returns if the "last_used_at" field was cleared in this mutation. +func (m *OAuthGrantMutation) LastUsedAtCleared() bool { + _, ok := m.clearedFields[oauthgrant.FieldLastUsedAt] + return ok +} + +// ResetLastUsedAt resets all changes to the "last_used_at" field. +func (m *OAuthGrantMutation) ResetLastUsedAt() { + m.last_used_at = nil + delete(m.clearedFields, oauthgrant.FieldLastUsedAt) +} + +// ClearUser clears the "user" edge to the User entity. +func (m *OAuthGrantMutation) ClearUser() { + m.cleareduser = true + m.clearedFields[oauthgrant.FieldUserID] = struct{}{} +} + +// UserCleared reports if the "user" edge to the User entity was cleared. +func (m *OAuthGrantMutation) 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 *OAuthGrantMutation) UserIDs() (ids []int) { + if id := m.user; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetUser resets all changes to the "user" edge. +func (m *OAuthGrantMutation) ResetUser() { + m.user = nil + m.cleareduser = false +} + +// ClearClient clears the "client" edge to the OAuthClient entity. +func (m *OAuthGrantMutation) ClearClient() { + m.clearedclient = true + m.clearedFields[oauthgrant.FieldClientID] = struct{}{} +} + +// ClientCleared reports if the "client" edge to the OAuthClient entity was cleared. +func (m *OAuthGrantMutation) ClientCleared() bool { + return m.clearedclient +} + +// ClientIDs returns the "client" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ClientID instead. It exists only for internal usage by the builders. +func (m *OAuthGrantMutation) ClientIDs() (ids []int) { + if id := m.client; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetClient resets all changes to the "client" edge. +func (m *OAuthGrantMutation) ResetClient() { + m.client = nil + m.clearedclient = false +} + +// Where appends a list predicates to the OAuthGrantMutation builder. +func (m *OAuthGrantMutation) Where(ps ...predicate.OAuthGrant) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the OAuthGrantMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *OAuthGrantMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.OAuthGrant, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *OAuthGrantMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *OAuthGrantMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (OAuthGrant). +func (m *OAuthGrantMutation) 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 *OAuthGrantMutation) Fields() []string { + fields := make([]string, 0, 7) + if m.created_at != nil { + fields = append(fields, oauthgrant.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, oauthgrant.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, oauthgrant.FieldDeletedAt) + } + if m.user != nil { + fields = append(fields, oauthgrant.FieldUserID) + } + if m.client != nil { + fields = append(fields, oauthgrant.FieldClientID) + } + if m.scopes != nil { + fields = append(fields, oauthgrant.FieldScopes) + } + if m.last_used_at != nil { + fields = append(fields, oauthgrant.FieldLastUsedAt) + } + 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 *OAuthGrantMutation) Field(name string) (ent.Value, bool) { + switch name { + case oauthgrant.FieldCreatedAt: + return m.CreatedAt() + case oauthgrant.FieldUpdatedAt: + return m.UpdatedAt() + case oauthgrant.FieldDeletedAt: + return m.DeletedAt() + case oauthgrant.FieldUserID: + return m.UserID() + case oauthgrant.FieldClientID: + return m.ClientID() + case oauthgrant.FieldScopes: + return m.Scopes() + case oauthgrant.FieldLastUsedAt: + return m.LastUsedAt() + } + 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 *OAuthGrantMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case oauthgrant.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case oauthgrant.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case oauthgrant.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case oauthgrant.FieldUserID: + return m.OldUserID(ctx) + case oauthgrant.FieldClientID: + return m.OldClientID(ctx) + case oauthgrant.FieldScopes: + return m.OldScopes(ctx) + case oauthgrant.FieldLastUsedAt: + return m.OldLastUsedAt(ctx) + } + return nil, fmt.Errorf("unknown OAuthGrant 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 *OAuthGrantMutation) SetField(name string, value ent.Value) error { + switch name { + case oauthgrant.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 oauthgrant.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 oauthgrant.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case oauthgrant.FieldUserID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUserID(v) + return nil + case oauthgrant.FieldClientID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetClientID(v) + return nil + case oauthgrant.FieldScopes: + v, ok := value.([]string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetScopes(v) + return nil + case oauthgrant.FieldLastUsedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLastUsedAt(v) + return nil + } + return fmt.Errorf("unknown OAuthGrant field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *OAuthGrantMutation) 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 *OAuthGrantMutation) 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 *OAuthGrantMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown OAuthGrant numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *OAuthGrantMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(oauthgrant.FieldDeletedAt) { + fields = append(fields, oauthgrant.FieldDeletedAt) + } + if m.FieldCleared(oauthgrant.FieldLastUsedAt) { + fields = append(fields, oauthgrant.FieldLastUsedAt) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *OAuthGrantMutation) 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 *OAuthGrantMutation) ClearField(name string) error { + switch name { + case oauthgrant.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case oauthgrant.FieldLastUsedAt: + m.ClearLastUsedAt() + return nil + } + return fmt.Errorf("unknown OAuthGrant 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 *OAuthGrantMutation) ResetField(name string) error { + switch name { + case oauthgrant.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case oauthgrant.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case oauthgrant.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case oauthgrant.FieldUserID: + m.ResetUserID() + return nil + case oauthgrant.FieldClientID: + m.ResetClientID() + return nil + case oauthgrant.FieldScopes: + m.ResetScopes() + return nil + case oauthgrant.FieldLastUsedAt: + m.ResetLastUsedAt() + return nil + } + return fmt.Errorf("unknown OAuthGrant field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *OAuthGrantMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.user != nil { + edges = append(edges, oauthgrant.EdgeUser) + } + if m.client != nil { + edges = append(edges, oauthgrant.EdgeClient) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *OAuthGrantMutation) AddedIDs(name string) []ent.Value { + switch name { + case oauthgrant.EdgeUser: + if id := m.user; id != nil { + return []ent.Value{*id} + } + case oauthgrant.EdgeClient: + if id := m.client; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *OAuthGrantMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *OAuthGrantMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *OAuthGrantMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.cleareduser { + edges = append(edges, oauthgrant.EdgeUser) + } + if m.clearedclient { + edges = append(edges, oauthgrant.EdgeClient) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *OAuthGrantMutation) EdgeCleared(name string) bool { + switch name { + case oauthgrant.EdgeUser: + return m.cleareduser + case oauthgrant.EdgeClient: + return m.clearedclient + } + 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 *OAuthGrantMutation) ClearEdge(name string) error { + switch name { + case oauthgrant.EdgeUser: + m.ClearUser() + return nil + case oauthgrant.EdgeClient: + m.ClearClient() + return nil + } + return fmt.Errorf("unknown OAuthGrant 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 *OAuthGrantMutation) ResetEdge(name string) error { + switch name { + case oauthgrant.EdgeUser: + m.ResetUser() + return nil + case oauthgrant.EdgeClient: + m.ResetClient() + return nil + } + return fmt.Errorf("unknown OAuthGrant edge %s", name) +} + // PasskeyMutation represents an operation that mutates the Passkey nodes in the graph. type PasskeyMutation struct { config @@ -13247,6 +15093,9 @@ type UserMutation struct { entities map[int]struct{} removedentities map[int]struct{} clearedentities bool + oauth_grants map[int]struct{} + removedoauth_grants map[int]struct{} + clearedoauth_grants bool done bool oldValue func(context.Context) (*User, error) predicates []predicate.User @@ -14285,6 +16134,60 @@ func (m *UserMutation) ResetEntities() { m.removedentities = nil } +// AddOauthGrantIDs adds the "oauth_grants" edge to the OAuthGrant entity by ids. +func (m *UserMutation) AddOauthGrantIDs(ids ...int) { + if m.oauth_grants == nil { + m.oauth_grants = make(map[int]struct{}) + } + for i := range ids { + m.oauth_grants[ids[i]] = struct{}{} + } +} + +// ClearOauthGrants clears the "oauth_grants" edge to the OAuthGrant entity. +func (m *UserMutation) ClearOauthGrants() { + m.clearedoauth_grants = true +} + +// OauthGrantsCleared reports if the "oauth_grants" edge to the OAuthGrant entity was cleared. +func (m *UserMutation) OauthGrantsCleared() bool { + return m.clearedoauth_grants +} + +// RemoveOauthGrantIDs removes the "oauth_grants" edge to the OAuthGrant entity by IDs. +func (m *UserMutation) RemoveOauthGrantIDs(ids ...int) { + if m.removedoauth_grants == nil { + m.removedoauth_grants = make(map[int]struct{}) + } + for i := range ids { + delete(m.oauth_grants, ids[i]) + m.removedoauth_grants[ids[i]] = struct{}{} + } +} + +// RemovedOauthGrants returns the removed IDs of the "oauth_grants" edge to the OAuthGrant entity. +func (m *UserMutation) RemovedOauthGrantsIDs() (ids []int) { + for id := range m.removedoauth_grants { + ids = append(ids, id) + } + return +} + +// OauthGrantsIDs returns the "oauth_grants" edge IDs in the mutation. +func (m *UserMutation) OauthGrantsIDs() (ids []int) { + for id := range m.oauth_grants { + ids = append(ids, id) + } + return +} + +// ResetOauthGrants resets all changes to the "oauth_grants" edge. +func (m *UserMutation) ResetOauthGrants() { + m.oauth_grants = nil + m.clearedoauth_grants = false + m.removedoauth_grants = nil +} + // Where appends a list predicates to the UserMutation builder. func (m *UserMutation) Where(ps ...predicate.User) { m.predicates = append(m.predicates, ps...) @@ -14653,7 +16556,7 @@ func (m *UserMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *UserMutation) AddedEdges() []string { - edges := make([]string, 0, 8) + edges := make([]string, 0, 9) if m.group != nil { edges = append(edges, user.EdgeGroup) } @@ -14678,6 +16581,9 @@ func (m *UserMutation) AddedEdges() []string { if m.entities != nil { edges = append(edges, user.EdgeEntities) } + if m.oauth_grants != nil { + edges = append(edges, user.EdgeOauthGrants) + } return edges } @@ -14731,13 +16637,19 @@ func (m *UserMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case user.EdgeOauthGrants: + ids := make([]ent.Value, 0, len(m.oauth_grants)) + for id := range m.oauth_grants { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *UserMutation) RemovedEdges() []string { - edges := make([]string, 0, 8) + edges := make([]string, 0, 9) if m.removedfiles != nil { edges = append(edges, user.EdgeFiles) } @@ -14759,6 +16671,9 @@ func (m *UserMutation) RemovedEdges() []string { if m.removedentities != nil { edges = append(edges, user.EdgeEntities) } + if m.removedoauth_grants != nil { + edges = append(edges, user.EdgeOauthGrants) + } return edges } @@ -14808,13 +16723,19 @@ func (m *UserMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case user.EdgeOauthGrants: + ids := make([]ent.Value, 0, len(m.removedoauth_grants)) + for id := range m.removedoauth_grants { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *UserMutation) ClearedEdges() []string { - edges := make([]string, 0, 8) + edges := make([]string, 0, 9) if m.clearedgroup { edges = append(edges, user.EdgeGroup) } @@ -14839,6 +16760,9 @@ func (m *UserMutation) ClearedEdges() []string { if m.clearedentities { edges = append(edges, user.EdgeEntities) } + if m.clearedoauth_grants { + edges = append(edges, user.EdgeOauthGrants) + } return edges } @@ -14862,6 +16786,8 @@ func (m *UserMutation) EdgeCleared(name string) bool { return m.clearedfsevents case user.EdgeEntities: return m.clearedentities + case user.EdgeOauthGrants: + return m.clearedoauth_grants } return false } @@ -14905,6 +16831,9 @@ func (m *UserMutation) ResetEdge(name string) error { case user.EdgeEntities: m.ResetEntities() return nil + case user.EdgeOauthGrants: + m.ResetOauthGrants() + return nil } return fmt.Errorf("unknown User edge %s", name) } diff --git a/ent/mutationhelper.go b/ent/mutationhelper.go index 1d337357..2361bddf 100644 --- a/ent/mutationhelper.go +++ b/ent/mutationhelper.go @@ -52,6 +52,18 @@ func (m *NodeMutation) SetRawID(t int) { // SetUpdatedAt sets the "updated_at" field. +func (m *OAuthClientMutation) SetRawID(t int) { + m.id = &t +} + +// SetUpdatedAt sets the "updated_at" field. + +func (m *OAuthGrantMutation) SetRawID(t int) { + m.id = &t +} + +// SetUpdatedAt sets the "updated_at" field. + func (m *PasskeyMutation) SetRawID(t int) { m.id = &t } diff --git a/ent/oauthclient.go b/ent/oauthclient.go new file mode 100644 index 00000000..26ae3fc3 --- /dev/null +++ b/ent/oauthclient.go @@ -0,0 +1,262 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// OAuthClient is the model entity for the OAuthClient schema. +type OAuthClient struct { + config `json:"-"` + // ID of the ent. + ID int `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"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt *time.Time `json:"deleted_at,omitempty"` + // GUID holds the value of the "guid" field. + GUID string `json:"guid,omitempty"` + // Secret holds the value of the "secret" field. + Secret string `json:"-"` + // Name holds the value of the "name" field. + Name string `json:"name,omitempty"` + // HomepageURL holds the value of the "homepage_url" field. + HomepageURL string `json:"homepage_url,omitempty"` + // RedirectUris holds the value of the "redirect_uris" field. + RedirectUris []string `json:"redirect_uris,omitempty"` + // Scopes holds the value of the "scopes" field. + Scopes []string `json:"scopes,omitempty"` + // Props holds the value of the "props" field. + Props *types.OAuthClientProps `json:"props,omitempty"` + // IsEnabled holds the value of the "is_enabled" field. + IsEnabled bool `json:"is_enabled,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the OAuthClientQuery when eager-loading is set. + Edges OAuthClientEdges `json:"edges"` + selectValues sql.SelectValues +} + +// OAuthClientEdges holds the relations/edges for other nodes in the graph. +type OAuthClientEdges struct { + // Grants holds the value of the grants edge. + Grants []*OAuthGrant `json:"grants,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// GrantsOrErr returns the Grants value or an error if the edge +// was not loaded in eager-loading. +func (e OAuthClientEdges) GrantsOrErr() ([]*OAuthGrant, error) { + if e.loadedTypes[0] { + return e.Grants, nil + } + return nil, &NotLoadedError{edge: "grants"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*OAuthClient) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case oauthclient.FieldRedirectUris, oauthclient.FieldScopes, oauthclient.FieldProps: + values[i] = new([]byte) + case oauthclient.FieldIsEnabled: + values[i] = new(sql.NullBool) + case oauthclient.FieldID: + values[i] = new(sql.NullInt64) + case oauthclient.FieldGUID, oauthclient.FieldSecret, oauthclient.FieldName, oauthclient.FieldHomepageURL: + values[i] = new(sql.NullString) + case oauthclient.FieldCreatedAt, oauthclient.FieldUpdatedAt, oauthclient.FieldDeletedAt: + 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 OAuthClient fields. +func (oc *OAuthClient) 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 oauthclient.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + oc.ID = int(value.Int64) + case oauthclient.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 { + oc.CreatedAt = value.Time + } + case oauthclient.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 { + oc.UpdatedAt = value.Time + } + case oauthclient.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + oc.DeletedAt = new(time.Time) + *oc.DeletedAt = value.Time + } + case oauthclient.FieldGUID: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field guid", values[i]) + } else if value.Valid { + oc.GUID = value.String + } + case oauthclient.FieldSecret: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field secret", values[i]) + } else if value.Valid { + oc.Secret = value.String + } + case oauthclient.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + oc.Name = value.String + } + case oauthclient.FieldHomepageURL: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field homepage_url", values[i]) + } else if value.Valid { + oc.HomepageURL = value.String + } + case oauthclient.FieldRedirectUris: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field redirect_uris", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &oc.RedirectUris); err != nil { + return fmt.Errorf("unmarshal field redirect_uris: %w", err) + } + } + case oauthclient.FieldScopes: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field scopes", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &oc.Scopes); err != nil { + return fmt.Errorf("unmarshal field scopes: %w", err) + } + } + case oauthclient.FieldProps: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field props", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &oc.Props); err != nil { + return fmt.Errorf("unmarshal field props: %w", err) + } + } + case oauthclient.FieldIsEnabled: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field is_enabled", values[i]) + } else if value.Valid { + oc.IsEnabled = value.Bool + } + default: + oc.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the OAuthClient. +// This includes values selected through modifiers, order, etc. +func (oc *OAuthClient) Value(name string) (ent.Value, error) { + return oc.selectValues.Get(name) +} + +// QueryGrants queries the "grants" edge of the OAuthClient entity. +func (oc *OAuthClient) QueryGrants() *OAuthGrantQuery { + return NewOAuthClientClient(oc.config).QueryGrants(oc) +} + +// Update returns a builder for updating this OAuthClient. +// Note that you need to call OAuthClient.Unwrap() before calling this method if this OAuthClient +// was returned from a transaction, and the transaction was committed or rolled back. +func (oc *OAuthClient) Update() *OAuthClientUpdateOne { + return NewOAuthClientClient(oc.config).UpdateOne(oc) +} + +// Unwrap unwraps the OAuthClient 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 (oc *OAuthClient) Unwrap() *OAuthClient { + _tx, ok := oc.config.driver.(*txDriver) + if !ok { + panic("ent: OAuthClient is not a transactional entity") + } + oc.config.driver = _tx.drv + return oc +} + +// String implements the fmt.Stringer. +func (oc *OAuthClient) String() string { + var builder strings.Builder + builder.WriteString("OAuthClient(") + builder.WriteString(fmt.Sprintf("id=%v, ", oc.ID)) + builder.WriteString("created_at=") + builder.WriteString(oc.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(oc.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + if v := oc.DeletedAt; v != nil { + builder.WriteString("deleted_at=") + builder.WriteString(v.Format(time.ANSIC)) + } + builder.WriteString(", ") + builder.WriteString("guid=") + builder.WriteString(oc.GUID) + builder.WriteString(", ") + builder.WriteString("secret=") + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(oc.Name) + builder.WriteString(", ") + builder.WriteString("homepage_url=") + builder.WriteString(oc.HomepageURL) + builder.WriteString(", ") + builder.WriteString("redirect_uris=") + builder.WriteString(fmt.Sprintf("%v", oc.RedirectUris)) + builder.WriteString(", ") + builder.WriteString("scopes=") + builder.WriteString(fmt.Sprintf("%v", oc.Scopes)) + builder.WriteString(", ") + builder.WriteString("props=") + builder.WriteString(fmt.Sprintf("%v", oc.Props)) + builder.WriteString(", ") + builder.WriteString("is_enabled=") + builder.WriteString(fmt.Sprintf("%v", oc.IsEnabled)) + builder.WriteByte(')') + return builder.String() +} + +// SetGrants manually set the edge as loaded state. +func (e *OAuthClient) SetGrants(v []*OAuthGrant) { + e.Edges.Grants = v + e.Edges.loadedTypes[0] = true +} + +// OAuthClients is a parsable slice of OAuthClient. +type OAuthClients []*OAuthClient diff --git a/ent/oauthclient/oauthclient.go b/ent/oauthclient/oauthclient.go new file mode 100644 index 00000000..71eee115 --- /dev/null +++ b/ent/oauthclient/oauthclient.go @@ -0,0 +1,179 @@ +// Code generated by ent, DO NOT EDIT. + +package oauthclient + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +const ( + // Label holds the string label denoting the oauthclient type in the database. + Label = "oauth_client" + // 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" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldGUID holds the string denoting the guid field in the database. + FieldGUID = "guid" + // FieldSecret holds the string denoting the secret field in the database. + FieldSecret = "secret" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldHomepageURL holds the string denoting the homepage_url field in the database. + FieldHomepageURL = "homepage_url" + // FieldRedirectUris holds the string denoting the redirect_uris field in the database. + FieldRedirectUris = "redirect_uris" + // FieldScopes holds the string denoting the scopes field in the database. + FieldScopes = "scopes" + // FieldProps holds the string denoting the props field in the database. + FieldProps = "props" + // FieldIsEnabled holds the string denoting the is_enabled field in the database. + FieldIsEnabled = "is_enabled" + // EdgeGrants holds the string denoting the grants edge name in mutations. + EdgeGrants = "grants" + // Table holds the table name of the oauthclient in the database. + Table = "oauth_clients" + // GrantsTable is the table that holds the grants relation/edge. + GrantsTable = "oauth_grants" + // GrantsInverseTable is the table name for the OAuthGrant entity. + // It exists in this package in order to avoid circular dependency with the "oauthgrant" package. + GrantsInverseTable = "oauth_grants" + // GrantsColumn is the table column denoting the grants relation/edge. + GrantsColumn = "client_id" +) + +// Columns holds all SQL columns for oauthclient fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldGUID, + FieldSecret, + FieldName, + FieldHomepageURL, + FieldRedirectUris, + FieldScopes, + FieldProps, + FieldIsEnabled, +} + +// 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 +} + +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/cloudreve/Cloudreve/v4/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // 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 + // GUIDValidator is a validator for the "guid" field. It is called by the builders before save. + GUIDValidator func(string) error + // SecretValidator is a validator for the "secret" field. It is called by the builders before save. + SecretValidator func(string) error + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // HomepageURLValidator is a validator for the "homepage_url" field. It is called by the builders before save. + HomepageURLValidator func(string) error + // DefaultRedirectUris holds the default value on creation for the "redirect_uris" field. + DefaultRedirectUris []string + // DefaultScopes holds the default value on creation for the "scopes" field. + DefaultScopes []string + // DefaultProps holds the default value on creation for the "props" field. + DefaultProps *types.OAuthClientProps + // DefaultIsEnabled holds the default value on creation for the "is_enabled" field. + DefaultIsEnabled bool +) + +// OrderOption defines the ordering options for the OAuthClient 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() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByGUID orders the results by the guid field. +func ByGUID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldGUID, opts...).ToFunc() +} + +// BySecret orders the results by the secret field. +func BySecret(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSecret, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByHomepageURL orders the results by the homepage_url field. +func ByHomepageURL(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldHomepageURL, opts...).ToFunc() +} + +// ByIsEnabled orders the results by the is_enabled field. +func ByIsEnabled(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldIsEnabled, opts...).ToFunc() +} + +// ByGrantsCount orders the results by grants count. +func ByGrantsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newGrantsStep(), opts...) + } +} + +// ByGrants orders the results by grants terms. +func ByGrants(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newGrantsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} +func newGrantsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(GrantsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, GrantsTable, GrantsColumn), + ) +} diff --git a/ent/oauthclient/where.go b/ent/oauthclient/where.go new file mode 100644 index 00000000..147c4c7b --- /dev/null +++ b/ent/oauthclient/where.go @@ -0,0 +1,544 @@ +// Code generated by ent, DO NOT EDIT. + +package oauthclient + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.OAuthClient { + return predicate.OAuthClient(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.OAuthClient { + return predicate.OAuthClient(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.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldDeletedAt, v)) +} + +// GUID applies equality check predicate on the "guid" field. It's identical to GUIDEQ. +func GUID(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldGUID, v)) +} + +// Secret applies equality check predicate on the "secret" field. It's identical to SecretEQ. +func Secret(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldSecret, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldName, v)) +} + +// HomepageURL applies equality check predicate on the "homepage_url" field. It's identical to HomepageURLEQ. +func HomepageURL(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldHomepageURL, v)) +} + +// IsEnabled applies equality check predicate on the "is_enabled" field. It's identical to IsEnabledEQ. +func IsEnabled(v bool) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldIsEnabled, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotNull(FieldDeletedAt)) +} + +// GUIDEQ applies the EQ predicate on the "guid" field. +func GUIDEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldGUID, v)) +} + +// GUIDNEQ applies the NEQ predicate on the "guid" field. +func GUIDNEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldGUID, v)) +} + +// GUIDIn applies the In predicate on the "guid" field. +func GUIDIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldGUID, vs...)) +} + +// GUIDNotIn applies the NotIn predicate on the "guid" field. +func GUIDNotIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldGUID, vs...)) +} + +// GUIDGT applies the GT predicate on the "guid" field. +func GUIDGT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldGUID, v)) +} + +// GUIDGTE applies the GTE predicate on the "guid" field. +func GUIDGTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldGUID, v)) +} + +// GUIDLT applies the LT predicate on the "guid" field. +func GUIDLT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldGUID, v)) +} + +// GUIDLTE applies the LTE predicate on the "guid" field. +func GUIDLTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldGUID, v)) +} + +// GUIDContains applies the Contains predicate on the "guid" field. +func GUIDContains(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContains(FieldGUID, v)) +} + +// GUIDHasPrefix applies the HasPrefix predicate on the "guid" field. +func GUIDHasPrefix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasPrefix(FieldGUID, v)) +} + +// GUIDHasSuffix applies the HasSuffix predicate on the "guid" field. +func GUIDHasSuffix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasSuffix(FieldGUID, v)) +} + +// GUIDEqualFold applies the EqualFold predicate on the "guid" field. +func GUIDEqualFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEqualFold(FieldGUID, v)) +} + +// GUIDContainsFold applies the ContainsFold predicate on the "guid" field. +func GUIDContainsFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContainsFold(FieldGUID, v)) +} + +// SecretEQ applies the EQ predicate on the "secret" field. +func SecretEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldSecret, v)) +} + +// SecretNEQ applies the NEQ predicate on the "secret" field. +func SecretNEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldSecret, v)) +} + +// SecretIn applies the In predicate on the "secret" field. +func SecretIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldSecret, vs...)) +} + +// SecretNotIn applies the NotIn predicate on the "secret" field. +func SecretNotIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldSecret, vs...)) +} + +// SecretGT applies the GT predicate on the "secret" field. +func SecretGT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldSecret, v)) +} + +// SecretGTE applies the GTE predicate on the "secret" field. +func SecretGTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldSecret, v)) +} + +// SecretLT applies the LT predicate on the "secret" field. +func SecretLT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldSecret, v)) +} + +// SecretLTE applies the LTE predicate on the "secret" field. +func SecretLTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldSecret, v)) +} + +// SecretContains applies the Contains predicate on the "secret" field. +func SecretContains(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContains(FieldSecret, v)) +} + +// SecretHasPrefix applies the HasPrefix predicate on the "secret" field. +func SecretHasPrefix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasPrefix(FieldSecret, v)) +} + +// SecretHasSuffix applies the HasSuffix predicate on the "secret" field. +func SecretHasSuffix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasSuffix(FieldSecret, v)) +} + +// SecretEqualFold applies the EqualFold predicate on the "secret" field. +func SecretEqualFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEqualFold(FieldSecret, v)) +} + +// SecretContainsFold applies the ContainsFold predicate on the "secret" field. +func SecretContainsFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContainsFold(FieldSecret, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContainsFold(FieldName, v)) +} + +// HomepageURLEQ applies the EQ predicate on the "homepage_url" field. +func HomepageURLEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldHomepageURL, v)) +} + +// HomepageURLNEQ applies the NEQ predicate on the "homepage_url" field. +func HomepageURLNEQ(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldHomepageURL, v)) +} + +// HomepageURLIn applies the In predicate on the "homepage_url" field. +func HomepageURLIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIn(FieldHomepageURL, vs...)) +} + +// HomepageURLNotIn applies the NotIn predicate on the "homepage_url" field. +func HomepageURLNotIn(vs ...string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotIn(FieldHomepageURL, vs...)) +} + +// HomepageURLGT applies the GT predicate on the "homepage_url" field. +func HomepageURLGT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGT(FieldHomepageURL, v)) +} + +// HomepageURLGTE applies the GTE predicate on the "homepage_url" field. +func HomepageURLGTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldGTE(FieldHomepageURL, v)) +} + +// HomepageURLLT applies the LT predicate on the "homepage_url" field. +func HomepageURLLT(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLT(FieldHomepageURL, v)) +} + +// HomepageURLLTE applies the LTE predicate on the "homepage_url" field. +func HomepageURLLTE(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldLTE(FieldHomepageURL, v)) +} + +// HomepageURLContains applies the Contains predicate on the "homepage_url" field. +func HomepageURLContains(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContains(FieldHomepageURL, v)) +} + +// HomepageURLHasPrefix applies the HasPrefix predicate on the "homepage_url" field. +func HomepageURLHasPrefix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasPrefix(FieldHomepageURL, v)) +} + +// HomepageURLHasSuffix applies the HasSuffix predicate on the "homepage_url" field. +func HomepageURLHasSuffix(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldHasSuffix(FieldHomepageURL, v)) +} + +// HomepageURLIsNil applies the IsNil predicate on the "homepage_url" field. +func HomepageURLIsNil() predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldIsNull(FieldHomepageURL)) +} + +// HomepageURLNotNil applies the NotNil predicate on the "homepage_url" field. +func HomepageURLNotNil() predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNotNull(FieldHomepageURL)) +} + +// HomepageURLEqualFold applies the EqualFold predicate on the "homepage_url" field. +func HomepageURLEqualFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEqualFold(FieldHomepageURL, v)) +} + +// HomepageURLContainsFold applies the ContainsFold predicate on the "homepage_url" field. +func HomepageURLContainsFold(v string) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldContainsFold(FieldHomepageURL, v)) +} + +// IsEnabledEQ applies the EQ predicate on the "is_enabled" field. +func IsEnabledEQ(v bool) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldEQ(FieldIsEnabled, v)) +} + +// IsEnabledNEQ applies the NEQ predicate on the "is_enabled" field. +func IsEnabledNEQ(v bool) predicate.OAuthClient { + return predicate.OAuthClient(sql.FieldNEQ(FieldIsEnabled, v)) +} + +// HasGrants applies the HasEdge predicate on the "grants" edge. +func HasGrants() predicate.OAuthClient { + return predicate.OAuthClient(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, GrantsTable, GrantsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasGrantsWith applies the HasEdge predicate on the "grants" edge with a given conditions (other predicates). +func HasGrantsWith(preds ...predicate.OAuthGrant) predicate.OAuthClient { + return predicate.OAuthClient(func(s *sql.Selector) { + step := newGrantsStep() + 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.OAuthClient) predicate.OAuthClient { + return predicate.OAuthClient(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.OAuthClient) predicate.OAuthClient { + return predicate.OAuthClient(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.OAuthClient) predicate.OAuthClient { + return predicate.OAuthClient(sql.NotPredicates(p)) +} diff --git a/ent/oauthclient_create.go b/ent/oauthclient_create.go new file mode 100644 index 00000000..ef04b78e --- /dev/null +++ b/ent/oauthclient_create.go @@ -0,0 +1,1135 @@ +// 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/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// OAuthClientCreate is the builder for creating a OAuthClient entity. +type OAuthClientCreate struct { + config + mutation *OAuthClientMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (occ *OAuthClientCreate) SetCreatedAt(t time.Time) *OAuthClientCreate { + occ.mutation.SetCreatedAt(t) + return occ +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (occ *OAuthClientCreate) SetNillableCreatedAt(t *time.Time) *OAuthClientCreate { + if t != nil { + occ.SetCreatedAt(*t) + } + return occ +} + +// SetUpdatedAt sets the "updated_at" field. +func (occ *OAuthClientCreate) SetUpdatedAt(t time.Time) *OAuthClientCreate { + occ.mutation.SetUpdatedAt(t) + return occ +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (occ *OAuthClientCreate) SetNillableUpdatedAt(t *time.Time) *OAuthClientCreate { + if t != nil { + occ.SetUpdatedAt(*t) + } + return occ +} + +// SetDeletedAt sets the "deleted_at" field. +func (occ *OAuthClientCreate) SetDeletedAt(t time.Time) *OAuthClientCreate { + occ.mutation.SetDeletedAt(t) + return occ +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (occ *OAuthClientCreate) SetNillableDeletedAt(t *time.Time) *OAuthClientCreate { + if t != nil { + occ.SetDeletedAt(*t) + } + return occ +} + +// SetGUID sets the "guid" field. +func (occ *OAuthClientCreate) SetGUID(s string) *OAuthClientCreate { + occ.mutation.SetGUID(s) + return occ +} + +// SetSecret sets the "secret" field. +func (occ *OAuthClientCreate) SetSecret(s string) *OAuthClientCreate { + occ.mutation.SetSecret(s) + return occ +} + +// SetName sets the "name" field. +func (occ *OAuthClientCreate) SetName(s string) *OAuthClientCreate { + occ.mutation.SetName(s) + return occ +} + +// SetHomepageURL sets the "homepage_url" field. +func (occ *OAuthClientCreate) SetHomepageURL(s string) *OAuthClientCreate { + occ.mutation.SetHomepageURL(s) + return occ +} + +// SetNillableHomepageURL sets the "homepage_url" field if the given value is not nil. +func (occ *OAuthClientCreate) SetNillableHomepageURL(s *string) *OAuthClientCreate { + if s != nil { + occ.SetHomepageURL(*s) + } + return occ +} + +// SetRedirectUris sets the "redirect_uris" field. +func (occ *OAuthClientCreate) SetRedirectUris(s []string) *OAuthClientCreate { + occ.mutation.SetRedirectUris(s) + return occ +} + +// SetScopes sets the "scopes" field. +func (occ *OAuthClientCreate) SetScopes(s []string) *OAuthClientCreate { + occ.mutation.SetScopes(s) + return occ +} + +// SetProps sets the "props" field. +func (occ *OAuthClientCreate) SetProps(tacp *types.OAuthClientProps) *OAuthClientCreate { + occ.mutation.SetProps(tacp) + return occ +} + +// SetIsEnabled sets the "is_enabled" field. +func (occ *OAuthClientCreate) SetIsEnabled(b bool) *OAuthClientCreate { + occ.mutation.SetIsEnabled(b) + return occ +} + +// SetNillableIsEnabled sets the "is_enabled" field if the given value is not nil. +func (occ *OAuthClientCreate) SetNillableIsEnabled(b *bool) *OAuthClientCreate { + if b != nil { + occ.SetIsEnabled(*b) + } + return occ +} + +// AddGrantIDs adds the "grants" edge to the OAuthGrant entity by IDs. +func (occ *OAuthClientCreate) AddGrantIDs(ids ...int) *OAuthClientCreate { + occ.mutation.AddGrantIDs(ids...) + return occ +} + +// AddGrants adds the "grants" edges to the OAuthGrant entity. +func (occ *OAuthClientCreate) AddGrants(o ...*OAuthGrant) *OAuthClientCreate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return occ.AddGrantIDs(ids...) +} + +// Mutation returns the OAuthClientMutation object of the builder. +func (occ *OAuthClientCreate) Mutation() *OAuthClientMutation { + return occ.mutation +} + +// Save creates the OAuthClient in the database. +func (occ *OAuthClientCreate) Save(ctx context.Context) (*OAuthClient, error) { + if err := occ.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, occ.sqlSave, occ.mutation, occ.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (occ *OAuthClientCreate) SaveX(ctx context.Context) *OAuthClient { + v, err := occ.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (occ *OAuthClientCreate) Exec(ctx context.Context) error { + _, err := occ.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (occ *OAuthClientCreate) ExecX(ctx context.Context) { + if err := occ.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (occ *OAuthClientCreate) defaults() error { + if _, ok := occ.mutation.CreatedAt(); !ok { + if oauthclient.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthclient.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := oauthclient.DefaultCreatedAt() + occ.mutation.SetCreatedAt(v) + } + if _, ok := occ.mutation.UpdatedAt(); !ok { + if oauthclient.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthclient.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthclient.DefaultUpdatedAt() + occ.mutation.SetUpdatedAt(v) + } + if _, ok := occ.mutation.RedirectUris(); !ok { + v := oauthclient.DefaultRedirectUris + occ.mutation.SetRedirectUris(v) + } + if _, ok := occ.mutation.Scopes(); !ok { + v := oauthclient.DefaultScopes + occ.mutation.SetScopes(v) + } + if _, ok := occ.mutation.Props(); !ok { + v := oauthclient.DefaultProps + occ.mutation.SetProps(v) + } + if _, ok := occ.mutation.IsEnabled(); !ok { + v := oauthclient.DefaultIsEnabled + occ.mutation.SetIsEnabled(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (occ *OAuthClientCreate) check() error { + if _, ok := occ.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "OAuthClient.created_at"`)} + } + if _, ok := occ.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "OAuthClient.updated_at"`)} + } + if _, ok := occ.mutation.GUID(); !ok { + return &ValidationError{Name: "guid", err: errors.New(`ent: missing required field "OAuthClient.guid"`)} + } + if v, ok := occ.mutation.GUID(); ok { + if err := oauthclient.GUIDValidator(v); err != nil { + return &ValidationError{Name: "guid", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.guid": %w`, err)} + } + } + if _, ok := occ.mutation.Secret(); !ok { + return &ValidationError{Name: "secret", err: errors.New(`ent: missing required field "OAuthClient.secret"`)} + } + if v, ok := occ.mutation.Secret(); ok { + if err := oauthclient.SecretValidator(v); err != nil { + return &ValidationError{Name: "secret", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.secret": %w`, err)} + } + } + if _, ok := occ.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "OAuthClient.name"`)} + } + if v, ok := occ.mutation.Name(); ok { + if err := oauthclient.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.name": %w`, err)} + } + } + if v, ok := occ.mutation.HomepageURL(); ok { + if err := oauthclient.HomepageURLValidator(v); err != nil { + return &ValidationError{Name: "homepage_url", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.homepage_url": %w`, err)} + } + } + if _, ok := occ.mutation.RedirectUris(); !ok { + return &ValidationError{Name: "redirect_uris", err: errors.New(`ent: missing required field "OAuthClient.redirect_uris"`)} + } + if _, ok := occ.mutation.Scopes(); !ok { + return &ValidationError{Name: "scopes", err: errors.New(`ent: missing required field "OAuthClient.scopes"`)} + } + if _, ok := occ.mutation.Props(); !ok { + return &ValidationError{Name: "props", err: errors.New(`ent: missing required field "OAuthClient.props"`)} + } + if _, ok := occ.mutation.IsEnabled(); !ok { + return &ValidationError{Name: "is_enabled", err: errors.New(`ent: missing required field "OAuthClient.is_enabled"`)} + } + return nil +} + +func (occ *OAuthClientCreate) sqlSave(ctx context.Context) (*OAuthClient, error) { + if err := occ.check(); err != nil { + return nil, err + } + _node, _spec := occ.createSpec() + if err := sqlgraph.CreateNode(ctx, occ.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 = int(id) + occ.mutation.id = &_node.ID + occ.mutation.done = true + return _node, nil +} + +func (occ *OAuthClientCreate) createSpec() (*OAuthClient, *sqlgraph.CreateSpec) { + var ( + _node = &OAuthClient{config: occ.config} + _spec = sqlgraph.NewCreateSpec(oauthclient.Table, sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt)) + ) + + if id, ok := occ.mutation.ID(); ok { + _node.ID = id + id64 := int64(id) + _spec.ID.Value = id64 + } + + _spec.OnConflict = occ.conflict + if value, ok := occ.mutation.CreatedAt(); ok { + _spec.SetField(oauthclient.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := occ.mutation.UpdatedAt(); ok { + _spec.SetField(oauthclient.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := occ.mutation.DeletedAt(); ok { + _spec.SetField(oauthclient.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = &value + } + if value, ok := occ.mutation.GUID(); ok { + _spec.SetField(oauthclient.FieldGUID, field.TypeString, value) + _node.GUID = value + } + if value, ok := occ.mutation.Secret(); ok { + _spec.SetField(oauthclient.FieldSecret, field.TypeString, value) + _node.Secret = value + } + if value, ok := occ.mutation.Name(); ok { + _spec.SetField(oauthclient.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := occ.mutation.HomepageURL(); ok { + _spec.SetField(oauthclient.FieldHomepageURL, field.TypeString, value) + _node.HomepageURL = value + } + if value, ok := occ.mutation.RedirectUris(); ok { + _spec.SetField(oauthclient.FieldRedirectUris, field.TypeJSON, value) + _node.RedirectUris = value + } + if value, ok := occ.mutation.Scopes(); ok { + _spec.SetField(oauthclient.FieldScopes, field.TypeJSON, value) + _node.Scopes = value + } + if value, ok := occ.mutation.Props(); ok { + _spec.SetField(oauthclient.FieldProps, field.TypeJSON, value) + _node.Props = value + } + if value, ok := occ.mutation.IsEnabled(); ok { + _spec.SetField(oauthclient.FieldIsEnabled, field.TypeBool, value) + _node.IsEnabled = value + } + if nodes := occ.mutation.GrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _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.OAuthClient.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.OAuthClientUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (occ *OAuthClientCreate) OnConflict(opts ...sql.ConflictOption) *OAuthClientUpsertOne { + occ.conflict = opts + return &OAuthClientUpsertOne{ + create: occ, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (occ *OAuthClientCreate) OnConflictColumns(columns ...string) *OAuthClientUpsertOne { + occ.conflict = append(occ.conflict, sql.ConflictColumns(columns...)) + return &OAuthClientUpsertOne{ + create: occ, + } +} + +type ( + // OAuthClientUpsertOne is the builder for "upsert"-ing + // one OAuthClient node. + OAuthClientUpsertOne struct { + create *OAuthClientCreate + } + + // OAuthClientUpsert is the "OnConflict" setter. + OAuthClientUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthClientUpsert) SetUpdatedAt(v time.Time) *OAuthClientUpsert { + u.Set(oauthclient.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateUpdatedAt() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldUpdatedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthClientUpsert) SetDeletedAt(v time.Time) *OAuthClientUpsert { + u.Set(oauthclient.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateDeletedAt() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthClientUpsert) ClearDeletedAt() *OAuthClientUpsert { + u.SetNull(oauthclient.FieldDeletedAt) + return u +} + +// SetGUID sets the "guid" field. +func (u *OAuthClientUpsert) SetGUID(v string) *OAuthClientUpsert { + u.Set(oauthclient.FieldGUID, v) + return u +} + +// UpdateGUID sets the "guid" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateGUID() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldGUID) + return u +} + +// SetSecret sets the "secret" field. +func (u *OAuthClientUpsert) SetSecret(v string) *OAuthClientUpsert { + u.Set(oauthclient.FieldSecret, v) + return u +} + +// UpdateSecret sets the "secret" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateSecret() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldSecret) + return u +} + +// SetName sets the "name" field. +func (u *OAuthClientUpsert) SetName(v string) *OAuthClientUpsert { + u.Set(oauthclient.FieldName, v) + return u +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateName() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldName) + return u +} + +// SetHomepageURL sets the "homepage_url" field. +func (u *OAuthClientUpsert) SetHomepageURL(v string) *OAuthClientUpsert { + u.Set(oauthclient.FieldHomepageURL, v) + return u +} + +// UpdateHomepageURL sets the "homepage_url" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateHomepageURL() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldHomepageURL) + return u +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (u *OAuthClientUpsert) ClearHomepageURL() *OAuthClientUpsert { + u.SetNull(oauthclient.FieldHomepageURL) + return u +} + +// SetRedirectUris sets the "redirect_uris" field. +func (u *OAuthClientUpsert) SetRedirectUris(v []string) *OAuthClientUpsert { + u.Set(oauthclient.FieldRedirectUris, v) + return u +} + +// UpdateRedirectUris sets the "redirect_uris" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateRedirectUris() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldRedirectUris) + return u +} + +// SetScopes sets the "scopes" field. +func (u *OAuthClientUpsert) SetScopes(v []string) *OAuthClientUpsert { + u.Set(oauthclient.FieldScopes, v) + return u +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateScopes() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldScopes) + return u +} + +// SetProps sets the "props" field. +func (u *OAuthClientUpsert) SetProps(v *types.OAuthClientProps) *OAuthClientUpsert { + u.Set(oauthclient.FieldProps, v) + return u +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateProps() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldProps) + return u +} + +// SetIsEnabled sets the "is_enabled" field. +func (u *OAuthClientUpsert) SetIsEnabled(v bool) *OAuthClientUpsert { + u.Set(oauthclient.FieldIsEnabled, v) + return u +} + +// UpdateIsEnabled sets the "is_enabled" field to the value that was provided on create. +func (u *OAuthClientUpsert) UpdateIsEnabled() *OAuthClientUpsert { + u.SetExcluded(oauthclient.FieldIsEnabled) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *OAuthClientUpsertOne) UpdateNewValues() *OAuthClientUpsertOne { + 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(oauthclient.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *OAuthClientUpsertOne) Ignore() *OAuthClientUpsertOne { + 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 *OAuthClientUpsertOne) DoNothing() *OAuthClientUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the OAuthClientCreate.OnConflict +// documentation for more info. +func (u *OAuthClientUpsertOne) Update(set func(*OAuthClientUpsert)) *OAuthClientUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&OAuthClientUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthClientUpsertOne) SetUpdatedAt(v time.Time) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateUpdatedAt() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthClientUpsertOne) SetDeletedAt(v time.Time) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateDeletedAt() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthClientUpsertOne) ClearDeletedAt() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.ClearDeletedAt() + }) +} + +// SetGUID sets the "guid" field. +func (u *OAuthClientUpsertOne) SetGUID(v string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetGUID(v) + }) +} + +// UpdateGUID sets the "guid" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateGUID() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateGUID() + }) +} + +// SetSecret sets the "secret" field. +func (u *OAuthClientUpsertOne) SetSecret(v string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetSecret(v) + }) +} + +// UpdateSecret sets the "secret" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateSecret() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateSecret() + }) +} + +// SetName sets the "name" field. +func (u *OAuthClientUpsertOne) SetName(v string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateName() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateName() + }) +} + +// SetHomepageURL sets the "homepage_url" field. +func (u *OAuthClientUpsertOne) SetHomepageURL(v string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetHomepageURL(v) + }) +} + +// UpdateHomepageURL sets the "homepage_url" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateHomepageURL() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateHomepageURL() + }) +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (u *OAuthClientUpsertOne) ClearHomepageURL() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.ClearHomepageURL() + }) +} + +// SetRedirectUris sets the "redirect_uris" field. +func (u *OAuthClientUpsertOne) SetRedirectUris(v []string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetRedirectUris(v) + }) +} + +// UpdateRedirectUris sets the "redirect_uris" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateRedirectUris() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateRedirectUris() + }) +} + +// SetScopes sets the "scopes" field. +func (u *OAuthClientUpsertOne) SetScopes(v []string) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetScopes(v) + }) +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateScopes() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateScopes() + }) +} + +// SetProps sets the "props" field. +func (u *OAuthClientUpsertOne) SetProps(v *types.OAuthClientProps) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetProps(v) + }) +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateProps() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateProps() + }) +} + +// SetIsEnabled sets the "is_enabled" field. +func (u *OAuthClientUpsertOne) SetIsEnabled(v bool) *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.SetIsEnabled(v) + }) +} + +// UpdateIsEnabled sets the "is_enabled" field to the value that was provided on create. +func (u *OAuthClientUpsertOne) UpdateIsEnabled() *OAuthClientUpsertOne { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateIsEnabled() + }) +} + +// Exec executes the query. +func (u *OAuthClientUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for OAuthClientCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *OAuthClientUpsertOne) 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 *OAuthClientUpsertOne) ID(ctx context.Context) (id int, 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 *OAuthClientUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +func (m *OAuthClientCreate) SetRawID(t int) *OAuthClientCreate { + m.mutation.SetRawID(t) + return m +} + +// OAuthClientCreateBulk is the builder for creating many OAuthClient entities in bulk. +type OAuthClientCreateBulk struct { + config + err error + builders []*OAuthClientCreate + conflict []sql.ConflictOption +} + +// Save creates the OAuthClient entities in the database. +func (occb *OAuthClientCreateBulk) Save(ctx context.Context) ([]*OAuthClient, error) { + if occb.err != nil { + return nil, occb.err + } + specs := make([]*sqlgraph.CreateSpec, len(occb.builders)) + nodes := make([]*OAuthClient, len(occb.builders)) + mutators := make([]Mutator, len(occb.builders)) + for i := range occb.builders { + func(i int, root context.Context) { + builder := occb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*OAuthClientMutation) + 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, occb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = occb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, occb.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 = int(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, occb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (occb *OAuthClientCreateBulk) SaveX(ctx context.Context) []*OAuthClient { + v, err := occb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (occb *OAuthClientCreateBulk) Exec(ctx context.Context) error { + _, err := occb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (occb *OAuthClientCreateBulk) ExecX(ctx context.Context) { + if err := occb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.OAuthClient.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.OAuthClientUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (occb *OAuthClientCreateBulk) OnConflict(opts ...sql.ConflictOption) *OAuthClientUpsertBulk { + occb.conflict = opts + return &OAuthClientUpsertBulk{ + create: occb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (occb *OAuthClientCreateBulk) OnConflictColumns(columns ...string) *OAuthClientUpsertBulk { + occb.conflict = append(occb.conflict, sql.ConflictColumns(columns...)) + return &OAuthClientUpsertBulk{ + create: occb, + } +} + +// OAuthClientUpsertBulk is the builder for "upsert"-ing +// a bulk of OAuthClient nodes. +type OAuthClientUpsertBulk struct { + create *OAuthClientCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *OAuthClientUpsertBulk) UpdateNewValues() *OAuthClientUpsertBulk { + 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(oauthclient.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.OAuthClient.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *OAuthClientUpsertBulk) Ignore() *OAuthClientUpsertBulk { + 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 *OAuthClientUpsertBulk) DoNothing() *OAuthClientUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the OAuthClientCreateBulk.OnConflict +// documentation for more info. +func (u *OAuthClientUpsertBulk) Update(set func(*OAuthClientUpsert)) *OAuthClientUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&OAuthClientUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthClientUpsertBulk) SetUpdatedAt(v time.Time) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateUpdatedAt() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthClientUpsertBulk) SetDeletedAt(v time.Time) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateDeletedAt() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthClientUpsertBulk) ClearDeletedAt() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.ClearDeletedAt() + }) +} + +// SetGUID sets the "guid" field. +func (u *OAuthClientUpsertBulk) SetGUID(v string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetGUID(v) + }) +} + +// UpdateGUID sets the "guid" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateGUID() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateGUID() + }) +} + +// SetSecret sets the "secret" field. +func (u *OAuthClientUpsertBulk) SetSecret(v string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetSecret(v) + }) +} + +// UpdateSecret sets the "secret" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateSecret() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateSecret() + }) +} + +// SetName sets the "name" field. +func (u *OAuthClientUpsertBulk) SetName(v string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateName() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateName() + }) +} + +// SetHomepageURL sets the "homepage_url" field. +func (u *OAuthClientUpsertBulk) SetHomepageURL(v string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetHomepageURL(v) + }) +} + +// UpdateHomepageURL sets the "homepage_url" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateHomepageURL() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateHomepageURL() + }) +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (u *OAuthClientUpsertBulk) ClearHomepageURL() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.ClearHomepageURL() + }) +} + +// SetRedirectUris sets the "redirect_uris" field. +func (u *OAuthClientUpsertBulk) SetRedirectUris(v []string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetRedirectUris(v) + }) +} + +// UpdateRedirectUris sets the "redirect_uris" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateRedirectUris() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateRedirectUris() + }) +} + +// SetScopes sets the "scopes" field. +func (u *OAuthClientUpsertBulk) SetScopes(v []string) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetScopes(v) + }) +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateScopes() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateScopes() + }) +} + +// SetProps sets the "props" field. +func (u *OAuthClientUpsertBulk) SetProps(v *types.OAuthClientProps) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetProps(v) + }) +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateProps() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateProps() + }) +} + +// SetIsEnabled sets the "is_enabled" field. +func (u *OAuthClientUpsertBulk) SetIsEnabled(v bool) *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.SetIsEnabled(v) + }) +} + +// UpdateIsEnabled sets the "is_enabled" field to the value that was provided on create. +func (u *OAuthClientUpsertBulk) UpdateIsEnabled() *OAuthClientUpsertBulk { + return u.Update(func(s *OAuthClientUpsert) { + s.UpdateIsEnabled() + }) +} + +// Exec executes the query. +func (u *OAuthClientUpsertBulk) 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 OAuthClientCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for OAuthClientCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *OAuthClientUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/oauthclient_delete.go b/ent/oauthclient_delete.go new file mode 100644 index 00000000..c5d69c41 --- /dev/null +++ b/ent/oauthclient_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/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// OAuthClientDelete is the builder for deleting a OAuthClient entity. +type OAuthClientDelete struct { + config + hooks []Hook + mutation *OAuthClientMutation +} + +// Where appends a list predicates to the OAuthClientDelete builder. +func (ocd *OAuthClientDelete) Where(ps ...predicate.OAuthClient) *OAuthClientDelete { + ocd.mutation.Where(ps...) + return ocd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ocd *OAuthClientDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, ocd.sqlExec, ocd.mutation, ocd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (ocd *OAuthClientDelete) ExecX(ctx context.Context) int { + n, err := ocd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ocd *OAuthClientDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(oauthclient.Table, sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt)) + if ps := ocd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ocd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + ocd.mutation.done = true + return affected, err +} + +// OAuthClientDeleteOne is the builder for deleting a single OAuthClient entity. +type OAuthClientDeleteOne struct { + ocd *OAuthClientDelete +} + +// Where appends a list predicates to the OAuthClientDelete builder. +func (ocdo *OAuthClientDeleteOne) Where(ps ...predicate.OAuthClient) *OAuthClientDeleteOne { + ocdo.ocd.mutation.Where(ps...) + return ocdo +} + +// Exec executes the deletion query. +func (ocdo *OAuthClientDeleteOne) Exec(ctx context.Context) error { + n, err := ocdo.ocd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{oauthclient.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ocdo *OAuthClientDeleteOne) ExecX(ctx context.Context) { + if err := ocdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/oauthclient_query.go b/ent/oauthclient_query.go new file mode 100644 index 00000000..1733aba5 --- /dev/null +++ b/ent/oauthclient_query.go @@ -0,0 +1,605 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// OAuthClientQuery is the builder for querying OAuthClient entities. +type OAuthClientQuery struct { + config + ctx *QueryContext + order []oauthclient.OrderOption + inters []Interceptor + predicates []predicate.OAuthClient + withGrants *OAuthGrantQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the OAuthClientQuery builder. +func (ocq *OAuthClientQuery) Where(ps ...predicate.OAuthClient) *OAuthClientQuery { + ocq.predicates = append(ocq.predicates, ps...) + return ocq +} + +// Limit the number of records to be returned by this query. +func (ocq *OAuthClientQuery) Limit(limit int) *OAuthClientQuery { + ocq.ctx.Limit = &limit + return ocq +} + +// Offset to start from. +func (ocq *OAuthClientQuery) Offset(offset int) *OAuthClientQuery { + ocq.ctx.Offset = &offset + return ocq +} + +// 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 (ocq *OAuthClientQuery) Unique(unique bool) *OAuthClientQuery { + ocq.ctx.Unique = &unique + return ocq +} + +// Order specifies how the records should be ordered. +func (ocq *OAuthClientQuery) Order(o ...oauthclient.OrderOption) *OAuthClientQuery { + ocq.order = append(ocq.order, o...) + return ocq +} + +// QueryGrants chains the current query on the "grants" edge. +func (ocq *OAuthClientQuery) QueryGrants() *OAuthGrantQuery { + query := (&OAuthGrantClient{config: ocq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := ocq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := ocq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(oauthclient.Table, oauthclient.FieldID, selector), + sqlgraph.To(oauthgrant.Table, oauthgrant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, oauthclient.GrantsTable, oauthclient.GrantsColumn), + ) + fromU = sqlgraph.SetNeighbors(ocq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first OAuthClient entity from the query. +// Returns a *NotFoundError when no OAuthClient was found. +func (ocq *OAuthClientQuery) First(ctx context.Context) (*OAuthClient, error) { + nodes, err := ocq.Limit(1).All(setContextOp(ctx, ocq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{oauthclient.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (ocq *OAuthClientQuery) FirstX(ctx context.Context) *OAuthClient { + node, err := ocq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first OAuthClient ID from the query. +// Returns a *NotFoundError when no OAuthClient ID was found. +func (ocq *OAuthClientQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ocq.Limit(1).IDs(setContextOp(ctx, ocq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{oauthclient.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (ocq *OAuthClientQuery) FirstIDX(ctx context.Context) int { + id, err := ocq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single OAuthClient entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one OAuthClient entity is found. +// Returns a *NotFoundError when no OAuthClient entities are found. +func (ocq *OAuthClientQuery) Only(ctx context.Context) (*OAuthClient, error) { + nodes, err := ocq.Limit(2).All(setContextOp(ctx, ocq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{oauthclient.Label} + default: + return nil, &NotSingularError{oauthclient.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (ocq *OAuthClientQuery) OnlyX(ctx context.Context) *OAuthClient { + node, err := ocq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only OAuthClient ID in the query. +// Returns a *NotSingularError when more than one OAuthClient ID is found. +// Returns a *NotFoundError when no entities are found. +func (ocq *OAuthClientQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ocq.Limit(2).IDs(setContextOp(ctx, ocq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{oauthclient.Label} + default: + err = &NotSingularError{oauthclient.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (ocq *OAuthClientQuery) OnlyIDX(ctx context.Context) int { + id, err := ocq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of OAuthClients. +func (ocq *OAuthClientQuery) All(ctx context.Context) ([]*OAuthClient, error) { + ctx = setContextOp(ctx, ocq.ctx, "All") + if err := ocq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*OAuthClient, *OAuthClientQuery]() + return withInterceptors[[]*OAuthClient](ctx, ocq, qr, ocq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (ocq *OAuthClientQuery) AllX(ctx context.Context) []*OAuthClient { + nodes, err := ocq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of OAuthClient IDs. +func (ocq *OAuthClientQuery) IDs(ctx context.Context) (ids []int, err error) { + if ocq.ctx.Unique == nil && ocq.path != nil { + ocq.Unique(true) + } + ctx = setContextOp(ctx, ocq.ctx, "IDs") + if err = ocq.Select(oauthclient.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (ocq *OAuthClientQuery) IDsX(ctx context.Context) []int { + ids, err := ocq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (ocq *OAuthClientQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, ocq.ctx, "Count") + if err := ocq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, ocq, querierCount[*OAuthClientQuery](), ocq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (ocq *OAuthClientQuery) CountX(ctx context.Context) int { + count, err := ocq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (ocq *OAuthClientQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, ocq.ctx, "Exist") + switch _, err := ocq.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 (ocq *OAuthClientQuery) ExistX(ctx context.Context) bool { + exist, err := ocq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the OAuthClientQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (ocq *OAuthClientQuery) Clone() *OAuthClientQuery { + if ocq == nil { + return nil + } + return &OAuthClientQuery{ + config: ocq.config, + ctx: ocq.ctx.Clone(), + order: append([]oauthclient.OrderOption{}, ocq.order...), + inters: append([]Interceptor{}, ocq.inters...), + predicates: append([]predicate.OAuthClient{}, ocq.predicates...), + withGrants: ocq.withGrants.Clone(), + // clone intermediate query. + sql: ocq.sql.Clone(), + path: ocq.path, + } +} + +// WithGrants tells the query-builder to eager-load the nodes that are connected to +// the "grants" edge. The optional arguments are used to configure the query builder of the edge. +func (ocq *OAuthClientQuery) WithGrants(opts ...func(*OAuthGrantQuery)) *OAuthClientQuery { + query := (&OAuthGrantClient{config: ocq.config}).Query() + for _, opt := range opts { + opt(query) + } + ocq.withGrants = query + return ocq +} + +// 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.OAuthClient.Query(). +// GroupBy(oauthclient.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (ocq *OAuthClientQuery) GroupBy(field string, fields ...string) *OAuthClientGroupBy { + ocq.ctx.Fields = append([]string{field}, fields...) + grbuild := &OAuthClientGroupBy{build: ocq} + grbuild.flds = &ocq.ctx.Fields + grbuild.label = oauthclient.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.OAuthClient.Query(). +// Select(oauthclient.FieldCreatedAt). +// Scan(ctx, &v) +func (ocq *OAuthClientQuery) Select(fields ...string) *OAuthClientSelect { + ocq.ctx.Fields = append(ocq.ctx.Fields, fields...) + sbuild := &OAuthClientSelect{OAuthClientQuery: ocq} + sbuild.label = oauthclient.Label + sbuild.flds, sbuild.scan = &ocq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a OAuthClientSelect configured with the given aggregations. +func (ocq *OAuthClientQuery) Aggregate(fns ...AggregateFunc) *OAuthClientSelect { + return ocq.Select().Aggregate(fns...) +} + +func (ocq *OAuthClientQuery) prepareQuery(ctx context.Context) error { + for _, inter := range ocq.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, ocq); err != nil { + return err + } + } + } + for _, f := range ocq.ctx.Fields { + if !oauthclient.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if ocq.path != nil { + prev, err := ocq.path(ctx) + if err != nil { + return err + } + ocq.sql = prev + } + return nil +} + +func (ocq *OAuthClientQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*OAuthClient, error) { + var ( + nodes = []*OAuthClient{} + _spec = ocq.querySpec() + loadedTypes = [1]bool{ + ocq.withGrants != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*OAuthClient).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &OAuthClient{config: ocq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, ocq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := ocq.withGrants; query != nil { + if err := ocq.loadGrants(ctx, query, nodes, + func(n *OAuthClient) { n.Edges.Grants = []*OAuthGrant{} }, + func(n *OAuthClient, e *OAuthGrant) { n.Edges.Grants = append(n.Edges.Grants, e) }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (ocq *OAuthClientQuery) loadGrants(ctx context.Context, query *OAuthGrantQuery, nodes []*OAuthClient, init func(*OAuthClient), assign func(*OAuthClient, *OAuthGrant)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*OAuthClient) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(oauthgrant.FieldClientID) + } + query.Where(predicate.OAuthGrant(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(oauthclient.GrantsColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.ClientID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "client_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} + +func (ocq *OAuthClientQuery) sqlCount(ctx context.Context) (int, error) { + _spec := ocq.querySpec() + _spec.Node.Columns = ocq.ctx.Fields + if len(ocq.ctx.Fields) > 0 { + _spec.Unique = ocq.ctx.Unique != nil && *ocq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, ocq.driver, _spec) +} + +func (ocq *OAuthClientQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(oauthclient.Table, oauthclient.Columns, sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt)) + _spec.From = ocq.sql + if unique := ocq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if ocq.path != nil { + _spec.Unique = true + } + if fields := ocq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, oauthclient.FieldID) + for i := range fields { + if fields[i] != oauthclient.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := ocq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := ocq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := ocq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := ocq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (ocq *OAuthClientQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(ocq.driver.Dialect()) + t1 := builder.Table(oauthclient.Table) + columns := ocq.ctx.Fields + if len(columns) == 0 { + columns = oauthclient.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if ocq.sql != nil { + selector = ocq.sql + selector.Select(selector.Columns(columns...)...) + } + if ocq.ctx.Unique != nil && *ocq.ctx.Unique { + selector.Distinct() + } + for _, p := range ocq.predicates { + p(selector) + } + for _, p := range ocq.order { + p(selector) + } + if offset := ocq.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 := ocq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// OAuthClientGroupBy is the group-by builder for OAuthClient entities. +type OAuthClientGroupBy struct { + selector + build *OAuthClientQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (ocgb *OAuthClientGroupBy) Aggregate(fns ...AggregateFunc) *OAuthClientGroupBy { + ocgb.fns = append(ocgb.fns, fns...) + return ocgb +} + +// Scan applies the selector query and scans the result into the given value. +func (ocgb *OAuthClientGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ocgb.build.ctx, "GroupBy") + if err := ocgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*OAuthClientQuery, *OAuthClientGroupBy](ctx, ocgb.build, ocgb, ocgb.build.inters, v) +} + +func (ocgb *OAuthClientGroupBy) sqlScan(ctx context.Context, root *OAuthClientQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(ocgb.fns)) + for _, fn := range ocgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*ocgb.flds)+len(ocgb.fns)) + for _, f := range *ocgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*ocgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ocgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// OAuthClientSelect is the builder for selecting fields of OAuthClient entities. +type OAuthClientSelect struct { + *OAuthClientQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ocs *OAuthClientSelect) Aggregate(fns ...AggregateFunc) *OAuthClientSelect { + ocs.fns = append(ocs.fns, fns...) + return ocs +} + +// Scan applies the selector query and scans the result into the given value. +func (ocs *OAuthClientSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ocs.ctx, "Select") + if err := ocs.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*OAuthClientQuery, *OAuthClientSelect](ctx, ocs.OAuthClientQuery, ocs, ocs.inters, v) +} + +func (ocs *OAuthClientSelect) sqlScan(ctx context.Context, root *OAuthClientQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ocs.fns)) + for _, fn := range ocs.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ocs.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 := ocs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/oauthclient_update.go b/ent/oauthclient_update.go new file mode 100644 index 00000000..262848b4 --- /dev/null +++ b/ent/oauthclient_update.go @@ -0,0 +1,783 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/dialect/sql/sqljson" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// OAuthClientUpdate is the builder for updating OAuthClient entities. +type OAuthClientUpdate struct { + config + hooks []Hook + mutation *OAuthClientMutation +} + +// Where appends a list predicates to the OAuthClientUpdate builder. +func (ocu *OAuthClientUpdate) Where(ps ...predicate.OAuthClient) *OAuthClientUpdate { + ocu.mutation.Where(ps...) + return ocu +} + +// SetUpdatedAt sets the "updated_at" field. +func (ocu *OAuthClientUpdate) SetUpdatedAt(t time.Time) *OAuthClientUpdate { + ocu.mutation.SetUpdatedAt(t) + return ocu +} + +// SetDeletedAt sets the "deleted_at" field. +func (ocu *OAuthClientUpdate) SetDeletedAt(t time.Time) *OAuthClientUpdate { + ocu.mutation.SetDeletedAt(t) + return ocu +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableDeletedAt(t *time.Time) *OAuthClientUpdate { + if t != nil { + ocu.SetDeletedAt(*t) + } + return ocu +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (ocu *OAuthClientUpdate) ClearDeletedAt() *OAuthClientUpdate { + ocu.mutation.ClearDeletedAt() + return ocu +} + +// SetGUID sets the "guid" field. +func (ocu *OAuthClientUpdate) SetGUID(s string) *OAuthClientUpdate { + ocu.mutation.SetGUID(s) + return ocu +} + +// SetNillableGUID sets the "guid" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableGUID(s *string) *OAuthClientUpdate { + if s != nil { + ocu.SetGUID(*s) + } + return ocu +} + +// SetSecret sets the "secret" field. +func (ocu *OAuthClientUpdate) SetSecret(s string) *OAuthClientUpdate { + ocu.mutation.SetSecret(s) + return ocu +} + +// SetNillableSecret sets the "secret" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableSecret(s *string) *OAuthClientUpdate { + if s != nil { + ocu.SetSecret(*s) + } + return ocu +} + +// SetName sets the "name" field. +func (ocu *OAuthClientUpdate) SetName(s string) *OAuthClientUpdate { + ocu.mutation.SetName(s) + return ocu +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableName(s *string) *OAuthClientUpdate { + if s != nil { + ocu.SetName(*s) + } + return ocu +} + +// SetHomepageURL sets the "homepage_url" field. +func (ocu *OAuthClientUpdate) SetHomepageURL(s string) *OAuthClientUpdate { + ocu.mutation.SetHomepageURL(s) + return ocu +} + +// SetNillableHomepageURL sets the "homepage_url" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableHomepageURL(s *string) *OAuthClientUpdate { + if s != nil { + ocu.SetHomepageURL(*s) + } + return ocu +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (ocu *OAuthClientUpdate) ClearHomepageURL() *OAuthClientUpdate { + ocu.mutation.ClearHomepageURL() + return ocu +} + +// SetRedirectUris sets the "redirect_uris" field. +func (ocu *OAuthClientUpdate) SetRedirectUris(s []string) *OAuthClientUpdate { + ocu.mutation.SetRedirectUris(s) + return ocu +} + +// AppendRedirectUris appends s to the "redirect_uris" field. +func (ocu *OAuthClientUpdate) AppendRedirectUris(s []string) *OAuthClientUpdate { + ocu.mutation.AppendRedirectUris(s) + return ocu +} + +// SetScopes sets the "scopes" field. +func (ocu *OAuthClientUpdate) SetScopes(s []string) *OAuthClientUpdate { + ocu.mutation.SetScopes(s) + return ocu +} + +// AppendScopes appends s to the "scopes" field. +func (ocu *OAuthClientUpdate) AppendScopes(s []string) *OAuthClientUpdate { + ocu.mutation.AppendScopes(s) + return ocu +} + +// SetProps sets the "props" field. +func (ocu *OAuthClientUpdate) SetProps(tacp *types.OAuthClientProps) *OAuthClientUpdate { + ocu.mutation.SetProps(tacp) + return ocu +} + +// SetIsEnabled sets the "is_enabled" field. +func (ocu *OAuthClientUpdate) SetIsEnabled(b bool) *OAuthClientUpdate { + ocu.mutation.SetIsEnabled(b) + return ocu +} + +// SetNillableIsEnabled sets the "is_enabled" field if the given value is not nil. +func (ocu *OAuthClientUpdate) SetNillableIsEnabled(b *bool) *OAuthClientUpdate { + if b != nil { + ocu.SetIsEnabled(*b) + } + return ocu +} + +// AddGrantIDs adds the "grants" edge to the OAuthGrant entity by IDs. +func (ocu *OAuthClientUpdate) AddGrantIDs(ids ...int) *OAuthClientUpdate { + ocu.mutation.AddGrantIDs(ids...) + return ocu +} + +// AddGrants adds the "grants" edges to the OAuthGrant entity. +func (ocu *OAuthClientUpdate) AddGrants(o ...*OAuthGrant) *OAuthClientUpdate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return ocu.AddGrantIDs(ids...) +} + +// Mutation returns the OAuthClientMutation object of the builder. +func (ocu *OAuthClientUpdate) Mutation() *OAuthClientMutation { + return ocu.mutation +} + +// ClearGrants clears all "grants" edges to the OAuthGrant entity. +func (ocu *OAuthClientUpdate) ClearGrants() *OAuthClientUpdate { + ocu.mutation.ClearGrants() + return ocu +} + +// RemoveGrantIDs removes the "grants" edge to OAuthGrant entities by IDs. +func (ocu *OAuthClientUpdate) RemoveGrantIDs(ids ...int) *OAuthClientUpdate { + ocu.mutation.RemoveGrantIDs(ids...) + return ocu +} + +// RemoveGrants removes "grants" edges to OAuthGrant entities. +func (ocu *OAuthClientUpdate) RemoveGrants(o ...*OAuthGrant) *OAuthClientUpdate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return ocu.RemoveGrantIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (ocu *OAuthClientUpdate) Save(ctx context.Context) (int, error) { + if err := ocu.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, ocu.sqlSave, ocu.mutation, ocu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ocu *OAuthClientUpdate) SaveX(ctx context.Context) int { + affected, err := ocu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (ocu *OAuthClientUpdate) Exec(ctx context.Context) error { + _, err := ocu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ocu *OAuthClientUpdate) ExecX(ctx context.Context) { + if err := ocu.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ocu *OAuthClientUpdate) defaults() error { + if _, ok := ocu.mutation.UpdatedAt(); !ok { + if oauthclient.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthclient.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthclient.UpdateDefaultUpdatedAt() + ocu.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ocu *OAuthClientUpdate) check() error { + if v, ok := ocu.mutation.GUID(); ok { + if err := oauthclient.GUIDValidator(v); err != nil { + return &ValidationError{Name: "guid", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.guid": %w`, err)} + } + } + if v, ok := ocu.mutation.Secret(); ok { + if err := oauthclient.SecretValidator(v); err != nil { + return &ValidationError{Name: "secret", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.secret": %w`, err)} + } + } + if v, ok := ocu.mutation.Name(); ok { + if err := oauthclient.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.name": %w`, err)} + } + } + if v, ok := ocu.mutation.HomepageURL(); ok { + if err := oauthclient.HomepageURLValidator(v); err != nil { + return &ValidationError{Name: "homepage_url", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.homepage_url": %w`, err)} + } + } + return nil +} + +func (ocu *OAuthClientUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := ocu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(oauthclient.Table, oauthclient.Columns, sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt)) + if ps := ocu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ocu.mutation.UpdatedAt(); ok { + _spec.SetField(oauthclient.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := ocu.mutation.DeletedAt(); ok { + _spec.SetField(oauthclient.FieldDeletedAt, field.TypeTime, value) + } + if ocu.mutation.DeletedAtCleared() { + _spec.ClearField(oauthclient.FieldDeletedAt, field.TypeTime) + } + if value, ok := ocu.mutation.GUID(); ok { + _spec.SetField(oauthclient.FieldGUID, field.TypeString, value) + } + if value, ok := ocu.mutation.Secret(); ok { + _spec.SetField(oauthclient.FieldSecret, field.TypeString, value) + } + if value, ok := ocu.mutation.Name(); ok { + _spec.SetField(oauthclient.FieldName, field.TypeString, value) + } + if value, ok := ocu.mutation.HomepageURL(); ok { + _spec.SetField(oauthclient.FieldHomepageURL, field.TypeString, value) + } + if ocu.mutation.HomepageURLCleared() { + _spec.ClearField(oauthclient.FieldHomepageURL, field.TypeString) + } + if value, ok := ocu.mutation.RedirectUris(); ok { + _spec.SetField(oauthclient.FieldRedirectUris, field.TypeJSON, value) + } + if value, ok := ocu.mutation.AppendedRedirectUris(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthclient.FieldRedirectUris, value) + }) + } + if value, ok := ocu.mutation.Scopes(); ok { + _spec.SetField(oauthclient.FieldScopes, field.TypeJSON, value) + } + if value, ok := ocu.mutation.AppendedScopes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthclient.FieldScopes, value) + }) + } + if value, ok := ocu.mutation.Props(); ok { + _spec.SetField(oauthclient.FieldProps, field.TypeJSON, value) + } + if value, ok := ocu.mutation.IsEnabled(); ok { + _spec.SetField(oauthclient.FieldIsEnabled, field.TypeBool, value) + } + if ocu.mutation.GrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ocu.mutation.RemovedGrantsIDs(); len(nodes) > 0 && !ocu.mutation.GrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ocu.mutation.GrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, ocu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{oauthclient.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + ocu.mutation.done = true + return n, nil +} + +// OAuthClientUpdateOne is the builder for updating a single OAuthClient entity. +type OAuthClientUpdateOne struct { + config + fields []string + hooks []Hook + mutation *OAuthClientMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (ocuo *OAuthClientUpdateOne) SetUpdatedAt(t time.Time) *OAuthClientUpdateOne { + ocuo.mutation.SetUpdatedAt(t) + return ocuo +} + +// SetDeletedAt sets the "deleted_at" field. +func (ocuo *OAuthClientUpdateOne) SetDeletedAt(t time.Time) *OAuthClientUpdateOne { + ocuo.mutation.SetDeletedAt(t) + return ocuo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableDeletedAt(t *time.Time) *OAuthClientUpdateOne { + if t != nil { + ocuo.SetDeletedAt(*t) + } + return ocuo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (ocuo *OAuthClientUpdateOne) ClearDeletedAt() *OAuthClientUpdateOne { + ocuo.mutation.ClearDeletedAt() + return ocuo +} + +// SetGUID sets the "guid" field. +func (ocuo *OAuthClientUpdateOne) SetGUID(s string) *OAuthClientUpdateOne { + ocuo.mutation.SetGUID(s) + return ocuo +} + +// SetNillableGUID sets the "guid" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableGUID(s *string) *OAuthClientUpdateOne { + if s != nil { + ocuo.SetGUID(*s) + } + return ocuo +} + +// SetSecret sets the "secret" field. +func (ocuo *OAuthClientUpdateOne) SetSecret(s string) *OAuthClientUpdateOne { + ocuo.mutation.SetSecret(s) + return ocuo +} + +// SetNillableSecret sets the "secret" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableSecret(s *string) *OAuthClientUpdateOne { + if s != nil { + ocuo.SetSecret(*s) + } + return ocuo +} + +// SetName sets the "name" field. +func (ocuo *OAuthClientUpdateOne) SetName(s string) *OAuthClientUpdateOne { + ocuo.mutation.SetName(s) + return ocuo +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableName(s *string) *OAuthClientUpdateOne { + if s != nil { + ocuo.SetName(*s) + } + return ocuo +} + +// SetHomepageURL sets the "homepage_url" field. +func (ocuo *OAuthClientUpdateOne) SetHomepageURL(s string) *OAuthClientUpdateOne { + ocuo.mutation.SetHomepageURL(s) + return ocuo +} + +// SetNillableHomepageURL sets the "homepage_url" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableHomepageURL(s *string) *OAuthClientUpdateOne { + if s != nil { + ocuo.SetHomepageURL(*s) + } + return ocuo +} + +// ClearHomepageURL clears the value of the "homepage_url" field. +func (ocuo *OAuthClientUpdateOne) ClearHomepageURL() *OAuthClientUpdateOne { + ocuo.mutation.ClearHomepageURL() + return ocuo +} + +// SetRedirectUris sets the "redirect_uris" field. +func (ocuo *OAuthClientUpdateOne) SetRedirectUris(s []string) *OAuthClientUpdateOne { + ocuo.mutation.SetRedirectUris(s) + return ocuo +} + +// AppendRedirectUris appends s to the "redirect_uris" field. +func (ocuo *OAuthClientUpdateOne) AppendRedirectUris(s []string) *OAuthClientUpdateOne { + ocuo.mutation.AppendRedirectUris(s) + return ocuo +} + +// SetScopes sets the "scopes" field. +func (ocuo *OAuthClientUpdateOne) SetScopes(s []string) *OAuthClientUpdateOne { + ocuo.mutation.SetScopes(s) + return ocuo +} + +// AppendScopes appends s to the "scopes" field. +func (ocuo *OAuthClientUpdateOne) AppendScopes(s []string) *OAuthClientUpdateOne { + ocuo.mutation.AppendScopes(s) + return ocuo +} + +// SetProps sets the "props" field. +func (ocuo *OAuthClientUpdateOne) SetProps(tacp *types.OAuthClientProps) *OAuthClientUpdateOne { + ocuo.mutation.SetProps(tacp) + return ocuo +} + +// SetIsEnabled sets the "is_enabled" field. +func (ocuo *OAuthClientUpdateOne) SetIsEnabled(b bool) *OAuthClientUpdateOne { + ocuo.mutation.SetIsEnabled(b) + return ocuo +} + +// SetNillableIsEnabled sets the "is_enabled" field if the given value is not nil. +func (ocuo *OAuthClientUpdateOne) SetNillableIsEnabled(b *bool) *OAuthClientUpdateOne { + if b != nil { + ocuo.SetIsEnabled(*b) + } + return ocuo +} + +// AddGrantIDs adds the "grants" edge to the OAuthGrant entity by IDs. +func (ocuo *OAuthClientUpdateOne) AddGrantIDs(ids ...int) *OAuthClientUpdateOne { + ocuo.mutation.AddGrantIDs(ids...) + return ocuo +} + +// AddGrants adds the "grants" edges to the OAuthGrant entity. +func (ocuo *OAuthClientUpdateOne) AddGrants(o ...*OAuthGrant) *OAuthClientUpdateOne { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return ocuo.AddGrantIDs(ids...) +} + +// Mutation returns the OAuthClientMutation object of the builder. +func (ocuo *OAuthClientUpdateOne) Mutation() *OAuthClientMutation { + return ocuo.mutation +} + +// ClearGrants clears all "grants" edges to the OAuthGrant entity. +func (ocuo *OAuthClientUpdateOne) ClearGrants() *OAuthClientUpdateOne { + ocuo.mutation.ClearGrants() + return ocuo +} + +// RemoveGrantIDs removes the "grants" edge to OAuthGrant entities by IDs. +func (ocuo *OAuthClientUpdateOne) RemoveGrantIDs(ids ...int) *OAuthClientUpdateOne { + ocuo.mutation.RemoveGrantIDs(ids...) + return ocuo +} + +// RemoveGrants removes "grants" edges to OAuthGrant entities. +func (ocuo *OAuthClientUpdateOne) RemoveGrants(o ...*OAuthGrant) *OAuthClientUpdateOne { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return ocuo.RemoveGrantIDs(ids...) +} + +// Where appends a list predicates to the OAuthClientUpdate builder. +func (ocuo *OAuthClientUpdateOne) Where(ps ...predicate.OAuthClient) *OAuthClientUpdateOne { + ocuo.mutation.Where(ps...) + return ocuo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (ocuo *OAuthClientUpdateOne) Select(field string, fields ...string) *OAuthClientUpdateOne { + ocuo.fields = append([]string{field}, fields...) + return ocuo +} + +// Save executes the query and returns the updated OAuthClient entity. +func (ocuo *OAuthClientUpdateOne) Save(ctx context.Context) (*OAuthClient, error) { + if err := ocuo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, ocuo.sqlSave, ocuo.mutation, ocuo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ocuo *OAuthClientUpdateOne) SaveX(ctx context.Context) *OAuthClient { + node, err := ocuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (ocuo *OAuthClientUpdateOne) Exec(ctx context.Context) error { + _, err := ocuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ocuo *OAuthClientUpdateOne) ExecX(ctx context.Context) { + if err := ocuo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ocuo *OAuthClientUpdateOne) defaults() error { + if _, ok := ocuo.mutation.UpdatedAt(); !ok { + if oauthclient.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthclient.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthclient.UpdateDefaultUpdatedAt() + ocuo.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ocuo *OAuthClientUpdateOne) check() error { + if v, ok := ocuo.mutation.GUID(); ok { + if err := oauthclient.GUIDValidator(v); err != nil { + return &ValidationError{Name: "guid", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.guid": %w`, err)} + } + } + if v, ok := ocuo.mutation.Secret(); ok { + if err := oauthclient.SecretValidator(v); err != nil { + return &ValidationError{Name: "secret", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.secret": %w`, err)} + } + } + if v, ok := ocuo.mutation.Name(); ok { + if err := oauthclient.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.name": %w`, err)} + } + } + if v, ok := ocuo.mutation.HomepageURL(); ok { + if err := oauthclient.HomepageURLValidator(v); err != nil { + return &ValidationError{Name: "homepage_url", err: fmt.Errorf(`ent: validator failed for field "OAuthClient.homepage_url": %w`, err)} + } + } + return nil +} + +func (ocuo *OAuthClientUpdateOne) sqlSave(ctx context.Context) (_node *OAuthClient, err error) { + if err := ocuo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(oauthclient.Table, oauthclient.Columns, sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt)) + id, ok := ocuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "OAuthClient.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := ocuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, oauthclient.FieldID) + for _, f := range fields { + if !oauthclient.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != oauthclient.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := ocuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ocuo.mutation.UpdatedAt(); ok { + _spec.SetField(oauthclient.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := ocuo.mutation.DeletedAt(); ok { + _spec.SetField(oauthclient.FieldDeletedAt, field.TypeTime, value) + } + if ocuo.mutation.DeletedAtCleared() { + _spec.ClearField(oauthclient.FieldDeletedAt, field.TypeTime) + } + if value, ok := ocuo.mutation.GUID(); ok { + _spec.SetField(oauthclient.FieldGUID, field.TypeString, value) + } + if value, ok := ocuo.mutation.Secret(); ok { + _spec.SetField(oauthclient.FieldSecret, field.TypeString, value) + } + if value, ok := ocuo.mutation.Name(); ok { + _spec.SetField(oauthclient.FieldName, field.TypeString, value) + } + if value, ok := ocuo.mutation.HomepageURL(); ok { + _spec.SetField(oauthclient.FieldHomepageURL, field.TypeString, value) + } + if ocuo.mutation.HomepageURLCleared() { + _spec.ClearField(oauthclient.FieldHomepageURL, field.TypeString) + } + if value, ok := ocuo.mutation.RedirectUris(); ok { + _spec.SetField(oauthclient.FieldRedirectUris, field.TypeJSON, value) + } + if value, ok := ocuo.mutation.AppendedRedirectUris(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthclient.FieldRedirectUris, value) + }) + } + if value, ok := ocuo.mutation.Scopes(); ok { + _spec.SetField(oauthclient.FieldScopes, field.TypeJSON, value) + } + if value, ok := ocuo.mutation.AppendedScopes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthclient.FieldScopes, value) + }) + } + if value, ok := ocuo.mutation.Props(); ok { + _spec.SetField(oauthclient.FieldProps, field.TypeJSON, value) + } + if value, ok := ocuo.mutation.IsEnabled(); ok { + _spec.SetField(oauthclient.FieldIsEnabled, field.TypeBool, value) + } + if ocuo.mutation.GrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ocuo.mutation.RemovedGrantsIDs(); len(nodes) > 0 && !ocuo.mutation.GrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ocuo.mutation.GrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: oauthclient.GrantsTable, + Columns: []string{oauthclient.GrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &OAuthClient{config: ocuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, ocuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{oauthclient.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + ocuo.mutation.done = true + return _node, nil +} diff --git a/ent/oauthgrant.go b/ent/oauthgrant.go new file mode 100644 index 00000000..a17636fb --- /dev/null +++ b/ent/oauthgrant.go @@ -0,0 +1,245 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/user" +) + +// OAuthGrant is the model entity for the OAuthGrant schema. +type OAuthGrant struct { + config `json:"-"` + // ID of the ent. + ID int `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"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt *time.Time `json:"deleted_at,omitempty"` + // UserID holds the value of the "user_id" field. + UserID int `json:"user_id,omitempty"` + // ClientID holds the value of the "client_id" field. + ClientID int `json:"client_id,omitempty"` + // Scopes holds the value of the "scopes" field. + Scopes []string `json:"scopes,omitempty"` + // LastUsedAt holds the value of the "last_used_at" field. + LastUsedAt *time.Time `json:"last_used_at,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the OAuthGrantQuery when eager-loading is set. + Edges OAuthGrantEdges `json:"edges"` + selectValues sql.SelectValues +} + +// OAuthGrantEdges holds the relations/edges for other nodes in the graph. +type OAuthGrantEdges struct { + // User holds the value of the user edge. + User *User `json:"user,omitempty"` + // Client holds the value of the client edge. + Client *OAuthClient `json:"client,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]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 OAuthGrantEdges) UserOrErr() (*User, error) { + if e.loadedTypes[0] { + if e.User == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: user.Label} + } + return e.User, nil + } + return nil, &NotLoadedError{edge: "user"} +} + +// ClientOrErr returns the Client value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e OAuthGrantEdges) ClientOrErr() (*OAuthClient, error) { + if e.loadedTypes[1] { + if e.Client == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: oauthclient.Label} + } + return e.Client, nil + } + return nil, &NotLoadedError{edge: "client"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*OAuthGrant) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case oauthgrant.FieldScopes: + values[i] = new([]byte) + case oauthgrant.FieldID, oauthgrant.FieldUserID, oauthgrant.FieldClientID: + values[i] = new(sql.NullInt64) + case oauthgrant.FieldCreatedAt, oauthgrant.FieldUpdatedAt, oauthgrant.FieldDeletedAt, oauthgrant.FieldLastUsedAt: + 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 OAuthGrant fields. +func (og *OAuthGrant) 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 oauthgrant.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + og.ID = int(value.Int64) + case oauthgrant.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 { + og.CreatedAt = value.Time + } + case oauthgrant.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 { + og.UpdatedAt = value.Time + } + case oauthgrant.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + og.DeletedAt = new(time.Time) + *og.DeletedAt = value.Time + } + case oauthgrant.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 { + og.UserID = int(value.Int64) + } + case oauthgrant.FieldClientID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field client_id", values[i]) + } else if value.Valid { + og.ClientID = int(value.Int64) + } + case oauthgrant.FieldScopes: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field scopes", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &og.Scopes); err != nil { + return fmt.Errorf("unmarshal field scopes: %w", err) + } + } + case oauthgrant.FieldLastUsedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field last_used_at", values[i]) + } else if value.Valid { + og.LastUsedAt = new(time.Time) + *og.LastUsedAt = value.Time + } + default: + og.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the OAuthGrant. +// This includes values selected through modifiers, order, etc. +func (og *OAuthGrant) Value(name string) (ent.Value, error) { + return og.selectValues.Get(name) +} + +// QueryUser queries the "user" edge of the OAuthGrant entity. +func (og *OAuthGrant) QueryUser() *UserQuery { + return NewOAuthGrantClient(og.config).QueryUser(og) +} + +// QueryClient queries the "client" edge of the OAuthGrant entity. +func (og *OAuthGrant) QueryClient() *OAuthClientQuery { + return NewOAuthGrantClient(og.config).QueryClient(og) +} + +// Update returns a builder for updating this OAuthGrant. +// Note that you need to call OAuthGrant.Unwrap() before calling this method if this OAuthGrant +// was returned from a transaction, and the transaction was committed or rolled back. +func (og *OAuthGrant) Update() *OAuthGrantUpdateOne { + return NewOAuthGrantClient(og.config).UpdateOne(og) +} + +// Unwrap unwraps the OAuthGrant 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 (og *OAuthGrant) Unwrap() *OAuthGrant { + _tx, ok := og.config.driver.(*txDriver) + if !ok { + panic("ent: OAuthGrant is not a transactional entity") + } + og.config.driver = _tx.drv + return og +} + +// String implements the fmt.Stringer. +func (og *OAuthGrant) String() string { + var builder strings.Builder + builder.WriteString("OAuthGrant(") + builder.WriteString(fmt.Sprintf("id=%v, ", og.ID)) + builder.WriteString("created_at=") + builder.WriteString(og.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(og.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + if v := og.DeletedAt; v != nil { + builder.WriteString("deleted_at=") + builder.WriteString(v.Format(time.ANSIC)) + } + builder.WriteString(", ") + builder.WriteString("user_id=") + builder.WriteString(fmt.Sprintf("%v", og.UserID)) + builder.WriteString(", ") + builder.WriteString("client_id=") + builder.WriteString(fmt.Sprintf("%v", og.ClientID)) + builder.WriteString(", ") + builder.WriteString("scopes=") + builder.WriteString(fmt.Sprintf("%v", og.Scopes)) + builder.WriteString(", ") + if v := og.LastUsedAt; v != nil { + builder.WriteString("last_used_at=") + builder.WriteString(v.Format(time.ANSIC)) + } + builder.WriteByte(')') + return builder.String() +} + +// SetUser manually set the edge as loaded state. +func (e *OAuthGrant) SetUser(v *User) { + e.Edges.User = v + e.Edges.loadedTypes[0] = true +} + +// SetClient manually set the edge as loaded state. +func (e *OAuthGrant) SetClient(v *OAuthClient) { + e.Edges.Client = v + e.Edges.loadedTypes[1] = true +} + +// OAuthGrants is a parsable slice of OAuthGrant. +type OAuthGrants []*OAuthGrant diff --git a/ent/oauthgrant/oauthgrant.go b/ent/oauthgrant/oauthgrant.go new file mode 100644 index 00000000..43adfe48 --- /dev/null +++ b/ent/oauthgrant/oauthgrant.go @@ -0,0 +1,158 @@ +// Code generated by ent, DO NOT EDIT. + +package oauthgrant + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the oauthgrant type in the database. + Label = "oauth_grant" + // 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" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldUserID holds the string denoting the user_id field in the database. + FieldUserID = "user_id" + // FieldClientID holds the string denoting the client_id field in the database. + FieldClientID = "client_id" + // FieldScopes holds the string denoting the scopes field in the database. + FieldScopes = "scopes" + // FieldLastUsedAt holds the string denoting the last_used_at field in the database. + FieldLastUsedAt = "last_used_at" + // EdgeUser holds the string denoting the user edge name in mutations. + EdgeUser = "user" + // EdgeClient holds the string denoting the client edge name in mutations. + EdgeClient = "client" + // Table holds the table name of the oauthgrant in the database. + Table = "oauth_grants" + // UserTable is the table that holds the user relation/edge. + UserTable = "oauth_grants" + // 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" + // ClientTable is the table that holds the client relation/edge. + ClientTable = "oauth_grants" + // ClientInverseTable is the table name for the OAuthClient entity. + // It exists in this package in order to avoid circular dependency with the "oauthclient" package. + ClientInverseTable = "oauth_clients" + // ClientColumn is the table column denoting the client relation/edge. + ClientColumn = "client_id" +) + +// Columns holds all SQL columns for oauthgrant fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldUserID, + FieldClientID, + FieldScopes, + FieldLastUsedAt, +} + +// 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 +} + +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/cloudreve/Cloudreve/v4/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // 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 + // DefaultScopes holds the default value on creation for the "scopes" field. + DefaultScopes []string +) + +// OrderOption defines the ordering options for the OAuthGrant 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() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByUserID orders the results by the user_id field. +func ByUserID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUserID, opts...).ToFunc() +} + +// ByClientID orders the results by the client_id field. +func ByClientID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldClientID, opts...).ToFunc() +} + +// ByLastUsedAt orders the results by the last_used_at field. +func ByLastUsedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLastUsedAt, 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...)) + } +} + +// ByClientField orders the results by client field. +func ByClientField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newClientStep(), sql.OrderByField(field, opts...)) + } +} +func newUserStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(UserInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn), + ) +} +func newClientStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ClientInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ClientTable, ClientColumn), + ) +} diff --git a/ent/oauthgrant/where.go b/ent/oauthgrant/where.go new file mode 100644 index 00000000..ef7b52fd --- /dev/null +++ b/ent/oauthgrant/where.go @@ -0,0 +1,367 @@ +// Code generated by ent, DO NOT EDIT. + +package oauthgrant + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.OAuthGrant { + return predicate.OAuthGrant(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.OAuthGrant { + return predicate.OAuthGrant(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.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldDeletedAt, v)) +} + +// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ. +func UserID(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldUserID, v)) +} + +// ClientID applies equality check predicate on the "client_id" field. It's identical to ClientIDEQ. +func ClientID(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldClientID, v)) +} + +// LastUsedAt applies equality check predicate on the "last_used_at" field. It's identical to LastUsedAtEQ. +func LastUsedAt(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldLastUsedAt, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotNull(FieldDeletedAt)) +} + +// UserIDEQ applies the EQ predicate on the "user_id" field. +func UserIDEQ(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldUserID, v)) +} + +// UserIDNEQ applies the NEQ predicate on the "user_id" field. +func UserIDNEQ(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldUserID, v)) +} + +// UserIDIn applies the In predicate on the "user_id" field. +func UserIDIn(vs ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldUserID, vs...)) +} + +// UserIDNotIn applies the NotIn predicate on the "user_id" field. +func UserIDNotIn(vs ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldUserID, vs...)) +} + +// ClientIDEQ applies the EQ predicate on the "client_id" field. +func ClientIDEQ(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldClientID, v)) +} + +// ClientIDNEQ applies the NEQ predicate on the "client_id" field. +func ClientIDNEQ(v int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldClientID, v)) +} + +// ClientIDIn applies the In predicate on the "client_id" field. +func ClientIDIn(vs ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldClientID, vs...)) +} + +// ClientIDNotIn applies the NotIn predicate on the "client_id" field. +func ClientIDNotIn(vs ...int) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldClientID, vs...)) +} + +// LastUsedAtEQ applies the EQ predicate on the "last_used_at" field. +func LastUsedAtEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldEQ(FieldLastUsedAt, v)) +} + +// LastUsedAtNEQ applies the NEQ predicate on the "last_used_at" field. +func LastUsedAtNEQ(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNEQ(FieldLastUsedAt, v)) +} + +// LastUsedAtIn applies the In predicate on the "last_used_at" field. +func LastUsedAtIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIn(FieldLastUsedAt, vs...)) +} + +// LastUsedAtNotIn applies the NotIn predicate on the "last_used_at" field. +func LastUsedAtNotIn(vs ...time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotIn(FieldLastUsedAt, vs...)) +} + +// LastUsedAtGT applies the GT predicate on the "last_used_at" field. +func LastUsedAtGT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGT(FieldLastUsedAt, v)) +} + +// LastUsedAtGTE applies the GTE predicate on the "last_used_at" field. +func LastUsedAtGTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldGTE(FieldLastUsedAt, v)) +} + +// LastUsedAtLT applies the LT predicate on the "last_used_at" field. +func LastUsedAtLT(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLT(FieldLastUsedAt, v)) +} + +// LastUsedAtLTE applies the LTE predicate on the "last_used_at" field. +func LastUsedAtLTE(v time.Time) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldLTE(FieldLastUsedAt, v)) +} + +// LastUsedAtIsNil applies the IsNil predicate on the "last_used_at" field. +func LastUsedAtIsNil() predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldIsNull(FieldLastUsedAt)) +} + +// LastUsedAtNotNil applies the NotNil predicate on the "last_used_at" field. +func LastUsedAtNotNil() predicate.OAuthGrant { + return predicate.OAuthGrant(sql.FieldNotNull(FieldLastUsedAt)) +} + +// HasUser applies the HasEdge predicate on the "user" edge. +func HasUser() predicate.OAuthGrant { + return predicate.OAuthGrant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates). +func HasUserWith(preds ...predicate.User) predicate.OAuthGrant { + return predicate.OAuthGrant(func(s *sql.Selector) { + step := newUserStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasClient applies the HasEdge predicate on the "client" edge. +func HasClient() predicate.OAuthGrant { + return predicate.OAuthGrant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ClientTable, ClientColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasClientWith applies the HasEdge predicate on the "client" edge with a given conditions (other predicates). +func HasClientWith(preds ...predicate.OAuthClient) predicate.OAuthGrant { + return predicate.OAuthGrant(func(s *sql.Selector) { + step := newClientStep() + 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.OAuthGrant) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.OAuthGrant) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.OAuthGrant) predicate.OAuthGrant { + return predicate.OAuthGrant(sql.NotPredicates(p)) +} diff --git a/ent/oauthgrant_create.go b/ent/oauthgrant_create.go new file mode 100644 index 00000000..17a53afc --- /dev/null +++ b/ent/oauthgrant_create.go @@ -0,0 +1,894 @@ +// 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/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/user" +) + +// OAuthGrantCreate is the builder for creating a OAuthGrant entity. +type OAuthGrantCreate struct { + config + mutation *OAuthGrantMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (ogc *OAuthGrantCreate) SetCreatedAt(t time.Time) *OAuthGrantCreate { + ogc.mutation.SetCreatedAt(t) + return ogc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (ogc *OAuthGrantCreate) SetNillableCreatedAt(t *time.Time) *OAuthGrantCreate { + if t != nil { + ogc.SetCreatedAt(*t) + } + return ogc +} + +// SetUpdatedAt sets the "updated_at" field. +func (ogc *OAuthGrantCreate) SetUpdatedAt(t time.Time) *OAuthGrantCreate { + ogc.mutation.SetUpdatedAt(t) + return ogc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (ogc *OAuthGrantCreate) SetNillableUpdatedAt(t *time.Time) *OAuthGrantCreate { + if t != nil { + ogc.SetUpdatedAt(*t) + } + return ogc +} + +// SetDeletedAt sets the "deleted_at" field. +func (ogc *OAuthGrantCreate) SetDeletedAt(t time.Time) *OAuthGrantCreate { + ogc.mutation.SetDeletedAt(t) + return ogc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ogc *OAuthGrantCreate) SetNillableDeletedAt(t *time.Time) *OAuthGrantCreate { + if t != nil { + ogc.SetDeletedAt(*t) + } + return ogc +} + +// SetUserID sets the "user_id" field. +func (ogc *OAuthGrantCreate) SetUserID(i int) *OAuthGrantCreate { + ogc.mutation.SetUserID(i) + return ogc +} + +// SetClientID sets the "client_id" field. +func (ogc *OAuthGrantCreate) SetClientID(i int) *OAuthGrantCreate { + ogc.mutation.SetClientID(i) + return ogc +} + +// SetScopes sets the "scopes" field. +func (ogc *OAuthGrantCreate) SetScopes(s []string) *OAuthGrantCreate { + ogc.mutation.SetScopes(s) + return ogc +} + +// SetLastUsedAt sets the "last_used_at" field. +func (ogc *OAuthGrantCreate) SetLastUsedAt(t time.Time) *OAuthGrantCreate { + ogc.mutation.SetLastUsedAt(t) + return ogc +} + +// SetNillableLastUsedAt sets the "last_used_at" field if the given value is not nil. +func (ogc *OAuthGrantCreate) SetNillableLastUsedAt(t *time.Time) *OAuthGrantCreate { + if t != nil { + ogc.SetLastUsedAt(*t) + } + return ogc +} + +// SetUser sets the "user" edge to the User entity. +func (ogc *OAuthGrantCreate) SetUser(u *User) *OAuthGrantCreate { + return ogc.SetUserID(u.ID) +} + +// SetClient sets the "client" edge to the OAuthClient entity. +func (ogc *OAuthGrantCreate) SetClient(o *OAuthClient) *OAuthGrantCreate { + return ogc.SetClientID(o.ID) +} + +// Mutation returns the OAuthGrantMutation object of the builder. +func (ogc *OAuthGrantCreate) Mutation() *OAuthGrantMutation { + return ogc.mutation +} + +// Save creates the OAuthGrant in the database. +func (ogc *OAuthGrantCreate) Save(ctx context.Context) (*OAuthGrant, error) { + if err := ogc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, ogc.sqlSave, ogc.mutation, ogc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (ogc *OAuthGrantCreate) SaveX(ctx context.Context) *OAuthGrant { + v, err := ogc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ogc *OAuthGrantCreate) Exec(ctx context.Context) error { + _, err := ogc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ogc *OAuthGrantCreate) ExecX(ctx context.Context) { + if err := ogc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ogc *OAuthGrantCreate) defaults() error { + if _, ok := ogc.mutation.CreatedAt(); !ok { + if oauthgrant.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthgrant.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := oauthgrant.DefaultCreatedAt() + ogc.mutation.SetCreatedAt(v) + } + if _, ok := ogc.mutation.UpdatedAt(); !ok { + if oauthgrant.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthgrant.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthgrant.DefaultUpdatedAt() + ogc.mutation.SetUpdatedAt(v) + } + if _, ok := ogc.mutation.Scopes(); !ok { + v := oauthgrant.DefaultScopes + ogc.mutation.SetScopes(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ogc *OAuthGrantCreate) check() error { + if _, ok := ogc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "OAuthGrant.created_at"`)} + } + if _, ok := ogc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "OAuthGrant.updated_at"`)} + } + if _, ok := ogc.mutation.UserID(); !ok { + return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "OAuthGrant.user_id"`)} + } + if _, ok := ogc.mutation.ClientID(); !ok { + return &ValidationError{Name: "client_id", err: errors.New(`ent: missing required field "OAuthGrant.client_id"`)} + } + if _, ok := ogc.mutation.Scopes(); !ok { + return &ValidationError{Name: "scopes", err: errors.New(`ent: missing required field "OAuthGrant.scopes"`)} + } + if _, ok := ogc.mutation.UserID(); !ok { + return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "OAuthGrant.user"`)} + } + if _, ok := ogc.mutation.ClientID(); !ok { + return &ValidationError{Name: "client", err: errors.New(`ent: missing required edge "OAuthGrant.client"`)} + } + return nil +} + +func (ogc *OAuthGrantCreate) sqlSave(ctx context.Context) (*OAuthGrant, error) { + if err := ogc.check(); err != nil { + return nil, err + } + _node, _spec := ogc.createSpec() + if err := sqlgraph.CreateNode(ctx, ogc.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 = int(id) + ogc.mutation.id = &_node.ID + ogc.mutation.done = true + return _node, nil +} + +func (ogc *OAuthGrantCreate) createSpec() (*OAuthGrant, *sqlgraph.CreateSpec) { + var ( + _node = &OAuthGrant{config: ogc.config} + _spec = sqlgraph.NewCreateSpec(oauthgrant.Table, sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt)) + ) + + if id, ok := ogc.mutation.ID(); ok { + _node.ID = id + id64 := int64(id) + _spec.ID.Value = id64 + } + + _spec.OnConflict = ogc.conflict + if value, ok := ogc.mutation.CreatedAt(); ok { + _spec.SetField(oauthgrant.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := ogc.mutation.UpdatedAt(); ok { + _spec.SetField(oauthgrant.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := ogc.mutation.DeletedAt(); ok { + _spec.SetField(oauthgrant.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = &value + } + if value, ok := ogc.mutation.Scopes(); ok { + _spec.SetField(oauthgrant.FieldScopes, field.TypeJSON, value) + _node.Scopes = value + } + if value, ok := ogc.mutation.LastUsedAt(); ok { + _spec.SetField(oauthgrant.FieldLastUsedAt, field.TypeTime, value) + _node.LastUsedAt = &value + } + if nodes := ogc.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.UserTable, + Columns: []string{oauthgrant.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.UserID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := ogc.mutation.ClientIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.ClientTable, + Columns: []string{oauthgrant.ClientColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.ClientID = 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.OAuthGrant.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.OAuthGrantUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (ogc *OAuthGrantCreate) OnConflict(opts ...sql.ConflictOption) *OAuthGrantUpsertOne { + ogc.conflict = opts + return &OAuthGrantUpsertOne{ + create: ogc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (ogc *OAuthGrantCreate) OnConflictColumns(columns ...string) *OAuthGrantUpsertOne { + ogc.conflict = append(ogc.conflict, sql.ConflictColumns(columns...)) + return &OAuthGrantUpsertOne{ + create: ogc, + } +} + +type ( + // OAuthGrantUpsertOne is the builder for "upsert"-ing + // one OAuthGrant node. + OAuthGrantUpsertOne struct { + create *OAuthGrantCreate + } + + // OAuthGrantUpsert is the "OnConflict" setter. + OAuthGrantUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthGrantUpsert) SetUpdatedAt(v time.Time) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateUpdatedAt() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldUpdatedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthGrantUpsert) SetDeletedAt(v time.Time) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateDeletedAt() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthGrantUpsert) ClearDeletedAt() *OAuthGrantUpsert { + u.SetNull(oauthgrant.FieldDeletedAt) + return u +} + +// SetUserID sets the "user_id" field. +func (u *OAuthGrantUpsert) SetUserID(v int) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldUserID, v) + return u +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateUserID() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldUserID) + return u +} + +// SetClientID sets the "client_id" field. +func (u *OAuthGrantUpsert) SetClientID(v int) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldClientID, v) + return u +} + +// UpdateClientID sets the "client_id" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateClientID() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldClientID) + return u +} + +// SetScopes sets the "scopes" field. +func (u *OAuthGrantUpsert) SetScopes(v []string) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldScopes, v) + return u +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateScopes() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldScopes) + return u +} + +// SetLastUsedAt sets the "last_used_at" field. +func (u *OAuthGrantUpsert) SetLastUsedAt(v time.Time) *OAuthGrantUpsert { + u.Set(oauthgrant.FieldLastUsedAt, v) + return u +} + +// UpdateLastUsedAt sets the "last_used_at" field to the value that was provided on create. +func (u *OAuthGrantUpsert) UpdateLastUsedAt() *OAuthGrantUpsert { + u.SetExcluded(oauthgrant.FieldLastUsedAt) + return u +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (u *OAuthGrantUpsert) ClearLastUsedAt() *OAuthGrantUpsert { + u.SetNull(oauthgrant.FieldLastUsedAt) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *OAuthGrantUpsertOne) UpdateNewValues() *OAuthGrantUpsertOne { + 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(oauthgrant.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *OAuthGrantUpsertOne) Ignore() *OAuthGrantUpsertOne { + 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 *OAuthGrantUpsertOne) DoNothing() *OAuthGrantUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the OAuthGrantCreate.OnConflict +// documentation for more info. +func (u *OAuthGrantUpsertOne) Update(set func(*OAuthGrantUpsert)) *OAuthGrantUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&OAuthGrantUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthGrantUpsertOne) SetUpdatedAt(v time.Time) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateUpdatedAt() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthGrantUpsertOne) SetDeletedAt(v time.Time) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateDeletedAt() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthGrantUpsertOne) ClearDeletedAt() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.ClearDeletedAt() + }) +} + +// SetUserID sets the "user_id" field. +func (u *OAuthGrantUpsertOne) SetUserID(v int) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetUserID(v) + }) +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateUserID() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateUserID() + }) +} + +// SetClientID sets the "client_id" field. +func (u *OAuthGrantUpsertOne) SetClientID(v int) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetClientID(v) + }) +} + +// UpdateClientID sets the "client_id" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateClientID() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateClientID() + }) +} + +// SetScopes sets the "scopes" field. +func (u *OAuthGrantUpsertOne) SetScopes(v []string) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetScopes(v) + }) +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateScopes() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateScopes() + }) +} + +// SetLastUsedAt sets the "last_used_at" field. +func (u *OAuthGrantUpsertOne) SetLastUsedAt(v time.Time) *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetLastUsedAt(v) + }) +} + +// UpdateLastUsedAt sets the "last_used_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertOne) UpdateLastUsedAt() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateLastUsedAt() + }) +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (u *OAuthGrantUpsertOne) ClearLastUsedAt() *OAuthGrantUpsertOne { + return u.Update(func(s *OAuthGrantUpsert) { + s.ClearLastUsedAt() + }) +} + +// Exec executes the query. +func (u *OAuthGrantUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for OAuthGrantCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *OAuthGrantUpsertOne) 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 *OAuthGrantUpsertOne) ID(ctx context.Context) (id int, 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 *OAuthGrantUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +func (m *OAuthGrantCreate) SetRawID(t int) *OAuthGrantCreate { + m.mutation.SetRawID(t) + return m +} + +// OAuthGrantCreateBulk is the builder for creating many OAuthGrant entities in bulk. +type OAuthGrantCreateBulk struct { + config + err error + builders []*OAuthGrantCreate + conflict []sql.ConflictOption +} + +// Save creates the OAuthGrant entities in the database. +func (ogcb *OAuthGrantCreateBulk) Save(ctx context.Context) ([]*OAuthGrant, error) { + if ogcb.err != nil { + return nil, ogcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(ogcb.builders)) + nodes := make([]*OAuthGrant, len(ogcb.builders)) + mutators := make([]Mutator, len(ogcb.builders)) + for i := range ogcb.builders { + func(i int, root context.Context) { + builder := ogcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*OAuthGrantMutation) + 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, ogcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = ogcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, ogcb.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 = int(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, ogcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (ogcb *OAuthGrantCreateBulk) SaveX(ctx context.Context) []*OAuthGrant { + v, err := ogcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ogcb *OAuthGrantCreateBulk) Exec(ctx context.Context) error { + _, err := ogcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ogcb *OAuthGrantCreateBulk) ExecX(ctx context.Context) { + if err := ogcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.OAuthGrant.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.OAuthGrantUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (ogcb *OAuthGrantCreateBulk) OnConflict(opts ...sql.ConflictOption) *OAuthGrantUpsertBulk { + ogcb.conflict = opts + return &OAuthGrantUpsertBulk{ + create: ogcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (ogcb *OAuthGrantCreateBulk) OnConflictColumns(columns ...string) *OAuthGrantUpsertBulk { + ogcb.conflict = append(ogcb.conflict, sql.ConflictColumns(columns...)) + return &OAuthGrantUpsertBulk{ + create: ogcb, + } +} + +// OAuthGrantUpsertBulk is the builder for "upsert"-ing +// a bulk of OAuthGrant nodes. +type OAuthGrantUpsertBulk struct { + create *OAuthGrantCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *OAuthGrantUpsertBulk) UpdateNewValues() *OAuthGrantUpsertBulk { + 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(oauthgrant.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.OAuthGrant.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *OAuthGrantUpsertBulk) Ignore() *OAuthGrantUpsertBulk { + 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 *OAuthGrantUpsertBulk) DoNothing() *OAuthGrantUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the OAuthGrantCreateBulk.OnConflict +// documentation for more info. +func (u *OAuthGrantUpsertBulk) Update(set func(*OAuthGrantUpsert)) *OAuthGrantUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&OAuthGrantUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *OAuthGrantUpsertBulk) SetUpdatedAt(v time.Time) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateUpdatedAt() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *OAuthGrantUpsertBulk) SetDeletedAt(v time.Time) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateDeletedAt() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *OAuthGrantUpsertBulk) ClearDeletedAt() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.ClearDeletedAt() + }) +} + +// SetUserID sets the "user_id" field. +func (u *OAuthGrantUpsertBulk) SetUserID(v int) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetUserID(v) + }) +} + +// UpdateUserID sets the "user_id" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateUserID() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateUserID() + }) +} + +// SetClientID sets the "client_id" field. +func (u *OAuthGrantUpsertBulk) SetClientID(v int) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetClientID(v) + }) +} + +// UpdateClientID sets the "client_id" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateClientID() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateClientID() + }) +} + +// SetScopes sets the "scopes" field. +func (u *OAuthGrantUpsertBulk) SetScopes(v []string) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetScopes(v) + }) +} + +// UpdateScopes sets the "scopes" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateScopes() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateScopes() + }) +} + +// SetLastUsedAt sets the "last_used_at" field. +func (u *OAuthGrantUpsertBulk) SetLastUsedAt(v time.Time) *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.SetLastUsedAt(v) + }) +} + +// UpdateLastUsedAt sets the "last_used_at" field to the value that was provided on create. +func (u *OAuthGrantUpsertBulk) UpdateLastUsedAt() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.UpdateLastUsedAt() + }) +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (u *OAuthGrantUpsertBulk) ClearLastUsedAt() *OAuthGrantUpsertBulk { + return u.Update(func(s *OAuthGrantUpsert) { + s.ClearLastUsedAt() + }) +} + +// Exec executes the query. +func (u *OAuthGrantUpsertBulk) 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 OAuthGrantCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for OAuthGrantCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *OAuthGrantUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/oauthgrant_delete.go b/ent/oauthgrant_delete.go new file mode 100644 index 00000000..1e231d21 --- /dev/null +++ b/ent/oauthgrant_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/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// OAuthGrantDelete is the builder for deleting a OAuthGrant entity. +type OAuthGrantDelete struct { + config + hooks []Hook + mutation *OAuthGrantMutation +} + +// Where appends a list predicates to the OAuthGrantDelete builder. +func (ogd *OAuthGrantDelete) Where(ps ...predicate.OAuthGrant) *OAuthGrantDelete { + ogd.mutation.Where(ps...) + return ogd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ogd *OAuthGrantDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, ogd.sqlExec, ogd.mutation, ogd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (ogd *OAuthGrantDelete) ExecX(ctx context.Context) int { + n, err := ogd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ogd *OAuthGrantDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(oauthgrant.Table, sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt)) + if ps := ogd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ogd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + ogd.mutation.done = true + return affected, err +} + +// OAuthGrantDeleteOne is the builder for deleting a single OAuthGrant entity. +type OAuthGrantDeleteOne struct { + ogd *OAuthGrantDelete +} + +// Where appends a list predicates to the OAuthGrantDelete builder. +func (ogdo *OAuthGrantDeleteOne) Where(ps ...predicate.OAuthGrant) *OAuthGrantDeleteOne { + ogdo.ogd.mutation.Where(ps...) + return ogdo +} + +// Exec executes the deletion query. +func (ogdo *OAuthGrantDeleteOne) Exec(ctx context.Context) error { + n, err := ogdo.ogd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{oauthgrant.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ogdo *OAuthGrantDeleteOne) ExecX(ctx context.Context) { + if err := ogdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/oauthgrant_query.go b/ent/oauthgrant_query.go new file mode 100644 index 00000000..8d0e56d7 --- /dev/null +++ b/ent/oauthgrant_query.go @@ -0,0 +1,680 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" + "github.com/cloudreve/Cloudreve/v4/ent/user" +) + +// OAuthGrantQuery is the builder for querying OAuthGrant entities. +type OAuthGrantQuery struct { + config + ctx *QueryContext + order []oauthgrant.OrderOption + inters []Interceptor + predicates []predicate.OAuthGrant + withUser *UserQuery + withClient *OAuthClientQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the OAuthGrantQuery builder. +func (ogq *OAuthGrantQuery) Where(ps ...predicate.OAuthGrant) *OAuthGrantQuery { + ogq.predicates = append(ogq.predicates, ps...) + return ogq +} + +// Limit the number of records to be returned by this query. +func (ogq *OAuthGrantQuery) Limit(limit int) *OAuthGrantQuery { + ogq.ctx.Limit = &limit + return ogq +} + +// Offset to start from. +func (ogq *OAuthGrantQuery) Offset(offset int) *OAuthGrantQuery { + ogq.ctx.Offset = &offset + return ogq +} + +// 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 (ogq *OAuthGrantQuery) Unique(unique bool) *OAuthGrantQuery { + ogq.ctx.Unique = &unique + return ogq +} + +// Order specifies how the records should be ordered. +func (ogq *OAuthGrantQuery) Order(o ...oauthgrant.OrderOption) *OAuthGrantQuery { + ogq.order = append(ogq.order, o...) + return ogq +} + +// QueryUser chains the current query on the "user" edge. +func (ogq *OAuthGrantQuery) QueryUser() *UserQuery { + query := (&UserClient{config: ogq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := ogq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := ogq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(oauthgrant.Table, oauthgrant.FieldID, selector), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, oauthgrant.UserTable, oauthgrant.UserColumn), + ) + fromU = sqlgraph.SetNeighbors(ogq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryClient chains the current query on the "client" edge. +func (ogq *OAuthGrantQuery) QueryClient() *OAuthClientQuery { + query := (&OAuthClientClient{config: ogq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := ogq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := ogq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(oauthgrant.Table, oauthgrant.FieldID, selector), + sqlgraph.To(oauthclient.Table, oauthclient.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, oauthgrant.ClientTable, oauthgrant.ClientColumn), + ) + fromU = sqlgraph.SetNeighbors(ogq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first OAuthGrant entity from the query. +// Returns a *NotFoundError when no OAuthGrant was found. +func (ogq *OAuthGrantQuery) First(ctx context.Context) (*OAuthGrant, error) { + nodes, err := ogq.Limit(1).All(setContextOp(ctx, ogq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{oauthgrant.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (ogq *OAuthGrantQuery) FirstX(ctx context.Context) *OAuthGrant { + node, err := ogq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first OAuthGrant ID from the query. +// Returns a *NotFoundError when no OAuthGrant ID was found. +func (ogq *OAuthGrantQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ogq.Limit(1).IDs(setContextOp(ctx, ogq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{oauthgrant.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (ogq *OAuthGrantQuery) FirstIDX(ctx context.Context) int { + id, err := ogq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single OAuthGrant entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one OAuthGrant entity is found. +// Returns a *NotFoundError when no OAuthGrant entities are found. +func (ogq *OAuthGrantQuery) Only(ctx context.Context) (*OAuthGrant, error) { + nodes, err := ogq.Limit(2).All(setContextOp(ctx, ogq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{oauthgrant.Label} + default: + return nil, &NotSingularError{oauthgrant.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (ogq *OAuthGrantQuery) OnlyX(ctx context.Context) *OAuthGrant { + node, err := ogq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only OAuthGrant ID in the query. +// Returns a *NotSingularError when more than one OAuthGrant ID is found. +// Returns a *NotFoundError when no entities are found. +func (ogq *OAuthGrantQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ogq.Limit(2).IDs(setContextOp(ctx, ogq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{oauthgrant.Label} + default: + err = &NotSingularError{oauthgrant.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (ogq *OAuthGrantQuery) OnlyIDX(ctx context.Context) int { + id, err := ogq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of OAuthGrants. +func (ogq *OAuthGrantQuery) All(ctx context.Context) ([]*OAuthGrant, error) { + ctx = setContextOp(ctx, ogq.ctx, "All") + if err := ogq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*OAuthGrant, *OAuthGrantQuery]() + return withInterceptors[[]*OAuthGrant](ctx, ogq, qr, ogq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (ogq *OAuthGrantQuery) AllX(ctx context.Context) []*OAuthGrant { + nodes, err := ogq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of OAuthGrant IDs. +func (ogq *OAuthGrantQuery) IDs(ctx context.Context) (ids []int, err error) { + if ogq.ctx.Unique == nil && ogq.path != nil { + ogq.Unique(true) + } + ctx = setContextOp(ctx, ogq.ctx, "IDs") + if err = ogq.Select(oauthgrant.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (ogq *OAuthGrantQuery) IDsX(ctx context.Context) []int { + ids, err := ogq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (ogq *OAuthGrantQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, ogq.ctx, "Count") + if err := ogq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, ogq, querierCount[*OAuthGrantQuery](), ogq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (ogq *OAuthGrantQuery) CountX(ctx context.Context) int { + count, err := ogq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (ogq *OAuthGrantQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, ogq.ctx, "Exist") + switch _, err := ogq.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 (ogq *OAuthGrantQuery) ExistX(ctx context.Context) bool { + exist, err := ogq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the OAuthGrantQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (ogq *OAuthGrantQuery) Clone() *OAuthGrantQuery { + if ogq == nil { + return nil + } + return &OAuthGrantQuery{ + config: ogq.config, + ctx: ogq.ctx.Clone(), + order: append([]oauthgrant.OrderOption{}, ogq.order...), + inters: append([]Interceptor{}, ogq.inters...), + predicates: append([]predicate.OAuthGrant{}, ogq.predicates...), + withUser: ogq.withUser.Clone(), + withClient: ogq.withClient.Clone(), + // clone intermediate query. + sql: ogq.sql.Clone(), + path: ogq.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 (ogq *OAuthGrantQuery) WithUser(opts ...func(*UserQuery)) *OAuthGrantQuery { + query := (&UserClient{config: ogq.config}).Query() + for _, opt := range opts { + opt(query) + } + ogq.withUser = query + return ogq +} + +// WithClient tells the query-builder to eager-load the nodes that are connected to +// the "client" edge. The optional arguments are used to configure the query builder of the edge. +func (ogq *OAuthGrantQuery) WithClient(opts ...func(*OAuthClientQuery)) *OAuthGrantQuery { + query := (&OAuthClientClient{config: ogq.config}).Query() + for _, opt := range opts { + opt(query) + } + ogq.withClient = query + return ogq +} + +// 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.OAuthGrant.Query(). +// GroupBy(oauthgrant.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (ogq *OAuthGrantQuery) GroupBy(field string, fields ...string) *OAuthGrantGroupBy { + ogq.ctx.Fields = append([]string{field}, fields...) + grbuild := &OAuthGrantGroupBy{build: ogq} + grbuild.flds = &ogq.ctx.Fields + grbuild.label = oauthgrant.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.OAuthGrant.Query(). +// Select(oauthgrant.FieldCreatedAt). +// Scan(ctx, &v) +func (ogq *OAuthGrantQuery) Select(fields ...string) *OAuthGrantSelect { + ogq.ctx.Fields = append(ogq.ctx.Fields, fields...) + sbuild := &OAuthGrantSelect{OAuthGrantQuery: ogq} + sbuild.label = oauthgrant.Label + sbuild.flds, sbuild.scan = &ogq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a OAuthGrantSelect configured with the given aggregations. +func (ogq *OAuthGrantQuery) Aggregate(fns ...AggregateFunc) *OAuthGrantSelect { + return ogq.Select().Aggregate(fns...) +} + +func (ogq *OAuthGrantQuery) prepareQuery(ctx context.Context) error { + for _, inter := range ogq.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, ogq); err != nil { + return err + } + } + } + for _, f := range ogq.ctx.Fields { + if !oauthgrant.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if ogq.path != nil { + prev, err := ogq.path(ctx) + if err != nil { + return err + } + ogq.sql = prev + } + return nil +} + +func (ogq *OAuthGrantQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*OAuthGrant, error) { + var ( + nodes = []*OAuthGrant{} + _spec = ogq.querySpec() + loadedTypes = [2]bool{ + ogq.withUser != nil, + ogq.withClient != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*OAuthGrant).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &OAuthGrant{config: ogq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, ogq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := ogq.withUser; query != nil { + if err := ogq.loadUser(ctx, query, nodes, nil, + func(n *OAuthGrant, e *User) { n.Edges.User = e }); err != nil { + return nil, err + } + } + if query := ogq.withClient; query != nil { + if err := ogq.loadClient(ctx, query, nodes, nil, + func(n *OAuthGrant, e *OAuthClient) { n.Edges.Client = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (ogq *OAuthGrantQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*OAuthGrant, init func(*OAuthGrant), assign func(*OAuthGrant, *User)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*OAuthGrant) + 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 (ogq *OAuthGrantQuery) loadClient(ctx context.Context, query *OAuthClientQuery, nodes []*OAuthGrant, init func(*OAuthGrant), assign func(*OAuthGrant, *OAuthClient)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*OAuthGrant) + for i := range nodes { + fk := nodes[i].ClientID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(oauthclient.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 "client_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (ogq *OAuthGrantQuery) sqlCount(ctx context.Context) (int, error) { + _spec := ogq.querySpec() + _spec.Node.Columns = ogq.ctx.Fields + if len(ogq.ctx.Fields) > 0 { + _spec.Unique = ogq.ctx.Unique != nil && *ogq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, ogq.driver, _spec) +} + +func (ogq *OAuthGrantQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(oauthgrant.Table, oauthgrant.Columns, sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt)) + _spec.From = ogq.sql + if unique := ogq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if ogq.path != nil { + _spec.Unique = true + } + if fields := ogq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, oauthgrant.FieldID) + for i := range fields { + if fields[i] != oauthgrant.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if ogq.withUser != nil { + _spec.Node.AddColumnOnce(oauthgrant.FieldUserID) + } + if ogq.withClient != nil { + _spec.Node.AddColumnOnce(oauthgrant.FieldClientID) + } + } + if ps := ogq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := ogq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := ogq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := ogq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (ogq *OAuthGrantQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(ogq.driver.Dialect()) + t1 := builder.Table(oauthgrant.Table) + columns := ogq.ctx.Fields + if len(columns) == 0 { + columns = oauthgrant.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if ogq.sql != nil { + selector = ogq.sql + selector.Select(selector.Columns(columns...)...) + } + if ogq.ctx.Unique != nil && *ogq.ctx.Unique { + selector.Distinct() + } + for _, p := range ogq.predicates { + p(selector) + } + for _, p := range ogq.order { + p(selector) + } + if offset := ogq.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 := ogq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// OAuthGrantGroupBy is the group-by builder for OAuthGrant entities. +type OAuthGrantGroupBy struct { + selector + build *OAuthGrantQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (oggb *OAuthGrantGroupBy) Aggregate(fns ...AggregateFunc) *OAuthGrantGroupBy { + oggb.fns = append(oggb.fns, fns...) + return oggb +} + +// Scan applies the selector query and scans the result into the given value. +func (oggb *OAuthGrantGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, oggb.build.ctx, "GroupBy") + if err := oggb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*OAuthGrantQuery, *OAuthGrantGroupBy](ctx, oggb.build, oggb, oggb.build.inters, v) +} + +func (oggb *OAuthGrantGroupBy) sqlScan(ctx context.Context, root *OAuthGrantQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(oggb.fns)) + for _, fn := range oggb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*oggb.flds)+len(oggb.fns)) + for _, f := range *oggb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*oggb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := oggb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// OAuthGrantSelect is the builder for selecting fields of OAuthGrant entities. +type OAuthGrantSelect struct { + *OAuthGrantQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ogs *OAuthGrantSelect) Aggregate(fns ...AggregateFunc) *OAuthGrantSelect { + ogs.fns = append(ogs.fns, fns...) + return ogs +} + +// Scan applies the selector query and scans the result into the given value. +func (ogs *OAuthGrantSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ogs.ctx, "Select") + if err := ogs.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*OAuthGrantQuery, *OAuthGrantSelect](ctx, ogs.OAuthGrantQuery, ogs, ogs.inters, v) +} + +func (ogs *OAuthGrantSelect) sqlScan(ctx context.Context, root *OAuthGrantQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ogs.fns)) + for _, fn := range ogs.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ogs.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 := ogs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/oauthgrant_update.go b/ent/oauthgrant_update.go new file mode 100644 index 00000000..b68ca908 --- /dev/null +++ b/ent/oauthgrant_update.go @@ -0,0 +1,615 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/dialect/sql/sqljson" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" + "github.com/cloudreve/Cloudreve/v4/ent/user" +) + +// OAuthGrantUpdate is the builder for updating OAuthGrant entities. +type OAuthGrantUpdate struct { + config + hooks []Hook + mutation *OAuthGrantMutation +} + +// Where appends a list predicates to the OAuthGrantUpdate builder. +func (ogu *OAuthGrantUpdate) Where(ps ...predicate.OAuthGrant) *OAuthGrantUpdate { + ogu.mutation.Where(ps...) + return ogu +} + +// SetUpdatedAt sets the "updated_at" field. +func (ogu *OAuthGrantUpdate) SetUpdatedAt(t time.Time) *OAuthGrantUpdate { + ogu.mutation.SetUpdatedAt(t) + return ogu +} + +// SetDeletedAt sets the "deleted_at" field. +func (ogu *OAuthGrantUpdate) SetDeletedAt(t time.Time) *OAuthGrantUpdate { + ogu.mutation.SetDeletedAt(t) + return ogu +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (ogu *OAuthGrantUpdate) SetNillableDeletedAt(t *time.Time) *OAuthGrantUpdate { + if t != nil { + ogu.SetDeletedAt(*t) + } + return ogu +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (ogu *OAuthGrantUpdate) ClearDeletedAt() *OAuthGrantUpdate { + ogu.mutation.ClearDeletedAt() + return ogu +} + +// SetUserID sets the "user_id" field. +func (ogu *OAuthGrantUpdate) SetUserID(i int) *OAuthGrantUpdate { + ogu.mutation.SetUserID(i) + return ogu +} + +// SetNillableUserID sets the "user_id" field if the given value is not nil. +func (ogu *OAuthGrantUpdate) SetNillableUserID(i *int) *OAuthGrantUpdate { + if i != nil { + ogu.SetUserID(*i) + } + return ogu +} + +// SetClientID sets the "client_id" field. +func (ogu *OAuthGrantUpdate) SetClientID(i int) *OAuthGrantUpdate { + ogu.mutation.SetClientID(i) + return ogu +} + +// SetNillableClientID sets the "client_id" field if the given value is not nil. +func (ogu *OAuthGrantUpdate) SetNillableClientID(i *int) *OAuthGrantUpdate { + if i != nil { + ogu.SetClientID(*i) + } + return ogu +} + +// SetScopes sets the "scopes" field. +func (ogu *OAuthGrantUpdate) SetScopes(s []string) *OAuthGrantUpdate { + ogu.mutation.SetScopes(s) + return ogu +} + +// AppendScopes appends s to the "scopes" field. +func (ogu *OAuthGrantUpdate) AppendScopes(s []string) *OAuthGrantUpdate { + ogu.mutation.AppendScopes(s) + return ogu +} + +// SetLastUsedAt sets the "last_used_at" field. +func (ogu *OAuthGrantUpdate) SetLastUsedAt(t time.Time) *OAuthGrantUpdate { + ogu.mutation.SetLastUsedAt(t) + return ogu +} + +// SetNillableLastUsedAt sets the "last_used_at" field if the given value is not nil. +func (ogu *OAuthGrantUpdate) SetNillableLastUsedAt(t *time.Time) *OAuthGrantUpdate { + if t != nil { + ogu.SetLastUsedAt(*t) + } + return ogu +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (ogu *OAuthGrantUpdate) ClearLastUsedAt() *OAuthGrantUpdate { + ogu.mutation.ClearLastUsedAt() + return ogu +} + +// SetUser sets the "user" edge to the User entity. +func (ogu *OAuthGrantUpdate) SetUser(u *User) *OAuthGrantUpdate { + return ogu.SetUserID(u.ID) +} + +// SetClient sets the "client" edge to the OAuthClient entity. +func (ogu *OAuthGrantUpdate) SetClient(o *OAuthClient) *OAuthGrantUpdate { + return ogu.SetClientID(o.ID) +} + +// Mutation returns the OAuthGrantMutation object of the builder. +func (ogu *OAuthGrantUpdate) Mutation() *OAuthGrantMutation { + return ogu.mutation +} + +// ClearUser clears the "user" edge to the User entity. +func (ogu *OAuthGrantUpdate) ClearUser() *OAuthGrantUpdate { + ogu.mutation.ClearUser() + return ogu +} + +// ClearClient clears the "client" edge to the OAuthClient entity. +func (ogu *OAuthGrantUpdate) ClearClient() *OAuthGrantUpdate { + ogu.mutation.ClearClient() + return ogu +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (ogu *OAuthGrantUpdate) Save(ctx context.Context) (int, error) { + if err := ogu.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, ogu.sqlSave, ogu.mutation, ogu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ogu *OAuthGrantUpdate) SaveX(ctx context.Context) int { + affected, err := ogu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (ogu *OAuthGrantUpdate) Exec(ctx context.Context) error { + _, err := ogu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ogu *OAuthGrantUpdate) ExecX(ctx context.Context) { + if err := ogu.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ogu *OAuthGrantUpdate) defaults() error { + if _, ok := ogu.mutation.UpdatedAt(); !ok { + if oauthgrant.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthgrant.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthgrant.UpdateDefaultUpdatedAt() + ogu.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (ogu *OAuthGrantUpdate) check() error { + if _, ok := ogu.mutation.UserID(); ogu.mutation.UserCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "OAuthGrant.user"`) + } + if _, ok := ogu.mutation.ClientID(); ogu.mutation.ClientCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "OAuthGrant.client"`) + } + return nil +} + +func (ogu *OAuthGrantUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := ogu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(oauthgrant.Table, oauthgrant.Columns, sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt)) + if ps := ogu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ogu.mutation.UpdatedAt(); ok { + _spec.SetField(oauthgrant.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := ogu.mutation.DeletedAt(); ok { + _spec.SetField(oauthgrant.FieldDeletedAt, field.TypeTime, value) + } + if ogu.mutation.DeletedAtCleared() { + _spec.ClearField(oauthgrant.FieldDeletedAt, field.TypeTime) + } + if value, ok := ogu.mutation.Scopes(); ok { + _spec.SetField(oauthgrant.FieldScopes, field.TypeJSON, value) + } + if value, ok := ogu.mutation.AppendedScopes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthgrant.FieldScopes, value) + }) + } + if value, ok := ogu.mutation.LastUsedAt(); ok { + _spec.SetField(oauthgrant.FieldLastUsedAt, field.TypeTime, value) + } + if ogu.mutation.LastUsedAtCleared() { + _spec.ClearField(oauthgrant.FieldLastUsedAt, field.TypeTime) + } + if ogu.mutation.UserCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.UserTable, + Columns: []string{oauthgrant.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ogu.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.UserTable, + Columns: []string{oauthgrant.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if ogu.mutation.ClientCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.ClientTable, + Columns: []string{oauthgrant.ClientColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := ogu.mutation.ClientIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.ClientTable, + Columns: []string{oauthgrant.ClientColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, ogu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{oauthgrant.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + ogu.mutation.done = true + return n, nil +} + +// OAuthGrantUpdateOne is the builder for updating a single OAuthGrant entity. +type OAuthGrantUpdateOne struct { + config + fields []string + hooks []Hook + mutation *OAuthGrantMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (oguo *OAuthGrantUpdateOne) SetUpdatedAt(t time.Time) *OAuthGrantUpdateOne { + oguo.mutation.SetUpdatedAt(t) + return oguo +} + +// SetDeletedAt sets the "deleted_at" field. +func (oguo *OAuthGrantUpdateOne) SetDeletedAt(t time.Time) *OAuthGrantUpdateOne { + oguo.mutation.SetDeletedAt(t) + return oguo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (oguo *OAuthGrantUpdateOne) SetNillableDeletedAt(t *time.Time) *OAuthGrantUpdateOne { + if t != nil { + oguo.SetDeletedAt(*t) + } + return oguo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (oguo *OAuthGrantUpdateOne) ClearDeletedAt() *OAuthGrantUpdateOne { + oguo.mutation.ClearDeletedAt() + return oguo +} + +// SetUserID sets the "user_id" field. +func (oguo *OAuthGrantUpdateOne) SetUserID(i int) *OAuthGrantUpdateOne { + oguo.mutation.SetUserID(i) + return oguo +} + +// SetNillableUserID sets the "user_id" field if the given value is not nil. +func (oguo *OAuthGrantUpdateOne) SetNillableUserID(i *int) *OAuthGrantUpdateOne { + if i != nil { + oguo.SetUserID(*i) + } + return oguo +} + +// SetClientID sets the "client_id" field. +func (oguo *OAuthGrantUpdateOne) SetClientID(i int) *OAuthGrantUpdateOne { + oguo.mutation.SetClientID(i) + return oguo +} + +// SetNillableClientID sets the "client_id" field if the given value is not nil. +func (oguo *OAuthGrantUpdateOne) SetNillableClientID(i *int) *OAuthGrantUpdateOne { + if i != nil { + oguo.SetClientID(*i) + } + return oguo +} + +// SetScopes sets the "scopes" field. +func (oguo *OAuthGrantUpdateOne) SetScopes(s []string) *OAuthGrantUpdateOne { + oguo.mutation.SetScopes(s) + return oguo +} + +// AppendScopes appends s to the "scopes" field. +func (oguo *OAuthGrantUpdateOne) AppendScopes(s []string) *OAuthGrantUpdateOne { + oguo.mutation.AppendScopes(s) + return oguo +} + +// SetLastUsedAt sets the "last_used_at" field. +func (oguo *OAuthGrantUpdateOne) SetLastUsedAt(t time.Time) *OAuthGrantUpdateOne { + oguo.mutation.SetLastUsedAt(t) + return oguo +} + +// SetNillableLastUsedAt sets the "last_used_at" field if the given value is not nil. +func (oguo *OAuthGrantUpdateOne) SetNillableLastUsedAt(t *time.Time) *OAuthGrantUpdateOne { + if t != nil { + oguo.SetLastUsedAt(*t) + } + return oguo +} + +// ClearLastUsedAt clears the value of the "last_used_at" field. +func (oguo *OAuthGrantUpdateOne) ClearLastUsedAt() *OAuthGrantUpdateOne { + oguo.mutation.ClearLastUsedAt() + return oguo +} + +// SetUser sets the "user" edge to the User entity. +func (oguo *OAuthGrantUpdateOne) SetUser(u *User) *OAuthGrantUpdateOne { + return oguo.SetUserID(u.ID) +} + +// SetClient sets the "client" edge to the OAuthClient entity. +func (oguo *OAuthGrantUpdateOne) SetClient(o *OAuthClient) *OAuthGrantUpdateOne { + return oguo.SetClientID(o.ID) +} + +// Mutation returns the OAuthGrantMutation object of the builder. +func (oguo *OAuthGrantUpdateOne) Mutation() *OAuthGrantMutation { + return oguo.mutation +} + +// ClearUser clears the "user" edge to the User entity. +func (oguo *OAuthGrantUpdateOne) ClearUser() *OAuthGrantUpdateOne { + oguo.mutation.ClearUser() + return oguo +} + +// ClearClient clears the "client" edge to the OAuthClient entity. +func (oguo *OAuthGrantUpdateOne) ClearClient() *OAuthGrantUpdateOne { + oguo.mutation.ClearClient() + return oguo +} + +// Where appends a list predicates to the OAuthGrantUpdate builder. +func (oguo *OAuthGrantUpdateOne) Where(ps ...predicate.OAuthGrant) *OAuthGrantUpdateOne { + oguo.mutation.Where(ps...) + return oguo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (oguo *OAuthGrantUpdateOne) Select(field string, fields ...string) *OAuthGrantUpdateOne { + oguo.fields = append([]string{field}, fields...) + return oguo +} + +// Save executes the query and returns the updated OAuthGrant entity. +func (oguo *OAuthGrantUpdateOne) Save(ctx context.Context) (*OAuthGrant, error) { + if err := oguo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, oguo.sqlSave, oguo.mutation, oguo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (oguo *OAuthGrantUpdateOne) SaveX(ctx context.Context) *OAuthGrant { + node, err := oguo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (oguo *OAuthGrantUpdateOne) Exec(ctx context.Context) error { + _, err := oguo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (oguo *OAuthGrantUpdateOne) ExecX(ctx context.Context) { + if err := oguo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (oguo *OAuthGrantUpdateOne) defaults() error { + if _, ok := oguo.mutation.UpdatedAt(); !ok { + if oauthgrant.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized oauthgrant.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := oauthgrant.UpdateDefaultUpdatedAt() + oguo.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (oguo *OAuthGrantUpdateOne) check() error { + if _, ok := oguo.mutation.UserID(); oguo.mutation.UserCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "OAuthGrant.user"`) + } + if _, ok := oguo.mutation.ClientID(); oguo.mutation.ClientCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "OAuthGrant.client"`) + } + return nil +} + +func (oguo *OAuthGrantUpdateOne) sqlSave(ctx context.Context) (_node *OAuthGrant, err error) { + if err := oguo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(oauthgrant.Table, oauthgrant.Columns, sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt)) + id, ok := oguo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "OAuthGrant.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := oguo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, oauthgrant.FieldID) + for _, f := range fields { + if !oauthgrant.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != oauthgrant.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := oguo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := oguo.mutation.UpdatedAt(); ok { + _spec.SetField(oauthgrant.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := oguo.mutation.DeletedAt(); ok { + _spec.SetField(oauthgrant.FieldDeletedAt, field.TypeTime, value) + } + if oguo.mutation.DeletedAtCleared() { + _spec.ClearField(oauthgrant.FieldDeletedAt, field.TypeTime) + } + if value, ok := oguo.mutation.Scopes(); ok { + _spec.SetField(oauthgrant.FieldScopes, field.TypeJSON, value) + } + if value, ok := oguo.mutation.AppendedScopes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, oauthgrant.FieldScopes, value) + }) + } + if value, ok := oguo.mutation.LastUsedAt(); ok { + _spec.SetField(oauthgrant.FieldLastUsedAt, field.TypeTime, value) + } + if oguo.mutation.LastUsedAtCleared() { + _spec.ClearField(oauthgrant.FieldLastUsedAt, field.TypeTime) + } + if oguo.mutation.UserCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.UserTable, + Columns: []string{oauthgrant.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := oguo.mutation.UserIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.UserTable, + Columns: []string{oauthgrant.UserColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if oguo.mutation.ClientCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.ClientTable, + Columns: []string{oauthgrant.ClientColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := oguo.mutation.ClientIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: oauthgrant.ClientTable, + Columns: []string{oauthgrant.ClientColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthclient.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &OAuthGrant{config: oguo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, oguo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{oauthgrant.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + oguo.mutation.done = true + return _node, nil +} diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index 9a8feb2e..d258dac0 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -30,6 +30,12 @@ type Metadata func(*sql.Selector) // Node is the predicate function for node builders. type Node func(*sql.Selector) +// OAuthClient is the predicate function for oauthclient builders. +type OAuthClient func(*sql.Selector) + +// OAuthGrant is the predicate function for oauthgrant builders. +type OAuthGrant func(*sql.Selector) + // Passkey is the predicate function for passkey builders. type Passkey func(*sql.Selector) diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go index 44655e0d..40303c99 100644 --- a/ent/runtime/runtime.go +++ b/ent/runtime/runtime.go @@ -13,6 +13,8 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/schema" "github.com/cloudreve/Cloudreve/v4/ent/setting" @@ -200,6 +202,80 @@ func init() { nodeDescWeight := nodeFields[7].Descriptor() // node.DefaultWeight holds the default value on creation for the weight field. node.DefaultWeight = nodeDescWeight.Default.(int) + oauthclientMixin := schema.OAuthClient{}.Mixin() + oauthclientMixinHooks0 := oauthclientMixin[0].Hooks() + oauthclient.Hooks[0] = oauthclientMixinHooks0[0] + oauthclientMixinInters0 := oauthclientMixin[0].Interceptors() + oauthclient.Interceptors[0] = oauthclientMixinInters0[0] + oauthclientMixinFields0 := oauthclientMixin[0].Fields() + _ = oauthclientMixinFields0 + oauthclientFields := schema.OAuthClient{}.Fields() + _ = oauthclientFields + // oauthclientDescCreatedAt is the schema descriptor for created_at field. + oauthclientDescCreatedAt := oauthclientMixinFields0[0].Descriptor() + // oauthclient.DefaultCreatedAt holds the default value on creation for the created_at field. + oauthclient.DefaultCreatedAt = oauthclientDescCreatedAt.Default.(func() time.Time) + // oauthclientDescUpdatedAt is the schema descriptor for updated_at field. + oauthclientDescUpdatedAt := oauthclientMixinFields0[1].Descriptor() + // oauthclient.DefaultUpdatedAt holds the default value on creation for the updated_at field. + oauthclient.DefaultUpdatedAt = oauthclientDescUpdatedAt.Default.(func() time.Time) + // oauthclient.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + oauthclient.UpdateDefaultUpdatedAt = oauthclientDescUpdatedAt.UpdateDefault.(func() time.Time) + // oauthclientDescGUID is the schema descriptor for guid field. + oauthclientDescGUID := oauthclientFields[0].Descriptor() + // oauthclient.GUIDValidator is a validator for the "guid" field. It is called by the builders before save. + oauthclient.GUIDValidator = oauthclientDescGUID.Validators[0].(func(string) error) + // oauthclientDescSecret is the schema descriptor for secret field. + oauthclientDescSecret := oauthclientFields[1].Descriptor() + // oauthclient.SecretValidator is a validator for the "secret" field. It is called by the builders before save. + oauthclient.SecretValidator = oauthclientDescSecret.Validators[0].(func(string) error) + // oauthclientDescName is the schema descriptor for name field. + oauthclientDescName := oauthclientFields[2].Descriptor() + // oauthclient.NameValidator is a validator for the "name" field. It is called by the builders before save. + oauthclient.NameValidator = oauthclientDescName.Validators[0].(func(string) error) + // oauthclientDescHomepageURL is the schema descriptor for homepage_url field. + oauthclientDescHomepageURL := oauthclientFields[3].Descriptor() + // oauthclient.HomepageURLValidator is a validator for the "homepage_url" field. It is called by the builders before save. + oauthclient.HomepageURLValidator = oauthclientDescHomepageURL.Validators[0].(func(string) error) + // oauthclientDescRedirectUris is the schema descriptor for redirect_uris field. + oauthclientDescRedirectUris := oauthclientFields[4].Descriptor() + // oauthclient.DefaultRedirectUris holds the default value on creation for the redirect_uris field. + oauthclient.DefaultRedirectUris = oauthclientDescRedirectUris.Default.([]string) + // oauthclientDescScopes is the schema descriptor for scopes field. + oauthclientDescScopes := oauthclientFields[5].Descriptor() + // oauthclient.DefaultScopes holds the default value on creation for the scopes field. + oauthclient.DefaultScopes = oauthclientDescScopes.Default.([]string) + // oauthclientDescProps is the schema descriptor for props field. + oauthclientDescProps := oauthclientFields[6].Descriptor() + // oauthclient.DefaultProps holds the default value on creation for the props field. + oauthclient.DefaultProps = oauthclientDescProps.Default.(*types.OAuthClientProps) + // oauthclientDescIsEnabled is the schema descriptor for is_enabled field. + oauthclientDescIsEnabled := oauthclientFields[7].Descriptor() + // oauthclient.DefaultIsEnabled holds the default value on creation for the is_enabled field. + oauthclient.DefaultIsEnabled = oauthclientDescIsEnabled.Default.(bool) + oauthgrantMixin := schema.OAuthGrant{}.Mixin() + oauthgrantMixinHooks0 := oauthgrantMixin[0].Hooks() + oauthgrant.Hooks[0] = oauthgrantMixinHooks0[0] + oauthgrantMixinInters0 := oauthgrantMixin[0].Interceptors() + oauthgrant.Interceptors[0] = oauthgrantMixinInters0[0] + oauthgrantMixinFields0 := oauthgrantMixin[0].Fields() + _ = oauthgrantMixinFields0 + oauthgrantFields := schema.OAuthGrant{}.Fields() + _ = oauthgrantFields + // oauthgrantDescCreatedAt is the schema descriptor for created_at field. + oauthgrantDescCreatedAt := oauthgrantMixinFields0[0].Descriptor() + // oauthgrant.DefaultCreatedAt holds the default value on creation for the created_at field. + oauthgrant.DefaultCreatedAt = oauthgrantDescCreatedAt.Default.(func() time.Time) + // oauthgrantDescUpdatedAt is the schema descriptor for updated_at field. + oauthgrantDescUpdatedAt := oauthgrantMixinFields0[1].Descriptor() + // oauthgrant.DefaultUpdatedAt holds the default value on creation for the updated_at field. + oauthgrant.DefaultUpdatedAt = oauthgrantDescUpdatedAt.Default.(func() time.Time) + // oauthgrant.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + oauthgrant.UpdateDefaultUpdatedAt = oauthgrantDescUpdatedAt.UpdateDefault.(func() time.Time) + // oauthgrantDescScopes is the schema descriptor for scopes field. + oauthgrantDescScopes := oauthgrantFields[2].Descriptor() + // oauthgrant.DefaultScopes holds the default value on creation for the scopes field. + oauthgrant.DefaultScopes = oauthgrantDescScopes.Default.([]string) passkeyMixin := schema.Passkey{}.Mixin() passkeyMixinHooks0 := passkeyMixin[0].Hooks() passkey.Hooks[0] = passkeyMixinHooks0[0] diff --git a/ent/schema/oauthclient.go b/ent/schema/oauthclient.go new file mode 100644 index 00000000..1b2c1f3c --- /dev/null +++ b/ent/schema/oauthclient.go @@ -0,0 +1,51 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// OAuthClient holds the schema definition for the OAuthClient entity. +type OAuthClient struct { + ent.Schema +} + +// Fields of the OAuthClient. +func (OAuthClient) Fields() []ent.Field { + return []ent.Field{ + field.String("guid"). + MaxLen(255). + Unique(), + field.String("secret"). + MaxLen(255). + Sensitive(), + field.String("name"). + MaxLen(255), + field.String("homepage_url"). + MaxLen(2048). + Optional(), + field.JSON("redirect_uris", []string{}). + Default([]string{}), + field.JSON("scopes", []string{}). + Default([]string{}), + field.JSON("props", &types.OAuthClientProps{}). + Default(&types.OAuthClientProps{}), + field.Bool("is_enabled"). + Default(true), + } +} + +// Edges of the OAuthClient. +func (OAuthClient) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("grants", OAuthGrant.Type), + } +} + +func (OAuthClient) Mixin() []ent.Mixin { + return []ent.Mixin{ + CommonMixin{}, + } +} diff --git a/ent/schema/oauthgrant.go b/ent/schema/oauthgrant.go new file mode 100644 index 00000000..29a40d44 --- /dev/null +++ b/ent/schema/oauthgrant.go @@ -0,0 +1,60 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// OAuthGrant holds the schema definition for the OAuthGrant entity. +type OAuthGrant struct { + ent.Schema +} + +// Fields of the OAuthGrant. +func (OAuthGrant) Fields() []ent.Field { + return []ent.Field{ + field.Int("user_id"), + field.Int("client_id"), + field.JSON("scopes", []string{}). + Default([]string{}), + field.Time("last_used_at"). + Optional(). + Nillable(). + SchemaType(map[string]string{ + dialect.MySQL: "datetime", + }), + } +} + +// Edges of the OAuthGrant. +func (OAuthGrant) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("user", User.Type). + Field("user_id"). + Ref("oauth_grants"). + Unique(). + Required(), + edge.From("client", OAuthClient.Type). + Field("client_id"). + Ref("grants"). + Unique(). + Required(), + } +} + +func (OAuthGrant) Mixin() []ent.Mixin { + return []ent.Mixin{ + CommonMixin{}, + } +} + +// Indexes of the OAuthGrant. +func (OAuthGrant) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("user_id", "client_id"). + Unique(), + } +} diff --git a/ent/schema/user.go b/ent/schema/user.go index 5d473638..28214350 100644 --- a/ent/schema/user.go +++ b/ent/schema/user.go @@ -53,6 +53,7 @@ func (User) Edges() []ent.Edge { edge.To("tasks", Task.Type), edge.To("fsevents", FsEvent.Type), edge.To("entities", Entity.Type), + edge.To("oauth_grants", OAuthGrant.Type), } } diff --git a/ent/tx.go b/ent/tx.go index f0e50149..9d71651a 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -30,6 +30,10 @@ type Tx struct { Metadata *MetadataClient // Node is the client for interacting with the Node builders. Node *NodeClient + // OAuthClient is the client for interacting with the OAuthClient builders. + OAuthClient *OAuthClientClient + // OAuthGrant is the client for interacting with the OAuthGrant builders. + OAuthGrant *OAuthGrantClient // Passkey is the client for interacting with the Passkey builders. Passkey *PasskeyClient // Setting is the client for interacting with the Setting builders. @@ -181,6 +185,8 @@ func (tx *Tx) init() { tx.Group = NewGroupClient(tx.config) tx.Metadata = NewMetadataClient(tx.config) tx.Node = NewNodeClient(tx.config) + tx.OAuthClient = NewOAuthClientClient(tx.config) + tx.OAuthGrant = NewOAuthGrantClient(tx.config) tx.Passkey = NewPasskeyClient(tx.config) tx.Setting = NewSettingClient(tx.config) tx.Share = NewShareClient(tx.config) diff --git a/ent/user.go b/ent/user.go index 2545a3ff..a7775e9f 100644 --- a/ent/user.go +++ b/ent/user.go @@ -68,9 +68,11 @@ type UserEdges struct { Fsevents []*FsEvent `json:"fsevents,omitempty"` // Entities holds the value of the entities edge. Entities []*Entity `json:"entities,omitempty"` + // OauthGrants holds the value of the oauth_grants edge. + OauthGrants []*OAuthGrant `json:"oauth_grants,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [8]bool + loadedTypes [9]bool } // GroupOrErr returns the Group value or an error if the edge @@ -149,6 +151,15 @@ func (e UserEdges) EntitiesOrErr() ([]*Entity, error) { return nil, &NotLoadedError{edge: "entities"} } +// OauthGrantsOrErr returns the OauthGrants value or an error if the edge +// was not loaded in eager-loading. +func (e UserEdges) OauthGrantsOrErr() ([]*OAuthGrant, error) { + if e.loadedTypes[8] { + return e.OauthGrants, nil + } + return nil, &NotLoadedError{edge: "oauth_grants"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*User) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -311,6 +322,11 @@ func (u *User) QueryEntities() *EntityQuery { return NewUserClient(u.config).QueryEntities(u) } +// QueryOauthGrants queries the "oauth_grants" edge of the User entity. +func (u *User) QueryOauthGrants() *OAuthGrantQuery { + return NewUserClient(u.config).QueryOauthGrants(u) +} + // Update returns a builder for updating this User. // Note that you need to call User.Unwrap() before calling this method if this User // was returned from a transaction, and the transaction was committed or rolled back. @@ -421,5 +437,11 @@ func (e *User) SetEntities(v []*Entity) { e.Edges.loadedTypes[7] = true } +// SetOauthGrants manually set the edge as loaded state. +func (e *User) SetOauthGrants(v []*OAuthGrant) { + e.Edges.OauthGrants = v + e.Edges.loadedTypes[8] = true +} + // Users is a parsable slice of User. type Users []*User diff --git a/ent/user/user.go b/ent/user/user.go index 8385e63e..99fad933 100644 --- a/ent/user/user.go +++ b/ent/user/user.go @@ -57,6 +57,8 @@ const ( EdgeFsevents = "fsevents" // EdgeEntities holds the string denoting the entities edge name in mutations. EdgeEntities = "entities" + // EdgeOauthGrants holds the string denoting the oauth_grants edge name in mutations. + EdgeOauthGrants = "oauth_grants" // Table holds the table name of the user in the database. Table = "users" // GroupTable is the table that holds the group relation/edge. @@ -115,6 +117,13 @@ const ( EntitiesInverseTable = "entities" // EntitiesColumn is the table column denoting the entities relation/edge. EntitiesColumn = "created_by" + // OauthGrantsTable is the table that holds the oauth_grants relation/edge. + OauthGrantsTable = "oauth_grants" + // OauthGrantsInverseTable is the table name for the OAuthGrant entity. + // It exists in this package in order to avoid circular dependency with the "oauthgrant" package. + OauthGrantsInverseTable = "oauth_grants" + // OauthGrantsColumn is the table column denoting the oauth_grants relation/edge. + OauthGrantsColumn = "user_id" ) // Columns holds all SQL columns for user fields. @@ -363,6 +372,20 @@ func ByEntities(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { sqlgraph.OrderByNeighborTerms(s, newEntitiesStep(), append([]sql.OrderTerm{term}, terms...)...) } } + +// ByOauthGrantsCount orders the results by oauth_grants count. +func ByOauthGrantsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newOauthGrantsStep(), opts...) + } +} + +// ByOauthGrants orders the results by oauth_grants terms. +func ByOauthGrants(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newOauthGrantsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} func newGroupStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -419,3 +442,10 @@ func newEntitiesStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, false, EntitiesTable, EntitiesColumn), ) } +func newOauthGrantsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OauthGrantsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, OauthGrantsTable, OauthGrantsColumn), + ) +} diff --git a/ent/user/where.go b/ent/user/where.go index 471f0958..1bb867ef 100644 --- a/ent/user/where.go +++ b/ent/user/where.go @@ -864,6 +864,29 @@ func HasEntitiesWith(preds ...predicate.Entity) predicate.User { }) } +// HasOauthGrants applies the HasEdge predicate on the "oauth_grants" edge. +func HasOauthGrants() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, OauthGrantsTable, OauthGrantsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasOauthGrantsWith applies the HasEdge predicate on the "oauth_grants" edge with a given conditions (other predicates). +func HasOauthGrantsWith(preds ...predicate.OAuthGrant) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := newOauthGrantsStep() + 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.User) predicate.User { return predicate.User(sql.AndPredicates(predicates...)) diff --git a/ent/user_create.go b/ent/user_create.go index 20301eb5..0ee53ef8 100644 --- a/ent/user_create.go +++ b/ent/user_create.go @@ -16,6 +16,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/share" "github.com/cloudreve/Cloudreve/v4/ent/task" @@ -283,6 +284,21 @@ func (uc *UserCreate) AddEntities(e ...*Entity) *UserCreate { return uc.AddEntityIDs(ids...) } +// AddOauthGrantIDs adds the "oauth_grants" edge to the OAuthGrant entity by IDs. +func (uc *UserCreate) AddOauthGrantIDs(ids ...int) *UserCreate { + uc.mutation.AddOauthGrantIDs(ids...) + return uc +} + +// AddOauthGrants adds the "oauth_grants" edges to the OAuthGrant entity. +func (uc *UserCreate) AddOauthGrants(o ...*OAuthGrant) *UserCreate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return uc.AddOauthGrantIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uc *UserCreate) Mutation() *UserMutation { return uc.mutation @@ -597,6 +613,22 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := uc.mutation.OauthGrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/ent/user_query.go b/ent/user_query.go index 2d44e1ed..a317c5d4 100644 --- a/ent/user_query.go +++ b/ent/user_query.go @@ -16,6 +16,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/share" @@ -38,6 +39,7 @@ type UserQuery struct { withTasks *TaskQuery withFsevents *FsEventQuery withEntities *EntityQuery + withOauthGrants *OAuthGrantQuery // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -250,6 +252,28 @@ func (uq *UserQuery) QueryEntities() *EntityQuery { return query } +// QueryOauthGrants chains the current query on the "oauth_grants" edge. +func (uq *UserQuery) QueryOauthGrants() *OAuthGrantQuery { + query := (&OAuthGrantClient{config: uq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := uq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := uq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, selector), + sqlgraph.To(oauthgrant.Table, oauthgrant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.OauthGrantsTable, user.OauthGrantsColumn), + ) + fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first User entity from the query. // Returns a *NotFoundError when no User was found. func (uq *UserQuery) First(ctx context.Context) (*User, error) { @@ -450,6 +474,7 @@ func (uq *UserQuery) Clone() *UserQuery { withTasks: uq.withTasks.Clone(), withFsevents: uq.withFsevents.Clone(), withEntities: uq.withEntities.Clone(), + withOauthGrants: uq.withOauthGrants.Clone(), // clone intermediate query. sql: uq.sql.Clone(), path: uq.path, @@ -544,6 +569,17 @@ func (uq *UserQuery) WithEntities(opts ...func(*EntityQuery)) *UserQuery { return uq } +// WithOauthGrants tells the query-builder to eager-load the nodes that are connected to +// the "oauth_grants" edge. The optional arguments are used to configure the query builder of the edge. +func (uq *UserQuery) WithOauthGrants(opts ...func(*OAuthGrantQuery)) *UserQuery { + query := (&OAuthGrantClient{config: uq.config}).Query() + for _, opt := range opts { + opt(query) + } + uq.withOauthGrants = query + return uq +} + // 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. // @@ -622,7 +658,7 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e var ( nodes = []*User{} _spec = uq.querySpec() - loadedTypes = [8]bool{ + loadedTypes = [9]bool{ uq.withGroup != nil, uq.withFiles != nil, uq.withDavAccounts != nil, @@ -631,6 +667,7 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e uq.withTasks != nil, uq.withFsevents != nil, uq.withEntities != nil, + uq.withOauthGrants != nil, } ) _spec.ScanValues = func(columns []string) ([]any, error) { @@ -706,6 +743,13 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e return nil, err } } + if query := uq.withOauthGrants; query != nil { + if err := uq.loadOauthGrants(ctx, query, nodes, + func(n *User) { n.Edges.OauthGrants = []*OAuthGrant{} }, + func(n *User, e *OAuthGrant) { n.Edges.OauthGrants = append(n.Edges.OauthGrants, e) }); err != nil { + return nil, err + } + } return nodes, nil } @@ -949,6 +993,36 @@ func (uq *UserQuery) loadEntities(ctx context.Context, query *EntityQuery, nodes } return nil } +func (uq *UserQuery) loadOauthGrants(ctx context.Context, query *OAuthGrantQuery, nodes []*User, init func(*User), assign func(*User, *OAuthGrant)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*User) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(oauthgrant.FieldUserID) + } + query.Where(predicate.OAuthGrant(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(user.OauthGrantsColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.UserID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "user_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) { _spec := uq.querySpec() diff --git a/ent/user_update.go b/ent/user_update.go index 843e4918..84c01b77 100644 --- a/ent/user_update.go +++ b/ent/user_update.go @@ -16,6 +16,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" "github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/share" @@ -328,6 +329,21 @@ func (uu *UserUpdate) AddEntities(e ...*Entity) *UserUpdate { return uu.AddEntityIDs(ids...) } +// AddOauthGrantIDs adds the "oauth_grants" edge to the OAuthGrant entity by IDs. +func (uu *UserUpdate) AddOauthGrantIDs(ids ...int) *UserUpdate { + uu.mutation.AddOauthGrantIDs(ids...) + return uu +} + +// AddOauthGrants adds the "oauth_grants" edges to the OAuthGrant entity. +func (uu *UserUpdate) AddOauthGrants(o ...*OAuthGrant) *UserUpdate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return uu.AddOauthGrantIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uu *UserUpdate) Mutation() *UserMutation { return uu.mutation @@ -486,6 +502,27 @@ func (uu *UserUpdate) RemoveEntities(e ...*Entity) *UserUpdate { return uu.RemoveEntityIDs(ids...) } +// ClearOauthGrants clears all "oauth_grants" edges to the OAuthGrant entity. +func (uu *UserUpdate) ClearOauthGrants() *UserUpdate { + uu.mutation.ClearOauthGrants() + return uu +} + +// RemoveOauthGrantIDs removes the "oauth_grants" edge to OAuthGrant entities by IDs. +func (uu *UserUpdate) RemoveOauthGrantIDs(ids ...int) *UserUpdate { + uu.mutation.RemoveOauthGrantIDs(ids...) + return uu +} + +// RemoveOauthGrants removes "oauth_grants" edges to OAuthGrant entities. +func (uu *UserUpdate) RemoveOauthGrants(o ...*OAuthGrant) *UserUpdate { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return uu.RemoveOauthGrantIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (uu *UserUpdate) Save(ctx context.Context) (int, error) { if err := uu.defaults(); err != nil { @@ -955,6 +992,51 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if uu.mutation.OauthGrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uu.mutation.RemovedOauthGrantsIDs(); len(nodes) > 0 && !uu.mutation.OauthGrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uu.mutation.OauthGrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{user.Label} @@ -1266,6 +1348,21 @@ func (uuo *UserUpdateOne) AddEntities(e ...*Entity) *UserUpdateOne { return uuo.AddEntityIDs(ids...) } +// AddOauthGrantIDs adds the "oauth_grants" edge to the OAuthGrant entity by IDs. +func (uuo *UserUpdateOne) AddOauthGrantIDs(ids ...int) *UserUpdateOne { + uuo.mutation.AddOauthGrantIDs(ids...) + return uuo +} + +// AddOauthGrants adds the "oauth_grants" edges to the OAuthGrant entity. +func (uuo *UserUpdateOne) AddOauthGrants(o ...*OAuthGrant) *UserUpdateOne { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return uuo.AddOauthGrantIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uuo *UserUpdateOne) Mutation() *UserMutation { return uuo.mutation @@ -1424,6 +1521,27 @@ func (uuo *UserUpdateOne) RemoveEntities(e ...*Entity) *UserUpdateOne { return uuo.RemoveEntityIDs(ids...) } +// ClearOauthGrants clears all "oauth_grants" edges to the OAuthGrant entity. +func (uuo *UserUpdateOne) ClearOauthGrants() *UserUpdateOne { + uuo.mutation.ClearOauthGrants() + return uuo +} + +// RemoveOauthGrantIDs removes the "oauth_grants" edge to OAuthGrant entities by IDs. +func (uuo *UserUpdateOne) RemoveOauthGrantIDs(ids ...int) *UserUpdateOne { + uuo.mutation.RemoveOauthGrantIDs(ids...) + return uuo +} + +// RemoveOauthGrants removes "oauth_grants" edges to OAuthGrant entities. +func (uuo *UserUpdateOne) RemoveOauthGrants(o ...*OAuthGrant) *UserUpdateOne { + ids := make([]int, len(o)) + for i := range o { + ids[i] = o[i].ID + } + return uuo.RemoveOauthGrantIDs(ids...) +} + // Where appends a list predicates to the UserUpdate builder. func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne { uuo.mutation.Where(ps...) @@ -1923,6 +2041,51 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if uuo.mutation.OauthGrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uuo.mutation.RemovedOauthGrantsIDs(); len(nodes) > 0 && !uuo.mutation.OauthGrantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uuo.mutation.OauthGrantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.OauthGrantsTable, + Columns: []string{user.OauthGrantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(oauthgrant.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &User{config: uuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/inventory/migration.go b/inventory/migration.go index 12fa1623..b779bf28 100644 --- a/inventory/migration.go +++ b/inventory/migration.go @@ -12,6 +12,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/node" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" "github.com/cloudreve/Cloudreve/v4/ent/setting" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/inventory/types" @@ -45,6 +46,10 @@ func migrate(l logging.Logger, client *ent.Client, ctx context.Context, kv cache return fmt.Errorf("failed migrating default storage policy: %w", err) } + if err := migrateOAuthClient(l, client, ctx); err != nil { + return fmt.Errorf("failed migrating OAuth client: %w", err) + } + if err := applyPatches(l, client, ctx, requiredDbVersion); err != nil { return fmt.Errorf("failed applying schema patches: %w", err) } @@ -269,6 +274,70 @@ func migrateMasterNode(l logging.Logger, client *ent.Client, ctx context.Context return nil } +const ( + OAuthClientDesktopGUID = "393a1839-f52e-498e-9972-e77cc2241eee" + OAuthClientDesktopSecret = "8GaQIu3lOSdqYoDHi9cR8IZ4pvuMH8ya" + OAuthClientDesktopName = "application:oauth.desktop" + OAuthClientDesktopRedirectURI = "/callback/desktop" + OAuthClientiOSGUID = "220db97a-44a3-44f7-99b6-d767262b4daa" + OAuthClientiOSSecret = "1kxOW4IyVOkPlsKCnTwzfHyP8XrbpfaF" + OAuthClientiOSName = "application:setting.iOSApp" + OAuthClientiOSRedirectURI = "/callback/ios" +) + +func migrateOAuthClient(l logging.Logger, client *ent.Client, ctx context.Context) error { + if err := migrateOAuthClientDesktop(l, client, ctx); err != nil { + return err + } + + if err := migrateOAuthClientiOS(l, client, ctx); err != nil { + return err + } + + return nil +} + +func migrateOAuthClientiOS(l logging.Logger, client *ent.Client, ctx context.Context) error { + if _, err := client.OAuthClient.Query().Where(oauthclient.GUID(OAuthClientiOSGUID)).First(ctx); err == nil { + l.Info("Default OAuth client (GUID=%s) already exists, skip migrating.", OAuthClientiOSGUID) + return nil + } + if _, err := client.OAuthClient.Create(). + SetGUID(OAuthClientiOSGUID). + SetSecret(OAuthClientiOSSecret). + SetName(OAuthClientiOSName). + SetRedirectUris([]string{OAuthClientiOSRedirectURI}). + SetScopes([]string{"profile", "email", "openid", "offline_access", "UserInfo.Write", "UserSecurityInfo.Write", "Workflow.Write", "Files.Write", "Shares.Write", "Finance.Write", "DavAccount.Write"}). + SetProps(&types.OAuthClientProps{Icon: "/static/img/cloudreve_ios.svg", RefreshTokenTTL: 7776000}). + SetIsEnabled(true). + Save(ctx); err != nil { + return fmt.Errorf("failed to create default OAuth client: %w", err) + } + + return nil +} + +func migrateOAuthClientDesktop(l logging.Logger, client *ent.Client, ctx context.Context) error { + if _, err := client.OAuthClient.Query().Where(oauthclient.GUID(OAuthClientDesktopGUID)).First(ctx); err == nil { + l.Info("Default OAuth client (GUID=%s) already exists, skip migrating.", OAuthClientDesktopGUID) + return nil + } + + if _, err := client.OAuthClient.Create(). + SetGUID(OAuthClientDesktopGUID). + SetSecret(OAuthClientDesktopSecret). + SetName(OAuthClientDesktopName). + SetRedirectUris([]string{OAuthClientDesktopRedirectURI}). + SetScopes([]string{"profile", "email", "openid", "offline_access", "UserInfo.Write", "Workflow.Write", "Files.Write", "Shares.Write"}). + SetProps(&types.OAuthClientProps{Icon: "/static/img/cloudreve.svg", RefreshTokenTTL: 7776000}). + SetIsEnabled(true). + Save(ctx); err != nil { + return fmt.Errorf("failed to create default OAuth client: %w", err) + } + + return nil +} + type ( PatchFunc func(l logging.Logger, client *ent.Client, ctx context.Context) error Patch struct { @@ -467,7 +536,7 @@ var patches = []Patch{ for i, t := range mailResetTemplate { mailResetTemplate[i].Title = fmt.Sprintf("[{{ .CommonContext.SiteBasic.Name }}] %s", t.Title) } - + newMailResetTemplate, err := json.Marshal(mailResetTemplate) if err != nil { return fmt.Errorf("failed to marshal mail_reset_template setting: %w", err) diff --git a/inventory/oauth_client.go b/inventory/oauth_client.go new file mode 100644 index 00000000..56065bdc --- /dev/null +++ b/inventory/oauth_client.go @@ -0,0 +1,82 @@ +package inventory + +import ( + "context" + "time" + + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" + "github.com/cloudreve/Cloudreve/v4/ent/oauthgrant" +) + +type ( + OAuthClientClient interface { + TxOperator + // GetByGUID returns the OAuth client by its GUID (client_id). + GetByGUID(ctx context.Context, guid string) (*ent.OAuthClient, error) + // GetByGUIDWithGrants returns the OAuth client by its GUID (client_id) with the grants for the user. + GetByGUIDWithGrants(ctx context.Context, guid string, uid int) (*ent.OAuthClient, error) + // UpsertGrant creates or updates an OAuth grant for a user and client. + UpsertGrant(ctx context.Context, userID, clientID int, scopes []string) error + // UpdateGrantLastUsedAt updates the last used at for an OAuth grant for a user and client. + UpdateGrantLastUsedAt(ctx context.Context, userID, clientID int) error + } +) + +func NewOAuthClientClient(client *ent.Client) OAuthClientClient { + return &oauthClientClient{ + client: client, + } +} + +type oauthClientClient struct { + client *ent.Client +} + +func (c *oauthClientClient) SetClient(newClient *ent.Client) TxOperator { + return &oauthClientClient{client: newClient} +} + +func (c *oauthClientClient) GetClient() *ent.Client { + return c.client +} + +func (c *oauthClientClient) GetByGUID(ctx context.Context, guid string) (*ent.OAuthClient, error) { + return c.client.OAuthClient.Query(). + Where(oauthclient.GUID(guid), oauthclient.IsEnabled(true)). + First(ctx) +} + +func (c *oauthClientClient) GetByGUIDWithGrants(ctx context.Context, guid string, uid int) (*ent.OAuthClient, error) { + stm := c.client.OAuthClient.Query(). + Where(oauthclient.GUID(guid), oauthclient.IsEnabled(true)) + if uid > 0 { + stm.WithGrants(func(ogq *ent.OAuthGrantQuery) { + ogq.Where(oauthgrant.UserID(uid)) + }) + } + + return stm.First(ctx) +} + +func (c *oauthClientClient) UpsertGrant(ctx context.Context, userID, clientID int, scopes []string) error { + return c.client.OAuthGrant.Create(). + SetUserID(userID). + SetClientID(clientID). + SetScopes(scopes). + SetLastUsedAt(time.Now()). + OnConflict( + sql.ConflictColumns(oauthgrant.FieldUserID, oauthgrant.FieldClientID), + ). + UpdateScopes(). + UpdateLastUsedAt(). + Exec(ctx) +} + +func (c *oauthClientClient) UpdateGrantLastUsedAt(ctx context.Context, userID, clientID int) error { + return c.client.OAuthGrant.Update(). + Where(oauthgrant.UserID(userID), oauthgrant.ClientID(clientID)). + SetLastUsedAt(time.Now()). + Exec(ctx) +} diff --git a/inventory/types/types.go b/inventory/types/types.go index 3c7a6ff5..839389ee 100644 --- a/inventory/types/types.go +++ b/inventory/types/types.go @@ -207,6 +207,12 @@ type ( ShowReadMe bool `json:"show_read_me,omitempty"` } + OAuthClientProps struct { + Description string `json:"description,omitempty"` + Icon string `json:"icon,omitempty"` + RefreshTokenTTL int64 `json:"refresh_token_ttl,omitempty"` // in seconds, 0 means default + } + FileTypeIconSetting struct { Exts []string `json:"exts"` Icon string `json:"icon,omitempty"` @@ -363,3 +369,26 @@ const ( const ( CipherAES256CTR Cipher = "aes-256-ctr" ) + +const ( + ScopeProfile = "profile" + ScopeEmail = "email" + ScopeOpenID = "openid" + ScopeOfflineAccess = "offline_access" + ScopeUserInfoRead = "UserInfo.Read" + ScopeUserInfoWrite = "UserInfo.Write" + ScopeUserSecurityInfoRead = "UserSecurityInfo.Read" + ScopeUserSecurityInfoWrite = "UserSecurityInfo.Write" + ScopeWorkflowRead = "Workflow.Read" + ScopeWorkflowWrite = "Workflow.Write" + ScopeAdminRead = "Admin.Read" + ScopeAdminWrite = "Admin.Write" + ScopeFilesRead = "Files.Read" + ScopeFilesWrite = "Files.Write" + ScopeSharesRead = "Shares.Read" + ScopeSharesWrite = "Shares.Write" + ScopeFinanceRead = "Finance.Read" + ScopeFinanceWrite = "Finance.Write" + ScopeDavAccountRead = "DavAccount.Read" + ScopeDavAccountWrite = "DavAccount.Write" +) diff --git a/middleware/auth.go b/middleware/auth.go index 4df7ed7f..8b51cc78 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -271,3 +271,19 @@ func IsAdmin() gin.HandlerFunc { c.Next() } } + +// RequiredScopes checks if the JWT token has the required scopes. +// If the token has scopes (hasScopes is true), it verifies the token has all required scopes. +// Write scopes implicitly include Read scopes for the same resource (e.g., "File.Write" includes "File.Read"). +// If hasScopes is false (e.g., session-based auth), the check is skipped. +func RequiredScopes(requiredScopes ...string) gin.HandlerFunc { + return func(c *gin.Context) { + if err := auth.CheckScope(c, requiredScopes...); err != nil { + c.JSON(200, serializer.Err(c, err)) + c.Abort() + return + } + + c.Next() + } +} diff --git a/pkg/auth/jwt.go b/pkg/auth/jwt.go index d5ebef1a..6017afc3 100644 --- a/pkg/auth/jwt.go +++ b/pkg/auth/jwt.go @@ -24,7 +24,7 @@ import ( type TokenAuth interface { // Issue issues a new pair of credentials for the given user. - Issue(ctx context.Context, u *ent.User, rootTokenID *uuid.UUID) (*Token, error) + Issue(ctx context.Context, args *IssueTokenArgs) (*Token, error) // VerifyAndRetrieveUser verifies the given token and inject the user into current context. // Returns if upper caller should continue process other session provider. VerifyAndRetrieveUser(c *gin.Context) (bool, error) @@ -34,6 +34,14 @@ type TokenAuth interface { Claims(ctx context.Context, tokenStr string) (*Claims, error) } +type IssueTokenArgs struct { + User *ent.User + RootTokenID *uuid.UUID + ClientID string + Scopes []string + RefreshTTLOverride time.Duration +} + // Token stores token pair for authentication type Token struct { AccessToken string `json:"access_token"` @@ -47,6 +55,7 @@ type Token struct { type ( TokenType string TokenIDContextKey struct{} + ScopeContextKey struct{} ) var ( @@ -68,28 +77,32 @@ type Claims struct { jwt.RegisteredClaims StateHash []byte `json:"state_hash,omitempty"` RootTokenID *uuid.UUID `json:"root_token_id,omitempty"` + Scopes []string `json:"scopes,omitempty"` + ClientID string `json:"client_id,omitempty"` } // NewTokenAuth creates a new token based auth provider. func NewTokenAuth(idEncoder hashid.Encoder, s setting.Provider, secret []byte, userClient inventory.UserClient, - l logging.Logger, kv cache.Driver) TokenAuth { + l logging.Logger, kv cache.Driver, oAuthClient inventory.OAuthClientClient) TokenAuth { return &tokenAuth{ - idEncoder: idEncoder, - s: s, - secret: secret, - userClient: userClient, - l: l, - kv: kv, + idEncoder: idEncoder, + s: s, + secret: secret, + userClient: userClient, + l: l, + kv: kv, + oAuthClient: oAuthClient, } } type tokenAuth struct { - l logging.Logger - idEncoder hashid.Encoder - s setting.Provider - secret []byte - userClient inventory.UserClient - kv cache.Driver + l logging.Logger + idEncoder hashid.Encoder + s setting.Provider + secret []byte + userClient inventory.UserClient + oAuthClient inventory.OAuthClientClient + kv cache.Driver } func (t *tokenAuth) Claims(ctx context.Context, tokenStr string) (*Claims, error) { @@ -149,7 +162,36 @@ func (t *tokenAuth) Refresh(ctx context.Context, refreshToken string) (*Token, e return nil, ErrInvalidRefreshToken } - return t.Issue(ctx, expectedUser, claims.RootTokenID) + // If token issued for an OAuth client, check if the client is still valid + refreshTTLOverride := time.Duration(0) + if claims.ClientID != "" { + client, err := t.oAuthClient.GetByGUIDWithGrants(ctx, claims.ClientID, expectedUser.ID) + if err != nil || len(client.Edges.Grants) == 0 { + return nil, ErrInvalidRefreshToken + } + + // Consented scopes must be a subset of the client's scopes + if !ValidateScopes(claims.Scopes, client.Edges.Grants[0].Scopes) { + return nil, ErrInvalidRefreshToken + } + + // Update last used at for the grant + if err := t.oAuthClient.UpdateGrantLastUsedAt(ctx, expectedUser.ID, client.ID); err != nil { + return nil, ErrInvalidRefreshToken + } + + if client.Props != nil { + refreshTTLOverride = time.Duration(client.Props.RefreshTokenTTL) * time.Second + } + } + + return t.Issue(ctx, &IssueTokenArgs{ + User: expectedUser, + RootTokenID: claims.RootTokenID, + Scopes: claims.Scopes, + ClientID: claims.ClientID, + RefreshTTLOverride: refreshTTLOverride, + }) } func (t *tokenAuth) VerifyAndRetrieveUser(c *gin.Context) (bool, error) { @@ -184,15 +226,25 @@ func (t *tokenAuth) VerifyAndRetrieveUser(c *gin.Context) (bool, error) { } util.WithValue(c, inventory.UserIDCtx{}, uid) + + if claims.ClientID != "" { + util.WithValue(c, ScopeContextKey{}, claims.Scopes) + } return false, nil } -func (t *tokenAuth) Issue(ctx context.Context, u *ent.User, rootTokenID *uuid.UUID) (*Token, error) { +func (t *tokenAuth) Issue(ctx context.Context, args *IssueTokenArgs) (*Token, error) { + u := args.User + rootTokenID := args.RootTokenID + uidEncoded := hashid.EncodeUserID(t.idEncoder, u.ID) tokenSettings := t.s.TokenAuth(ctx) issueDate := time.Now() accessTokenExpired := time.Now().Add(tokenSettings.AccessTokenTTL) refreshTokenExpired := time.Now().Add(tokenSettings.RefreshTokenTTL) + if args.RefreshTTLOverride > 0 { + refreshTokenExpired = time.Now().Add(args.RefreshTTLOverride) + } if rootTokenID == nil { newRootTokenID := uuid.Must(uuid.NewV4()) rootTokenID = &newRootTokenID @@ -205,6 +257,7 @@ func (t *tokenAuth) Issue(ctx context.Context, u *ent.User, rootTokenID *uuid.UU NotBefore: jwt.NewNumericDate(issueDate), ExpiresAt: jwt.NewNumericDate(accessTokenExpired), }, + Scopes: args.Scopes, }).SignedString(t.secret) if err != nil { return nil, fmt.Errorf("faield to sign access token: %w", err) @@ -219,6 +272,8 @@ func (t *tokenAuth) Issue(ctx context.Context, u *ent.User, rootTokenID *uuid.UU NotBefore: jwt.NewNumericDate(issueDate), ExpiresAt: jwt.NewNumericDate(refreshTokenExpired), }, + Scopes: args.Scopes, + ClientID: args.ClientID, StateHash: userHash[:], }).SignedString(t.secret) if err != nil { @@ -239,3 +294,63 @@ func (t *tokenAuth) Issue(ctx context.Context, u *ent.User, rootTokenID *uuid.UU func (t *tokenAuth) hashUserState(ctx context.Context, u *ent.User) [32]byte { return sha256.Sum256([]byte(fmt.Sprintf("%s/%s/%s", u.Email, u.Password, t.s.SiteBasic(ctx).ID))) } + +// ValidateScopes checks if all requested scopes are a subset of the allowed scopes. +// Returns true if all requested scopes are valid, false otherwise. +func ValidateScopes(requestedScopes, allowedScopes []string) bool { + allowed := make(map[string]struct{}, len(allowedScopes)) + for _, scope := range allowedScopes { + allowed[scope] = struct{}{} + } + for _, scope := range requestedScopes { + if _, ok := allowed[scope]; !ok { + return false + } + } + return true +} + +func GetScopesFromContext(ctx context.Context) (bool, []string) { + scopes, ok := ctx.Value(ScopeContextKey{}).([]string) + if !ok { + return false, nil + } + return true, scopes +} + +func CheckScope(c *gin.Context, requiredScopes ...string) error { + hasScopes, tokenScopes := GetScopesFromContext(c) + if !hasScopes { + return nil + } + + // Build a set of token scopes including implicit read permissions from write scopes + scopeSet := make(map[string]struct{}, len(tokenScopes)*2) + for _, scope := range tokenScopes { + scopeSet[scope] = struct{}{} + // If scope is "xxx.Write", also grant "xxx.Read" + if resource, ok := extractWriteResource(scope); ok { + scopeSet[resource+".Read"] = struct{}{} + } + } + + // Check if all required scopes are present + for _, required := range requiredScopes { + if _, ok := scopeSet[required]; !ok { + return serializer.NewError(serializer.CodeInsufficientScope, + "Insufficient scope: "+required, nil) + } + } + + return nil +} + +// extractWriteResource extracts the resource name from a write scope. +// For example, "File.Write" returns ("File", true), "File.Read" returns ("", false). +func extractWriteResource(scope string) (string, bool) { + const writeSuffix = ".Write" + if len(scope) > len(writeSuffix) && scope[len(scope)-len(writeSuffix):] == writeSuffix { + return scope[:len(scope)-len(writeSuffix)], true + } + return "", false +} diff --git a/pkg/cluster/routes/routes.go b/pkg/cluster/routes/routes.go index 3e315978..bd51d215 100644 --- a/pkg/cluster/routes/routes.go +++ b/pkg/cluster/routes/routes.go @@ -61,6 +61,11 @@ func MasterUserResetUrl(base *url.URL) *url.URL { return base.ResolveReference(masterUserReset) } +func MasterUserAvatarUrl(base *url.URL, uid string) *url.URL { + route, _ := url.Parse(constants.APIPrefix + "/user/avatar/" + uid) + return base.ResolveReference(route) +} + func MasterShareUrl(base *url.URL, id, password string) *url.URL { p := "/s/" + id if password != "" { diff --git a/pkg/serializer/error.go b/pkg/serializer/error.go index 74c8d9c9..28666d33 100644 --- a/pkg/serializer/error.go +++ b/pkg/serializer/error.go @@ -255,6 +255,8 @@ const ( CodeDomainNotLicensed = 40087 // CodeAnonymouseAccessDenied 匿名用户无法访问分享 CodeAnonymouseAccessDenied = 40088 + // CodeInsufficientScope OAuth token scope insufficient + CodeInsufficientScope = 40089 // CodeDBError 数据库操作失败 CodeDBError = 50001 // CodeEncryptError 加密失败 diff --git a/routers/controllers/main.go b/routers/controllers/main.go index aa0335a7..48ac68f2 100644 --- a/routers/controllers/main.go +++ b/routers/controllers/main.go @@ -3,6 +3,7 @@ package controllers import ( "context" "encoding/json" + "github.com/cloudreve/Cloudreve/v4/pkg/serializer" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" @@ -85,6 +86,19 @@ func FromQuery[T any](ctxKey any) gin.HandlerFunc { } } +func FromForm[T any](ctxKey any) gin.HandlerFunc { + return func(c *gin.Context) { + var service T + if err := c.ShouldBind(&service); err == nil { + c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), ctxKey, &service)) + c.Next() + } else { + c.JSON(200, ErrorResponse(err)) + c.Abort() + } + } +} + // FromUri Parse and validate form from request uri func FromUri[T any](ctxKey any) gin.HandlerFunc { return func(c *gin.Context) { diff --git a/routers/controllers/oauth.go b/routers/controllers/oauth.go new file mode 100644 index 00000000..97b1ea4b --- /dev/null +++ b/routers/controllers/oauth.go @@ -0,0 +1,68 @@ +package controllers + +import ( + "github.com/cloudreve/Cloudreve/v4/pkg/serializer" + "github.com/cloudreve/Cloudreve/v4/service/oauth" + "github.com/gin-gonic/gin" +) + +func GetAppRegistration(c *gin.Context) { + service := ParametersFromContext[*oauth.GetAppRegistrationService](c, oauth.GetAppRegistrationParamCtx{}) + app, err := service.Get(c) + if err != nil { + c.JSON(200, serializer.Err(c, err)) + c.Abort() + return + } + + c.JSON(200, serializer.Response{Data: app}) +} + +func GrantAppConsent(c *gin.Context) { + service := ParametersFromContext[*oauth.GrantService](c, oauth.GrantParamCtx{}) + res, err := service.Get(c) + if err != nil { + c.JSON(200, serializer.Err(c, err)) + c.Abort() + return + } + + c.JSON(200, serializer.Response{Data: res}) +} + +type ExchangeErrorResponse struct { + Error string `json:"error"` + ErrorDescription string `json:"error_description"` + ErrorCodes []int `json:"error_codes"` + CorrelationID string `json:"correlation_id"` +} + +func ExchangeToken(c *gin.Context) { + service := ParametersFromContext[*oauth.ExchangeTokenService](c, oauth.ExchangeTokenParamCtx{}) + res, err := service.Exchange(c) + if err != nil { + errResp := serializer.Err(c, err) + c.JSON(400, ExchangeErrorResponse{ + Error: errResp.Msg, + ErrorDescription: errResp.Error, + ErrorCodes: []int{errResp.Code}, + CorrelationID: errResp.CorrelationID, + }) + c.Abort() + return + } + + c.JSON(200, res) +} + +func OpenIDUserInfo(c *gin.Context) { + service := ParametersFromContext[*oauth.UserInfoService](c, oauth.UserInfoParamCtx{}) + res, err := service.GetUserInfo(c) + if err != nil { + c.JSON(200, serializer.Err(c, err)) + c.Abort() + return + } + + c.JSON(200, res) +} diff --git a/routers/router.go b/routers/router.go index e8256cf4..cb138520 100644 --- a/routers/router.go +++ b/routers/router.go @@ -19,6 +19,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/service/basic" "github.com/cloudreve/Cloudreve/v4/service/explorer" "github.com/cloudreve/Cloudreve/v4/service/node" + "github.com/cloudreve/Cloudreve/v4/service/oauth" "github.com/cloudreve/Cloudreve/v4/service/setting" sharesvc "github.com/cloudreve/Cloudreve/v4/service/share" usersvc "github.com/cloudreve/Cloudreve/v4/service/user" @@ -299,6 +300,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.UserIssueToken, ) token.POST("refresh", + middleware.RequiredScopes(types.ScopeOfflineAccess), controllers.FromJSON[usersvc.RefreshTokenService](usersvc.RefreshTokenParameterCtx{}), controllers.UserRefreshToken, ) @@ -314,6 +316,27 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.UserPrepareLogin, ) + oauthRouter := session.Group("oauth") + { + oauthRouter.GET("app/:app_id", + controllers.FromUri[oauth.GetAppRegistrationService](oauth.GetAppRegistrationParamCtx{}), + controllers.GetAppRegistration, + ) + oauthRouter.POST("consent", + middleware.Logging(), + controllers.FromJSON[oauth.GrantService](oauth.GrantParamCtx{}), + controllers.GrantAppConsent, + ) + oauthRouter.POST("token", + controllers.FromForm[oauth.ExchangeTokenService](oauth.ExchangeTokenParamCtx{}), + controllers.ExchangeToken, + ) + oauthRouter.GET("userinfo", + controllers.FromQuery[oauth.UserInfoService](oauth.UserInfoParamCtx{}), + controllers.OpenIDUserInfo, + ) + } + authn := session.Group("authn") { // WebAuthn login prepare @@ -516,6 +539,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // Workflows wf := v4.Group("workflow") wf.Use(middleware.LoginRequired()) + wf.Use(middleware.RequiredScopes(types.ScopeWorkflowRead)) { // List wf.GET("", @@ -529,11 +553,13 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Create task to create an archive file wf.POST("archive", + middleware.RequiredScopes(types.ScopeWorkflowWrite), controllers.FromJSON[explorer.ArchiveWorkflowService](explorer.CreateArchiveParamCtx{}), controllers.CreateArchive, ) // Create task to extract an archive file wf.POST("extract", + middleware.RequiredScopes(types.ScopeWorkflowWrite), controllers.FromJSON[explorer.ArchiveWorkflowService](explorer.CreateArchiveParamCtx{}), controllers.ExtractArchive, ) @@ -542,16 +568,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { { // Create task to download a file remoteDownload.POST("", + middleware.RequiredScopes(types.ScopeWorkflowWrite), controllers.FromJSON[explorer.DownloadWorkflowService](explorer.CreateDownloadParamCtx{}), controllers.CreateRemoteDownload, ) // Set download target remoteDownload.PATCH(":id", + middleware.RequiredScopes(types.ScopeWorkflowWrite), middleware.HashID(hashid.TaskID), controllers.FromJSON[explorer.SetDownloadFilesService](explorer.SetDownloadFilesParamCtx{}), controllers.SetDownloadTaskTarget, ) remoteDownload.DELETE(":id", + middleware.RequiredScopes(types.ScopeWorkflowWrite), middleware.HashID(hashid.TaskID), controllers.CancelDownloadTask, ) @@ -560,6 +589,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // 文件 file := v4.Group("file") + file.Use(middleware.RequiredScopes(types.ScopeFilesRead)) { // List files file.GET("", @@ -572,16 +602,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Create file file.POST("create", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.CreateFileService](explorer.CreateFileParameterCtx{}), controllers.CreateFile, ) // Rename file file.POST("rename", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.RenameFileService](explorer.RenameFileParameterCtx{}), controllers.RenameFile, ) // Move or copy files file.POST("move", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.MoveFileService](explorer.MoveFileParameterCtx{}), middleware.ValidateBatchFileCount(dep, explorer.MoveFileParameterCtx{}), controllers.MoveFile) @@ -594,6 +627,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Update file content file.PUT("content", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromQuery[explorer.FileUpdateService](explorer.FileUpdateParameterCtx{}), controllers.PutContent) // Get entity content for preview/download @@ -626,29 +660,33 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Delete files file.DELETE("", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.DeleteFileService](explorer.DeleteFileParameterCtx{}), middleware.ValidateBatchFileCount(dep, explorer.DeleteFileParameterCtx{}), controllers.Delete, ) // Force unlock file.DELETE("lock", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.UnlockFileService](explorer.UnlockFileParameterCtx{}), controllers.Unlock, ) // Restore files file.POST("restore", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.DeleteFileService](explorer.DeleteFileParameterCtx{}), middleware.ValidateBatchFileCount(dep, explorer.DeleteFileParameterCtx{}), controllers.Restore, ) // Patch metadata file.PATCH("metadata", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.PatchMetadataService](explorer.PatchMetadataParameterCtx{}), middleware.ValidateBatchFileCount(dep, explorer.PatchMetadataParameterCtx{}), controllers.PatchMetadata, ) // Upload related - upload := file.Group("upload") + upload := file.Group("upload", middleware.RequiredScopes(types.ScopeFilesWrite)) { // Create upload session upload.PUT("", @@ -666,7 +704,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) } // Pin file - pin := file.Group("pin") + pin := file.Group("pin", middleware.RequiredScopes(types.ScopeFilesWrite)) { // Pin file pin.PUT("", @@ -685,7 +723,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.GetFileInfo, ) // Version management - version := file.Group("version") + version := file.Group("version", middleware.RequiredScopes(types.ScopeFilesWrite)) { // Set current version version.POST("current", @@ -699,12 +737,14 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) } file.PUT("viewerSession", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.CreateViewerSessionService](explorer.CreateViewerSessionParamCtx{}), controllers.CreateViewerSession, ) // Create task to import files wf.POST("import", middleware.IsAdmin(), + middleware.RequiredScopes(types.ScopeWorkflowWrite, types.ScopeAdminWrite), controllers.FromJSON[explorer.ImportWorkflowService](explorer.CreateImportParamCtx{}), controllers.ImportFiles, ) @@ -724,6 +764,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { } // Patch view file.PATCH("view", + middleware.RequiredScopes(types.ScopeFilesWrite), controllers.FromJSON[explorer.PatchViewService](explorer.PatchViewParameterCtx{}), controllers.PatchView, ) @@ -738,16 +779,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // 分享相关 share := v4.Group("share") + share.Use(middleware.RequiredScopes(types.ScopeSharesRead)) { // Create share link share.PUT("", middleware.LoginRequired(), + middleware.RequiredScopes(types.ScopeSharesWrite), controllers.FromJSON[sharesvc.ShareCreateService](sharesvc.ShareCreateParamCtx{}), controllers.CreateShare, ) // Edit existing share link share.POST(":id", middleware.LoginRequired(), + middleware.RequiredScopes(types.ScopeSharesWrite), middleware.HashID(hashid.ShareID), controllers.FromJSON[sharesvc.ShareCreateService](sharesvc.ShareCreateParamCtx{}), controllers.EditShare, @@ -767,6 +811,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // 删除分享 share.DELETE(":id", middleware.LoginRequired(), + middleware.RequiredScopes(types.ScopeSharesWrite), middleware.HashID(hashid.ShareID), controllers.DeleteShare, ) @@ -785,6 +830,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // 需要登录保护的 auth := v4.Group("") auth.Use(middleware.LoginRequired()) + auth.Use(middleware.RequiredScopes(types.ScopeAdminRead)) { // 管理 admin := auth.Group("admin", middleware.IsAdmin()) @@ -803,6 +849,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Patch settings settings.PATCH("", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.SetSettingService](adminsvc.SetSettingParamCtx{}), controllers.AdminSetSettings, ) @@ -823,16 +870,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // 创建用户组 group.PUT("", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertGroupService](adminsvc.UpsertGroupParamCtx{}), controllers.AdminCreateGroup, ) // 更新用户组 group.PUT(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertGroupService](adminsvc.UpsertGroupParamCtx{}), controllers.AdminUpdateGroup, ) // 删除用户组 group.DELETE(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromUri[adminsvc.SingleGroupService](adminsvc.SingleGroupParamCtx{}), controllers.AdminDeleteGroup, ) @@ -852,6 +902,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.AdminSendTestMail, ) tool.DELETE("entityUrlCache", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.AdminClearEntityUrlCache, ) } @@ -871,11 +922,13 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Batch delete task queue.POST("batch/delete", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.BatchTaskService](adminsvc.BatchTaskParamCtx{}), controllers.AdminBatchDeleteTask, ) // Cleanup tasks queue.POST("cleanup", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.CleanupTaskService](adminsvc.CleanupTaskParameterCtx{}), controllers.AdminCleanupTask, ) @@ -900,16 +953,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // 创建存储策略 policy.PUT("", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.CreateStoragePolicyService](adminsvc.CreateStoragePolicyParamCtx{}), controllers.AdminCreatePolicy, ) // 更新存储策略 policy.PUT(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpdateStoragePolicyService](adminsvc.UpdateStoragePolicyParamCtx{}), controllers.AdminUpdatePolicy, ) // 创建跨域策略 policy.POST("cors", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.CreateStoragePolicyCorsService](adminsvc.CreateStoragePolicyCorsParamCtx{}), controllers.AdminCreateStoragePolicyCors, ) @@ -928,6 +984,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.AdminGetPolicyOAuthStatus, ) oauth.POST("callback", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.FinishOauthCallbackService](adminsvc.FinishOauthCallbackParamCtx{}), controllers.AdminFinishOauthCallback, ) @@ -941,6 +998,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // policy.GET(":id", controllers.AdminGetPolicy) // 删除 存储策略 policy.DELETE(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromUri[adminsvc.SingleStoragePolicyService](adminsvc.GetStoragePolicyParamCtx{}), controllers.AdminDeletePolicy, ) @@ -965,14 +1023,17 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { controllers.AdminTestDownloader, ) node.PUT("", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertNodeService](adminsvc.UpsertNodeParamCtx{}), controllers.AdminCreateNode, ) node.PUT(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertNodeService](adminsvc.UpsertNodeParamCtx{}), controllers.AdminUpdateNode, ) node.DELETE(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromUri[adminsvc.SingleNodeService](adminsvc.SingleNodeParamCtx{}), controllers.AdminDeleteNode, ) @@ -992,11 +1053,13 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // 更新用户 user.PUT(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertUserService](adminsvc.UpsertUserParamCtx{}), controllers.AdminUpdateUser, ) // 创建用户 user.PUT("", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertUserService](adminsvc.UpsertUserParamCtx{}), controllers.AdminCreateUser, ) @@ -1004,11 +1067,13 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { { // 批量删除用户 batch.POST("delete", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.BatchUserService](adminsvc.BatchUserParamCtx{}), controllers.AdminDeleteUser, ) } user.POST(":id/calibrate", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromUri[adminsvc.SingleUserService](adminsvc.SingleUserParamCtx{}), controllers.AdminCalibrateStorage, ) @@ -1028,6 +1093,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // 更新文件 file.PUT(":id", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.UpsertFileService](adminsvc.UpsertFileParamCtx{}), controllers.AdminUpdateFile, ) @@ -1038,6 +1104,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // 批量删除文件 file.POST("batch/delete", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.BatchFileService](adminsvc.BatchFileParamCtx{}), controllers.AdminBatchDeleteFile, ) @@ -1057,6 +1124,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Batch delete entity entity.POST("batch/delete", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.BatchEntityService](adminsvc.BatchEntityParamCtx{}), controllers.AdminBatchDeleteEntity, ) @@ -1081,6 +1149,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Batch delete shares share.POST("batch/delete", + middleware.RequiredScopes(types.ScopeAdminWrite), controllers.FromJSON[adminsvc.BatchShareService](adminsvc.BatchShareParamCtx{}), controllers.AdminBatchDeleteShare, ) @@ -1091,17 +1160,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { user := auth.Group("user") { // 当前登录用户信息 - user.GET("me", controllers.UserMe) + user.GET("me", middleware.RequiredScopes(types.ScopeUserInfoRead), controllers.UserMe) // 存储信息 - user.GET("capacity", controllers.UserStorage) + user.GET("capacity", middleware.RequiredScopes(types.ScopeUserInfoRead), controllers.UserStorage) // Search user by keywords user.GET("search", + middleware.RequiredScopes(types.ScopeUserInfoRead), controllers.FromQuery[usersvc.SearchUserService](usersvc.SearchUserParamCtx{}), controllers.UserSearch, ) // WebAuthn 注册相关 authn := user.Group("authn", + middleware.RequiredScopes(types.ScopeUserSecurityInfoWrite), middleware.IsFunctionEnabled(func(c *gin.Context) bool { return dep.SettingProvider().AuthnEnabled(c) })) @@ -1119,13 +1190,15 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // 用户设置 setting := user.Group("setting") + setting.Use(middleware.RequiredScopes(types.ScopeUserInfoRead)) { // 获取当前用户设定 setting.GET("", controllers.UserSetting) // 从文件上传头像 - setting.PUT("avatar", controllers.UploadAvatar) + setting.PUT("avatar", middleware.RequiredScopes(types.ScopeUserInfoWrite), controllers.UploadAvatar) // 更改用户设定 setting.PATCH("", + middleware.RequiredScopes(types.ScopeUserInfoWrite), controllers.FromJSON[usersvc.PatchUserSetting](usersvc.PatchUserSettingParamsCtx{}), controllers.UpdateOption, ) @@ -1136,6 +1209,7 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // WebDAV and devices devices := auth.Group("devices") + devices.Use(middleware.RequiredScopes(types.ScopeDavAccountRead)) { dav := devices.Group("dav") { @@ -1146,17 +1220,20 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) // Create WebDAV account dav.PUT("", + middleware.RequiredScopes(types.ScopeDavAccountWrite), controllers.FromJSON[setting.CreateDavAccountService](setting.CreateDavAccountParamCtx{}), controllers.CreateDAVAccounts, ) // Create WebDAV account dav.PATCH(":id", + middleware.RequiredScopes(types.ScopeDavAccountWrite), middleware.HashID(hashid.DavAccountID), controllers.FromJSON[setting.CreateDavAccountService](setting.CreateDavAccountParamCtx{}), controllers.UpdateDAVAccounts, ) // Delete WebDAV account dav.DELETE(":id", + middleware.RequiredScopes(types.ScopeDavAccountWrite), middleware.HashID(hashid.DavAccountID), controllers.DeleteDAVAccounts, ) diff --git a/service/oauth/oauth.go b/service/oauth/oauth.go new file mode 100644 index 00000000..adb01520 --- /dev/null +++ b/service/oauth/oauth.go @@ -0,0 +1,281 @@ +package oauth + +import ( + "crypto/sha256" + "encoding/base64" + "strings" + "time" + + "github.com/cloudreve/Cloudreve/v4/application/dependency" + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/inventory" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/auth" + "github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes" + "github.com/cloudreve/Cloudreve/v4/pkg/hashid" + "github.com/cloudreve/Cloudreve/v4/pkg/serializer" + "github.com/cloudreve/Cloudreve/v4/pkg/util" + "github.com/gin-gonic/gin" +) + +type ( + GetAppRegistrationParamCtx struct{} + GetAppRegistrationService struct { + AppID string `uri:"app_id" binding:"required"` + } +) + +func (s *GetAppRegistrationService) Get(c *gin.Context) (*AppRegistration, error) { + dep := dependency.FromContext(c) + oAuthClient := dep.OAuthClientClient() + + app, err := oAuthClient.GetByGUIDWithGrants(c, s.AppID, inventory.UserIDFromContext(c)) + if err != nil { + return nil, serializer.NewError(serializer.CodeNotFound, "App not found", err) + } + + var grant *ent.OAuthGrant + if len(app.Edges.Grants) == 1 { + grant = app.Edges.Grants[0] + } + + return BuildAppRegistration(app, grant), nil +} + +type ( + GrantParamCtx struct{} + GrantService struct { + ClientID string `json:"client_id" binding:"required"` + ResponseType string `json:"response_type" binding:"required,eq=code"` + RedirectURI string `json:"redirect_uri" binding:"required"` + State string `json:"state" binding:"max=255"` + Scope string `json:"scope" binding:"required"` + CodeChallenge string `json:"code_challenge" binding:"max=255"` + CodeChallengeMethod string `json:"code_challenge_method" binding:"eq=S256,omitempty"` + } +) + +func (s *GrantService) Get(c *gin.Context) (*GrantResponse, error) { + dep := dependency.FromContext(c) + user := inventory.UserFromContext(c) + kv := dep.KV() + oAuthClient := dep.OAuthClientClient() + + // 1. Get app registration and grant + app, err := oAuthClient.GetByGUIDWithGrants(c, s.ClientID, user.ID) + if err != nil { + return nil, serializer.NewError(serializer.CodeNotFound, "App not found", err) + } + + // 2. Validate redirect URL: must match one of the registered redirect URIs + redirectValid := false + for _, uri := range app.RedirectUris { + if uri == s.RedirectURI { + redirectValid = true + break + } + } + if !redirectValid { + return nil, serializer.NewError(serializer.CodeParamErr, "Invalid redirect URI", nil) + } + + // Parse requested scopes (space-separated per OAuth 2.0 spec) + requestedScopes := strings.Split(s.Scope, " ") + + // Validate requested scopes: must be a subset of registered app scopes + if !auth.ValidateScopes(requestedScopes, app.Scopes) { + return nil, serializer.NewError(serializer.CodeParamErr, "Invalid scope requested", nil) + } + + // 3. Create/update grant + if err := oAuthClient.UpsertGrant(c, user.ID, app.ID, requestedScopes); err != nil { + return nil, serializer.NewError(serializer.CodeDBError, "Failed to create grant", err) + } + + // 4. Generate code and save required state into KV for future token exchange request. + code := util.RandStringRunesCrypto(128) + authCode := &AuthorizationCode{ + ClientID: s.ClientID, + UserID: user.ID, + Scopes: requestedScopes, + RedirectURI: s.RedirectURI, + CodeChallenge: s.CodeChallenge, + } + + // Store auth code in KV with 10 minute TTL + if err := kv.Set(authCodeKey(code), authCode, 600); err != nil { + return nil, serializer.NewError(serializer.CodeCacheOperation, "Failed to store authorization code", err) + } + + return &GrantResponse{ + Code: code, + State: s.State, + }, nil +} + +type ( + ExchangeTokenParamCtx struct{} + ExchangeTokenService struct { + ClientID string `form:"client_id" binding:"required"` + ClientSecret string `form:"client_secret" binding:"required"` + GrantType string `form:"grant_type" binding:"required,eq=authorization_code"` + Code string `form:"code" binding:"required"` + CodeVerifier string `form:"code_verifier"` + } +) + +func (s *ExchangeTokenService) Exchange(c *gin.Context) (*TokenResponse, error) { + dep := dependency.FromContext(c) + kv := dep.KV() + oAuthClient := dep.OAuthClientClient() + userClient := dep.UserClient() + tokenAuth := dep.TokenAuth() + + // 1. Retrieve and validate authorization code from KV + codeKey := authCodeKey(s.Code) + authCodeRaw, ok := kv.Get(codeKey) + if !ok { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Invalid or expired authorization code", nil) + } + + authCode, ok := authCodeRaw.(*AuthorizationCode) + if !ok { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Invalid authorization code", nil) + } + + // Delete the code immediately to prevent replay attacks + _ = kv.Delete("", codeKey) + + // 2. Validate client_id matches the one in authorization code + if authCode.ClientID != s.ClientID { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Client ID mismatch", nil) + } + + // 3. Verify PKCE: SHA256(code_verifier) should match code_challenge + if authCode.CodeChallenge != "" { + verifierHash := sha256.Sum256([]byte(s.CodeVerifier)) + expectedChallenge := base64.RawURLEncoding.EncodeToString(verifierHash[:]) + if expectedChallenge != authCode.CodeChallenge { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Invalid code verifier", nil) + } + } + + // 4. Validate client secret + app, err := oAuthClient.GetByGUID(c, s.ClientID) + if err != nil { + return nil, serializer.NewError(serializer.CodeNotFound, "App not found", err) + } + + if app.Secret != s.ClientSecret { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Invalid client secret", nil) + } + + // 5. Validate scopes are still valid for this app + if !auth.ValidateScopes(authCode.Scopes, app.Scopes) { + return nil, serializer.NewError(serializer.CodeParamErr, "Invalid scope", nil) + } + + // 6. Get user + user, err := userClient.GetActiveByID(c, authCode.UserID) + if err != nil { + return nil, serializer.NewError(serializer.CodeUserNotFound, "User not found", err) + } + + // 7. Determine refresh token TTL override from app settings + var refreshTTLOverride time.Duration + if app.Props != nil && app.Props.RefreshTokenTTL > 0 { + refreshTTLOverride = time.Duration(app.Props.RefreshTokenTTL) * time.Second + } + + // 8. Issue tokens + token, err := tokenAuth.Issue(c, &auth.IssueTokenArgs{ + User: user, + ClientID: s.ClientID, + Scopes: authCode.Scopes, + RefreshTTLOverride: refreshTTLOverride, + }) + if err != nil { + return nil, serializer.NewError(serializer.CodeCredentialInvalid, "Failed to issue token", err) + } + + // 9. Update grant last used at + if err := oAuthClient.UpdateGrantLastUsedAt(c, user.ID, app.ID); err != nil { + dep.Logger().Warning("Failed to update grant last used at: %s", err) + } + + // 10. + + // 11. Build response, only include refresh token if offline_access scope is present + resp := &TokenResponse{ + AccessToken: token.AccessToken, + TokenType: "Bearer", + ExpiresIn: int64(time.Until(token.AccessExpires).Seconds()), + RefreshTokenExpiresIn: int64(time.Until(token.RefreshExpires).Seconds()), + Scope: strings.Join(authCode.Scopes, " "), + } + + for _, scope := range authCode.Scopes { + if scope == types.ScopeOfflineAccess { + resp.RefreshToken = token.RefreshToken + break + } + } + + return resp, nil +} + +type ( + UserInfoParamCtx struct{} + UserInfoService struct{} +) + +// GetUserInfo returns OpenID Connect userinfo based on the access token's scopes. +// The response fields are conditionally included based on granted scopes: +// - openid: sub (always required) +// - profile: name, preferred_username, picture, updated_at +// - email: email, email_verified +func (s *UserInfoService) GetUserInfo(c *gin.Context) (*UserInfoResponse, error) { + dep := dependency.FromContext(c) + u := inventory.UserFromContext(c) + hashIDEncoder := dep.HashIDEncoder() + + // 1. Get and parse the access token from Authorization header + hasScopes, scopes := auth.GetScopesFromContext(c) + if hasScopes { + // 2. Verify openid scope is present (required for userinfo endpoint) + hasOpenID := false + for _, scope := range scopes { + if scope == types.ScopeOpenID { + hasOpenID = true + break + } + } + if !hasOpenID { + return nil, serializer.NewError(serializer.CodeNoPermissionErr, "openid scope required", nil) + } + } else { + scopes = []string{types.ScopeOpenID, types.ScopeProfile, types.ScopeEmail} + } + + // 4. Build response based on scopes + resp := &UserInfoResponse{ + Sub: hashid.EncodeUserID(hashIDEncoder, u.ID), + } + + // Check scopes and populate fields accordingly + for _, scope := range scopes { + switch scope { + case types.ScopeProfile: + siteUrl := dep.SettingProvider().SiteURL(c) + resp.Name = u.Nick + resp.PreferredUsername = u.Nick + resp.Picture = routes.MasterUserAvatarUrl(siteUrl, hashid.EncodeUserID(hashIDEncoder, u.ID)).String() + resp.UpdatedAt = u.UpdatedAt.Unix() + case types.ScopeEmail: + resp.Email = u.Email + resp.EmailVerified = true // Users in Cloudreve have verified emails + } + } + + return resp, nil +} diff --git a/service/oauth/response.go b/service/oauth/response.go new file mode 100644 index 00000000..49a99df1 --- /dev/null +++ b/service/oauth/response.go @@ -0,0 +1,89 @@ +package oauth + +import ( + "encoding/gob" + + "github.com/cloudreve/Cloudreve/v4/ent" +) + +const ( + authCodeKeyPrefix = "oauth_code_" +) + +type AppRegistration struct { + ID string `json:"id"` + Name string `json:"name"` + HomepageURL string `json:"homepage_url,omitempty"` + Icon string `json:"icon,omitempty"` + Description string `json:"description,omitempty"` + ConstentedScopes []string `json:"consented_scopes,omitempty"` +} + +func BuildAppRegistration(app *ent.OAuthClient, grant *ent.OAuthGrant) *AppRegistration { + res := &AppRegistration{ + ID: app.GUID, + Name: app.Name, + HomepageURL: app.HomepageURL, + } + + if app.Props != nil { + res.Description = app.Props.Description + res.Icon = app.Props.Icon + } + + if grant != nil { + res.ConstentedScopes = grant.Scopes + } + + return res +} + +type GrantResponse struct { + Code string `json:"code"` + State string `json:"state"` +} + +// TokenResponse represents the OAuth token response. +type TokenResponse struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + ExpiresIn int64 `json:"expires_in"` + RefreshTokenExpiresIn int64 `json:"refresh_token_expires_in"` + RefreshToken string `json:"refresh_token,omitempty"` + Scope string `json:"scope"` +} + +// UserInfoResponse represents the OpenID Connect userinfo response. +// Fields are conditionally included based on granted scopes. +type UserInfoResponse struct { + // Always included (openid scope) + Sub string `json:"sub"` + + // Profile scope + Name string `json:"name,omitempty"` + PreferredUsername string `json:"preferred_username,omitempty"` + Picture string `json:"picture,omitempty"` + UpdatedAt int64 `json:"updated_at,omitempty"` + + // Email scope + Email string `json:"email,omitempty"` + EmailVerified bool `json:"email_verified,omitempty"` +} + +// AuthorizationCode represents the data stored in KV for an OAuth authorization code. +// Used for PKCE verification during token exchange. +type AuthorizationCode struct { + ClientID string `json:"client_id"` + UserID int `json:"user_id"` + Scopes []string `json:"scopes"` + RedirectURI string `json:"redirect_uri"` + CodeChallenge string `json:"code_challenge"` +} + +func authCodeKey(code string) string { + return authCodeKeyPrefix + code +} + +func init() { + gob.Register(&AuthorizationCode{}) +} diff --git a/service/user/login.go b/service/user/login.go index 52d0d229..f380a283 100644 --- a/service/user/login.go +++ b/service/user/login.go @@ -159,7 +159,10 @@ type ( func IssueToken(c *gin.Context) (*BuiltinLoginResponse, error) { dep := dependency.FromContext(c) u := inventory.UserFromContext(c) - token, err := dep.TokenAuth().Issue(c, u, nil) + token, err := dep.TokenAuth().Issue(c, &auth.IssueTokenArgs{ + User: u, + RootTokenID: nil, + }) if err != nil { return nil, serializer.NewError(serializer.CodeEncryptError, "Failed to issue token pair", err) } diff --git a/service/user/setting.go b/service/user/setting.go index 1c2181bc..70ab7db3 100644 --- a/service/user/setting.go +++ b/service/user/setting.go @@ -15,6 +15,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/inventory" "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/auth" "github.com/cloudreve/Cloudreve/v4/pkg/hashid" "github.com/cloudreve/Cloudreve/v4/pkg/request" "github.com/cloudreve/Cloudreve/v4/pkg/serializer" @@ -275,6 +276,10 @@ func (s *PatchUserSetting) Patch(c *gin.Context) error { } if s.CurrentPassword != nil && s.NewPassword != nil { + if err := auth.CheckScope(c, types.ScopeUserSecurityInfoWrite); err != nil { + return err + } + if err := inventory.CheckPassword(u, *s.CurrentPassword); err != nil { return serializer.NewError(serializer.CodeIncorrectPassword, "Incorrect password", err) } @@ -285,6 +290,10 @@ func (s *PatchUserSetting) Patch(c *gin.Context) error { } if s.TwoFAEnabled != nil { + if err := auth.CheckScope(c, types.ScopeUserSecurityInfoWrite); err != nil { + return err + } + if *s.TwoFAEnabled { kv := dep.KV() secret, ok := kv.Get(fmt.Sprintf("%s%d", twoFaEnableSessionKey, u.ID))