feat: port user-group mapping to M2M

basic DB definition and api migrate.
pull/2499/head
wintbit 3 months ago
parent 9d28fde00c
commit c2d28f95c5

@ -71,7 +71,7 @@ func (m *Migrator) migrateUser() error {
SetNick(u.Nick). SetNick(u.Nick).
SetStatus(userStatus). SetStatus(userStatus).
SetStorage(int64(u.Storage)). SetStorage(int64(u.Storage)).
SetGroupID(int(u.GroupID)). AddGroupIDs(int(u.GroupID)).
SetSettings(setting). SetSettings(setting).
SetPassword(u.Password) SetPassword(u.Password)

@ -28,6 +28,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
stdsql "database/sql" stdsql "database/sql"
) )
@ -63,6 +64,8 @@ type Client struct {
Task *TaskClient Task *TaskClient
// User is the client for interacting with the User builders. // User is the client for interacting with the User builders.
User *UserClient User *UserClient
// UserGroup is the client for interacting with the UserGroup builders.
UserGroup *UserGroupClient
} }
// NewClient creates a new client configured with the given options. // NewClient creates a new client configured with the given options.
@ -87,6 +90,7 @@ func (c *Client) init() {
c.StoragePolicy = NewStoragePolicyClient(c.config) c.StoragePolicy = NewStoragePolicyClient(c.config)
c.Task = NewTaskClient(c.config) c.Task = NewTaskClient(c.config)
c.User = NewUserClient(c.config) c.User = NewUserClient(c.config)
c.UserGroup = NewUserGroupClient(c.config)
} }
type ( type (
@ -192,6 +196,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
StoragePolicy: NewStoragePolicyClient(cfg), StoragePolicy: NewStoragePolicyClient(cfg),
Task: NewTaskClient(cfg), Task: NewTaskClient(cfg),
User: NewUserClient(cfg), User: NewUserClient(cfg),
UserGroup: NewUserGroupClient(cfg),
}, nil }, nil
} }
@ -224,6 +229,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
StoragePolicy: NewStoragePolicyClient(cfg), StoragePolicy: NewStoragePolicyClient(cfg),
Task: NewTaskClient(cfg), Task: NewTaskClient(cfg),
User: NewUserClient(cfg), User: NewUserClient(cfg),
UserGroup: NewUserGroupClient(cfg),
}, nil }, nil
} }
@ -254,7 +260,7 @@ func (c *Client) Close() error {
func (c *Client) Use(hooks ...Hook) { func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...Hook) }{ for _, n := range []interface{ Use(...Hook) }{
c.DavAccount, c.DirectLink, c.Entity, c.File, c.Group, c.Metadata, c.Node, c.DavAccount, c.DirectLink, c.Entity, c.File, c.Group, c.Metadata, c.Node,
c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.UserGroup,
} { } {
n.Use(hooks...) n.Use(hooks...)
} }
@ -265,7 +271,7 @@ func (c *Client) Use(hooks ...Hook) {
func (c *Client) Intercept(interceptors ...Interceptor) { func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...Interceptor) }{ for _, n := range []interface{ Intercept(...Interceptor) }{
c.DavAccount, c.DirectLink, c.Entity, c.File, c.Group, c.Metadata, c.Node, c.DavAccount, c.DirectLink, c.Entity, c.File, c.Group, c.Metadata, c.Node,
c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.Passkey, c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.UserGroup,
} { } {
n.Intercept(interceptors...) n.Intercept(interceptors...)
} }
@ -300,6 +306,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.Task.mutate(ctx, m) return c.Task.mutate(ctx, m)
case *UserMutation: case *UserMutation:
return c.User.mutate(ctx, m) return c.User.mutate(ctx, m)
case *UserGroupMutation:
return c.UserGroup.mutate(ctx, m)
default: default:
return nil, fmt.Errorf("ent: unknown mutation type %T", m) return nil, fmt.Errorf("ent: unknown mutation type %T", m)
} }
@ -1169,7 +1177,7 @@ func (c *GroupClient) QueryUsers(gr *Group) *UserQuery {
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, id), sqlgraph.From(group.Table, group.FieldID, id),
sqlgraph.To(user.Table, user.FieldID), sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.UsersTable, group.UsersColumn), sqlgraph.Edge(sqlgraph.M2M, false, group.UsersTable, group.UsersPrimaryKey...),
) )
fromV = sqlgraph.Neighbors(gr.driver.Dialect(), step) fromV = sqlgraph.Neighbors(gr.driver.Dialect(), step)
return fromV, nil return fromV, nil
@ -1193,6 +1201,22 @@ func (c *GroupClient) QueryStoragePolicies(gr *Group) *StoragePolicyQuery {
return query return query
} }
// QueryUserGroup queries the user_group edge of a Group.
func (c *GroupClient) QueryUserGroup(gr *Group) *UserGroupQuery {
query := (&UserGroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := gr.ID
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, id),
sqlgraph.To(usergroup.Table, usergroup.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, group.UserGroupTable, group.UserGroupColumn),
)
fromV = sqlgraph.Neighbors(gr.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks. // Hooks returns the client hooks.
func (c *GroupClient) Hooks() []Hook { func (c *GroupClient) Hooks() []Hook {
hooks := c.hooks.Group hooks := c.hooks.Group
@ -2433,15 +2457,15 @@ func (c *UserClient) GetX(ctx context.Context, id int) *User {
return obj return obj
} }
// QueryGroup queries the group edge of a User. // QueryGroups queries the groups edge of a User.
func (c *UserClient) QueryGroup(u *User) *GroupQuery { func (c *UserClient) QueryGroups(u *User) *GroupQuery {
query := (&GroupClient{config: c.config}).Query() query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) { query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := u.ID id := u.ID
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, id), sqlgraph.From(user.Table, user.FieldID, id),
sqlgraph.To(group.Table, group.FieldID), sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, user.GroupTable, user.GroupColumn), sqlgraph.Edge(sqlgraph.M2M, true, user.GroupsTable, user.GroupsPrimaryKey...),
) )
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step) fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil return fromV, nil
@ -2545,6 +2569,22 @@ func (c *UserClient) QueryEntities(u *User) *EntityQuery {
return query return query
} }
// QueryUserGroup queries the user_group edge of a User.
func (c *UserClient) QueryUserGroup(u *User) *UserGroupQuery {
query := (&UserGroupClient{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(usergroup.Table, usergroup.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, user.UserGroupTable, user.UserGroupColumn),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks. // Hooks returns the client hooks.
func (c *UserClient) Hooks() []Hook { func (c *UserClient) Hooks() []Hook {
hooks := c.hooks.User hooks := c.hooks.User
@ -2572,15 +2612,180 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error)
} }
} }
// UserGroupClient is a client for the UserGroup schema.
type UserGroupClient struct {
config
}
// NewUserGroupClient returns a client for the UserGroup from the given config.
func NewUserGroupClient(c config) *UserGroupClient {
return &UserGroupClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `usergroup.Hooks(f(g(h())))`.
func (c *UserGroupClient) Use(hooks ...Hook) {
c.hooks.UserGroup = append(c.hooks.UserGroup, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `usergroup.Intercept(f(g(h())))`.
func (c *UserGroupClient) Intercept(interceptors ...Interceptor) {
c.inters.UserGroup = append(c.inters.UserGroup, interceptors...)
}
// Create returns a builder for creating a UserGroup entity.
func (c *UserGroupClient) Create() *UserGroupCreate {
mutation := newUserGroupMutation(c.config, OpCreate)
return &UserGroupCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of UserGroup entities.
func (c *UserGroupClient) CreateBulk(builders ...*UserGroupCreate) *UserGroupCreateBulk {
return &UserGroupCreateBulk{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 *UserGroupClient) MapCreateBulk(slice any, setFunc func(*UserGroupCreate, int)) *UserGroupCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &UserGroupCreateBulk{err: fmt.Errorf("calling to UserGroupClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*UserGroupCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &UserGroupCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for UserGroup.
func (c *UserGroupClient) Update() *UserGroupUpdate {
mutation := newUserGroupMutation(c.config, OpUpdate)
return &UserGroupUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *UserGroupClient) UpdateOne(ug *UserGroup) *UserGroupUpdateOne {
mutation := newUserGroupMutation(c.config, OpUpdateOne, withUserGroup(ug))
return &UserGroupUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *UserGroupClient) UpdateOneID(id int) *UserGroupUpdateOne {
mutation := newUserGroupMutation(c.config, OpUpdateOne, withUserGroupID(id))
return &UserGroupUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for UserGroup.
func (c *UserGroupClient) Delete() *UserGroupDelete {
mutation := newUserGroupMutation(c.config, OpDelete)
return &UserGroupDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *UserGroupClient) DeleteOne(ug *UserGroup) *UserGroupDeleteOne {
return c.DeleteOneID(ug.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *UserGroupClient) DeleteOneID(id int) *UserGroupDeleteOne {
builder := c.Delete().Where(usergroup.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &UserGroupDeleteOne{builder}
}
// Query returns a query builder for UserGroup.
func (c *UserGroupClient) Query() *UserGroupQuery {
return &UserGroupQuery{
config: c.config,
ctx: &QueryContext{Type: TypeUserGroup},
inters: c.Interceptors(),
}
}
// Get returns a UserGroup entity by its id.
func (c *UserGroupClient) Get(ctx context.Context, id int) (*UserGroup, error) {
return c.Query().Where(usergroup.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *UserGroupClient) GetX(ctx context.Context, id int) *UserGroup {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUser queries the user edge of a UserGroup.
func (c *UserGroupClient) QueryUser(ug *UserGroup) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := ug.ID
step := sqlgraph.NewStep(
sqlgraph.From(usergroup.Table, usergroup.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, usergroup.UserTable, usergroup.UserColumn),
)
fromV = sqlgraph.Neighbors(ug.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryGroup queries the group edge of a UserGroup.
func (c *UserGroupClient) QueryGroup(ug *UserGroup) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := ug.ID
step := sqlgraph.NewStep(
sqlgraph.From(usergroup.Table, usergroup.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, usergroup.GroupTable, usergroup.GroupColumn),
)
fromV = sqlgraph.Neighbors(ug.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *UserGroupClient) Hooks() []Hook {
return c.hooks.UserGroup
}
// Interceptors returns the client interceptors.
func (c *UserGroupClient) Interceptors() []Interceptor {
return c.inters.UserGroup
}
func (c *UserGroupClient) mutate(ctx context.Context, m *UserGroupMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&UserGroupCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&UserGroupUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&UserGroupUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&UserGroupDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown UserGroup mutation op: %q", m.Op())
}
}
// hooks and interceptors per client, for fast access. // hooks and interceptors per client, for fast access.
type ( type (
hooks struct { hooks struct {
DavAccount, DirectLink, Entity, File, Group, Metadata, Node, Passkey, Setting, DavAccount, DirectLink, Entity, File, Group, Metadata, Node, Passkey, Setting,
Share, StoragePolicy, Task, User []ent.Hook Share, StoragePolicy, Task, User, UserGroup []ent.Hook
} }
inters struct { inters struct {
DavAccount, DirectLink, Entity, File, Group, Metadata, Node, Passkey, Setting, DavAccount, DirectLink, Entity, File, Group, Metadata, Node, Passkey, Setting,
Share, StoragePolicy, Task, User []ent.Interceptor Share, StoragePolicy, Task, User, UserGroup []ent.Interceptor
} }
) )

@ -25,6 +25,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
) )
// ent aliases to avoid import conflicts in user's code. // ent aliases to avoid import conflicts in user's code.
@ -98,6 +99,7 @@ func checkColumn(table, column string) error {
storagepolicy.Table: storagepolicy.ValidColumn, storagepolicy.Table: storagepolicy.ValidColumn,
task.Table: task.ValidColumn, task.Table: task.ValidColumn,
user.Table: user.ValidColumn, user.Table: user.ValidColumn,
usergroup.Table: usergroup.ValidColumn,
}) })
}) })
return columnCheck(table, column) return columnCheck(table, column)

@ -51,9 +51,11 @@ type GroupEdges struct {
Users []*User `json:"users,omitempty"` Users []*User `json:"users,omitempty"`
// StoragePolicies holds the value of the storage_policies edge. // StoragePolicies holds the value of the storage_policies edge.
StoragePolicies *StoragePolicy `json:"storage_policies,omitempty"` StoragePolicies *StoragePolicy `json:"storage_policies,omitempty"`
// UserGroup holds the value of the user_group edge.
UserGroup []*UserGroup `json:"user_group,omitempty"`
// loadedTypes holds the information for reporting if a // loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not. // type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool loadedTypes [3]bool
} }
// UsersOrErr returns the Users value or an error if the edge // UsersOrErr returns the Users value or an error if the edge
@ -78,6 +80,15 @@ func (e GroupEdges) StoragePoliciesOrErr() (*StoragePolicy, error) {
return nil, &NotLoadedError{edge: "storage_policies"} return nil, &NotLoadedError{edge: "storage_policies"}
} }
// UserGroupOrErr returns the UserGroup value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) UserGroupOrErr() ([]*UserGroup, error) {
if e.loadedTypes[2] {
return e.UserGroup, nil
}
return nil, &NotLoadedError{edge: "user_group"}
}
// scanValues returns the types for scanning values from sql.Rows. // scanValues returns the types for scanning values from sql.Rows.
func (*Group) scanValues(columns []string) ([]any, error) { func (*Group) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns)) values := make([]any, len(columns))
@ -194,6 +205,11 @@ func (gr *Group) QueryStoragePolicies() *StoragePolicyQuery {
return NewGroupClient(gr.config).QueryStoragePolicies(gr) return NewGroupClient(gr.config).QueryStoragePolicies(gr)
} }
// QueryUserGroup queries the "user_group" edge of the Group entity.
func (gr *Group) QueryUserGroup() *UserGroupQuery {
return NewGroupClient(gr.config).QueryUserGroup(gr)
}
// Update returns a builder for updating this Group. // Update returns a builder for updating this Group.
// Note that you need to call Group.Unwrap() before calling this method if this Group // Note that you need to call Group.Unwrap() before calling this method if this Group
// was returned from a transaction, and the transaction was committed or rolled back. // was returned from a transaction, and the transaction was committed or rolled back.
@ -261,5 +277,11 @@ func (e *Group) SetStoragePolicies(v *StoragePolicy) {
e.Edges.loadedTypes[1] = true e.Edges.loadedTypes[1] = true
} }
// SetUserGroup manually set the edge as loaded state.
func (e *Group) SetUserGroup(v []*UserGroup) {
e.Edges.UserGroup = v
e.Edges.loadedTypes[2] = true
}
// Groups is a parsable slice of Group. // Groups is a parsable slice of Group.
type Groups []*Group type Groups []*Group

@ -38,15 +38,15 @@ const (
EdgeUsers = "users" EdgeUsers = "users"
// EdgeStoragePolicies holds the string denoting the storage_policies edge name in mutations. // EdgeStoragePolicies holds the string denoting the storage_policies edge name in mutations.
EdgeStoragePolicies = "storage_policies" EdgeStoragePolicies = "storage_policies"
// EdgeUserGroup holds the string denoting the user_group edge name in mutations.
EdgeUserGroup = "user_group"
// Table holds the table name of the group in the database. // Table holds the table name of the group in the database.
Table = "groups" Table = "groups"
// UsersTable is the table that holds the users relation/edge. // UsersTable is the table that holds the users relation/edge. The primary key declared below.
UsersTable = "users" UsersTable = "user_groups"
// UsersInverseTable is the table name for the User entity. // UsersInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package. // It exists in this package in order to avoid circular dependency with the "user" package.
UsersInverseTable = "users" UsersInverseTable = "users"
// UsersColumn is the table column denoting the users relation/edge.
UsersColumn = "group_users"
// StoragePoliciesTable is the table that holds the storage_policies relation/edge. // StoragePoliciesTable is the table that holds the storage_policies relation/edge.
StoragePoliciesTable = "groups" StoragePoliciesTable = "groups"
// StoragePoliciesInverseTable is the table name for the StoragePolicy entity. // StoragePoliciesInverseTable is the table name for the StoragePolicy entity.
@ -54,6 +54,13 @@ const (
StoragePoliciesInverseTable = "storage_policies" StoragePoliciesInverseTable = "storage_policies"
// StoragePoliciesColumn is the table column denoting the storage_policies relation/edge. // StoragePoliciesColumn is the table column denoting the storage_policies relation/edge.
StoragePoliciesColumn = "storage_policy_id" StoragePoliciesColumn = "storage_policy_id"
// UserGroupTable is the table that holds the user_group relation/edge.
UserGroupTable = "user_groups"
// UserGroupInverseTable is the table name for the UserGroup entity.
// It exists in this package in order to avoid circular dependency with the "usergroup" package.
UserGroupInverseTable = "user_groups"
// UserGroupColumn is the table column denoting the user_group relation/edge.
UserGroupColumn = "group_id"
) )
// Columns holds all SQL columns for group fields. // Columns holds all SQL columns for group fields.
@ -70,6 +77,12 @@ var Columns = []string{
FieldStoragePolicyID, FieldStoragePolicyID,
} }
var (
// UsersPrimaryKey and UsersColumn2 are the table columns denoting the
// primary key for the users relation (M2M).
UsersPrimaryKey = []string{"group_id", "user_id"}
)
// ValidColumn reports if the column name is valid (part of the table columns). // ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool { func ValidColumn(column string) bool {
for i := range Columns { for i := range Columns {
@ -161,11 +174,25 @@ func ByStoragePoliciesField(field string, opts ...sql.OrderTermOption) OrderOpti
sqlgraph.OrderByNeighborTerms(s, newStoragePoliciesStep(), sql.OrderByField(field, opts...)) sqlgraph.OrderByNeighborTerms(s, newStoragePoliciesStep(), sql.OrderByField(field, opts...))
} }
} }
// ByUserGroupCount orders the results by user_group count.
func ByUserGroupCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newUserGroupStep(), opts...)
}
}
// ByUserGroup orders the results by user_group terms.
func ByUserGroup(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newUserGroupStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newUsersStep() *sqlgraph.Step { func newUsersStep() *sqlgraph.Step {
return sqlgraph.NewStep( return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID), sqlgraph.From(Table, FieldID),
sqlgraph.To(UsersInverseTable, FieldID), sqlgraph.To(UsersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, UsersTable, UsersColumn), sqlgraph.Edge(sqlgraph.M2M, false, UsersTable, UsersPrimaryKey...),
) )
} }
func newStoragePoliciesStep() *sqlgraph.Step { func newStoragePoliciesStep() *sqlgraph.Step {
@ -175,3 +202,10 @@ func newStoragePoliciesStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2O, true, StoragePoliciesTable, StoragePoliciesColumn), sqlgraph.Edge(sqlgraph.M2O, true, StoragePoliciesTable, StoragePoliciesColumn),
) )
} }
func newUserGroupStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserGroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, UserGroupTable, UserGroupColumn),
)
}

@ -476,7 +476,7 @@ func HasUsers() predicate.Group {
return predicate.Group(func(s *sql.Selector) { return predicate.Group(func(s *sql.Selector) {
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID), sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, UsersTable, UsersColumn), sqlgraph.Edge(sqlgraph.M2M, false, UsersTable, UsersPrimaryKey...),
) )
sqlgraph.HasNeighbors(s, step) sqlgraph.HasNeighbors(s, step)
}) })
@ -517,6 +517,29 @@ func HasStoragePoliciesWith(preds ...predicate.StoragePolicy) predicate.Group {
}) })
} }
// HasUserGroup applies the HasEdge predicate on the "user_group" edge.
func HasUserGroup() predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, UserGroupTable, UserGroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasUserGroupWith applies the HasEdge predicate on the "user_group" edge with a given conditions (other predicates).
func HasUserGroupWith(preds ...predicate.UserGroup) predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := newUserGroupStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them. // And groups predicates with the AND operator between them.
func And(predicates ...predicate.Group) predicate.Group { func And(predicates ...predicate.Group) predicate.Group {
return predicate.Group(sql.AndPredicates(predicates...)) return predicate.Group(sql.AndPredicates(predicates...))

@ -14,6 +14,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/group" "github.com/cloudreve/Cloudreve/v4/ent/group"
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/boolset" "github.com/cloudreve/Cloudreve/v4/pkg/boolset"
) )
@ -162,6 +163,21 @@ func (gc *GroupCreate) SetStoragePolicies(s *StoragePolicy) *GroupCreate {
return gc.SetStoragePoliciesID(s.ID) return gc.SetStoragePoliciesID(s.ID)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (gc *GroupCreate) AddUserGroupIDs(ids ...int) *GroupCreate {
gc.mutation.AddUserGroupIDs(ids...)
return gc
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (gc *GroupCreate) AddUserGroup(u ...*UserGroup) *GroupCreate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return gc.AddUserGroupIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder. // Mutation returns the GroupMutation object of the builder.
func (gc *GroupCreate) Mutation() *GroupMutation { func (gc *GroupCreate) Mutation() *GroupMutation {
return gc.mutation return gc.mutation
@ -302,10 +318,10 @@ func (gc *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
} }
if nodes := gc.mutation.UsersIDs(); len(nodes) > 0 { if nodes := gc.mutation.UsersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
@ -314,6 +330,10 @@ func (gc *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: gc.config, mutation: newUserGroupMutation(gc.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges = append(_spec.Edges, edge) _spec.Edges = append(_spec.Edges, edge)
} }
if nodes := gc.mutation.StoragePoliciesIDs(); len(nodes) > 0 { if nodes := gc.mutation.StoragePoliciesIDs(); len(nodes) > 0 {
@ -333,6 +353,22 @@ func (gc *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_node.StoragePolicyID = nodes[0] _node.StoragePolicyID = nodes[0]
_spec.Edges = append(_spec.Edges, edge) _spec.Edges = append(_spec.Edges, edge)
} }
if nodes := gc.mutation.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec return _node, _spec
} }

@ -15,6 +15,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/predicate"
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
) )
// GroupQuery is the builder for querying Group entities. // GroupQuery is the builder for querying Group entities.
@ -26,6 +27,7 @@ type GroupQuery struct {
predicates []predicate.Group predicates []predicate.Group
withUsers *UserQuery withUsers *UserQuery
withStoragePolicies *StoragePolicyQuery withStoragePolicies *StoragePolicyQuery
withUserGroup *UserGroupQuery
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -76,7 +78,7 @@ func (gq *GroupQuery) QueryUsers() *UserQuery {
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, selector), sqlgraph.From(group.Table, group.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID), sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.UsersTable, group.UsersColumn), sqlgraph.Edge(sqlgraph.M2M, false, group.UsersTable, group.UsersPrimaryKey...),
) )
fromU = sqlgraph.SetNeighbors(gq.driver.Dialect(), step) fromU = sqlgraph.SetNeighbors(gq.driver.Dialect(), step)
return fromU, nil return fromU, nil
@ -106,6 +108,28 @@ func (gq *GroupQuery) QueryStoragePolicies() *StoragePolicyQuery {
return query return query
} }
// QueryUserGroup chains the current query on the "user_group" edge.
func (gq *GroupQuery) QueryUserGroup() *UserGroupQuery {
query := (&UserGroupClient{config: gq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := gq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := gq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, selector),
sqlgraph.To(usergroup.Table, usergroup.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, group.UserGroupTable, group.UserGroupColumn),
)
fromU = sqlgraph.SetNeighbors(gq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Group entity from the query. // First returns the first Group entity from the query.
// Returns a *NotFoundError when no Group was found. // Returns a *NotFoundError when no Group was found.
func (gq *GroupQuery) First(ctx context.Context) (*Group, error) { func (gq *GroupQuery) First(ctx context.Context) (*Group, error) {
@ -300,6 +324,7 @@ func (gq *GroupQuery) Clone() *GroupQuery {
predicates: append([]predicate.Group{}, gq.predicates...), predicates: append([]predicate.Group{}, gq.predicates...),
withUsers: gq.withUsers.Clone(), withUsers: gq.withUsers.Clone(),
withStoragePolicies: gq.withStoragePolicies.Clone(), withStoragePolicies: gq.withStoragePolicies.Clone(),
withUserGroup: gq.withUserGroup.Clone(),
// clone intermediate query. // clone intermediate query.
sql: gq.sql.Clone(), sql: gq.sql.Clone(),
path: gq.path, path: gq.path,
@ -328,6 +353,17 @@ func (gq *GroupQuery) WithStoragePolicies(opts ...func(*StoragePolicyQuery)) *Gr
return gq return gq
} }
// WithUserGroup tells the query-builder to eager-load the nodes that are connected to
// the "user_group" edge. The optional arguments are used to configure the query builder of the edge.
func (gq *GroupQuery) WithUserGroup(opts ...func(*UserGroupQuery)) *GroupQuery {
query := (&UserGroupClient{config: gq.config}).Query()
for _, opt := range opts {
opt(query)
}
gq.withUserGroup = query
return gq
}
// GroupBy is used to group vertices by one or more fields/columns. // 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. // It is often used with aggregate functions, like: count, max, mean, min, sum.
// //
@ -406,9 +442,10 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
var ( var (
nodes = []*Group{} nodes = []*Group{}
_spec = gq.querySpec() _spec = gq.querySpec()
loadedTypes = [2]bool{ loadedTypes = [3]bool{
gq.withUsers != nil, gq.withUsers != nil,
gq.withStoragePolicies != nil, gq.withStoragePolicies != nil,
gq.withUserGroup != nil,
} }
) )
_spec.ScanValues = func(columns []string) ([]any, error) { _spec.ScanValues = func(columns []string) ([]any, error) {
@ -442,36 +479,74 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
return nil, err return nil, err
} }
} }
if query := gq.withUserGroup; query != nil {
if err := gq.loadUserGroup(ctx, query, nodes,
func(n *Group) { n.Edges.UserGroup = []*UserGroup{} },
func(n *Group, e *UserGroup) { n.Edges.UserGroup = append(n.Edges.UserGroup, e) }); err != nil {
return nil, err
}
}
return nodes, nil return nodes, nil
} }
func (gq *GroupQuery) loadUsers(ctx context.Context, query *UserQuery, nodes []*Group, init func(*Group), assign func(*Group, *User)) error { func (gq *GroupQuery) loadUsers(ctx context.Context, query *UserQuery, nodes []*Group, init func(*Group), assign func(*Group, *User)) error {
fks := make([]driver.Value, 0, len(nodes)) edgeIDs := make([]driver.Value, len(nodes))
nodeids := make(map[int]*Group) byID := make(map[int]*Group)
for i := range nodes { nids := make(map[int]map[*Group]struct{})
fks = append(fks, nodes[i].ID) for i, node := range nodes {
nodeids[nodes[i].ID] = nodes[i] edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil { if init != nil {
init(nodes[i]) init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(group.UsersTable)
s.Join(joinT).On(s.C(user.FieldID), joinT.C(group.UsersPrimaryKey[1]))
s.Where(sql.InValues(joinT.C(group.UsersPrimaryKey[0]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(group.UsersPrimaryKey[0]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
} }
return append([]any{new(sql.NullInt64)}, values...), nil
} }
if len(query.ctx.Fields) > 0 { spec.Assign = func(columns []string, values []any) error {
query.ctx.AppendFieldOnce(user.FieldGroupUsers) outValue := int(values[0].(*sql.NullInt64).Int64)
inValue := int(values[1].(*sql.NullInt64).Int64)
if nids[inValue] == nil {
nids[inValue] = map[*Group]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
} }
query.Where(predicate.User(func(s *sql.Selector) { nids[inValue][byID[outValue]] = struct{}{}
s.Where(sql.InValues(s.C(group.UsersColumn), fks...)) return nil
})) }
neighbors, err := query.All(ctx) })
})
neighbors, err := withInterceptors[[]*User](ctx, query, qr, query.inters)
if err != nil { if err != nil {
return err return err
} }
for _, n := range neighbors { for _, n := range neighbors {
fk := n.GroupUsers nodes, ok := nids[n.ID]
node, ok := nodeids[fk]
if !ok { if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "group_users" returned %v for node %v`, fk, n.ID) return fmt.Errorf(`unexpected "users" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
} }
assign(node, n)
} }
return nil return nil
} }
@ -504,6 +579,36 @@ func (gq *GroupQuery) loadStoragePolicies(ctx context.Context, query *StoragePol
} }
return nil return nil
} }
func (gq *GroupQuery) loadUserGroup(ctx context.Context, query *UserGroupQuery, nodes []*Group, init func(*Group), assign func(*Group, *UserGroup)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int]*Group)
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(usergroup.FieldGroupID)
}
query.Where(predicate.UserGroup(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(group.UserGroupColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.GroupID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "group_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (gq *GroupQuery) sqlCount(ctx context.Context) (int, error) { func (gq *GroupQuery) sqlCount(ctx context.Context) (int, error) {
_spec := gq.querySpec() _spec := gq.querySpec()

@ -15,6 +15,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/predicate" "github.com/cloudreve/Cloudreve/v4/ent/predicate"
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/boolset" "github.com/cloudreve/Cloudreve/v4/pkg/boolset"
) )
@ -198,6 +199,21 @@ func (gu *GroupUpdate) SetStoragePolicies(s *StoragePolicy) *GroupUpdate {
return gu.SetStoragePoliciesID(s.ID) return gu.SetStoragePoliciesID(s.ID)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (gu *GroupUpdate) AddUserGroupIDs(ids ...int) *GroupUpdate {
gu.mutation.AddUserGroupIDs(ids...)
return gu
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (gu *GroupUpdate) AddUserGroup(u ...*UserGroup) *GroupUpdate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return gu.AddUserGroupIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder. // Mutation returns the GroupMutation object of the builder.
func (gu *GroupUpdate) Mutation() *GroupMutation { func (gu *GroupUpdate) Mutation() *GroupMutation {
return gu.mutation return gu.mutation
@ -230,6 +246,27 @@ func (gu *GroupUpdate) ClearStoragePolicies() *GroupUpdate {
return gu return gu
} }
// ClearUserGroup clears all "user_group" edges to the UserGroup entity.
func (gu *GroupUpdate) ClearUserGroup() *GroupUpdate {
gu.mutation.ClearUserGroup()
return gu
}
// RemoveUserGroupIDs removes the "user_group" edge to UserGroup entities by IDs.
func (gu *GroupUpdate) RemoveUserGroupIDs(ids ...int) *GroupUpdate {
gu.mutation.RemoveUserGroupIDs(ids...)
return gu
}
// RemoveUserGroup removes "user_group" edges to UserGroup entities.
func (gu *GroupUpdate) RemoveUserGroup(u ...*UserGroup) *GroupUpdate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return gu.RemoveUserGroupIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation. // Save executes the query and returns the number of nodes affected by the update operation.
func (gu *GroupUpdate) Save(ctx context.Context) (int, error) { func (gu *GroupUpdate) Save(ctx context.Context) (int, error) {
if err := gu.defaults(); err != nil { if err := gu.defaults(); err != nil {
@ -322,23 +359,27 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
} }
if gu.mutation.UsersCleared() { if gu.mutation.UsersCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
}, },
} }
createE := &UserGroupCreate{config: gu.config, mutation: newUserGroupMutation(gu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := gu.mutation.RemovedUsersIDs(); len(nodes) > 0 && !gu.mutation.UsersCleared() { if nodes := gu.mutation.RemovedUsersIDs(); len(nodes) > 0 && !gu.mutation.UsersCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
@ -347,14 +388,18 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: gu.config, mutation: newUserGroupMutation(gu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := gu.mutation.UsersIDs(); len(nodes) > 0 { if nodes := gu.mutation.UsersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
@ -363,6 +408,10 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: gu.config, mutation: newUserGroupMutation(gu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if gu.mutation.StoragePoliciesCleared() { if gu.mutation.StoragePoliciesCleared() {
@ -394,6 +443,51 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
} }
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if gu.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := gu.mutation.RemovedUserGroupIDs(); len(nodes) > 0 && !gu.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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 := gu.mutation.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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, gu.driver, _spec); err != nil { if n, err = sqlgraph.UpdateNodes(ctx, gu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok { if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{group.Label} err = &NotFoundError{group.Label}
@ -580,6 +674,21 @@ func (guo *GroupUpdateOne) SetStoragePolicies(s *StoragePolicy) *GroupUpdateOne
return guo.SetStoragePoliciesID(s.ID) return guo.SetStoragePoliciesID(s.ID)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (guo *GroupUpdateOne) AddUserGroupIDs(ids ...int) *GroupUpdateOne {
guo.mutation.AddUserGroupIDs(ids...)
return guo
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (guo *GroupUpdateOne) AddUserGroup(u ...*UserGroup) *GroupUpdateOne {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return guo.AddUserGroupIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder. // Mutation returns the GroupMutation object of the builder.
func (guo *GroupUpdateOne) Mutation() *GroupMutation { func (guo *GroupUpdateOne) Mutation() *GroupMutation {
return guo.mutation return guo.mutation
@ -612,6 +721,27 @@ func (guo *GroupUpdateOne) ClearStoragePolicies() *GroupUpdateOne {
return guo return guo
} }
// ClearUserGroup clears all "user_group" edges to the UserGroup entity.
func (guo *GroupUpdateOne) ClearUserGroup() *GroupUpdateOne {
guo.mutation.ClearUserGroup()
return guo
}
// RemoveUserGroupIDs removes the "user_group" edge to UserGroup entities by IDs.
func (guo *GroupUpdateOne) RemoveUserGroupIDs(ids ...int) *GroupUpdateOne {
guo.mutation.RemoveUserGroupIDs(ids...)
return guo
}
// RemoveUserGroup removes "user_group" edges to UserGroup entities.
func (guo *GroupUpdateOne) RemoveUserGroup(u ...*UserGroup) *GroupUpdateOne {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return guo.RemoveUserGroupIDs(ids...)
}
// Where appends a list predicates to the GroupUpdate builder. // Where appends a list predicates to the GroupUpdate builder.
func (guo *GroupUpdateOne) Where(ps ...predicate.Group) *GroupUpdateOne { func (guo *GroupUpdateOne) Where(ps ...predicate.Group) *GroupUpdateOne {
guo.mutation.Where(ps...) guo.mutation.Where(ps...)
@ -734,23 +864,27 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
} }
if guo.mutation.UsersCleared() { if guo.mutation.UsersCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
}, },
} }
createE := &UserGroupCreate{config: guo.config, mutation: newUserGroupMutation(guo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := guo.mutation.RemovedUsersIDs(); len(nodes) > 0 && !guo.mutation.UsersCleared() { if nodes := guo.mutation.RemovedUsersIDs(); len(nodes) > 0 && !guo.mutation.UsersCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
@ -759,14 +893,18 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: guo.config, mutation: newUserGroupMutation(guo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := guo.mutation.UsersIDs(); len(nodes) > 0 { if nodes := guo.mutation.UsersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M, Rel: sqlgraph.M2M,
Inverse: false, Inverse: false,
Table: group.UsersTable, Table: group.UsersTable,
Columns: []string{group.UsersColumn}, Columns: group.UsersPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
@ -775,6 +913,10 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: guo.config, mutation: newUserGroupMutation(guo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if guo.mutation.StoragePoliciesCleared() { if guo.mutation.StoragePoliciesCleared() {
@ -806,6 +948,51 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
} }
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if guo.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := guo.mutation.RemovedUserGroupIDs(); len(nodes) > 0 && !guo.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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 := guo.mutation.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: group.UserGroupTable,
Columns: []string{group.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Group{config: guo.config} _node = &Group{config: guo.config}
_spec.Assign = _node.assignValues _spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues _spec.ScanValues = _node.scanValues

@ -165,6 +165,18 @@ func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error)
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m) return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m)
} }
// The UserGroupFunc type is an adapter to allow the use of ordinary
// function as UserGroup mutator.
type UserGroupFunc func(context.Context, *ent.UserGroupMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f UserGroupFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.UserGroupMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserGroupMutation", m)
}
// Condition is a hook condition function. // Condition is a hook condition function.
type Condition func(context.Context, ent.Mutation) bool type Condition func(context.Context, ent.Mutation) bool

@ -22,6 +22,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
) )
// The Query interface represents an operation that queries a graph. // The Query interface represents an operation that queries a graph.
@ -431,6 +432,33 @@ func (f TraverseUser) Traverse(ctx context.Context, q ent.Query) error {
return fmt.Errorf("unexpected query type %T. expect *ent.UserQuery", q) return fmt.Errorf("unexpected query type %T. expect *ent.UserQuery", q)
} }
// The UserGroupFunc type is an adapter to allow the use of ordinary function as a Querier.
type UserGroupFunc func(context.Context, *ent.UserGroupQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f UserGroupFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.UserGroupQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.UserGroupQuery", q)
}
// The TraverseUserGroup type is an adapter to allow the use of ordinary function as Traverser.
type TraverseUserGroup func(context.Context, *ent.UserGroupQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraverseUserGroup) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraverseUserGroup) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.UserGroupQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.UserGroupQuery", q)
}
// NewQuery returns the generic Query interface for the given typed query. // NewQuery returns the generic Query interface for the given typed query.
func NewQuery(q ent.Query) (Query, error) { func NewQuery(q ent.Query) (Query, error) {
switch q := q.(type) { switch q := q.(type) {
@ -460,6 +488,8 @@ func NewQuery(q ent.Query) (Query, error) {
return &query[*ent.TaskQuery, predicate.Task, task.OrderOption]{typ: ent.TypeTask, tq: q}, nil return &query[*ent.TaskQuery, predicate.Task, task.OrderOption]{typ: ent.TypeTask, tq: q}, nil
case *ent.UserQuery: case *ent.UserQuery:
return &query[*ent.UserQuery, predicate.User, user.OrderOption]{typ: ent.TypeUser, tq: q}, nil return &query[*ent.UserQuery, predicate.User, user.OrderOption]{typ: ent.TypeUser, tq: q}, nil
case *ent.UserGroupQuery:
return &query[*ent.UserGroupQuery, predicate.UserGroup, usergroup.OrderOption]{typ: ent.TypeUserGroup, tq: q}, nil
default: default:
return nil, fmt.Errorf("unknown query type %T", q) return nil, fmt.Errorf("unknown query type %T", q)
} }

File diff suppressed because one or more lines are too long

@ -398,21 +398,47 @@ var (
{Name: "two_factor_secret", Type: field.TypeString, Nullable: true}, {Name: "two_factor_secret", Type: field.TypeString, Nullable: true},
{Name: "avatar", Type: field.TypeString, Nullable: true}, {Name: "avatar", Type: field.TypeString, Nullable: true},
{Name: "settings", Type: field.TypeJSON, Nullable: true}, {Name: "settings", Type: field.TypeJSON, Nullable: true},
{Name: "group_users", Type: field.TypeInt},
} }
// UsersTable holds the schema information for the "users" table. // UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{ UsersTable = &schema.Table{
Name: "users", Name: "users",
Columns: UsersColumns, Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]}, PrimaryKey: []*schema.Column{UsersColumns[0]},
}
// UserGroupsColumns holds the columns for the "user_groups" table.
UserGroupsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "is_primary", Type: field.TypeBool, Default: false},
{Name: "expires_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}},
{Name: "user_id", Type: field.TypeInt},
{Name: "group_id", Type: field.TypeInt},
}
// UserGroupsTable holds the schema information for the "user_groups" table.
UserGroupsTable = &schema.Table{
Name: "user_groups",
Columns: UserGroupsColumns,
PrimaryKey: []*schema.Column{UserGroupsColumns[0]},
ForeignKeys: []*schema.ForeignKey{ ForeignKeys: []*schema.ForeignKey{
{ {
Symbol: "users_groups_users", Symbol: "user_groups_users_user",
Columns: []*schema.Column{UsersColumns[12]}, Columns: []*schema.Column{UserGroupsColumns[3]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "user_groups_groups_group",
Columns: []*schema.Column{UserGroupsColumns[4]},
RefColumns: []*schema.Column{GroupsColumns[0]}, RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.NoAction, OnDelete: schema.NoAction,
}, },
}, },
Indexes: []*schema.Index{
{
Name: "usergroup_group_id_user_id",
Unique: true,
Columns: []*schema.Column{UserGroupsColumns[4], UserGroupsColumns[3]},
},
},
} }
// FileEntitiesColumns holds the columns for the "file_entities" table. // FileEntitiesColumns holds the columns for the "file_entities" table.
FileEntitiesColumns = []*schema.Column{ FileEntitiesColumns = []*schema.Column{
@ -454,6 +480,7 @@ var (
StoragePoliciesTable, StoragePoliciesTable,
TasksTable, TasksTable,
UsersTable, UsersTable,
UserGroupsTable,
FileEntitiesTable, FileEntitiesTable,
} }
) )
@ -473,7 +500,8 @@ func init() {
SharesTable.ForeignKeys[1].RefTable = UsersTable SharesTable.ForeignKeys[1].RefTable = UsersTable
StoragePoliciesTable.ForeignKeys[0].RefTable = NodesTable StoragePoliciesTable.ForeignKeys[0].RefTable = NodesTable
TasksTable.ForeignKeys[0].RefTable = UsersTable TasksTable.ForeignKeys[0].RefTable = UsersTable
UsersTable.ForeignKeys[0].RefTable = GroupsTable UserGroupsTable.ForeignKeys[0].RefTable = UsersTable
UserGroupsTable.ForeignKeys[1].RefTable = GroupsTable
FileEntitiesTable.ForeignKeys[0].RefTable = FilesTable FileEntitiesTable.ForeignKeys[0].RefTable = FilesTable
FileEntitiesTable.ForeignKeys[1].RefTable = EntitiesTable FileEntitiesTable.ForeignKeys[1].RefTable = EntitiesTable
} }

File diff suppressed because it is too large Load Diff

@ -79,3 +79,9 @@ func (m *TaskMutation) SetRawID(t int) {
func (m *UserMutation) SetRawID(t int) { func (m *UserMutation) SetRawID(t int) {
m.id = &t m.id = &t
} }
// SetUpdatedAt sets the "updated_at" field.
func (m *UserGroupMutation) SetRawID(t int) {
m.id = &t
}

@ -44,3 +44,6 @@ type Task func(*sql.Selector)
// User is the predicate function for user builders. // User is the predicate function for user builders.
type User func(*sql.Selector) type User func(*sql.Selector)
// UserGroup is the predicate function for usergroup builders.
type UserGroup func(*sql.Selector)

@ -19,6 +19,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/storagepolicy" "github.com/cloudreve/Cloudreve/v4/ent/storagepolicy"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
) )
@ -329,6 +330,12 @@ func init() {
userDescSettings := userFields[7].Descriptor() userDescSettings := userFields[7].Descriptor()
// user.DefaultSettings holds the default value on creation for the settings field. // user.DefaultSettings holds the default value on creation for the settings field.
user.DefaultSettings = userDescSettings.Default.(*types.UserSetting) user.DefaultSettings = userDescSettings.Default.(*types.UserSetting)
usergroupFields := schema.UserGroup{}.Fields()
_ = usergroupFields
// usergroupDescIsPrimary is the schema descriptor for is_primary field.
usergroupDescIsPrimary := usergroupFields[2].Descriptor()
// usergroup.DefaultIsPrimary holds the default value on creation for the is_primary field.
usergroup.DefaultIsPrimary = usergroupDescIsPrimary.Default.(bool)
} }
const ( const (

@ -36,7 +36,8 @@ func (Group) Mixin() []ent.Mixin {
func (Group) Edges() []ent.Edge { func (Group) Edges() []ent.Edge {
return []ent.Edge{ return []ent.Edge{
edge.To("users", User.Type), edge.To("users", User.Type).
Through("user_group", UserGroup.Type),
edge.From("storage_policies", StoragePolicy.Type). edge.From("storage_policies", StoragePolicy.Type).
Ref("groups"). Ref("groups").
Field("storage_policy_id"). Field("storage_policy_id").

@ -35,17 +35,14 @@ func (User) Fields() []ent.Field {
field.JSON("settings", &types.UserSetting{}). field.JSON("settings", &types.UserSetting{}).
Default(&types.UserSetting{}). Default(&types.UserSetting{}).
Optional(), Optional(),
field.Int("group_users"),
} }
} }
func (User) Edges() []ent.Edge { func (User) Edges() []ent.Edge {
return []ent.Edge{ return []ent.Edge{
edge.From("group", Group.Type). edge.From("groups", Group.Type).
Ref("users"). Ref("users").
Field("group_users"). Through("user_group", UserGroup.Type),
Unique().
Required(),
edge.To("files", File.Type), edge.To("files", File.Type),
edge.To("dav_accounts", DavAccount.Type), edge.To("dav_accounts", DavAccount.Type),
edge.To("shares", Share.Type), edge.To("shares", Share.Type),

@ -0,0 +1,40 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)
type UserGroup struct {
ent.Schema
}
func (UserGroup) Fields() []ent.Field {
return []ent.Field{
field.Int("user_id"),
field.Int("group_id"),
field.Bool("is_primary").
Default(false),
field.Time("expires_at").
Optional().
Nillable().
SchemaType(map[string]string{
dialect.MySQL: "datetime",
}),
}
}
func (UserGroup) Edges() []ent.Edge {
return []ent.Edge{
edge.To("user", User.Type).
Required().
Unique().
Field("user_id"),
edge.To("group", Group.Type).
Required().
Unique().
Field("group_id"),
}
}

@ -40,6 +40,8 @@ type Tx struct {
Task *TaskClient Task *TaskClient
// User is the client for interacting with the User builders. // User is the client for interacting with the User builders.
User *UserClient User *UserClient
// UserGroup is the client for interacting with the UserGroup builders.
UserGroup *UserGroupClient
// lazily loaded. // lazily loaded.
client *Client client *Client
@ -184,6 +186,7 @@ func (tx *Tx) init() {
tx.StoragePolicy = NewStoragePolicyClient(tx.config) tx.StoragePolicy = NewStoragePolicyClient(tx.config)
tx.Task = NewTaskClient(tx.config) tx.Task = NewTaskClient(tx.config)
tx.User = NewUserClient(tx.config) tx.User = NewUserClient(tx.config)
tx.UserGroup = NewUserGroupClient(tx.config)
} }
// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. // txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.

@ -10,7 +10,6 @@ import (
"entgo.io/ent" "entgo.io/ent"
"entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql"
"github.com/cloudreve/Cloudreve/v4/ent/group"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
) )
@ -42,8 +41,6 @@ type User struct {
Avatar string `json:"avatar,omitempty"` Avatar string `json:"avatar,omitempty"`
// Settings holds the value of the "settings" field. // Settings holds the value of the "settings" field.
Settings *types.UserSetting `json:"settings,omitempty"` Settings *types.UserSetting `json:"settings,omitempty"`
// GroupUsers holds the value of the "group_users" field.
GroupUsers int `json:"group_users,omitempty"`
// Edges holds the relations/edges for other nodes in the graph. // Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the UserQuery when eager-loading is set. // The values are being populated by the UserQuery when eager-loading is set.
Edges UserEdges `json:"edges"` Edges UserEdges `json:"edges"`
@ -52,8 +49,8 @@ type User struct {
// UserEdges holds the relations/edges for other nodes in the graph. // UserEdges holds the relations/edges for other nodes in the graph.
type UserEdges struct { type UserEdges struct {
// Group holds the value of the group edge. // Groups holds the value of the groups edge.
Group *Group `json:"group,omitempty"` Groups []*Group `json:"groups,omitempty"`
// Files holds the value of the files edge. // Files holds the value of the files edge.
Files []*File `json:"files,omitempty"` Files []*File `json:"files,omitempty"`
// DavAccounts holds the value of the dav_accounts edge. // DavAccounts holds the value of the dav_accounts edge.
@ -66,22 +63,20 @@ type UserEdges struct {
Tasks []*Task `json:"tasks,omitempty"` Tasks []*Task `json:"tasks,omitempty"`
// Entities holds the value of the entities edge. // Entities holds the value of the entities edge.
Entities []*Entity `json:"entities,omitempty"` Entities []*Entity `json:"entities,omitempty"`
// UserGroup holds the value of the user_group edge.
UserGroup []*UserGroup `json:"user_group,omitempty"`
// loadedTypes holds the information for reporting if a // loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not. // type was loaded (or requested) in eager-loading or not.
loadedTypes [7]bool loadedTypes [8]bool
} }
// GroupOrErr returns the Group value or an error if the edge // GroupsOrErr returns the Groups value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found. // was not loaded in eager-loading.
func (e UserEdges) GroupOrErr() (*Group, error) { func (e UserEdges) GroupsOrErr() ([]*Group, error) {
if e.loadedTypes[0] { if e.loadedTypes[0] {
if e.Group == nil { return e.Groups, nil
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
} }
return nil, &NotLoadedError{edge: "group"} return nil, &NotLoadedError{edge: "groups"}
} }
// FilesOrErr returns the Files value or an error if the edge // FilesOrErr returns the Files value or an error if the edge
@ -138,6 +133,15 @@ func (e UserEdges) EntitiesOrErr() ([]*Entity, error) {
return nil, &NotLoadedError{edge: "entities"} return nil, &NotLoadedError{edge: "entities"}
} }
// UserGroupOrErr returns the UserGroup value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) UserGroupOrErr() ([]*UserGroup, error) {
if e.loadedTypes[7] {
return e.UserGroup, nil
}
return nil, &NotLoadedError{edge: "user_group"}
}
// scanValues returns the types for scanning values from sql.Rows. // scanValues returns the types for scanning values from sql.Rows.
func (*User) scanValues(columns []string) ([]any, error) { func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns)) values := make([]any, len(columns))
@ -145,7 +149,7 @@ func (*User) scanValues(columns []string) ([]any, error) {
switch columns[i] { switch columns[i] {
case user.FieldSettings: case user.FieldSettings:
values[i] = new([]byte) values[i] = new([]byte)
case user.FieldID, user.FieldStorage, user.FieldGroupUsers: case user.FieldID, user.FieldStorage:
values[i] = new(sql.NullInt64) values[i] = new(sql.NullInt64)
case user.FieldEmail, user.FieldNick, user.FieldPassword, user.FieldStatus, user.FieldTwoFactorSecret, user.FieldAvatar: case user.FieldEmail, user.FieldNick, user.FieldPassword, user.FieldStatus, user.FieldTwoFactorSecret, user.FieldAvatar:
values[i] = new(sql.NullString) values[i] = new(sql.NullString)
@ -241,12 +245,6 @@ func (u *User) assignValues(columns []string, values []any) error {
return fmt.Errorf("unmarshal field settings: %w", err) return fmt.Errorf("unmarshal field settings: %w", err)
} }
} }
case user.FieldGroupUsers:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field group_users", values[i])
} else if value.Valid {
u.GroupUsers = int(value.Int64)
}
default: default:
u.selectValues.Set(columns[i], values[i]) u.selectValues.Set(columns[i], values[i])
} }
@ -260,9 +258,9 @@ func (u *User) Value(name string) (ent.Value, error) {
return u.selectValues.Get(name) return u.selectValues.Get(name)
} }
// QueryGroup queries the "group" edge of the User entity. // QueryGroups queries the "groups" edge of the User entity.
func (u *User) QueryGroup() *GroupQuery { func (u *User) QueryGroups() *GroupQuery {
return NewUserClient(u.config).QueryGroup(u) return NewUserClient(u.config).QueryGroups(u)
} }
// QueryFiles queries the "files" edge of the User entity. // QueryFiles queries the "files" edge of the User entity.
@ -295,6 +293,11 @@ func (u *User) QueryEntities() *EntityQuery {
return NewUserClient(u.config).QueryEntities(u) return NewUserClient(u.config).QueryEntities(u)
} }
// QueryUserGroup queries the "user_group" edge of the User entity.
func (u *User) QueryUserGroup() *UserGroupQuery {
return NewUserClient(u.config).QueryUserGroup(u)
}
// Update returns a builder for updating this User. // Update returns a builder for updating this User.
// Note that you need to call User.Unwrap() before calling this method if 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. // was returned from a transaction, and the transaction was committed or rolled back.
@ -350,16 +353,13 @@ func (u *User) String() string {
builder.WriteString(", ") builder.WriteString(", ")
builder.WriteString("settings=") builder.WriteString("settings=")
builder.WriteString(fmt.Sprintf("%v", u.Settings)) builder.WriteString(fmt.Sprintf("%v", u.Settings))
builder.WriteString(", ")
builder.WriteString("group_users=")
builder.WriteString(fmt.Sprintf("%v", u.GroupUsers))
builder.WriteByte(')') builder.WriteByte(')')
return builder.String() return builder.String()
} }
// SetGroup manually set the edge as loaded state. // SetGroups manually set the edge as loaded state.
func (e *User) SetGroup(v *Group) { func (e *User) SetGroups(v []*Group) {
e.Edges.Group = v e.Edges.Groups = v
e.Edges.loadedTypes[0] = true e.Edges.loadedTypes[0] = true
} }
@ -399,5 +399,11 @@ func (e *User) SetEntities(v []*Entity) {
e.Edges.loadedTypes[6] = true e.Edges.loadedTypes[6] = true
} }
// SetUserGroup manually set the edge as loaded state.
func (e *User) SetUserGroup(v []*UserGroup) {
e.Edges.UserGroup = v
e.Edges.loadedTypes[7] = true
}
// Users is a parsable slice of User. // Users is a parsable slice of User.
type Users []*User type Users []*User

@ -39,10 +39,8 @@ const (
FieldAvatar = "avatar" FieldAvatar = "avatar"
// FieldSettings holds the string denoting the settings field in the database. // FieldSettings holds the string denoting the settings field in the database.
FieldSettings = "settings" FieldSettings = "settings"
// FieldGroupUsers holds the string denoting the group_users field in the database. // EdgeGroups holds the string denoting the groups edge name in mutations.
FieldGroupUsers = "group_users" EdgeGroups = "groups"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeFiles holds the string denoting the files edge name in mutations. // EdgeFiles holds the string denoting the files edge name in mutations.
EdgeFiles = "files" EdgeFiles = "files"
// EdgeDavAccounts holds the string denoting the dav_accounts edge name in mutations. // EdgeDavAccounts holds the string denoting the dav_accounts edge name in mutations.
@ -55,15 +53,15 @@ const (
EdgeTasks = "tasks" EdgeTasks = "tasks"
// EdgeEntities holds the string denoting the entities edge name in mutations. // EdgeEntities holds the string denoting the entities edge name in mutations.
EdgeEntities = "entities" EdgeEntities = "entities"
// EdgeUserGroup holds the string denoting the user_group edge name in mutations.
EdgeUserGroup = "user_group"
// Table holds the table name of the user in the database. // Table holds the table name of the user in the database.
Table = "users" Table = "users"
// GroupTable is the table that holds the group relation/edge. // GroupsTable is the table that holds the groups relation/edge. The primary key declared below.
GroupTable = "users" GroupsTable = "user_groups"
// GroupInverseTable is the table name for the Group entity. // GroupsInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package. // It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups" GroupsInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_users"
// FilesTable is the table that holds the files relation/edge. // FilesTable is the table that holds the files relation/edge.
FilesTable = "files" FilesTable = "files"
// FilesInverseTable is the table name for the File entity. // FilesInverseTable is the table name for the File entity.
@ -106,6 +104,13 @@ const (
EntitiesInverseTable = "entities" EntitiesInverseTable = "entities"
// EntitiesColumn is the table column denoting the entities relation/edge. // EntitiesColumn is the table column denoting the entities relation/edge.
EntitiesColumn = "created_by" EntitiesColumn = "created_by"
// UserGroupTable is the table that holds the user_group relation/edge.
UserGroupTable = "user_groups"
// UserGroupInverseTable is the table name for the UserGroup entity.
// It exists in this package in order to avoid circular dependency with the "usergroup" package.
UserGroupInverseTable = "user_groups"
// UserGroupColumn is the table column denoting the user_group relation/edge.
UserGroupColumn = "user_id"
) )
// Columns holds all SQL columns for user fields. // Columns holds all SQL columns for user fields.
@ -122,9 +127,14 @@ var Columns = []string{
FieldTwoFactorSecret, FieldTwoFactorSecret,
FieldAvatar, FieldAvatar,
FieldSettings, FieldSettings,
FieldGroupUsers,
} }
var (
// GroupsPrimaryKey and GroupsColumn2 are the table columns denoting the
// primary key for the groups relation (M2M).
GroupsPrimaryKey = []string{"group_id", "user_id"}
)
// ValidColumn reports if the column name is valid (part of the table columns). // ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool { func ValidColumn(column string) bool {
for i := range Columns { for i := range Columns {
@ -245,15 +255,17 @@ func ByAvatar(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldAvatar, opts...).ToFunc() return sql.OrderByField(FieldAvatar, opts...).ToFunc()
} }
// ByGroupUsers orders the results by the group_users field. // ByGroupsCount orders the results by groups count.
func ByGroupUsers(opts ...sql.OrderTermOption) OrderOption { func ByGroupsCount(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldGroupUsers, opts...).ToFunc() return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newGroupsStep(), opts...)
}
} }
// ByGroupField orders the results by group field. // ByGroups orders the results by groups terms.
func ByGroupField(field string, opts ...sql.OrderTermOption) OrderOption { func ByGroups(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) { return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newGroupStep(), sql.OrderByField(field, opts...)) sqlgraph.OrderByNeighborTerms(s, newGroupsStep(), append([]sql.OrderTerm{term}, terms...)...)
} }
} }
@ -340,11 +352,25 @@ func ByEntities(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
sqlgraph.OrderByNeighborTerms(s, newEntitiesStep(), append([]sql.OrderTerm{term}, terms...)...) sqlgraph.OrderByNeighborTerms(s, newEntitiesStep(), append([]sql.OrderTerm{term}, terms...)...)
} }
} }
func newGroupStep() *sqlgraph.Step {
// ByUserGroupCount orders the results by user_group count.
func ByUserGroupCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newUserGroupStep(), opts...)
}
}
// ByUserGroup orders the results by user_group terms.
func ByUserGroup(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newUserGroupStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newGroupsStep() *sqlgraph.Step {
return sqlgraph.NewStep( return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID), sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID), sqlgraph.To(GroupsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn), sqlgraph.Edge(sqlgraph.M2M, true, GroupsTable, GroupsPrimaryKey...),
) )
} }
func newFilesStep() *sqlgraph.Step { func newFilesStep() *sqlgraph.Step {
@ -389,3 +415,10 @@ func newEntitiesStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.O2M, false, EntitiesTable, EntitiesColumn), sqlgraph.Edge(sqlgraph.O2M, false, EntitiesTable, EntitiesColumn),
) )
} }
func newUserGroupStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserGroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, UserGroupTable, UserGroupColumn),
)
}

@ -100,11 +100,6 @@ func Avatar(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldAvatar, v)) return predicate.User(sql.FieldEQ(FieldAvatar, v))
} }
// GroupUsers applies equality check predicate on the "group_users" field. It's identical to GroupUsersEQ.
func GroupUsers(v int) predicate.User {
return predicate.User(sql.FieldEQ(FieldGroupUsers, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field. // CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.User { func CreatedAtEQ(v time.Time) predicate.User {
return predicate.User(sql.FieldEQ(FieldCreatedAt, v)) return predicate.User(sql.FieldEQ(FieldCreatedAt, v))
@ -660,41 +655,21 @@ func SettingsNotNil() predicate.User {
return predicate.User(sql.FieldNotNull(FieldSettings)) return predicate.User(sql.FieldNotNull(FieldSettings))
} }
// GroupUsersEQ applies the EQ predicate on the "group_users" field. // HasGroups applies the HasEdge predicate on the "groups" edge.
func GroupUsersEQ(v int) predicate.User { func HasGroups() predicate.User {
return predicate.User(sql.FieldEQ(FieldGroupUsers, v))
}
// GroupUsersNEQ applies the NEQ predicate on the "group_users" field.
func GroupUsersNEQ(v int) predicate.User {
return predicate.User(sql.FieldNEQ(FieldGroupUsers, v))
}
// GroupUsersIn applies the In predicate on the "group_users" field.
func GroupUsersIn(vs ...int) predicate.User {
return predicate.User(sql.FieldIn(FieldGroupUsers, vs...))
}
// GroupUsersNotIn applies the NotIn predicate on the "group_users" field.
func GroupUsersNotIn(vs ...int) predicate.User {
return predicate.User(sql.FieldNotIn(FieldGroupUsers, vs...))
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.User {
return predicate.User(func(s *sql.Selector) { return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID), sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn), sqlgraph.Edge(sqlgraph.M2M, true, GroupsTable, GroupsPrimaryKey...),
) )
sqlgraph.HasNeighbors(s, step) sqlgraph.HasNeighbors(s, step)
}) })
} }
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates). // HasGroupsWith applies the HasEdge predicate on the "groups" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.User { func HasGroupsWith(preds ...predicate.Group) predicate.User {
return predicate.User(func(s *sql.Selector) { return predicate.User(func(s *sql.Selector) {
step := newGroupStep() step := newGroupsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds { for _, p := range preds {
p(s) p(s)
@ -841,6 +816,29 @@ func HasEntitiesWith(preds ...predicate.Entity) predicate.User {
}) })
} }
// HasUserGroup applies the HasEdge predicate on the "user_group" edge.
func HasUserGroup() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, UserGroupTable, UserGroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasUserGroupWith applies the HasEdge predicate on the "user_group" edge with a given conditions (other predicates).
func HasUserGroupWith(preds ...predicate.UserGroup) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newUserGroupStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them. // And groups predicates with the AND operator between them.
func And(predicates ...predicate.User) predicate.User { func And(predicates ...predicate.User) predicate.User {
return predicate.User(sql.AndPredicates(predicates...)) return predicate.User(sql.AndPredicates(predicates...))

@ -19,6 +19,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/share" "github.com/cloudreve/Cloudreve/v4/ent/share"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
) )
@ -160,21 +161,19 @@ func (uc *UserCreate) SetSettings(ts *types.UserSetting) *UserCreate {
return uc return uc
} }
// SetGroupUsers sets the "group_users" field. // AddGroupIDs adds the "groups" edge to the Group entity by IDs.
func (uc *UserCreate) SetGroupUsers(i int) *UserCreate { func (uc *UserCreate) AddGroupIDs(ids ...int) *UserCreate {
uc.mutation.SetGroupUsers(i) uc.mutation.AddGroupIDs(ids...)
return uc return uc
} }
// SetGroupID sets the "group" edge to the Group entity by ID. // AddGroups adds the "groups" edges to the Group entity.
func (uc *UserCreate) SetGroupID(id int) *UserCreate { func (uc *UserCreate) AddGroups(g ...*Group) *UserCreate {
uc.mutation.SetGroupID(id) ids := make([]int, len(g))
return uc for i := range g {
} ids[i] = g[i].ID
}
// SetGroup sets the "group" edge to the Group entity. return uc.AddGroupIDs(ids...)
func (uc *UserCreate) SetGroup(g *Group) *UserCreate {
return uc.SetGroupID(g.ID)
} }
// AddFileIDs adds the "files" edge to the File entity by IDs. // AddFileIDs adds the "files" edge to the File entity by IDs.
@ -267,6 +266,21 @@ func (uc *UserCreate) AddEntities(e ...*Entity) *UserCreate {
return uc.AddEntityIDs(ids...) return uc.AddEntityIDs(ids...)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (uc *UserCreate) AddUserGroupIDs(ids ...int) *UserCreate {
uc.mutation.AddUserGroupIDs(ids...)
return uc
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (uc *UserCreate) AddUserGroup(u ...*UserGroup) *UserCreate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return uc.AddUserGroupIDs(ids...)
}
// Mutation returns the UserMutation object of the builder. // Mutation returns the UserMutation object of the builder.
func (uc *UserCreate) Mutation() *UserMutation { func (uc *UserCreate) Mutation() *UserMutation {
return uc.mutation return uc.mutation
@ -368,12 +382,6 @@ func (uc *UserCreate) check() error {
if _, ok := uc.mutation.Storage(); !ok { if _, ok := uc.mutation.Storage(); !ok {
return &ValidationError{Name: "storage", err: errors.New(`ent: missing required field "User.storage"`)} return &ValidationError{Name: "storage", err: errors.New(`ent: missing required field "User.storage"`)}
} }
if _, ok := uc.mutation.GroupUsers(); !ok {
return &ValidationError{Name: "group_users", err: errors.New(`ent: missing required field "User.group_users"`)}
}
if _, ok := uc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group", err: errors.New(`ent: missing required edge "User.group"`)}
}
return nil return nil
} }
@ -452,12 +460,12 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
_spec.SetField(user.FieldSettings, field.TypeJSON, value) _spec.SetField(user.FieldSettings, field.TypeJSON, value)
_node.Settings = value _node.Settings = value
} }
if nodes := uc.mutation.GroupIDs(); len(nodes) > 0 { if nodes := uc.mutation.GroupsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2M,
Inverse: true, Inverse: true,
Table: user.GroupTable, Table: user.GroupsTable,
Columns: []string{user.GroupColumn}, Columns: user.GroupsPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
@ -466,7 +474,10 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
_node.GroupUsers = nodes[0] createE := &UserGroupCreate{config: uc.config, mutation: newUserGroupMutation(uc.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges = append(_spec.Edges, edge) _spec.Edges = append(_spec.Edges, edge)
} }
if nodes := uc.mutation.FilesIDs(); len(nodes) > 0 { if nodes := uc.mutation.FilesIDs(); len(nodes) > 0 {
@ -565,6 +576,22 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
} }
_spec.Edges = append(_spec.Edges, edge) _spec.Edges = append(_spec.Edges, edge)
} }
if nodes := uc.mutation.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec return _node, _spec
} }
@ -773,18 +800,6 @@ func (u *UserUpsert) ClearSettings() *UserUpsert {
return u return u
} }
// SetGroupUsers sets the "group_users" field.
func (u *UserUpsert) SetGroupUsers(v int) *UserUpsert {
u.Set(user.FieldGroupUsers, v)
return u
}
// UpdateGroupUsers sets the "group_users" field to the value that was provided on create.
func (u *UserUpsert) UpdateGroupUsers() *UserUpsert {
u.SetExcluded(user.FieldGroupUsers)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create. // UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using: // Using this option is equivalent to using:
// //
@ -1012,20 +1027,6 @@ func (u *UserUpsertOne) ClearSettings() *UserUpsertOne {
}) })
} }
// SetGroupUsers sets the "group_users" field.
func (u *UserUpsertOne) SetGroupUsers(v int) *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.SetGroupUsers(v)
})
}
// UpdateGroupUsers sets the "group_users" field to the value that was provided on create.
func (u *UserUpsertOne) UpdateGroupUsers() *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.UpdateGroupUsers()
})
}
// Exec executes the query. // Exec executes the query.
func (u *UserUpsertOne) Exec(ctx context.Context) error { func (u *UserUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 { if len(u.create.conflict) == 0 {
@ -1424,20 +1425,6 @@ func (u *UserUpsertBulk) ClearSettings() *UserUpsertBulk {
}) })
} }
// SetGroupUsers sets the "group_users" field.
func (u *UserUpsertBulk) SetGroupUsers(v int) *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.SetGroupUsers(v)
})
}
// UpdateGroupUsers sets the "group_users" field to the value that was provided on create.
func (u *UserUpsertBulk) UpdateGroupUsers() *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.UpdateGroupUsers()
})
}
// Exec executes the query. // Exec executes the query.
func (u *UserUpsertBulk) Exec(ctx context.Context) error { func (u *UserUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil { if u.create.err != nil {

@ -20,6 +20,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/share" "github.com/cloudreve/Cloudreve/v4/ent/share"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
) )
// UserQuery is the builder for querying User entities. // UserQuery is the builder for querying User entities.
@ -29,13 +30,14 @@ type UserQuery struct {
order []user.OrderOption order []user.OrderOption
inters []Interceptor inters []Interceptor
predicates []predicate.User predicates []predicate.User
withGroup *GroupQuery withGroups *GroupQuery
withFiles *FileQuery withFiles *FileQuery
withDavAccounts *DavAccountQuery withDavAccounts *DavAccountQuery
withShares *ShareQuery withShares *ShareQuery
withPasskey *PasskeyQuery withPasskey *PasskeyQuery
withTasks *TaskQuery withTasks *TaskQuery
withEntities *EntityQuery withEntities *EntityQuery
withUserGroup *UserGroupQuery
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -72,8 +74,8 @@ func (uq *UserQuery) Order(o ...user.OrderOption) *UserQuery {
return uq return uq
} }
// QueryGroup chains the current query on the "group" edge. // QueryGroups chains the current query on the "groups" edge.
func (uq *UserQuery) QueryGroup() *GroupQuery { func (uq *UserQuery) QueryGroups() *GroupQuery {
query := (&GroupClient{config: uq.config}).Query() query := (&GroupClient{config: uq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := uq.prepareQuery(ctx); err != nil { if err := uq.prepareQuery(ctx); err != nil {
@ -86,7 +88,7 @@ func (uq *UserQuery) QueryGroup() *GroupQuery {
step := sqlgraph.NewStep( step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, selector), sqlgraph.From(user.Table, user.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID), sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, user.GroupTable, user.GroupColumn), sqlgraph.Edge(sqlgraph.M2M, true, user.GroupsTable, user.GroupsPrimaryKey...),
) )
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil return fromU, nil
@ -226,6 +228,28 @@ func (uq *UserQuery) QueryEntities() *EntityQuery {
return query return query
} }
// QueryUserGroup chains the current query on the "user_group" edge.
func (uq *UserQuery) QueryUserGroup() *UserGroupQuery {
query := (&UserGroupClient{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(usergroup.Table, usergroup.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, user.UserGroupTable, user.UserGroupColumn),
)
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first User entity from the query. // First returns the first User entity from the query.
// Returns a *NotFoundError when no User was found. // Returns a *NotFoundError when no User was found.
func (uq *UserQuery) First(ctx context.Context) (*User, error) { func (uq *UserQuery) First(ctx context.Context) (*User, error) {
@ -418,27 +442,28 @@ func (uq *UserQuery) Clone() *UserQuery {
order: append([]user.OrderOption{}, uq.order...), order: append([]user.OrderOption{}, uq.order...),
inters: append([]Interceptor{}, uq.inters...), inters: append([]Interceptor{}, uq.inters...),
predicates: append([]predicate.User{}, uq.predicates...), predicates: append([]predicate.User{}, uq.predicates...),
withGroup: uq.withGroup.Clone(), withGroups: uq.withGroups.Clone(),
withFiles: uq.withFiles.Clone(), withFiles: uq.withFiles.Clone(),
withDavAccounts: uq.withDavAccounts.Clone(), withDavAccounts: uq.withDavAccounts.Clone(),
withShares: uq.withShares.Clone(), withShares: uq.withShares.Clone(),
withPasskey: uq.withPasskey.Clone(), withPasskey: uq.withPasskey.Clone(),
withTasks: uq.withTasks.Clone(), withTasks: uq.withTasks.Clone(),
withEntities: uq.withEntities.Clone(), withEntities: uq.withEntities.Clone(),
withUserGroup: uq.withUserGroup.Clone(),
// clone intermediate query. // clone intermediate query.
sql: uq.sql.Clone(), sql: uq.sql.Clone(),
path: uq.path, path: uq.path,
} }
} }
// WithGroup tells the query-builder to eager-load the nodes that are connected to // WithGroups tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge. // the "groups" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithGroup(opts ...func(*GroupQuery)) *UserQuery { func (uq *UserQuery) WithGroups(opts ...func(*GroupQuery)) *UserQuery {
query := (&GroupClient{config: uq.config}).Query() query := (&GroupClient{config: uq.config}).Query()
for _, opt := range opts { for _, opt := range opts {
opt(query) opt(query)
} }
uq.withGroup = query uq.withGroups = query
return uq return uq
} }
@ -508,6 +533,17 @@ func (uq *UserQuery) WithEntities(opts ...func(*EntityQuery)) *UserQuery {
return uq return uq
} }
// WithUserGroup tells the query-builder to eager-load the nodes that are connected to
// the "user_group" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithUserGroup(opts ...func(*UserGroupQuery)) *UserQuery {
query := (&UserGroupClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withUserGroup = query
return uq
}
// GroupBy is used to group vertices by one or more fields/columns. // 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. // It is often used with aggregate functions, like: count, max, mean, min, sum.
// //
@ -586,14 +622,15 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
var ( var (
nodes = []*User{} nodes = []*User{}
_spec = uq.querySpec() _spec = uq.querySpec()
loadedTypes = [7]bool{ loadedTypes = [8]bool{
uq.withGroup != nil, uq.withGroups != nil,
uq.withFiles != nil, uq.withFiles != nil,
uq.withDavAccounts != nil, uq.withDavAccounts != nil,
uq.withShares != nil, uq.withShares != nil,
uq.withPasskey != nil, uq.withPasskey != nil,
uq.withTasks != nil, uq.withTasks != nil,
uq.withEntities != nil, uq.withEntities != nil,
uq.withUserGroup != nil,
} }
) )
_spec.ScanValues = func(columns []string) ([]any, error) { _spec.ScanValues = func(columns []string) ([]any, error) {
@ -614,9 +651,10 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
if len(nodes) == 0 { if len(nodes) == 0 {
return nodes, nil return nodes, nil
} }
if query := uq.withGroup; query != nil { if query := uq.withGroups; query != nil {
if err := uq.loadGroup(ctx, query, nodes, nil, if err := uq.loadGroups(ctx, query, nodes,
func(n *User, e *Group) { n.Edges.Group = e }); err != nil { func(n *User) { n.Edges.Groups = []*Group{} },
func(n *User, e *Group) { n.Edges.Groups = append(n.Edges.Groups, e) }); err != nil {
return nil, err return nil, err
} }
} }
@ -662,34 +700,73 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nil, err return nil, err
} }
} }
if query := uq.withUserGroup; query != nil {
if err := uq.loadUserGroup(ctx, query, nodes,
func(n *User) { n.Edges.UserGroup = []*UserGroup{} },
func(n *User, e *UserGroup) { n.Edges.UserGroup = append(n.Edges.UserGroup, e) }); err != nil {
return nil, err
}
}
return nodes, nil return nodes, nil
} }
func (uq *UserQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*User, init func(*User), assign func(*User, *Group)) error { func (uq *UserQuery) loadGroups(ctx context.Context, query *GroupQuery, nodes []*User, init func(*User), assign func(*User, *Group)) error {
ids := make([]int, 0, len(nodes)) edgeIDs := make([]driver.Value, len(nodes))
nodeids := make(map[int][]*User) byID := make(map[int]*User)
for i := range nodes { nids := make(map[int]map[*User]struct{})
fk := nodes[i].GroupUsers for i, node := range nodes {
if _, ok := nodeids[fk]; !ok { edgeIDs[i] = node.ID
ids = append(ids, fk) byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(user.GroupsTable)
s.Join(joinT).On(s.C(group.FieldID), joinT.C(user.GroupsPrimaryKey[0]))
s.Where(sql.InValues(joinT.C(user.GroupsPrimaryKey[1]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(user.GroupsPrimaryKey[1]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
} }
nodeids[fk] = append(nodeids[fk], nodes[i]) qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
} }
if len(ids) == 0 { return append([]any{new(sql.NullInt64)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := int(values[0].(*sql.NullInt64).Int64)
inValue := int(values[1].(*sql.NullInt64).Int64)
if nids[inValue] == nil {
nids[inValue] = map[*User]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil return nil
} }
query.Where(group.IDIn(ids...)) })
neighbors, err := query.All(ctx) })
neighbors, err := withInterceptors[[]*Group](ctx, query, qr, query.inters)
if err != nil { if err != nil {
return err return err
} }
for _, n := range neighbors { for _, n := range neighbors {
nodes, ok := nodeids[n.ID] nodes, ok := nids[n.ID]
if !ok { if !ok {
return fmt.Errorf(`unexpected foreign-key "group_users" returned %v`, n.ID) return fmt.Errorf(`unexpected "groups" node returned %v`, n.ID)
} }
for i := range nodes { for kn := range nodes {
assign(nodes[i], n) assign(kn, n)
} }
} }
return nil return nil
@ -875,6 +952,36 @@ func (uq *UserQuery) loadEntities(ctx context.Context, query *EntityQuery, nodes
} }
return nil return nil
} }
func (uq *UserQuery) loadUserGroup(ctx context.Context, query *UserGroupQuery, nodes []*User, init func(*User), assign func(*User, *UserGroup)) 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(usergroup.FieldUserID)
}
query.Where(predicate.UserGroup(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(user.UserGroupColumn), 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) { func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
_spec := uq.querySpec() _spec := uq.querySpec()
@ -901,9 +1008,6 @@ func (uq *UserQuery) querySpec() *sqlgraph.QuerySpec {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i]) _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
} }
} }
if uq.withGroup != nil {
_spec.Node.AddColumnOnce(user.FieldGroupUsers)
}
} }
if ps := uq.predicates; len(ps) > 0 { if ps := uq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) { _spec.Predicate = func(selector *sql.Selector) {

@ -20,6 +20,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent/share" "github.com/cloudreve/Cloudreve/v4/ent/share"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
) )
@ -197,29 +198,19 @@ func (uu *UserUpdate) ClearSettings() *UserUpdate {
return uu return uu
} }
// SetGroupUsers sets the "group_users" field. // AddGroupIDs adds the "groups" edge to the Group entity by IDs.
func (uu *UserUpdate) SetGroupUsers(i int) *UserUpdate { func (uu *UserUpdate) AddGroupIDs(ids ...int) *UserUpdate {
uu.mutation.SetGroupUsers(i) uu.mutation.AddGroupIDs(ids...)
return uu return uu
} }
// SetNillableGroupUsers sets the "group_users" field if the given value is not nil. // AddGroups adds the "groups" edges to the Group entity.
func (uu *UserUpdate) SetNillableGroupUsers(i *int) *UserUpdate { func (uu *UserUpdate) AddGroups(g ...*Group) *UserUpdate {
if i != nil { ids := make([]int, len(g))
uu.SetGroupUsers(*i) for i := range g {
ids[i] = g[i].ID
} }
return uu return uu.AddGroupIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (uu *UserUpdate) SetGroupID(id int) *UserUpdate {
uu.mutation.SetGroupID(id)
return uu
}
// SetGroup sets the "group" edge to the Group entity.
func (uu *UserUpdate) SetGroup(g *Group) *UserUpdate {
return uu.SetGroupID(g.ID)
} }
// AddFileIDs adds the "files" edge to the File entity by IDs. // AddFileIDs adds the "files" edge to the File entity by IDs.
@ -312,17 +303,47 @@ func (uu *UserUpdate) AddEntities(e ...*Entity) *UserUpdate {
return uu.AddEntityIDs(ids...) return uu.AddEntityIDs(ids...)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (uu *UserUpdate) AddUserGroupIDs(ids ...int) *UserUpdate {
uu.mutation.AddUserGroupIDs(ids...)
return uu
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (uu *UserUpdate) AddUserGroup(u ...*UserGroup) *UserUpdate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return uu.AddUserGroupIDs(ids...)
}
// Mutation returns the UserMutation object of the builder. // Mutation returns the UserMutation object of the builder.
func (uu *UserUpdate) Mutation() *UserMutation { func (uu *UserUpdate) Mutation() *UserMutation {
return uu.mutation return uu.mutation
} }
// ClearGroup clears the "group" edge to the Group entity. // ClearGroups clears all "groups" edges to the Group entity.
func (uu *UserUpdate) ClearGroup() *UserUpdate { func (uu *UserUpdate) ClearGroups() *UserUpdate {
uu.mutation.ClearGroup() uu.mutation.ClearGroups()
return uu return uu
} }
// RemoveGroupIDs removes the "groups" edge to Group entities by IDs.
func (uu *UserUpdate) RemoveGroupIDs(ids ...int) *UserUpdate {
uu.mutation.RemoveGroupIDs(ids...)
return uu
}
// RemoveGroups removes "groups" edges to Group entities.
func (uu *UserUpdate) RemoveGroups(g ...*Group) *UserUpdate {
ids := make([]int, len(g))
for i := range g {
ids[i] = g[i].ID
}
return uu.RemoveGroupIDs(ids...)
}
// ClearFiles clears all "files" edges to the File entity. // ClearFiles clears all "files" edges to the File entity.
func (uu *UserUpdate) ClearFiles() *UserUpdate { func (uu *UserUpdate) ClearFiles() *UserUpdate {
uu.mutation.ClearFiles() uu.mutation.ClearFiles()
@ -449,6 +470,27 @@ func (uu *UserUpdate) RemoveEntities(e ...*Entity) *UserUpdate {
return uu.RemoveEntityIDs(ids...) return uu.RemoveEntityIDs(ids...)
} }
// ClearUserGroup clears all "user_group" edges to the UserGroup entity.
func (uu *UserUpdate) ClearUserGroup() *UserUpdate {
uu.mutation.ClearUserGroup()
return uu
}
// RemoveUserGroupIDs removes the "user_group" edge to UserGroup entities by IDs.
func (uu *UserUpdate) RemoveUserGroupIDs(ids ...int) *UserUpdate {
uu.mutation.RemoveUserGroupIDs(ids...)
return uu
}
// RemoveUserGroup removes "user_group" edges to UserGroup entities.
func (uu *UserUpdate) RemoveUserGroup(u ...*UserGroup) *UserUpdate {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return uu.RemoveUserGroupIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation. // Save executes the query and returns the number of nodes affected by the update operation.
func (uu *UserUpdate) Save(ctx context.Context) (int, error) { func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
if err := uu.defaults(); err != nil { if err := uu.defaults(); err != nil {
@ -508,9 +550,6 @@ func (uu *UserUpdate) check() error {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "User.status": %w`, err)} return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "User.status": %w`, err)}
} }
} }
if _, ok := uu.mutation.GroupID(); uu.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "User.group"`)
}
return nil return nil
} }
@ -574,25 +613,49 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if uu.mutation.SettingsCleared() { if uu.mutation.SettingsCleared() {
_spec.ClearField(user.FieldSettings, field.TypeJSON) _spec.ClearField(user.FieldSettings, field.TypeJSON)
} }
if uu.mutation.GroupCleared() { if uu.mutation.GroupsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.GroupsTable,
Columns: user.GroupsPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
createE := &UserGroupCreate{config: uu.config, mutation: newUserGroupMutation(uu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedGroupsIDs(); len(nodes) > 0 && !uu.mutation.GroupsCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2M,
Inverse: true, Inverse: true,
Table: user.GroupTable, Table: user.GroupsTable,
Columns: []string{user.GroupColumn}, Columns: user.GroupsPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
}, },
} }
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
createE := &UserGroupCreate{config: uu.config, mutation: newUserGroupMutation(uu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := uu.mutation.GroupIDs(); len(nodes) > 0 { if nodes := uu.mutation.GroupsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2M,
Inverse: true, Inverse: true,
Table: user.GroupTable, Table: user.GroupsTable,
Columns: []string{user.GroupColumn}, Columns: user.GroupsPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
@ -601,6 +664,10 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: uu.config, mutation: newUserGroupMutation(uu.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if uu.mutation.FilesCleared() { if uu.mutation.FilesCleared() {
@ -873,6 +940,51 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
} }
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if uu.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedUserGroupIDs(); len(nodes) > 0 && !uu.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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 n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok { if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label} err = &NotFoundError{user.Label}
@ -1054,29 +1166,19 @@ func (uuo *UserUpdateOne) ClearSettings() *UserUpdateOne {
return uuo return uuo
} }
// SetGroupUsers sets the "group_users" field. // AddGroupIDs adds the "groups" edge to the Group entity by IDs.
func (uuo *UserUpdateOne) SetGroupUsers(i int) *UserUpdateOne { func (uuo *UserUpdateOne) AddGroupIDs(ids ...int) *UserUpdateOne {
uuo.mutation.SetGroupUsers(i) uuo.mutation.AddGroupIDs(ids...)
return uuo return uuo
} }
// SetNillableGroupUsers sets the "group_users" field if the given value is not nil. // AddGroups adds the "groups" edges to the Group entity.
func (uuo *UserUpdateOne) SetNillableGroupUsers(i *int) *UserUpdateOne { func (uuo *UserUpdateOne) AddGroups(g ...*Group) *UserUpdateOne {
if i != nil { ids := make([]int, len(g))
uuo.SetGroupUsers(*i) for i := range g {
ids[i] = g[i].ID
} }
return uuo return uuo.AddGroupIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (uuo *UserUpdateOne) SetGroupID(id int) *UserUpdateOne {
uuo.mutation.SetGroupID(id)
return uuo
}
// SetGroup sets the "group" edge to the Group entity.
func (uuo *UserUpdateOne) SetGroup(g *Group) *UserUpdateOne {
return uuo.SetGroupID(g.ID)
} }
// AddFileIDs adds the "files" edge to the File entity by IDs. // AddFileIDs adds the "files" edge to the File entity by IDs.
@ -1169,17 +1271,47 @@ func (uuo *UserUpdateOne) AddEntities(e ...*Entity) *UserUpdateOne {
return uuo.AddEntityIDs(ids...) return uuo.AddEntityIDs(ids...)
} }
// AddUserGroupIDs adds the "user_group" edge to the UserGroup entity by IDs.
func (uuo *UserUpdateOne) AddUserGroupIDs(ids ...int) *UserUpdateOne {
uuo.mutation.AddUserGroupIDs(ids...)
return uuo
}
// AddUserGroup adds the "user_group" edges to the UserGroup entity.
func (uuo *UserUpdateOne) AddUserGroup(u ...*UserGroup) *UserUpdateOne {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return uuo.AddUserGroupIDs(ids...)
}
// Mutation returns the UserMutation object of the builder. // Mutation returns the UserMutation object of the builder.
func (uuo *UserUpdateOne) Mutation() *UserMutation { func (uuo *UserUpdateOne) Mutation() *UserMutation {
return uuo.mutation return uuo.mutation
} }
// ClearGroup clears the "group" edge to the Group entity. // ClearGroups clears all "groups" edges to the Group entity.
func (uuo *UserUpdateOne) ClearGroup() *UserUpdateOne { func (uuo *UserUpdateOne) ClearGroups() *UserUpdateOne {
uuo.mutation.ClearGroup() uuo.mutation.ClearGroups()
return uuo return uuo
} }
// RemoveGroupIDs removes the "groups" edge to Group entities by IDs.
func (uuo *UserUpdateOne) RemoveGroupIDs(ids ...int) *UserUpdateOne {
uuo.mutation.RemoveGroupIDs(ids...)
return uuo
}
// RemoveGroups removes "groups" edges to Group entities.
func (uuo *UserUpdateOne) RemoveGroups(g ...*Group) *UserUpdateOne {
ids := make([]int, len(g))
for i := range g {
ids[i] = g[i].ID
}
return uuo.RemoveGroupIDs(ids...)
}
// ClearFiles clears all "files" edges to the File entity. // ClearFiles clears all "files" edges to the File entity.
func (uuo *UserUpdateOne) ClearFiles() *UserUpdateOne { func (uuo *UserUpdateOne) ClearFiles() *UserUpdateOne {
uuo.mutation.ClearFiles() uuo.mutation.ClearFiles()
@ -1306,6 +1438,27 @@ func (uuo *UserUpdateOne) RemoveEntities(e ...*Entity) *UserUpdateOne {
return uuo.RemoveEntityIDs(ids...) return uuo.RemoveEntityIDs(ids...)
} }
// ClearUserGroup clears all "user_group" edges to the UserGroup entity.
func (uuo *UserUpdateOne) ClearUserGroup() *UserUpdateOne {
uuo.mutation.ClearUserGroup()
return uuo
}
// RemoveUserGroupIDs removes the "user_group" edge to UserGroup entities by IDs.
func (uuo *UserUpdateOne) RemoveUserGroupIDs(ids ...int) *UserUpdateOne {
uuo.mutation.RemoveUserGroupIDs(ids...)
return uuo
}
// RemoveUserGroup removes "user_group" edges to UserGroup entities.
func (uuo *UserUpdateOne) RemoveUserGroup(u ...*UserGroup) *UserUpdateOne {
ids := make([]int, len(u))
for i := range u {
ids[i] = u[i].ID
}
return uuo.RemoveUserGroupIDs(ids...)
}
// Where appends a list predicates to the UserUpdate builder. // Where appends a list predicates to the UserUpdate builder.
func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne { func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
uuo.mutation.Where(ps...) uuo.mutation.Where(ps...)
@ -1378,9 +1531,6 @@ func (uuo *UserUpdateOne) check() error {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "User.status": %w`, err)} return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "User.status": %w`, err)}
} }
} }
if _, ok := uuo.mutation.GroupID(); uuo.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "User.group"`)
}
return nil return nil
} }
@ -1461,25 +1611,49 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
if uuo.mutation.SettingsCleared() { if uuo.mutation.SettingsCleared() {
_spec.ClearField(user.FieldSettings, field.TypeJSON) _spec.ClearField(user.FieldSettings, field.TypeJSON)
} }
if uuo.mutation.GroupCleared() { if uuo.mutation.GroupsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.GroupsTable,
Columns: user.GroupsPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
createE := &UserGroupCreate{config: uuo.config, mutation: newUserGroupMutation(uuo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedGroupsIDs(); len(nodes) > 0 && !uuo.mutation.GroupsCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2M,
Inverse: true, Inverse: true,
Table: user.GroupTable, Table: user.GroupsTable,
Columns: []string{user.GroupColumn}, Columns: user.GroupsPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
}, },
} }
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
createE := &UserGroupCreate{config: uuo.config, mutation: newUserGroupMutation(uuo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Clear = append(_spec.Edges.Clear, edge) _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
} }
if nodes := uuo.mutation.GroupIDs(); len(nodes) > 0 { if nodes := uuo.mutation.GroupsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2M,
Inverse: true, Inverse: true,
Table: user.GroupTable, Table: user.GroupsTable,
Columns: []string{user.GroupColumn}, Columns: user.GroupsPrimaryKey,
Bidi: false, Bidi: false,
Target: &sqlgraph.EdgeTarget{ Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt), IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
@ -1488,6 +1662,10 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
for _, k := range nodes { for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k) edge.Target.Nodes = append(edge.Target.Nodes, k)
} }
createE := &UserGroupCreate{config: uuo.config, mutation: newUserGroupMutation(uuo.config, OpCreate)}
createE.defaults()
_, specE := createE.createSpec()
edge.Target.Fields = specE.Fields
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if uuo.mutation.FilesCleared() { if uuo.mutation.FilesCleared() {
@ -1760,6 +1938,51 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
} }
_spec.Edges.Add = append(_spec.Edges.Add, edge) _spec.Edges.Add = append(_spec.Edges.Add, edge)
} }
if uuo.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedUserGroupIDs(); len(nodes) > 0 && !uuo.mutation.UserGroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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.UserGroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.UserGroupTable,
Columns: []string{user.UserGroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(usergroup.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} _node = &User{config: uuo.config}
_spec.Assign = _node.assignValues _spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues _spec.ScanValues = _node.scanValues

@ -0,0 +1,206 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/cloudreve/Cloudreve/v4/ent/group"
"github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
)
// UserGroup is the model entity for the UserGroup schema.
type UserGroup struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// UserID holds the value of the "user_id" field.
UserID int `json:"user_id,omitempty"`
// GroupID holds the value of the "group_id" field.
GroupID int `json:"group_id,omitempty"`
// IsPrimary holds the value of the "is_primary" field.
IsPrimary bool `json:"is_primary,omitempty"`
// ExpiresAt holds the value of the "expires_at" field.
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the UserGroupQuery when eager-loading is set.
Edges UserGroupEdges `json:"edges"`
selectValues sql.SelectValues
}
// UserGroupEdges holds the relations/edges for other nodes in the graph.
type UserGroupEdges struct {
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// Group holds the value of the group edge.
Group *Group `json:"group,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 UserGroupEdges) 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"}
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e UserGroupEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[1] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*UserGroup) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case usergroup.FieldIsPrimary:
values[i] = new(sql.NullBool)
case usergroup.FieldID, usergroup.FieldUserID, usergroup.FieldGroupID:
values[i] = new(sql.NullInt64)
case usergroup.FieldExpiresAt:
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 UserGroup fields.
func (ug *UserGroup) 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 usergroup.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
ug.ID = int(value.Int64)
case usergroup.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 {
ug.UserID = int(value.Int64)
}
case usergroup.FieldGroupID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field group_id", values[i])
} else if value.Valid {
ug.GroupID = int(value.Int64)
}
case usergroup.FieldIsPrimary:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field is_primary", values[i])
} else if value.Valid {
ug.IsPrimary = value.Bool
}
case usergroup.FieldExpiresAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field expires_at", values[i])
} else if value.Valid {
ug.ExpiresAt = new(time.Time)
*ug.ExpiresAt = value.Time
}
default:
ug.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the UserGroup.
// This includes values selected through modifiers, order, etc.
func (ug *UserGroup) Value(name string) (ent.Value, error) {
return ug.selectValues.Get(name)
}
// QueryUser queries the "user" edge of the UserGroup entity.
func (ug *UserGroup) QueryUser() *UserQuery {
return NewUserGroupClient(ug.config).QueryUser(ug)
}
// QueryGroup queries the "group" edge of the UserGroup entity.
func (ug *UserGroup) QueryGroup() *GroupQuery {
return NewUserGroupClient(ug.config).QueryGroup(ug)
}
// Update returns a builder for updating this UserGroup.
// Note that you need to call UserGroup.Unwrap() before calling this method if this UserGroup
// was returned from a transaction, and the transaction was committed or rolled back.
func (ug *UserGroup) Update() *UserGroupUpdateOne {
return NewUserGroupClient(ug.config).UpdateOne(ug)
}
// Unwrap unwraps the UserGroup 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 (ug *UserGroup) Unwrap() *UserGroup {
_tx, ok := ug.config.driver.(*txDriver)
if !ok {
panic("ent: UserGroup is not a transactional entity")
}
ug.config.driver = _tx.drv
return ug
}
// String implements the fmt.Stringer.
func (ug *UserGroup) String() string {
var builder strings.Builder
builder.WriteString("UserGroup(")
builder.WriteString(fmt.Sprintf("id=%v, ", ug.ID))
builder.WriteString("user_id=")
builder.WriteString(fmt.Sprintf("%v", ug.UserID))
builder.WriteString(", ")
builder.WriteString("group_id=")
builder.WriteString(fmt.Sprintf("%v", ug.GroupID))
builder.WriteString(", ")
builder.WriteString("is_primary=")
builder.WriteString(fmt.Sprintf("%v", ug.IsPrimary))
builder.WriteString(", ")
if v := ug.ExpiresAt; v != nil {
builder.WriteString("expires_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteByte(')')
return builder.String()
}
// SetUser manually set the edge as loaded state.
func (e *UserGroup) SetUser(v *User) {
e.Edges.User = v
e.Edges.loadedTypes[0] = true
}
// SetGroup manually set the edge as loaded state.
func (e *UserGroup) SetGroup(v *Group) {
e.Edges.Group = v
e.Edges.loadedTypes[1] = true
}
// UserGroups is a parsable slice of UserGroup.
type UserGroups []*UserGroup

@ -0,0 +1,123 @@
// Code generated by ent, DO NOT EDIT.
package usergroup
import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
const (
// Label holds the string label denoting the usergroup type in the database.
Label = "user_group"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldUserID holds the string denoting the user_id field in the database.
FieldUserID = "user_id"
// FieldGroupID holds the string denoting the group_id field in the database.
FieldGroupID = "group_id"
// FieldIsPrimary holds the string denoting the is_primary field in the database.
FieldIsPrimary = "is_primary"
// FieldExpiresAt holds the string denoting the expires_at field in the database.
FieldExpiresAt = "expires_at"
// EdgeUser holds the string denoting the user edge name in mutations.
EdgeUser = "user"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// Table holds the table name of the usergroup in the database.
Table = "user_groups"
// UserTable is the table that holds the user relation/edge.
UserTable = "user_groups"
// 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"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "user_groups"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_id"
)
// Columns holds all SQL columns for usergroup fields.
var Columns = []string{
FieldID,
FieldUserID,
FieldGroupID,
FieldIsPrimary,
FieldExpiresAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultIsPrimary holds the default value on creation for the "is_primary" field.
DefaultIsPrimary bool
)
// OrderOption defines the ordering options for the UserGroup 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()
}
// ByUserID orders the results by the user_id field.
func ByUserID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserID, opts...).ToFunc()
}
// ByGroupID orders the results by the group_id field.
func ByGroupID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldGroupID, opts...).ToFunc()
}
// ByIsPrimary orders the results by the is_primary field.
func ByIsPrimary(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldIsPrimary, opts...).ToFunc()
}
// ByExpiresAt orders the results by the expires_at field.
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldExpiresAt, 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...))
}
}
// ByGroupField orders the results by group field.
func ByGroupField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newGroupStep(), sql.OrderByField(field, opts...))
}
}
func newUserStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn),
)
}
func newGroupStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, GroupTable, GroupColumn),
)
}

@ -0,0 +1,237 @@
// Code generated by ent, DO NOT EDIT.
package usergroup
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.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldLTE(FieldID, id))
}
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
func UserID(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldUserID, v))
}
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
func GroupID(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldGroupID, v))
}
// IsPrimary applies equality check predicate on the "is_primary" field. It's identical to IsPrimaryEQ.
func IsPrimary(v bool) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldIsPrimary, v))
}
// ExpiresAt applies equality check predicate on the "expires_at" field. It's identical to ExpiresAtEQ.
func ExpiresAt(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldExpiresAt, v))
}
// UserIDEQ applies the EQ predicate on the "user_id" field.
func UserIDEQ(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldUserID, v))
}
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
func UserIDNEQ(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNEQ(FieldUserID, v))
}
// UserIDIn applies the In predicate on the "user_id" field.
func UserIDIn(vs ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldIn(FieldUserID, vs...))
}
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
func UserIDNotIn(vs ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNotIn(FieldUserID, vs...))
}
// GroupIDEQ applies the EQ predicate on the "group_id" field.
func GroupIDEQ(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldGroupID, v))
}
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
func GroupIDNEQ(v int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNEQ(FieldGroupID, v))
}
// GroupIDIn applies the In predicate on the "group_id" field.
func GroupIDIn(vs ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldIn(FieldGroupID, vs...))
}
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
func GroupIDNotIn(vs ...int) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNotIn(FieldGroupID, vs...))
}
// IsPrimaryEQ applies the EQ predicate on the "is_primary" field.
func IsPrimaryEQ(v bool) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldIsPrimary, v))
}
// IsPrimaryNEQ applies the NEQ predicate on the "is_primary" field.
func IsPrimaryNEQ(v bool) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNEQ(FieldIsPrimary, v))
}
// ExpiresAtEQ applies the EQ predicate on the "expires_at" field.
func ExpiresAtEQ(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldEQ(FieldExpiresAt, v))
}
// ExpiresAtNEQ applies the NEQ predicate on the "expires_at" field.
func ExpiresAtNEQ(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNEQ(FieldExpiresAt, v))
}
// ExpiresAtIn applies the In predicate on the "expires_at" field.
func ExpiresAtIn(vs ...time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldIn(FieldExpiresAt, vs...))
}
// ExpiresAtNotIn applies the NotIn predicate on the "expires_at" field.
func ExpiresAtNotIn(vs ...time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldNotIn(FieldExpiresAt, vs...))
}
// ExpiresAtGT applies the GT predicate on the "expires_at" field.
func ExpiresAtGT(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldGT(FieldExpiresAt, v))
}
// ExpiresAtGTE applies the GTE predicate on the "expires_at" field.
func ExpiresAtGTE(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldGTE(FieldExpiresAt, v))
}
// ExpiresAtLT applies the LT predicate on the "expires_at" field.
func ExpiresAtLT(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldLT(FieldExpiresAt, v))
}
// ExpiresAtLTE applies the LTE predicate on the "expires_at" field.
func ExpiresAtLTE(v time.Time) predicate.UserGroup {
return predicate.UserGroup(sql.FieldLTE(FieldExpiresAt, v))
}
// ExpiresAtIsNil applies the IsNil predicate on the "expires_at" field.
func ExpiresAtIsNil() predicate.UserGroup {
return predicate.UserGroup(sql.FieldIsNull(FieldExpiresAt))
}
// ExpiresAtNotNil applies the NotNil predicate on the "expires_at" field.
func ExpiresAtNotNil() predicate.UserGroup {
return predicate.UserGroup(sql.FieldNotNull(FieldExpiresAt))
}
// HasUser applies the HasEdge predicate on the "user" edge.
func HasUser() predicate.UserGroup {
return predicate.UserGroup(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
func HasUserWith(preds ...predicate.User) predicate.UserGroup {
return predicate.UserGroup(func(s *sql.Selector) {
step := newUserStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.UserGroup {
return predicate.UserGroup(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.UserGroup {
return predicate.UserGroup(func(s *sql.Selector) {
step := newGroupStep()
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.UserGroup) predicate.UserGroup {
return predicate.UserGroup(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.UserGroup) predicate.UserGroup {
return predicate.UserGroup(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.UserGroup) predicate.UserGroup {
return predicate.UserGroup(sql.NotPredicates(p))
}

@ -0,0 +1,713 @@
// 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/group"
"github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
)
// UserGroupCreate is the builder for creating a UserGroup entity.
type UserGroupCreate struct {
config
mutation *UserGroupMutation
hooks []Hook
conflict []sql.ConflictOption
}
// SetUserID sets the "user_id" field.
func (ugc *UserGroupCreate) SetUserID(i int) *UserGroupCreate {
ugc.mutation.SetUserID(i)
return ugc
}
// SetGroupID sets the "group_id" field.
func (ugc *UserGroupCreate) SetGroupID(i int) *UserGroupCreate {
ugc.mutation.SetGroupID(i)
return ugc
}
// SetIsPrimary sets the "is_primary" field.
func (ugc *UserGroupCreate) SetIsPrimary(b bool) *UserGroupCreate {
ugc.mutation.SetIsPrimary(b)
return ugc
}
// SetNillableIsPrimary sets the "is_primary" field if the given value is not nil.
func (ugc *UserGroupCreate) SetNillableIsPrimary(b *bool) *UserGroupCreate {
if b != nil {
ugc.SetIsPrimary(*b)
}
return ugc
}
// SetExpiresAt sets the "expires_at" field.
func (ugc *UserGroupCreate) SetExpiresAt(t time.Time) *UserGroupCreate {
ugc.mutation.SetExpiresAt(t)
return ugc
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (ugc *UserGroupCreate) SetNillableExpiresAt(t *time.Time) *UserGroupCreate {
if t != nil {
ugc.SetExpiresAt(*t)
}
return ugc
}
// SetUser sets the "user" edge to the User entity.
func (ugc *UserGroupCreate) SetUser(u *User) *UserGroupCreate {
return ugc.SetUserID(u.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (ugc *UserGroupCreate) SetGroup(g *Group) *UserGroupCreate {
return ugc.SetGroupID(g.ID)
}
// Mutation returns the UserGroupMutation object of the builder.
func (ugc *UserGroupCreate) Mutation() *UserGroupMutation {
return ugc.mutation
}
// Save creates the UserGroup in the database.
func (ugc *UserGroupCreate) Save(ctx context.Context) (*UserGroup, error) {
ugc.defaults()
return withHooks(ctx, ugc.sqlSave, ugc.mutation, ugc.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (ugc *UserGroupCreate) SaveX(ctx context.Context) *UserGroup {
v, err := ugc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ugc *UserGroupCreate) Exec(ctx context.Context) error {
_, err := ugc.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ugc *UserGroupCreate) ExecX(ctx context.Context) {
if err := ugc.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (ugc *UserGroupCreate) defaults() {
if _, ok := ugc.mutation.IsPrimary(); !ok {
v := usergroup.DefaultIsPrimary
ugc.mutation.SetIsPrimary(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (ugc *UserGroupCreate) check() error {
if _, ok := ugc.mutation.UserID(); !ok {
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "UserGroup.user_id"`)}
}
if _, ok := ugc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group_id", err: errors.New(`ent: missing required field "UserGroup.group_id"`)}
}
if _, ok := ugc.mutation.IsPrimary(); !ok {
return &ValidationError{Name: "is_primary", err: errors.New(`ent: missing required field "UserGroup.is_primary"`)}
}
if _, ok := ugc.mutation.UserID(); !ok {
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "UserGroup.user"`)}
}
if _, ok := ugc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group", err: errors.New(`ent: missing required edge "UserGroup.group"`)}
}
return nil
}
func (ugc *UserGroupCreate) sqlSave(ctx context.Context) (*UserGroup, error) {
if err := ugc.check(); err != nil {
return nil, err
}
_node, _spec := ugc.createSpec()
if err := sqlgraph.CreateNode(ctx, ugc.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)
ugc.mutation.id = &_node.ID
ugc.mutation.done = true
return _node, nil
}
func (ugc *UserGroupCreate) createSpec() (*UserGroup, *sqlgraph.CreateSpec) {
var (
_node = &UserGroup{config: ugc.config}
_spec = sqlgraph.NewCreateSpec(usergroup.Table, sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt))
)
if id, ok := ugc.mutation.ID(); ok {
_node.ID = id
id64 := int64(id)
_spec.ID.Value = id64
}
_spec.OnConflict = ugc.conflict
if value, ok := ugc.mutation.IsPrimary(); ok {
_spec.SetField(usergroup.FieldIsPrimary, field.TypeBool, value)
_node.IsPrimary = value
}
if value, ok := ugc.mutation.ExpiresAt(); ok {
_spec.SetField(usergroup.FieldExpiresAt, field.TypeTime, value)
_node.ExpiresAt = &value
}
if nodes := ugc.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.UserTable,
Columns: []string{usergroup.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 := ugc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.GroupTable,
Columns: []string{usergroup.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.GroupID = 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.UserGroup.Create().
// SetUserID(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.UserGroupUpsert) {
// SetUserID(v+v).
// }).
// Exec(ctx)
func (ugc *UserGroupCreate) OnConflict(opts ...sql.ConflictOption) *UserGroupUpsertOne {
ugc.conflict = opts
return &UserGroupUpsertOne{
create: ugc,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (ugc *UserGroupCreate) OnConflictColumns(columns ...string) *UserGroupUpsertOne {
ugc.conflict = append(ugc.conflict, sql.ConflictColumns(columns...))
return &UserGroupUpsertOne{
create: ugc,
}
}
type (
// UserGroupUpsertOne is the builder for "upsert"-ing
// one UserGroup node.
UserGroupUpsertOne struct {
create *UserGroupCreate
}
// UserGroupUpsert is the "OnConflict" setter.
UserGroupUpsert struct {
*sql.UpdateSet
}
)
// SetUserID sets the "user_id" field.
func (u *UserGroupUpsert) SetUserID(v int) *UserGroupUpsert {
u.Set(usergroup.FieldUserID, v)
return u
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *UserGroupUpsert) UpdateUserID() *UserGroupUpsert {
u.SetExcluded(usergroup.FieldUserID)
return u
}
// SetGroupID sets the "group_id" field.
func (u *UserGroupUpsert) SetGroupID(v int) *UserGroupUpsert {
u.Set(usergroup.FieldGroupID, v)
return u
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *UserGroupUpsert) UpdateGroupID() *UserGroupUpsert {
u.SetExcluded(usergroup.FieldGroupID)
return u
}
// SetIsPrimary sets the "is_primary" field.
func (u *UserGroupUpsert) SetIsPrimary(v bool) *UserGroupUpsert {
u.Set(usergroup.FieldIsPrimary, v)
return u
}
// UpdateIsPrimary sets the "is_primary" field to the value that was provided on create.
func (u *UserGroupUpsert) UpdateIsPrimary() *UserGroupUpsert {
u.SetExcluded(usergroup.FieldIsPrimary)
return u
}
// SetExpiresAt sets the "expires_at" field.
func (u *UserGroupUpsert) SetExpiresAt(v time.Time) *UserGroupUpsert {
u.Set(usergroup.FieldExpiresAt, v)
return u
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *UserGroupUpsert) UpdateExpiresAt() *UserGroupUpsert {
u.SetExcluded(usergroup.FieldExpiresAt)
return u
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *UserGroupUpsert) ClearExpiresAt() *UserGroupUpsert {
u.SetNull(usergroup.FieldExpiresAt)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *UserGroupUpsertOne) UpdateNewValues() *UserGroupUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *UserGroupUpsertOne) Ignore() *UserGroupUpsertOne {
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 *UserGroupUpsertOne) DoNothing() *UserGroupUpsertOne {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the UserGroupCreate.OnConflict
// documentation for more info.
func (u *UserGroupUpsertOne) Update(set func(*UserGroupUpsert)) *UserGroupUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&UserGroupUpsert{UpdateSet: update})
}))
return u
}
// SetUserID sets the "user_id" field.
func (u *UserGroupUpsertOne) SetUserID(v int) *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.SetUserID(v)
})
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *UserGroupUpsertOne) UpdateUserID() *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateUserID()
})
}
// SetGroupID sets the "group_id" field.
func (u *UserGroupUpsertOne) SetGroupID(v int) *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.SetGroupID(v)
})
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *UserGroupUpsertOne) UpdateGroupID() *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateGroupID()
})
}
// SetIsPrimary sets the "is_primary" field.
func (u *UserGroupUpsertOne) SetIsPrimary(v bool) *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.SetIsPrimary(v)
})
}
// UpdateIsPrimary sets the "is_primary" field to the value that was provided on create.
func (u *UserGroupUpsertOne) UpdateIsPrimary() *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateIsPrimary()
})
}
// SetExpiresAt sets the "expires_at" field.
func (u *UserGroupUpsertOne) SetExpiresAt(v time.Time) *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.SetExpiresAt(v)
})
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *UserGroupUpsertOne) UpdateExpiresAt() *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateExpiresAt()
})
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *UserGroupUpsertOne) ClearExpiresAt() *UserGroupUpsertOne {
return u.Update(func(s *UserGroupUpsert) {
s.ClearExpiresAt()
})
}
// Exec executes the query.
func (u *UserGroupUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for UserGroupCreate.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *UserGroupUpsertOne) 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 *UserGroupUpsertOne) 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 *UserGroupUpsertOne) IDX(ctx context.Context) int {
id, err := u.ID(ctx)
if err != nil {
panic(err)
}
return id
}
func (m *UserGroupCreate) SetRawID(t int) *UserGroupCreate {
m.mutation.SetRawID(t)
return m
}
// UserGroupCreateBulk is the builder for creating many UserGroup entities in bulk.
type UserGroupCreateBulk struct {
config
err error
builders []*UserGroupCreate
conflict []sql.ConflictOption
}
// Save creates the UserGroup entities in the database.
func (ugcb *UserGroupCreateBulk) Save(ctx context.Context) ([]*UserGroup, error) {
if ugcb.err != nil {
return nil, ugcb.err
}
specs := make([]*sqlgraph.CreateSpec, len(ugcb.builders))
nodes := make([]*UserGroup, len(ugcb.builders))
mutators := make([]Mutator, len(ugcb.builders))
for i := range ugcb.builders {
func(i int, root context.Context) {
builder := ugcb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*UserGroupMutation)
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, ugcb.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
spec.OnConflict = ugcb.conflict
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, ugcb.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, ugcb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (ugcb *UserGroupCreateBulk) SaveX(ctx context.Context) []*UserGroup {
v, err := ugcb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ugcb *UserGroupCreateBulk) Exec(ctx context.Context) error {
_, err := ugcb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ugcb *UserGroupCreateBulk) ExecX(ctx context.Context) {
if err := ugcb.Exec(ctx); err != nil {
panic(err)
}
}
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.UserGroup.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.UserGroupUpsert) {
// SetUserID(v+v).
// }).
// Exec(ctx)
func (ugcb *UserGroupCreateBulk) OnConflict(opts ...sql.ConflictOption) *UserGroupUpsertBulk {
ugcb.conflict = opts
return &UserGroupUpsertBulk{
create: ugcb,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (ugcb *UserGroupCreateBulk) OnConflictColumns(columns ...string) *UserGroupUpsertBulk {
ugcb.conflict = append(ugcb.conflict, sql.ConflictColumns(columns...))
return &UserGroupUpsertBulk{
create: ugcb,
}
}
// UserGroupUpsertBulk is the builder for "upsert"-ing
// a bulk of UserGroup nodes.
type UserGroupUpsertBulk struct {
create *UserGroupCreateBulk
}
// UpdateNewValues updates the mutable fields using the new values that
// were set on create. Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *UserGroupUpsertBulk) UpdateNewValues() *UserGroupUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.UserGroup.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *UserGroupUpsertBulk) Ignore() *UserGroupUpsertBulk {
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 *UserGroupUpsertBulk) DoNothing() *UserGroupUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the UserGroupCreateBulk.OnConflict
// documentation for more info.
func (u *UserGroupUpsertBulk) Update(set func(*UserGroupUpsert)) *UserGroupUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&UserGroupUpsert{UpdateSet: update})
}))
return u
}
// SetUserID sets the "user_id" field.
func (u *UserGroupUpsertBulk) SetUserID(v int) *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.SetUserID(v)
})
}
// UpdateUserID sets the "user_id" field to the value that was provided on create.
func (u *UserGroupUpsertBulk) UpdateUserID() *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateUserID()
})
}
// SetGroupID sets the "group_id" field.
func (u *UserGroupUpsertBulk) SetGroupID(v int) *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.SetGroupID(v)
})
}
// UpdateGroupID sets the "group_id" field to the value that was provided on create.
func (u *UserGroupUpsertBulk) UpdateGroupID() *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateGroupID()
})
}
// SetIsPrimary sets the "is_primary" field.
func (u *UserGroupUpsertBulk) SetIsPrimary(v bool) *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.SetIsPrimary(v)
})
}
// UpdateIsPrimary sets the "is_primary" field to the value that was provided on create.
func (u *UserGroupUpsertBulk) UpdateIsPrimary() *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateIsPrimary()
})
}
// SetExpiresAt sets the "expires_at" field.
func (u *UserGroupUpsertBulk) SetExpiresAt(v time.Time) *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.SetExpiresAt(v)
})
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *UserGroupUpsertBulk) UpdateExpiresAt() *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.UpdateExpiresAt()
})
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *UserGroupUpsertBulk) ClearExpiresAt() *UserGroupUpsertBulk {
return u.Update(func(s *UserGroupUpsert) {
s.ClearExpiresAt()
})
}
// Exec executes the query.
func (u *UserGroupUpsertBulk) 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 UserGroupCreateBulk instead", i)
}
}
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for UserGroupCreateBulk.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *UserGroupUpsertBulk) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}

@ -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/predicate"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
)
// UserGroupDelete is the builder for deleting a UserGroup entity.
type UserGroupDelete struct {
config
hooks []Hook
mutation *UserGroupMutation
}
// Where appends a list predicates to the UserGroupDelete builder.
func (ugd *UserGroupDelete) Where(ps ...predicate.UserGroup) *UserGroupDelete {
ugd.mutation.Where(ps...)
return ugd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (ugd *UserGroupDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, ugd.sqlExec, ugd.mutation, ugd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (ugd *UserGroupDelete) ExecX(ctx context.Context) int {
n, err := ugd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (ugd *UserGroupDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(usergroup.Table, sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt))
if ps := ugd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, ugd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
ugd.mutation.done = true
return affected, err
}
// UserGroupDeleteOne is the builder for deleting a single UserGroup entity.
type UserGroupDeleteOne struct {
ugd *UserGroupDelete
}
// Where appends a list predicates to the UserGroupDelete builder.
func (ugdo *UserGroupDeleteOne) Where(ps ...predicate.UserGroup) *UserGroupDeleteOne {
ugdo.ugd.mutation.Where(ps...)
return ugdo
}
// Exec executes the deletion query.
func (ugdo *UserGroupDeleteOne) Exec(ctx context.Context) error {
n, err := ugdo.ugd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{usergroup.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (ugdo *UserGroupDeleteOne) ExecX(ctx context.Context) {
if err := ugdo.Exec(ctx); err != nil {
panic(err)
}
}

@ -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/group"
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
"github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
)
// UserGroupQuery is the builder for querying UserGroup entities.
type UserGroupQuery struct {
config
ctx *QueryContext
order []usergroup.OrderOption
inters []Interceptor
predicates []predicate.UserGroup
withUser *UserQuery
withGroup *GroupQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the UserGroupQuery builder.
func (ugq *UserGroupQuery) Where(ps ...predicate.UserGroup) *UserGroupQuery {
ugq.predicates = append(ugq.predicates, ps...)
return ugq
}
// Limit the number of records to be returned by this query.
func (ugq *UserGroupQuery) Limit(limit int) *UserGroupQuery {
ugq.ctx.Limit = &limit
return ugq
}
// Offset to start from.
func (ugq *UserGroupQuery) Offset(offset int) *UserGroupQuery {
ugq.ctx.Offset = &offset
return ugq
}
// 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 (ugq *UserGroupQuery) Unique(unique bool) *UserGroupQuery {
ugq.ctx.Unique = &unique
return ugq
}
// Order specifies how the records should be ordered.
func (ugq *UserGroupQuery) Order(o ...usergroup.OrderOption) *UserGroupQuery {
ugq.order = append(ugq.order, o...)
return ugq
}
// QueryUser chains the current query on the "user" edge.
func (ugq *UserGroupQuery) QueryUser() *UserQuery {
query := (&UserClient{config: ugq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := ugq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := ugq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(usergroup.Table, usergroup.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, usergroup.UserTable, usergroup.UserColumn),
)
fromU = sqlgraph.SetNeighbors(ugq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryGroup chains the current query on the "group" edge.
func (ugq *UserGroupQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: ugq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := ugq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := ugq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(usergroup.Table, usergroup.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, usergroup.GroupTable, usergroup.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(ugq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first UserGroup entity from the query.
// Returns a *NotFoundError when no UserGroup was found.
func (ugq *UserGroupQuery) First(ctx context.Context) (*UserGroup, error) {
nodes, err := ugq.Limit(1).All(setContextOp(ctx, ugq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{usergroup.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (ugq *UserGroupQuery) FirstX(ctx context.Context) *UserGroup {
node, err := ugq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first UserGroup ID from the query.
// Returns a *NotFoundError when no UserGroup ID was found.
func (ugq *UserGroupQuery) FirstID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ugq.Limit(1).IDs(setContextOp(ctx, ugq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{usergroup.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (ugq *UserGroupQuery) FirstIDX(ctx context.Context) int {
id, err := ugq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single UserGroup entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one UserGroup entity is found.
// Returns a *NotFoundError when no UserGroup entities are found.
func (ugq *UserGroupQuery) Only(ctx context.Context) (*UserGroup, error) {
nodes, err := ugq.Limit(2).All(setContextOp(ctx, ugq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{usergroup.Label}
default:
return nil, &NotSingularError{usergroup.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (ugq *UserGroupQuery) OnlyX(ctx context.Context) *UserGroup {
node, err := ugq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only UserGroup ID in the query.
// Returns a *NotSingularError when more than one UserGroup ID is found.
// Returns a *NotFoundError when no entities are found.
func (ugq *UserGroupQuery) OnlyID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ugq.Limit(2).IDs(setContextOp(ctx, ugq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{usergroup.Label}
default:
err = &NotSingularError{usergroup.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (ugq *UserGroupQuery) OnlyIDX(ctx context.Context) int {
id, err := ugq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of UserGroups.
func (ugq *UserGroupQuery) All(ctx context.Context) ([]*UserGroup, error) {
ctx = setContextOp(ctx, ugq.ctx, "All")
if err := ugq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*UserGroup, *UserGroupQuery]()
return withInterceptors[[]*UserGroup](ctx, ugq, qr, ugq.inters)
}
// AllX is like All, but panics if an error occurs.
func (ugq *UserGroupQuery) AllX(ctx context.Context) []*UserGroup {
nodes, err := ugq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of UserGroup IDs.
func (ugq *UserGroupQuery) IDs(ctx context.Context) (ids []int, err error) {
if ugq.ctx.Unique == nil && ugq.path != nil {
ugq.Unique(true)
}
ctx = setContextOp(ctx, ugq.ctx, "IDs")
if err = ugq.Select(usergroup.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (ugq *UserGroupQuery) IDsX(ctx context.Context) []int {
ids, err := ugq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (ugq *UserGroupQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, ugq.ctx, "Count")
if err := ugq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, ugq, querierCount[*UserGroupQuery](), ugq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (ugq *UserGroupQuery) CountX(ctx context.Context) int {
count, err := ugq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (ugq *UserGroupQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, ugq.ctx, "Exist")
switch _, err := ugq.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 (ugq *UserGroupQuery) ExistX(ctx context.Context) bool {
exist, err := ugq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the UserGroupQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (ugq *UserGroupQuery) Clone() *UserGroupQuery {
if ugq == nil {
return nil
}
return &UserGroupQuery{
config: ugq.config,
ctx: ugq.ctx.Clone(),
order: append([]usergroup.OrderOption{}, ugq.order...),
inters: append([]Interceptor{}, ugq.inters...),
predicates: append([]predicate.UserGroup{}, ugq.predicates...),
withUser: ugq.withUser.Clone(),
withGroup: ugq.withGroup.Clone(),
// clone intermediate query.
sql: ugq.sql.Clone(),
path: ugq.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 (ugq *UserGroupQuery) WithUser(opts ...func(*UserQuery)) *UserGroupQuery {
query := (&UserClient{config: ugq.config}).Query()
for _, opt := range opts {
opt(query)
}
ugq.withUser = query
return ugq
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (ugq *UserGroupQuery) WithGroup(opts ...func(*GroupQuery)) *UserGroupQuery {
query := (&GroupClient{config: ugq.config}).Query()
for _, opt := range opts {
opt(query)
}
ugq.withGroup = query
return ugq
}
// 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 {
// UserID int `json:"user_id,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.UserGroup.Query().
// GroupBy(usergroup.FieldUserID).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (ugq *UserGroupQuery) GroupBy(field string, fields ...string) *UserGroupGroupBy {
ugq.ctx.Fields = append([]string{field}, fields...)
grbuild := &UserGroupGroupBy{build: ugq}
grbuild.flds = &ugq.ctx.Fields
grbuild.label = usergroup.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 {
// UserID int `json:"user_id,omitempty"`
// }
//
// client.UserGroup.Query().
// Select(usergroup.FieldUserID).
// Scan(ctx, &v)
func (ugq *UserGroupQuery) Select(fields ...string) *UserGroupSelect {
ugq.ctx.Fields = append(ugq.ctx.Fields, fields...)
sbuild := &UserGroupSelect{UserGroupQuery: ugq}
sbuild.label = usergroup.Label
sbuild.flds, sbuild.scan = &ugq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a UserGroupSelect configured with the given aggregations.
func (ugq *UserGroupQuery) Aggregate(fns ...AggregateFunc) *UserGroupSelect {
return ugq.Select().Aggregate(fns...)
}
func (ugq *UserGroupQuery) prepareQuery(ctx context.Context) error {
for _, inter := range ugq.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, ugq); err != nil {
return err
}
}
}
for _, f := range ugq.ctx.Fields {
if !usergroup.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if ugq.path != nil {
prev, err := ugq.path(ctx)
if err != nil {
return err
}
ugq.sql = prev
}
return nil
}
func (ugq *UserGroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*UserGroup, error) {
var (
nodes = []*UserGroup{}
_spec = ugq.querySpec()
loadedTypes = [2]bool{
ugq.withUser != nil,
ugq.withGroup != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*UserGroup).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &UserGroup{config: ugq.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, ugq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := ugq.withUser; query != nil {
if err := ugq.loadUser(ctx, query, nodes, nil,
func(n *UserGroup, e *User) { n.Edges.User = e }); err != nil {
return nil, err
}
}
if query := ugq.withGroup; query != nil {
if err := ugq.loadGroup(ctx, query, nodes, nil,
func(n *UserGroup, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (ugq *UserGroupQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*UserGroup, init func(*UserGroup), assign func(*UserGroup, *User)) error {
ids := make([]int, 0, len(nodes))
nodeids := make(map[int][]*UserGroup)
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 (ugq *UserGroupQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*UserGroup, init func(*UserGroup), assign func(*UserGroup, *Group)) error {
ids := make([]int, 0, len(nodes))
nodeids := make(map[int][]*UserGroup)
for i := range nodes {
fk := nodes[i].GroupID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (ugq *UserGroupQuery) sqlCount(ctx context.Context) (int, error) {
_spec := ugq.querySpec()
_spec.Node.Columns = ugq.ctx.Fields
if len(ugq.ctx.Fields) > 0 {
_spec.Unique = ugq.ctx.Unique != nil && *ugq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, ugq.driver, _spec)
}
func (ugq *UserGroupQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(usergroup.Table, usergroup.Columns, sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt))
_spec.From = ugq.sql
if unique := ugq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if ugq.path != nil {
_spec.Unique = true
}
if fields := ugq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, usergroup.FieldID)
for i := range fields {
if fields[i] != usergroup.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
if ugq.withUser != nil {
_spec.Node.AddColumnOnce(usergroup.FieldUserID)
}
if ugq.withGroup != nil {
_spec.Node.AddColumnOnce(usergroup.FieldGroupID)
}
}
if ps := ugq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := ugq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := ugq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := ugq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (ugq *UserGroupQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(ugq.driver.Dialect())
t1 := builder.Table(usergroup.Table)
columns := ugq.ctx.Fields
if len(columns) == 0 {
columns = usergroup.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if ugq.sql != nil {
selector = ugq.sql
selector.Select(selector.Columns(columns...)...)
}
if ugq.ctx.Unique != nil && *ugq.ctx.Unique {
selector.Distinct()
}
for _, p := range ugq.predicates {
p(selector)
}
for _, p := range ugq.order {
p(selector)
}
if offset := ugq.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 := ugq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// UserGroupGroupBy is the group-by builder for UserGroup entities.
type UserGroupGroupBy struct {
selector
build *UserGroupQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (uggb *UserGroupGroupBy) Aggregate(fns ...AggregateFunc) *UserGroupGroupBy {
uggb.fns = append(uggb.fns, fns...)
return uggb
}
// Scan applies the selector query and scans the result into the given value.
func (uggb *UserGroupGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, uggb.build.ctx, "GroupBy")
if err := uggb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*UserGroupQuery, *UserGroupGroupBy](ctx, uggb.build, uggb, uggb.build.inters, v)
}
func (uggb *UserGroupGroupBy) sqlScan(ctx context.Context, root *UserGroupQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(uggb.fns))
for _, fn := range uggb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*uggb.flds)+len(uggb.fns))
for _, f := range *uggb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*uggb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := uggb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// UserGroupSelect is the builder for selecting fields of UserGroup entities.
type UserGroupSelect struct {
*UserGroupQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (ugs *UserGroupSelect) Aggregate(fns ...AggregateFunc) *UserGroupSelect {
ugs.fns = append(ugs.fns, fns...)
return ugs
}
// Scan applies the selector query and scans the result into the given value.
func (ugs *UserGroupSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ugs.ctx, "Select")
if err := ugs.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*UserGroupQuery, *UserGroupSelect](ctx, ugs.UserGroupQuery, ugs, ugs.inters, v)
}
func (ugs *UserGroupSelect) sqlScan(ctx context.Context, root *UserGroupQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(ugs.fns))
for _, fn := range ugs.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*ugs.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 := ugs.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

@ -0,0 +1,508 @@
// 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/group"
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
"github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/ent/usergroup"
)
// UserGroupUpdate is the builder for updating UserGroup entities.
type UserGroupUpdate struct {
config
hooks []Hook
mutation *UserGroupMutation
}
// Where appends a list predicates to the UserGroupUpdate builder.
func (ugu *UserGroupUpdate) Where(ps ...predicate.UserGroup) *UserGroupUpdate {
ugu.mutation.Where(ps...)
return ugu
}
// SetUserID sets the "user_id" field.
func (ugu *UserGroupUpdate) SetUserID(i int) *UserGroupUpdate {
ugu.mutation.SetUserID(i)
return ugu
}
// SetNillableUserID sets the "user_id" field if the given value is not nil.
func (ugu *UserGroupUpdate) SetNillableUserID(i *int) *UserGroupUpdate {
if i != nil {
ugu.SetUserID(*i)
}
return ugu
}
// SetGroupID sets the "group_id" field.
func (ugu *UserGroupUpdate) SetGroupID(i int) *UserGroupUpdate {
ugu.mutation.SetGroupID(i)
return ugu
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (ugu *UserGroupUpdate) SetNillableGroupID(i *int) *UserGroupUpdate {
if i != nil {
ugu.SetGroupID(*i)
}
return ugu
}
// SetIsPrimary sets the "is_primary" field.
func (ugu *UserGroupUpdate) SetIsPrimary(b bool) *UserGroupUpdate {
ugu.mutation.SetIsPrimary(b)
return ugu
}
// SetNillableIsPrimary sets the "is_primary" field if the given value is not nil.
func (ugu *UserGroupUpdate) SetNillableIsPrimary(b *bool) *UserGroupUpdate {
if b != nil {
ugu.SetIsPrimary(*b)
}
return ugu
}
// SetExpiresAt sets the "expires_at" field.
func (ugu *UserGroupUpdate) SetExpiresAt(t time.Time) *UserGroupUpdate {
ugu.mutation.SetExpiresAt(t)
return ugu
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (ugu *UserGroupUpdate) SetNillableExpiresAt(t *time.Time) *UserGroupUpdate {
if t != nil {
ugu.SetExpiresAt(*t)
}
return ugu
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (ugu *UserGroupUpdate) ClearExpiresAt() *UserGroupUpdate {
ugu.mutation.ClearExpiresAt()
return ugu
}
// SetUser sets the "user" edge to the User entity.
func (ugu *UserGroupUpdate) SetUser(u *User) *UserGroupUpdate {
return ugu.SetUserID(u.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (ugu *UserGroupUpdate) SetGroup(g *Group) *UserGroupUpdate {
return ugu.SetGroupID(g.ID)
}
// Mutation returns the UserGroupMutation object of the builder.
func (ugu *UserGroupUpdate) Mutation() *UserGroupMutation {
return ugu.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (ugu *UserGroupUpdate) ClearUser() *UserGroupUpdate {
ugu.mutation.ClearUser()
return ugu
}
// ClearGroup clears the "group" edge to the Group entity.
func (ugu *UserGroupUpdate) ClearGroup() *UserGroupUpdate {
ugu.mutation.ClearGroup()
return ugu
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (ugu *UserGroupUpdate) Save(ctx context.Context) (int, error) {
return withHooks(ctx, ugu.sqlSave, ugu.mutation, ugu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (ugu *UserGroupUpdate) SaveX(ctx context.Context) int {
affected, err := ugu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (ugu *UserGroupUpdate) Exec(ctx context.Context) error {
_, err := ugu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ugu *UserGroupUpdate) ExecX(ctx context.Context) {
if err := ugu.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (ugu *UserGroupUpdate) check() error {
if _, ok := ugu.mutation.UserID(); ugu.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "UserGroup.user"`)
}
if _, ok := ugu.mutation.GroupID(); ugu.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "UserGroup.group"`)
}
return nil
}
func (ugu *UserGroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := ugu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(usergroup.Table, usergroup.Columns, sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt))
if ps := ugu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := ugu.mutation.IsPrimary(); ok {
_spec.SetField(usergroup.FieldIsPrimary, field.TypeBool, value)
}
if value, ok := ugu.mutation.ExpiresAt(); ok {
_spec.SetField(usergroup.FieldExpiresAt, field.TypeTime, value)
}
if ugu.mutation.ExpiresAtCleared() {
_spec.ClearField(usergroup.FieldExpiresAt, field.TypeTime)
}
if ugu.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.UserTable,
Columns: []string{usergroup.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ugu.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.UserTable,
Columns: []string{usergroup.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 ugu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.GroupTable,
Columns: []string{usergroup.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ugu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.GroupTable,
Columns: []string{usergroup.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.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, ugu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{usergroup.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
ugu.mutation.done = true
return n, nil
}
// UserGroupUpdateOne is the builder for updating a single UserGroup entity.
type UserGroupUpdateOne struct {
config
fields []string
hooks []Hook
mutation *UserGroupMutation
}
// SetUserID sets the "user_id" field.
func (uguo *UserGroupUpdateOne) SetUserID(i int) *UserGroupUpdateOne {
uguo.mutation.SetUserID(i)
return uguo
}
// SetNillableUserID sets the "user_id" field if the given value is not nil.
func (uguo *UserGroupUpdateOne) SetNillableUserID(i *int) *UserGroupUpdateOne {
if i != nil {
uguo.SetUserID(*i)
}
return uguo
}
// SetGroupID sets the "group_id" field.
func (uguo *UserGroupUpdateOne) SetGroupID(i int) *UserGroupUpdateOne {
uguo.mutation.SetGroupID(i)
return uguo
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (uguo *UserGroupUpdateOne) SetNillableGroupID(i *int) *UserGroupUpdateOne {
if i != nil {
uguo.SetGroupID(*i)
}
return uguo
}
// SetIsPrimary sets the "is_primary" field.
func (uguo *UserGroupUpdateOne) SetIsPrimary(b bool) *UserGroupUpdateOne {
uguo.mutation.SetIsPrimary(b)
return uguo
}
// SetNillableIsPrimary sets the "is_primary" field if the given value is not nil.
func (uguo *UserGroupUpdateOne) SetNillableIsPrimary(b *bool) *UserGroupUpdateOne {
if b != nil {
uguo.SetIsPrimary(*b)
}
return uguo
}
// SetExpiresAt sets the "expires_at" field.
func (uguo *UserGroupUpdateOne) SetExpiresAt(t time.Time) *UserGroupUpdateOne {
uguo.mutation.SetExpiresAt(t)
return uguo
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (uguo *UserGroupUpdateOne) SetNillableExpiresAt(t *time.Time) *UserGroupUpdateOne {
if t != nil {
uguo.SetExpiresAt(*t)
}
return uguo
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (uguo *UserGroupUpdateOne) ClearExpiresAt() *UserGroupUpdateOne {
uguo.mutation.ClearExpiresAt()
return uguo
}
// SetUser sets the "user" edge to the User entity.
func (uguo *UserGroupUpdateOne) SetUser(u *User) *UserGroupUpdateOne {
return uguo.SetUserID(u.ID)
}
// SetGroup sets the "group" edge to the Group entity.
func (uguo *UserGroupUpdateOne) SetGroup(g *Group) *UserGroupUpdateOne {
return uguo.SetGroupID(g.ID)
}
// Mutation returns the UserGroupMutation object of the builder.
func (uguo *UserGroupUpdateOne) Mutation() *UserGroupMutation {
return uguo.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (uguo *UserGroupUpdateOne) ClearUser() *UserGroupUpdateOne {
uguo.mutation.ClearUser()
return uguo
}
// ClearGroup clears the "group" edge to the Group entity.
func (uguo *UserGroupUpdateOne) ClearGroup() *UserGroupUpdateOne {
uguo.mutation.ClearGroup()
return uguo
}
// Where appends a list predicates to the UserGroupUpdate builder.
func (uguo *UserGroupUpdateOne) Where(ps ...predicate.UserGroup) *UserGroupUpdateOne {
uguo.mutation.Where(ps...)
return uguo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (uguo *UserGroupUpdateOne) Select(field string, fields ...string) *UserGroupUpdateOne {
uguo.fields = append([]string{field}, fields...)
return uguo
}
// Save executes the query and returns the updated UserGroup entity.
func (uguo *UserGroupUpdateOne) Save(ctx context.Context) (*UserGroup, error) {
return withHooks(ctx, uguo.sqlSave, uguo.mutation, uguo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (uguo *UserGroupUpdateOne) SaveX(ctx context.Context) *UserGroup {
node, err := uguo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (uguo *UserGroupUpdateOne) Exec(ctx context.Context) error {
_, err := uguo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (uguo *UserGroupUpdateOne) ExecX(ctx context.Context) {
if err := uguo.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (uguo *UserGroupUpdateOne) check() error {
if _, ok := uguo.mutation.UserID(); uguo.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "UserGroup.user"`)
}
if _, ok := uguo.mutation.GroupID(); uguo.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "UserGroup.group"`)
}
return nil
}
func (uguo *UserGroupUpdateOne) sqlSave(ctx context.Context) (_node *UserGroup, err error) {
if err := uguo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(usergroup.Table, usergroup.Columns, sqlgraph.NewFieldSpec(usergroup.FieldID, field.TypeInt))
id, ok := uguo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "UserGroup.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := uguo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, usergroup.FieldID)
for _, f := range fields {
if !usergroup.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != usergroup.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := uguo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := uguo.mutation.IsPrimary(); ok {
_spec.SetField(usergroup.FieldIsPrimary, field.TypeBool, value)
}
if value, ok := uguo.mutation.ExpiresAt(); ok {
_spec.SetField(usergroup.FieldExpiresAt, field.TypeTime, value)
}
if uguo.mutation.ExpiresAtCleared() {
_spec.ClearField(usergroup.FieldExpiresAt, field.TypeTime)
}
if uguo.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.UserTable,
Columns: []string{usergroup.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uguo.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.UserTable,
Columns: []string{usergroup.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 uguo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.GroupTable,
Columns: []string{usergroup.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uguo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: usergroup.GroupTable,
Columns: []string{usergroup.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &UserGroup{config: uguo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, uguo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{usergroup.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
uguo.mutation.done = true
return _node, nil
}

@ -16,6 +16,9 @@ type (
) )
const ( const (
AdminGroupID = 1
UserGroupID = 2
// Deprecated: AnonymousGroupID is no longer used.
AnonymousGroupID = 3 AnonymousGroupID = 3
) )
@ -23,6 +26,7 @@ type (
GroupClient interface { GroupClient interface {
TxOperator TxOperator
// AnonymousGroup returns the anonymous group. // AnonymousGroup returns the anonymous group.
// Deprecated: anonymous group is no longer used.
AnonymousGroup(ctx context.Context) (*ent.Group, error) AnonymousGroup(ctx context.Context) (*ent.Group, error)
// ListAll returns all groups. // ListAll returns all groups.
ListAll(ctx context.Context) ([]*ent.Group, error) ListAll(ctx context.Context) ([]*ent.Group, error)

@ -16,6 +16,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/ent/davaccount" "github.com/cloudreve/Cloudreve/v4/ent/davaccount"
"github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/file"
"github.com/cloudreve/Cloudreve/v4/ent/group"
"github.com/cloudreve/Cloudreve/v4/ent/passkey" "github.com/cloudreve/Cloudreve/v4/ent/passkey"
"github.com/cloudreve/Cloudreve/v4/ent/schema" "github.com/cloudreve/Cloudreve/v4/ent/schema"
"github.com/cloudreve/Cloudreve/v4/ent/task" "github.com/cloudreve/Cloudreve/v4/ent/task"
@ -288,8 +289,8 @@ func (c *userClient) Create(ctx context.Context, args *NewUserArgs) (*ent.User,
SetEmail(args.Email). SetEmail(args.Email).
SetNick(nick). SetNick(nick).
SetStatus(args.Status). SetStatus(args.Status).
SetGroupID(args.GroupID). SetAvatar(args.Avatar).
SetAvatar(args.Avatar) AddGroupIDs(args.GroupID)
if args.PlainPassword != "" { if args.PlainPassword != "" {
pwdDigest, err := digestPassword(args.PlainPassword) pwdDigest, err := digestPassword(args.PlainPassword)
@ -313,7 +314,7 @@ func (c *userClient) Create(ctx context.Context, args *NewUserArgs) (*ent.User,
if newUser.ID == 1 { if newUser.ID == 1 {
// For the first user registered, elevate it to admin group. // For the first user registered, elevate it to admin group.
if _, err := newUser.Update().SetGroupID(1).Save(ctx); err != nil { if _, err := newUser.Update().AddGroupIDs(AdminGroupID).Save(ctx); err != nil {
return newUser, fmt.Errorf("failed to elevate user to admin: %w", err) return newUser, fmt.Errorf("failed to elevate user to admin: %w", err)
} }
} }
@ -403,24 +404,18 @@ func UserIDFromContext(ctx context.Context) int {
} }
func (c *userClient) AnonymousUser(ctx context.Context) (*ent.User, error) { func (c *userClient) AnonymousUser(ctx context.Context) (*ent.User, error) {
groupClient := NewGroupClient(c.client, "", nil)
anonymousGroup, err := groupClient.AnonymousGroup(ctx)
if err != nil {
return nil, fmt.Errorf("anyonymous group not found: %w", err)
}
// TODO: save into cache // TODO: save into cache
anonymous := &ent.User{ anonymous := &ent.User{
Settings: &types.UserSetting{}, Settings: &types.UserSetting{},
} }
anonymous.SetGroup(anonymousGroup) anonymous.SetGroups(nil)
return anonymous, nil return anonymous, nil
} }
func (c *userClient) ListUsers(ctx context.Context, args *ListUserParameters) (*ListUserResult, error) { func (c *userClient) ListUsers(ctx context.Context, args *ListUserParameters) (*ListUserResult, error) {
query := c.client.User.Query() query := c.client.User.Query()
if args.GroupID != 0 { if args.GroupID != 0 {
query = query.Where(user.GroupUsers(args.GroupID)) query = query.QueryGroups().Where(group.ID(args.GroupID)).QueryUsers()
} }
if args.Status != "" { if args.Status != "" {
query = query.Where(user.StatusEQ(args.Status)) query = query.Where(user.StatusEQ(args.Status))
@ -461,7 +456,7 @@ func (c *userClient) Upsert(ctx context.Context, u *ent.User, password, twoFa st
SetNick(u.Nick). SetNick(u.Nick).
SetAvatar(u.Avatar). SetAvatar(u.Avatar).
SetStatus(u.Status). SetStatus(u.Status).
SetGroupID(u.GroupUsers). //SetGroupID(u.GroupUsers).
SetPassword(u.Password). SetPassword(u.Password).
SetSettings(&types.UserSetting{}) SetSettings(&types.UserSetting{})
@ -480,8 +475,8 @@ func (c *userClient) Upsert(ctx context.Context, u *ent.User, password, twoFa st
SetEmail(u.Email). SetEmail(u.Email).
SetNick(u.Nick). SetNick(u.Nick).
SetAvatar(u.Avatar). SetAvatar(u.Avatar).
SetStatus(u.Status). SetStatus(u.Status)
SetGroupID(u.GroupUsers) //SetGroupID(u.GroupUsers)
if password != "" { if password != "" {
pwdDigest, err := digestPassword(password) pwdDigest, err := digestPassword(password)
@ -567,7 +562,7 @@ func CheckPassword(u *ent.User, password string) error {
func withUserEagerLoading(ctx context.Context, q *ent.UserQuery) *ent.UserQuery { func withUserEagerLoading(ctx context.Context, q *ent.UserQuery) *ent.UserQuery {
if v, ok := ctx.Value(LoadUserGroup{}).(bool); ok && v { if v, ok := ctx.Value(LoadUserGroup{}).(bool); ok && v {
q.WithGroup(func(gq *ent.GroupQuery) { q.WithGroups(func(gq *ent.GroupQuery) {
withGroupEagerLoading(ctx, gq) withGroupEagerLoading(ctx, gq)
}) })
} }

@ -7,16 +7,16 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/inventory" "github.com/cloudreve/Cloudreve/v4/inventory"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/auth"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver/oss" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver/oss"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
"github.com/cloudreve/Cloudreve/v4/pkg/logging" "github.com/cloudreve/Cloudreve/v4/pkg/logging"
"github.com/cloudreve/Cloudreve/v4/pkg/request" "github.com/cloudreve/Cloudreve/v4/pkg/request"
"github.com/cloudreve/Cloudreve/v4/pkg/util"
"github.com/cloudreve/Cloudreve/v4/pkg/auth"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer" "github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/cloudreve/Cloudreve/v4/pkg/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/samber/lo"
) )
const ( const (
@ -144,7 +144,7 @@ func WebDAVAuth() gin.HandlerFunc {
} }
// 用户组已启用WebDAV // 用户组已启用WebDAV
group, err := expectedUser.Edges.GroupOrErr() groups, err := expectedUser.Edges.GroupsOrErr()
if err != nil { if err != nil {
l.Debug("WebDAVAuth: user group not found: %s", err) l.Debug("WebDAVAuth: user group not found: %s", err)
c.Status(http.StatusInternalServerError) c.Status(http.StatusInternalServerError)
@ -152,7 +152,9 @@ func WebDAVAuth() gin.HandlerFunc {
return return
} }
if !group.Permissions.Enabled(int(types.GroupPermissionWebDAV)) { if !lo.ContainsBy(groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionWebDAV))
}) {
c.Status(http.StatusForbidden) c.Status(http.StatusForbidden)
l.Debug("WebDAVAuth: user %q does not have WebDAV permission.", expectedUser.Email) l.Debug("WebDAVAuth: user %q does not have WebDAV permission.", expectedUser.Email)
c.Abort() c.Abort()
@ -262,7 +264,9 @@ func OSSCallbackAuth() gin.HandlerFunc {
func IsAdmin() gin.HandlerFunc { func IsAdmin() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
user := inventory.UserFromContext(c) user := inventory.UserFromContext(c)
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeNoPermissionErr, "", nil)) c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeNoPermissionErr, "", nil))
c.Abort() c.Abort()
return return

@ -228,13 +228,15 @@ func (f *DBFS) Capacity(ctx context.Context, u *ent.User) (*fs.Capacity, error)
res = &fs.Capacity{} res = &fs.Capacity{}
) )
requesterGroup, err := u.Edges.GroupOrErr() requesterGroup, err := u.Edges.GroupsOrErr()
if err != nil { if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user's group", err) return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user's group", err)
} }
res.Used = f.user.Storage res.Used = f.user.Storage
res.Total = requesterGroup.MaxStorage res.Total = lo.Max(lo.Map(requesterGroup, func(g *ent.Group, _ int) int64 {
return g.MaxStorage
}))
return res, nil return res, nil
} }
@ -416,7 +418,9 @@ func (f *DBFS) Get(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.Fil
} }
target.FileExtendedInfo = extendedInfo target.FileExtendedInfo = extendedInfo
if target.OwnerID() == f.user.ID || f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if target.OwnerID() == f.user.ID || lo.ContainsBy(f.user.Edges.Groups, func(g *ent.Group) bool {
return g.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
target.FileExtendedInfo.Shares = target.Model.Edges.Shares target.FileExtendedInfo.Shares = target.Model.Edges.Shares
if target.Model.Props != nil { if target.Model.Props != nil {
target.FileExtendedInfo.View = target.Model.Props.View target.FileExtendedInfo.View = target.Model.Props.View
@ -450,10 +454,12 @@ func (f *DBFS) Get(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.Fil
} else { } else {
// cache miss, walk the folder to get the summary // cache miss, walk the folder to get the summary
newSummary := &fs.FolderSummary{Completed: true} newSummary := &fs.FolderSummary{Completed: true}
if f.user.Edges.Group == nil { if len(f.user.Edges.Groups) == 0 {
return nil, fmt.Errorf("user group not loaded") return nil, fmt.Errorf("user group not loaded")
} }
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1) limit := max(lo.Max(lo.Map(f.user.Edges.Groups, func(g *ent.Group, _ int) int {
return g.Settings.MaxWalkedFiles
})), 1)
// disable load metadata to speed up // disable load metadata to speed up
ctxWalk := context.WithValue(ctx, inventory.LoadFilePublicMetadata{}, false) ctxWalk := context.WithValue(ctx, inventory.LoadFilePublicMetadata{}, false)
@ -539,10 +545,12 @@ func (f *DBFS) Walk(ctx context.Context, path *fs.URI, depth int, walk fs.WalkFu
} }
// Walk // Walk
if f.user.Edges.Group == nil { if len(f.user.Edges.Groups) == 0 {
return fmt.Errorf("user group not loaded") return fmt.Errorf("user group not loaded")
} }
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1) limit := max(lo.Max(lo.Map(f.user.Edges.Groups, func(g *ent.Group, _ int) int {
return g.Settings.MaxWalkedFiles
})), 1)
if err := navigator.Walk(ctx, []*File{target}, limit, depth, func(files []*File, l int) error { if err := navigator.Walk(ctx, []*File{target}, limit, depth, func(files []*File, l int) error {
for _, file := range files { for _, file := range files {
@ -637,12 +645,12 @@ func (f *DBFS) createFile(ctx context.Context, parent *File, name string, fileTy
// getPreferredPolicy tries to get the preferred storage policy for the given file. // getPreferredPolicy tries to get the preferred storage policy for the given file.
func (f *DBFS) getPreferredPolicy(ctx context.Context, file *File) (*ent.StoragePolicy, error) { func (f *DBFS) getPreferredPolicy(ctx context.Context, file *File) (*ent.StoragePolicy, error) {
ownerGroup := file.Owner().Edges.Group ownerGroup := file.Owner().Edges.Groups
if ownerGroup == nil { if len(ownerGroup) == 0 {
return nil, fmt.Errorf("owner group not loaded") return nil, fmt.Errorf("owner group not loaded")
} }
groupPolicy, err := f.storagePolicyClient.GetByGroup(ctx, ownerGroup) groupPolicy, err := f.storagePolicyClient.GetByGroup(ctx, ownerGroup[0])
if err != nil { if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get available storage policies", err) return nil, serializer.NewError(serializer.CodeDBError, "Failed to get available storage policies", err)
} }

@ -267,12 +267,13 @@ func (f *DBFS) SoftDelete(ctx context.Context, path ...*fs.URI) error {
_ = inventory.Rollback(tx) _ = inventory.Rollback(tx)
return serializer.NewError(serializer.CodeDBError, "failed to soft-delete file", err) return serializer.NewError(serializer.CodeDBError, "failed to soft-delete file", err)
} }
// Save restore uri into metadata // Save restore uri into metadata
if err := fc.UpsertMetadata(ctx, target.Model, map[string]string{ if err := fc.UpsertMetadata(ctx, target.Model, map[string]string{
MetadataRestoreUri: target.Uri(true).String(), MetadataRestoreUri: target.Uri(true).String(),
MetadataExpectedCollectTime: strconv.FormatInt( MetadataExpectedCollectTime: strconv.FormatInt(
time.Now().Add(time.Duration(target.Owner().Edges.Group.Settings.TrashRetention)*time.Second).Unix(), time.Now().Add(time.Duration(lo.Max(lo.Map(target.Owner().Edges.Groups, func(item *ent.Group, index int) int {
return item.Settings.TrashRetention
})))*time.Second).Unix(),
10), 10),
}, nil); err != nil { }, nil); err != nil {
_ = inventory.Rollback(tx) _ = inventory.Rollback(tx)
@ -647,7 +648,9 @@ func (f *DBFS) TraverseFile(ctx context.Context, fileID int) (fs.File, error) {
return nil, err return nil, err
} }
if fileModel.OwnerID != f.user.ID && !f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if fileModel.OwnerID != f.user.ID && !lo.ContainsBy(f.user.Edges.Groups, func(g *ent.Group) bool {
return g.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
return nil, fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can traverse file's uri")) return nil, fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can traverse file's uri"))
} }
@ -739,10 +742,12 @@ func (f *DBFS) setCurrentVersion(ctx context.Context, target *File, versionId in
} }
func (f *DBFS) deleteFiles(ctx context.Context, targets map[Navigator][]*File, fc inventory.FileClient, opt *types.EntityRecycleOption) ([]fs.Entity, inventory.StorageDiff, error) { func (f *DBFS) deleteFiles(ctx context.Context, targets map[Navigator][]*File, fc inventory.FileClient, opt *types.EntityRecycleOption) ([]fs.Entity, inventory.StorageDiff, error) {
if f.user.Edges.Group == nil { if len(f.user.Edges.Groups) == 0 {
return nil, nil, fmt.Errorf("user group not loaded") return nil, nil, fmt.Errorf("user group not loaded")
} }
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1) limit := max(lo.Max(lo.Map(f.user.Edges.Groups, func(g *ent.Group, index int) int {
return g.Settings.MaxWalkedFiles
})), 1)
allStaleEntities := make([]fs.Entity, 0, len(targets)) allStaleEntities := make([]fs.Entity, 0, len(targets))
storageDiff := make(inventory.StorageDiff) storageDiff := make(inventory.StorageDiff)
for n, files := range targets { for n, files := range targets {
@ -781,10 +786,12 @@ func (f *DBFS) deleteFiles(ctx context.Context, targets map[Navigator][]*File, f
} }
func (f *DBFS) copyFiles(ctx context.Context, targets map[Navigator][]*File, destination *File, fc inventory.FileClient) (map[int]*ent.File, inventory.StorageDiff, error) { func (f *DBFS) copyFiles(ctx context.Context, targets map[Navigator][]*File, destination *File, fc inventory.FileClient) (map[int]*ent.File, inventory.StorageDiff, error) {
if f.user.Edges.Group == nil { if len(f.user.Edges.Groups) == 0 {
return nil, nil, fmt.Errorf("user group not loaded") return nil, nil, fmt.Errorf("user group not loaded")
} }
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1) limit := max(lo.Max(lo.Map(f.user.Edges.Groups, func(g *ent.Group, index int) int {
return g.Settings.MaxWalkedFiles
})), 1)
capacity, err := f.Capacity(ctx, destination.Owner()) capacity, err := f.Capacity(ctx, destination.Owner())
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("copy files: failed to destination owner capacity: %w", err) return nil, nil, fmt.Errorf("copy files: failed to destination owner capacity: %w", err)

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/samber/lo"
"github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/ent/user" "github.com/cloudreve/Cloudreve/v4/ent/user"
@ -92,7 +93,9 @@ func (n *myNavigator) To(ctx context.Context, path *fs.URI) (*File, error) {
return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("user not found: %w", err)) return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("user not found: %w", err))
} }
if targetUser.Status != user.StatusActive && !n.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if targetUser.Status != user.StatusActive && !lo.ContainsBy(n.user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("inactive user")) return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("inactive user"))
} }

@ -3,6 +3,7 @@ package dbfs
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/inventory" "github.com/cloudreve/Cloudreve/v4/inventory"
"github.com/cloudreve/Cloudreve/v4/inventory/types" "github.com/cloudreve/Cloudreve/v4/inventory/types"
@ -22,7 +23,9 @@ func (f *DBFS) PatchProps(ctx context.Context, uri *fs.URI, props *types.FilePro
return fmt.Errorf("failed to get target file: %w", err) return fmt.Errorf("failed to get target file: %w", err)
} }
if target.OwnerID() != f.user.ID && !f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if target.OwnerID() != f.user.ID && !lo.ContainsBy(f.user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
return fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can modify file props")) return fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can modify file props"))
} }

@ -3,6 +3,7 @@ package dbfs
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/samber/lo"
"github.com/cloudreve/Cloudreve/v4/application/constants" "github.com/cloudreve/Cloudreve/v4/application/constants"
"github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/ent"
@ -156,7 +157,9 @@ func (n *shareNavigator) Root(ctx context.Context, path *fs.URI) (*File, error)
return nil, ErrShareNotFound return nil, ErrShareNotFound
} }
if n.user.ID != n.owner.ID && !n.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionShareDownload)) { if n.user.ID != n.owner.ID && !lo.ContainsBy(n.user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionShareDownload))
}) {
return nil, serializer.NewError( return nil, serializer.NewError(
serializer.CodeNoPermissionErr, serializer.CodeNoPermissionErr,
fmt.Sprintf("You don't have permission to access share links"), fmt.Sprintf("You don't have permission to access share links"),

@ -61,7 +61,9 @@ type (
func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectLink, error) { func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectLink, error) {
ae := serializer.NewAggregateError() ae := serializer.NewAggregateError()
res := make([]DirectLink, 0, len(urls)) res := make([]DirectLink, 0, len(urls))
useRedirect := m.user.Edges.Group.Settings.RedirectedSource useRedirect := lo.ContainsBy(m.user.Edges.Groups, func(item *ent.Group) bool {
return item.Settings.RedirectedSource
})
fileClient := m.dep.FileClient() fileClient := m.dep.FileClient()
siteUrl := m.settings.SiteURL(ctx) siteUrl := m.settings.SiteURL(ctx)
@ -76,7 +78,9 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
continue continue
} }
if file.OwnerID() != m.user.ID && !m.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if file.OwnerID() != m.user.ID && !lo.ContainsBy(m.user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
ae.Add(url.String(), fs.ErrOwnerOnly) ae.Add(url.String(), fs.ErrOwnerOnly)
continue continue
} }
@ -99,7 +103,9 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
if useRedirect { if useRedirect {
// Use redirect source // Use redirect source
link, err := fileClient.CreateDirectLink(ctx, file.ID(), file.Name(), m.user.Edges.Group.SpeedLimit) link, err := fileClient.CreateDirectLink(ctx, file.ID(), file.Name(), lo.Max(lo.Map(m.user.Edges.Groups, func(item *ent.Group, _ int) int {
return item.SpeedLimit
})))
if err != nil { if err != nil {
ae.Add(url.String(), err) ae.Add(url.String(), err)
continue continue
@ -121,7 +127,9 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
source := entitysource.NewEntitySource(target, d, policy, m.auth, m.settings, m.hasher, m.dep.RequestClient(), source := entitysource.NewEntitySource(target, d, policy, m.auth, m.settings, m.hasher, m.dep.RequestClient(),
m.l, m.config, m.dep.MimeDetector(ctx)) m.l, m.config, m.dep.MimeDetector(ctx))
sourceUrl, err := source.Url(ctx, sourceUrl, err := source.Url(ctx,
entitysource.WithSpeedLimit(int64(m.user.Edges.Group.SpeedLimit)), entitysource.WithSpeedLimit(int64(lo.Max(lo.Map(m.user.Edges.Groups, func(item *ent.Group, _ int) int {
return item.SpeedLimit
})))),
entitysource.WithDisplayName(file.Name()), entitysource.WithDisplayName(file.Name()),
) )
if err != nil { if err != nil {

@ -5,6 +5,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/samber/lo"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
@ -233,7 +234,9 @@ func (m *CreateArchiveTask) listEntitiesAndSendToSlave(ctx context.Context, dep
} }
} }
}), }),
fs.WithMaxArchiveSize(user.Edges.Group.Settings.CompressSize), fs.WithMaxArchiveSize(lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int64 {
return item.Settings.CompressSize
}))),
) )
if err != nil { if err != nil {
return task.StatusError, fmt.Errorf("failed to compress files: %w", err) return task.StatusError, fmt.Errorf("failed to compress files: %w", err)
@ -390,7 +393,9 @@ func (m *CreateArchiveTask) createArchiveFile(ctx context.Context, dep dependenc
m.Unlock() m.Unlock()
failed, err := fm.CreateArchive(ctx, uris, zipFile, failed, err := fm.CreateArchive(ctx, uris, zipFile,
fs.WithArchiveCompression(true), fs.WithArchiveCompression(true),
fs.WithMaxArchiveSize(user.Edges.Group.Settings.CompressSize), fs.WithMaxArchiveSize(lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int64 {
return item.Settings.CompressSize
}))),
fs.WithProgressFunc(func(current, diff int64, total int64) { fs.WithProgressFunc(func(current, diff int64, total int64) {
atomic.AddInt64(&m.progress[ProgressTypeArchiveSize].Current, diff) atomic.AddInt64(&m.progress[ProgressTypeArchiveSize].Current, diff)
atomic.AddInt64(&m.progress[ProgressTypeArchiveCount].Current, 1) atomic.AddInt64(&m.progress[ProgressTypeArchiveCount].Current, 1)

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/samber/lo"
"io" "io"
"os" "os"
"path" "path"
@ -178,9 +179,12 @@ func (m *ExtractArchiveTask) createSlaveExtractTask(ctx context.Context, dep dep
} }
// Validate file size // Validate file size
if user.Edges.Group.Settings.DecompressSize > 0 && archiveFile.Size() > user.Edges.Group.Settings.DecompressSize { decompressSize := lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int64 {
return item.Settings.DecompressSize
}))
if decompressSize > 0 && archiveFile.Size() > decompressSize {
return task.StatusError, return task.StatusError,
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.Edges.Group.Settings.DecompressSize, queue.CriticalErr) fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), decompressSize, queue.CriticalErr)
} }
// Create slave task // Create slave task
@ -263,9 +267,12 @@ func (m *ExtractArchiveTask) masterExtractArchive(ctx context.Context, dep depen
} }
// Validate file size // Validate file size
if user.Edges.Group.Settings.DecompressSize > 0 && archiveFile.Size() > user.Edges.Group.Settings.DecompressSize { decompressSize := lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int64 {
return item.Settings.DecompressSize
}))
if decompressSize > 0 && archiveFile.Size() > decompressSize {
return task.StatusError, return task.StatusError,
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.Edges.Group.Settings.DecompressSize, queue.CriticalErr) fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), decompressSize, queue.CriticalErr)
} }
es, err := fm.GetEntitySource(ctx, 0, fs.WithEntity(archiveFile.PrimaryEntity())) es, err := fm.GetEntitySource(ctx, 0, fs.WithEntity(archiveFile.PrimaryEntity()))

@ -198,7 +198,7 @@ func (m *RemoteDownloadTask) createDownloadTask(ctx context.Context, dep depende
} }
// Create download task // Create download task
handle, err := m.d.CreateTask(ctx, torrentUrl, user.Edges.Group.Settings.RemoteDownloadOptions) handle, err := m.d.CreateTask(ctx, torrentUrl, user.Edges.Groups[0].Settings.RemoteDownloadOptions)
if err != nil { if err != nil {
return task.StatusError, fmt.Errorf("failed to create download task: %w", err) return task.StatusError, fmt.Errorf("failed to create download task: %w", err)
} }

@ -340,10 +340,14 @@ func handleGetHeadPost(c *gin.Context, user *ent.User, fm manager.FileManager) (
defer es.Close() defer es.Close()
es.Apply(entitysource.WithSpeedLimit(int64(user.Edges.Group.SpeedLimit))) es.Apply(entitysource.WithSpeedLimit(int64(lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int {
return item.SpeedLimit
})))))
if es.ShouldInternalProxy() || if es.ShouldInternalProxy() ||
(user.Edges.DavAccounts[0].Options.Enabled(int(types.DavAccountProxy)) && (user.Edges.DavAccounts[0].Options.Enabled(int(types.DavAccountProxy)) &&
user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy))) { lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy))
})) {
es.Serve(c.Writer, c.Request) es.Serve(c.Writer, c.Request)
} else { } else {
settings := dependency.FromContext(c).SettingProvider() settings := dependency.FromContext(c).SettingProvider()

@ -154,10 +154,12 @@ func (s *UpsertUserService) Update(c *gin.Context) (*GetUserResponse, error) {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user", err) return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user", err)
} }
if s.User.ID == 1 && existing.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if s.User.ID == 1 && lo.ContainsBy(existing.Edges.Groups, func(item *ent.Group) bool {
if s.User.GroupUsers != existing.GroupUsers { return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
return nil, serializer.NewError(serializer.CodeInvalidActionOnDefaultUser, "Cannot change default user's group", nil) }) {
} //if s.User.GroupUsers != existing.GroupUsers {
// return nil, serializer.NewError(serializer.CodeInvalidActionOnDefaultUser, "Cannot change default user's group", nil)
//}
if s.User.Status != user.StatusActive { if s.User.Status != user.StatusActive {
return nil, serializer.NewError(serializer.CodeInvalidActionOnDefaultUser, "Cannot change default user's status", nil) return nil, serializer.NewError(serializer.CodeInvalidActionOnDefaultUser, "Cannot change default user's status", nil)

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"github.com/cloudreve/Cloudreve/v4/ent"
"net/http" "net/http"
"time" "time"
@ -100,11 +101,14 @@ func (s *GetDirectLinkService) Get(c *gin.Context) ([]DirectLinkResponse, error)
dep := dependency.FromContext(c) dep := dependency.FromContext(c)
u := inventory.UserFromContext(c) u := inventory.UserFromContext(c)
if u.Edges.Group.Settings.SourceBatchSize == 0 { sourceBatchSize := lo.Max(lo.Map(u.Edges.Groups, func(item *ent.Group, index int) int {
return item.Settings.SourceBatchSize
}))
if sourceBatchSize == 0 {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil)
} }
if len(s.Uris) > u.Edges.Group.Settings.SourceBatchSize { if len(s.Uris) > sourceBatchSize {
return nil, serializer.NewError(serializer.CodeBatchSourceSize, "", nil) return nil, serializer.NewError(serializer.CodeBatchSourceSize, "", nil)
} }
@ -369,7 +373,9 @@ func (s *FileURLService) GetArchiveDownloadSession(c *gin.Context) (*FileURLResp
return nil, serializer.NewError(serializer.CodeParamErr, "unknown uri", err) return nil, serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
} }
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveDownload)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionArchiveDownload))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil)
} }
@ -429,7 +435,9 @@ func (s *FileURLService) Get(c *gin.Context) (*FileURLResponse, error) {
} }
res, earliestExpire, err := m.GetEntityUrls(ctx, urlReq, res, earliestExpire, err := m.GetEntityUrls(ctx, urlReq,
fs.WithDownloadSpeed(int64(user.Edges.Group.SpeedLimit)), fs.WithDownloadSpeed(int64(lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int {
return item.SpeedLimit
})))),
fs.WithIsDownload(s.Download), fs.WithIsDownload(s.Download),
fs.WithNoCache(s.NoCache), fs.WithNoCache(s.NoCache),
fs.WithUrlExpire(&expire), fs.WithUrlExpire(&expire),
@ -522,7 +530,9 @@ func (s *DeleteFileService) Delete(c *gin.Context) error {
return serializer.NewError(serializer.CodeParamErr, "unknown uri", err) return serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
} }
if s.UnlinkOnly && !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionAdvanceDelete)) { if s.UnlinkOnly && !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionAdvanceDelete))
}) {
return serializer.NewError(serializer.CodeNoPermissionErr, "advance delete permission is required", nil) return serializer.NewError(serializer.CodeNoPermissionErr, "advance delete permission is required", nil)
} }

@ -85,7 +85,9 @@ func (service *DownloadWorkflowService) CreateDownloadTask(c *gin.Context) ([]*T
m := manager.NewFileManager(dep, user) m := manager.NewFileManager(dep, user)
defer m.Recycle() defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionRemoteDownload)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionRemoteDownload))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to download files", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to download files", nil)
} }
@ -111,7 +113,9 @@ func (service *DownloadWorkflowService) CreateDownloadTask(c *gin.Context) ([]*T
} }
// 检查批量任务数量 // 检查批量任务数量
limit := user.Edges.Group.Settings.Aria2BatchSize limit := lo.Max(lo.Map(user.Edges.Groups, func(item *ent.Group, index int) int {
return item.Settings.Aria2BatchSize
}))
if limit > 0 && len(service.Src) > limit { if limit > 0 && len(service.Src) > limit {
return nil, serializer.NewError(serializer.CodeBatchAria2Size, "", nil) return nil, serializer.NewError(serializer.CodeBatchAria2Size, "", nil)
} }
@ -184,7 +188,9 @@ func (service *ArchiveWorkflowService) CreateExtractTask(c *gin.Context) (*TaskR
m := manager.NewFileManager(dep, user) m := manager.NewFileManager(dep, user)
defer m.Recycle() defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveTask)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionArchiveTask))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil)
} }
@ -223,7 +229,9 @@ func (service *ArchiveWorkflowService) CreateCompressTask(c *gin.Context) (*Task
m := manager.NewFileManager(dep, user) m := manager.NewFileManager(dep, user)
defer m.Recycle() defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveTask)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionArchiveTask))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil)
} }
@ -278,7 +286,9 @@ func (service *ImportWorkflowService) CreateImportTask(c *gin.Context) (*TaskRes
m := manager.NewFileManager(dep, user) m := manager.NewFileManager(dep, user)
defer m.Recycle() defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Only admin can import files", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Only admin can import files", nil)
} }
@ -386,7 +396,10 @@ func TaskPhaseProgress(c *gin.Context, taskID int) (queue.Progresses, error) {
u := inventory.UserFromContext(c) u := inventory.UserFromContext(c)
r := dep.TaskRegistry() r := dep.TaskRegistry()
t, found := r.Get(taskID) t, found := r.Get(taskID)
if !found || (t.Owner().ID != u.ID && !u.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin))) {
if !found || (t.Owner().ID != u.ID && !lo.ContainsBy(u.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
})) {
return queue.Progresses{}, nil return queue.Progresses{}, nil
} }

@ -12,6 +12,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/pkg/serializer" "github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/cloudreve/Cloudreve/v4/pkg/util" "github.com/cloudreve/Cloudreve/v4/pkg/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/samber/lo"
) )
// WebDAVAccountService WebDAV 账号管理服务 // WebDAVAccountService WebDAV 账号管理服务
@ -153,7 +154,9 @@ func (service *CreateDavAccountService) Update(c *gin.Context) (*DavAccount, err
} }
func (service *CreateDavAccountService) validateAndGetBs(user *ent.User) (*boolset.BooleanSet, error) { func (service *CreateDavAccountService) validateAndGetBs(user *ent.User) (*boolset.BooleanSet, error) {
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAV)) { if !lo.ContainsBy(user.Edges.Groups, func(g *ent.Group) bool {
return g.Permissions.Enabled(int(types.GroupPermissionWebDAV))
}) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "WebDAV is not enabled for this user group", nil) return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "WebDAV is not enabled for this user group", nil)
} }
@ -173,7 +176,9 @@ func (service *CreateDavAccountService) validateAndGetBs(user *ent.User) (*bools
boolset.Set(types.DavAccountReadOnly, true, &bs) boolset.Set(types.DavAccountReadOnly, true, &bs)
} }
if service.Proxy && user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy)) { if service.Proxy && lo.ContainsBy(user.Edges.Groups, func(g *ent.Group) bool {
return g.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy))
}) {
boolset.Set(types.DavAccountProxy, true, &bs) boolset.Set(types.DavAccountProxy, true, &bs)
} }
return &bs, nil return &bs, nil

@ -2,6 +2,7 @@ package share
import ( import (
"context" "context"
"github.com/samber/lo"
"time" "time"
"github.com/cloudreve/Cloudreve/v4/application/dependency" "github.com/cloudreve/Cloudreve/v4/application/dependency"
@ -36,7 +37,9 @@ func (service *ShareCreateService) Upsert(c *gin.Context, existed int) (string,
defer m.Recycle() defer m.Recycle()
// Check group permission for creating share link // Check group permission for creating share link
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionShare)) { if !lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionShare))
}) {
return "", serializer.NewError(serializer.CodeGroupNotAllowed, "Group permission denied", nil) return "", serializer.NewError(serializer.CodeGroupNotAllowed, "Group permission denied", nil)
} }
@ -77,7 +80,10 @@ func DeleteShare(c *gin.Context, shareId int) error {
share *ent.Share share *ent.Share
err error err error
) )
if user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if lo.ContainsBy(user.Edges.Groups, func(item *ent.Group) bool {
return item.Permissions.Enabled(int(types.GroupPermissionIsAdmin))
}) {
share, err = shareClient.GetByID(ctx, shareId) share, err = shareClient.GetByID(ctx, shareId)
} else { } else {
share, err = shareClient.GetByIDUser(ctx, shareId, user.ID) share, err = shareClient.GetByIDUser(ctx, shareId, user.ID)

@ -105,7 +105,7 @@ type User struct {
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
PreferredTheme string `json:"preferred_theme,omitempty"` PreferredTheme string `json:"preferred_theme,omitempty"`
Anonymous bool `json:"anonymous,omitempty"` Anonymous bool `json:"anonymous,omitempty"`
Group *Group `json:"group,omitempty"` Groups []*Group `json:"groups,omitempty"`
Pined []types.PinedFile `json:"pined,omitempty"` Pined []types.PinedFile `json:"pined,omitempty"`
Language string `json:"language,omitempty"` Language string `json:"language,omitempty"`
DisableViewSync bool `json:"disable_view_sync,omitempty"` DisableViewSync bool `json:"disable_view_sync,omitempty"`
@ -161,7 +161,9 @@ func BuildUser(user *ent.User, idEncoder hashid.Encoder) User {
CreatedAt: user.CreatedAt, CreatedAt: user.CreatedAt,
PreferredTheme: user.Settings.PreferredTheme, PreferredTheme: user.Settings.PreferredTheme,
Anonymous: user.ID == 0, Anonymous: user.ID == 0,
Group: BuildGroup(user.Edges.Group, idEncoder), Groups: lo.Map(user.Edges.Groups, func(item *ent.Group, index int) *Group {
return BuildGroup(item, idEncoder)
}),
Pined: user.Settings.Pined, Pined: user.Settings.Pined,
Language: user.Settings.Language, Language: user.Settings.Language,
DisableViewSync: user.Settings.DisableViewSync, DisableViewSync: user.Settings.DisableViewSync,
@ -199,8 +201,10 @@ func BuildUserRedacted(u *ent.User, level int, idEncoder hashid.Encoder) User {
CreatedAt: userRaw.CreatedAt, CreatedAt: userRaw.CreatedAt,
} }
if userRaw.Group != nil { if userRaw.Groups != nil {
user.Group = RedactedGroup(userRaw.Group) user.Groups = lo.Map(userRaw.Groups, func(item *Group, index int) *Group {
return RedactedGroup(item)
})
} }
if level == RedactLevelUser { if level == RedactLevelUser {

Loading…
Cancel
Save