Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>pull/3587/head
commit
d04e7a0783
@ -0,0 +1,215 @@
|
||||
// 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/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/file"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
// AclEntry is the model entity for the AclEntry schema.
|
||||
type AclEntry struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
// DeletedAt holds the value of the "deleted_at" field.
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
||||
// FileID holds the value of the "file_id" field.
|
||||
FileID int `json:"file_id,omitempty"`
|
||||
// SubjectType holds the value of the "subject_type" field.
|
||||
SubjectType aclentry.SubjectType `json:"subject_type,omitempty"`
|
||||
// SubjectID holds the value of the "subject_id" field.
|
||||
SubjectID int `json:"subject_id,omitempty"`
|
||||
// Permissions holds the value of the "permissions" field.
|
||||
Permissions *boolset.BooleanSet `json:"permissions,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AclEntryQuery when eager-loading is set.
|
||||
Edges AclEntryEdges `json:"edges"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// AclEntryEdges holds the relations/edges for other nodes in the graph.
|
||||
type AclEntryEdges struct {
|
||||
// File holds the value of the file edge.
|
||||
File *File `json:"file,omitempty"`
|
||||
// loadedTypes holds the information for reporting if a
|
||||
// type was loaded (or requested) in eager-loading or not.
|
||||
loadedTypes [1]bool
|
||||
}
|
||||
|
||||
// FileOrErr returns the File value or an error if the edge
|
||||
// was not loaded in eager-loading, or loaded but was not found.
|
||||
func (e AclEntryEdges) FileOrErr() (*File, error) {
|
||||
if e.loadedTypes[0] {
|
||||
if e.File == nil {
|
||||
// Edge was loaded but was not found.
|
||||
return nil, &NotFoundError{label: file.Label}
|
||||
}
|
||||
return e.File, nil
|
||||
}
|
||||
return nil, &NotLoadedError{edge: "file"}
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*AclEntry) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case aclentry.FieldPermissions:
|
||||
values[i] = new(boolset.BooleanSet)
|
||||
case aclentry.FieldID, aclentry.FieldFileID, aclentry.FieldSubjectID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case aclentry.FieldSubjectType:
|
||||
values[i] = new(sql.NullString)
|
||||
case aclentry.FieldCreatedAt, aclentry.FieldUpdatedAt, aclentry.FieldDeletedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
values[i] = new(sql.UnknownType)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the AclEntry fields.
|
||||
func (ae *AclEntry) 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 aclentry.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
ae.ID = int(value.Int64)
|
||||
case aclentry.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
ae.CreatedAt = value.Time
|
||||
}
|
||||
case aclentry.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
ae.UpdatedAt = value.Time
|
||||
}
|
||||
case aclentry.FieldDeletedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
|
||||
} else if value.Valid {
|
||||
ae.DeletedAt = new(time.Time)
|
||||
*ae.DeletedAt = value.Time
|
||||
}
|
||||
case aclentry.FieldFileID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field file_id", values[i])
|
||||
} else if value.Valid {
|
||||
ae.FileID = int(value.Int64)
|
||||
}
|
||||
case aclentry.FieldSubjectType:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field subject_type", values[i])
|
||||
} else if value.Valid {
|
||||
ae.SubjectType = aclentry.SubjectType(value.String)
|
||||
}
|
||||
case aclentry.FieldSubjectID:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field subject_id", values[i])
|
||||
} else if value.Valid {
|
||||
ae.SubjectID = int(value.Int64)
|
||||
}
|
||||
case aclentry.FieldPermissions:
|
||||
if value, ok := values[i].(*boolset.BooleanSet); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field permissions", values[i])
|
||||
} else if value != nil {
|
||||
ae.Permissions = value
|
||||
}
|
||||
default:
|
||||
ae.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the AclEntry.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (ae *AclEntry) Value(name string) (ent.Value, error) {
|
||||
return ae.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// QueryFile queries the "file" edge of the AclEntry entity.
|
||||
func (ae *AclEntry) QueryFile() *FileQuery {
|
||||
return NewAclEntryClient(ae.config).QueryFile(ae)
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this AclEntry.
|
||||
// Note that you need to call AclEntry.Unwrap() before calling this method if this AclEntry
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (ae *AclEntry) Update() *AclEntryUpdateOne {
|
||||
return NewAclEntryClient(ae.config).UpdateOne(ae)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the AclEntry 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 (ae *AclEntry) Unwrap() *AclEntry {
|
||||
_tx, ok := ae.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: AclEntry is not a transactional entity")
|
||||
}
|
||||
ae.config.driver = _tx.drv
|
||||
return ae
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (ae *AclEntry) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("AclEntry(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", ae.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(ae.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(ae.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
if v := ae.DeletedAt; v != nil {
|
||||
builder.WriteString("deleted_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("file_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", ae.FileID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("subject_type=")
|
||||
builder.WriteString(fmt.Sprintf("%v", ae.SubjectType))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("subject_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", ae.SubjectID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("permissions=")
|
||||
builder.WriteString(fmt.Sprintf("%v", ae.Permissions))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// SetFile manually set the edge as loaded state.
|
||||
func (e *AclEntry) SetFile(v *File) {
|
||||
e.Edges.File = v
|
||||
e.Edges.loadedTypes[0] = true
|
||||
}
|
||||
|
||||
// AclEntries is a parsable slice of AclEntry.
|
||||
type AclEntries []*AclEntry
|
||||
@ -0,0 +1,159 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package aclentry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the aclentry type in the database.
|
||||
Label = "acl_entry"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldDeletedAt holds the string denoting the deleted_at field in the database.
|
||||
FieldDeletedAt = "deleted_at"
|
||||
// FieldFileID holds the string denoting the file_id field in the database.
|
||||
FieldFileID = "file_id"
|
||||
// FieldSubjectType holds the string denoting the subject_type field in the database.
|
||||
FieldSubjectType = "subject_type"
|
||||
// FieldSubjectID holds the string denoting the subject_id field in the database.
|
||||
FieldSubjectID = "subject_id"
|
||||
// FieldPermissions holds the string denoting the permissions field in the database.
|
||||
FieldPermissions = "permissions"
|
||||
// EdgeFile holds the string denoting the file edge name in mutations.
|
||||
EdgeFile = "file"
|
||||
// Table holds the table name of the aclentry in the database.
|
||||
Table = "acl_entries"
|
||||
// FileTable is the table that holds the file relation/edge.
|
||||
FileTable = "acl_entries"
|
||||
// FileInverseTable is the table name for the File entity.
|
||||
// It exists in this package in order to avoid circular dependency with the "file" package.
|
||||
FileInverseTable = "files"
|
||||
// FileColumn is the table column denoting the file relation/edge.
|
||||
FileColumn = "file_id"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for aclentry fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldDeletedAt,
|
||||
FieldFileID,
|
||||
FieldSubjectType,
|
||||
FieldSubjectID,
|
||||
FieldPermissions,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Note that the variables below are initialized by the runtime
|
||||
// package on the initialization of the application. Therefore,
|
||||
// it should be imported in the main as follows:
|
||||
//
|
||||
// import _ "github.com/cloudreve/Cloudreve/v4/ent/runtime"
|
||||
var (
|
||||
Hooks [1]ent.Hook
|
||||
Interceptors [1]ent.Interceptor
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
)
|
||||
|
||||
// SubjectType defines the type for the "subject_type" enum field.
|
||||
type SubjectType string
|
||||
|
||||
// SubjectType values.
|
||||
const (
|
||||
SubjectTypeUser SubjectType = "user"
|
||||
SubjectTypeGroup SubjectType = "group"
|
||||
SubjectTypeAnonymous SubjectType = "anonymous"
|
||||
SubjectTypeEveryone SubjectType = "everyone"
|
||||
)
|
||||
|
||||
func (st SubjectType) String() string {
|
||||
return string(st)
|
||||
}
|
||||
|
||||
// SubjectTypeValidator is a validator for the "subject_type" field enum values. It is called by the builders before save.
|
||||
func SubjectTypeValidator(st SubjectType) error {
|
||||
switch st {
|
||||
case SubjectTypeUser, SubjectTypeGroup, SubjectTypeAnonymous, SubjectTypeEveryone:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("aclentry: invalid enum value for subject_type field: %q", st)
|
||||
}
|
||||
}
|
||||
|
||||
// OrderOption defines the ordering options for the AclEntry queries.
|
||||
type OrderOption func(*sql.Selector)
|
||||
|
||||
// ByID orders the results by the id field.
|
||||
func ByID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByCreatedAt orders the results by the created_at field.
|
||||
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByUpdatedAt orders the results by the updated_at field.
|
||||
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByDeletedAt orders the results by the deleted_at field.
|
||||
func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByFileID orders the results by the file_id field.
|
||||
func ByFileID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldFileID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySubjectType orders the results by the subject_type field.
|
||||
func BySubjectType(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSubjectType, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySubjectID orders the results by the subject_id field.
|
||||
func BySubjectID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSubjectID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByFileField orders the results by file field.
|
||||
func ByFileField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
sqlgraph.OrderByNeighborTerms(s, newFileStep(), sql.OrderByField(field, opts...))
|
||||
}
|
||||
}
|
||||
func newFileStep() *sqlgraph.Step {
|
||||
return sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.To(FileInverseTable, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, FileTable, FileColumn),
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,385 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package aclentry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldID, id))
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
|
||||
func DeletedAt(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// FileID applies equality check predicate on the "file_id" field. It's identical to FileIDEQ.
|
||||
func FileID(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldFileID, v))
|
||||
}
|
||||
|
||||
// SubjectID applies equality check predicate on the "subject_id" field. It's identical to SubjectIDEQ.
|
||||
func SubjectID(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// Permissions applies equality check predicate on the "permissions" field. It's identical to PermissionsEQ.
|
||||
func Permissions(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
|
||||
func DeletedAtEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
|
||||
func DeletedAtNEQ(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtIn applies the In predicate on the "deleted_at" field.
|
||||
func DeletedAtIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldDeletedAt, vs...))
|
||||
}
|
||||
|
||||
// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
|
||||
func DeletedAtNotIn(vs ...time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldDeletedAt, vs...))
|
||||
}
|
||||
|
||||
// DeletedAtGT applies the GT predicate on the "deleted_at" field.
|
||||
func DeletedAtGT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
|
||||
func DeletedAtGTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtLT applies the LT predicate on the "deleted_at" field.
|
||||
func DeletedAtLT(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
|
||||
func DeletedAtLTE(v time.Time) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldDeletedAt, v))
|
||||
}
|
||||
|
||||
// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
|
||||
func DeletedAtIsNil() predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIsNull(FieldDeletedAt))
|
||||
}
|
||||
|
||||
// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
|
||||
func DeletedAtNotNil() predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotNull(FieldDeletedAt))
|
||||
}
|
||||
|
||||
// FileIDEQ applies the EQ predicate on the "file_id" field.
|
||||
func FileIDEQ(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldFileID, v))
|
||||
}
|
||||
|
||||
// FileIDNEQ applies the NEQ predicate on the "file_id" field.
|
||||
func FileIDNEQ(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldFileID, v))
|
||||
}
|
||||
|
||||
// FileIDIn applies the In predicate on the "file_id" field.
|
||||
func FileIDIn(vs ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldFileID, vs...))
|
||||
}
|
||||
|
||||
// FileIDNotIn applies the NotIn predicate on the "file_id" field.
|
||||
func FileIDNotIn(vs ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldFileID, vs...))
|
||||
}
|
||||
|
||||
// SubjectTypeEQ applies the EQ predicate on the "subject_type" field.
|
||||
func SubjectTypeEQ(v SubjectType) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldSubjectType, v))
|
||||
}
|
||||
|
||||
// SubjectTypeNEQ applies the NEQ predicate on the "subject_type" field.
|
||||
func SubjectTypeNEQ(v SubjectType) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldSubjectType, v))
|
||||
}
|
||||
|
||||
// SubjectTypeIn applies the In predicate on the "subject_type" field.
|
||||
func SubjectTypeIn(vs ...SubjectType) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldSubjectType, vs...))
|
||||
}
|
||||
|
||||
// SubjectTypeNotIn applies the NotIn predicate on the "subject_type" field.
|
||||
func SubjectTypeNotIn(vs ...SubjectType) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldSubjectType, vs...))
|
||||
}
|
||||
|
||||
// SubjectIDEQ applies the EQ predicate on the "subject_id" field.
|
||||
func SubjectIDEQ(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDNEQ applies the NEQ predicate on the "subject_id" field.
|
||||
func SubjectIDNEQ(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDIn applies the In predicate on the "subject_id" field.
|
||||
func SubjectIDIn(vs ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldSubjectID, vs...))
|
||||
}
|
||||
|
||||
// SubjectIDNotIn applies the NotIn predicate on the "subject_id" field.
|
||||
func SubjectIDNotIn(vs ...int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldSubjectID, vs...))
|
||||
}
|
||||
|
||||
// SubjectIDGT applies the GT predicate on the "subject_id" field.
|
||||
func SubjectIDGT(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDGTE applies the GTE predicate on the "subject_id" field.
|
||||
func SubjectIDGTE(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDLT applies the LT predicate on the "subject_id" field.
|
||||
func SubjectIDLT(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDLTE applies the LTE predicate on the "subject_id" field.
|
||||
func SubjectIDLTE(v int) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldSubjectID, v))
|
||||
}
|
||||
|
||||
// SubjectIDIsNil applies the IsNil predicate on the "subject_id" field.
|
||||
func SubjectIDIsNil() predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIsNull(FieldSubjectID))
|
||||
}
|
||||
|
||||
// SubjectIDNotNil applies the NotNil predicate on the "subject_id" field.
|
||||
func SubjectIDNotNil() predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotNull(FieldSubjectID))
|
||||
}
|
||||
|
||||
// PermissionsEQ applies the EQ predicate on the "permissions" field.
|
||||
func PermissionsEQ(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldEQ(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// PermissionsNEQ applies the NEQ predicate on the "permissions" field.
|
||||
func PermissionsNEQ(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNEQ(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// PermissionsIn applies the In predicate on the "permissions" field.
|
||||
func PermissionsIn(vs ...*boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldIn(FieldPermissions, vs...))
|
||||
}
|
||||
|
||||
// PermissionsNotIn applies the NotIn predicate on the "permissions" field.
|
||||
func PermissionsNotIn(vs ...*boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldNotIn(FieldPermissions, vs...))
|
||||
}
|
||||
|
||||
// PermissionsGT applies the GT predicate on the "permissions" field.
|
||||
func PermissionsGT(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGT(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// PermissionsGTE applies the GTE predicate on the "permissions" field.
|
||||
func PermissionsGTE(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldGTE(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// PermissionsLT applies the LT predicate on the "permissions" field.
|
||||
func PermissionsLT(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLT(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// PermissionsLTE applies the LTE predicate on the "permissions" field.
|
||||
func PermissionsLTE(v *boolset.BooleanSet) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.FieldLTE(FieldPermissions, v))
|
||||
}
|
||||
|
||||
// HasFile applies the HasEdge predicate on the "file" edge.
|
||||
func HasFile() predicate.AclEntry {
|
||||
return predicate.AclEntry(func(s *sql.Selector) {
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(Table, FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, FileTable, FileColumn),
|
||||
)
|
||||
sqlgraph.HasNeighbors(s, step)
|
||||
})
|
||||
}
|
||||
|
||||
// HasFileWith applies the HasEdge predicate on the "file" edge with a given conditions (other predicates).
|
||||
func HasFileWith(preds ...predicate.File) predicate.AclEntry {
|
||||
return predicate.AclEntry(func(s *sql.Selector) {
|
||||
step := newFileStep()
|
||||
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.AclEntry) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.AclEntry) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.AclEntry) predicate.AclEntry {
|
||||
return predicate.AclEntry(sql.NotPredicates(p))
|
||||
}
|
||||
@ -0,0 +1,894 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/file"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
// AclEntryCreate is the builder for creating a AclEntry entity.
|
||||
type AclEntryCreate struct {
|
||||
config
|
||||
mutation *AclEntryMutation
|
||||
hooks []Hook
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (aec *AclEntryCreate) SetCreatedAt(t time.Time) *AclEntryCreate {
|
||||
aec.mutation.SetCreatedAt(t)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (aec *AclEntryCreate) SetNillableCreatedAt(t *time.Time) *AclEntryCreate {
|
||||
if t != nil {
|
||||
aec.SetCreatedAt(*t)
|
||||
}
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (aec *AclEntryCreate) SetUpdatedAt(t time.Time) *AclEntryCreate {
|
||||
aec.mutation.SetUpdatedAt(t)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||
func (aec *AclEntryCreate) SetNillableUpdatedAt(t *time.Time) *AclEntryCreate {
|
||||
if t != nil {
|
||||
aec.SetUpdatedAt(*t)
|
||||
}
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (aec *AclEntryCreate) SetDeletedAt(t time.Time) *AclEntryCreate {
|
||||
aec.mutation.SetDeletedAt(t)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||
func (aec *AclEntryCreate) SetNillableDeletedAt(t *time.Time) *AclEntryCreate {
|
||||
if t != nil {
|
||||
aec.SetDeletedAt(*t)
|
||||
}
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (aec *AclEntryCreate) SetFileID(i int) *AclEntryCreate {
|
||||
aec.mutation.SetFileID(i)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (aec *AclEntryCreate) SetSubjectType(at aclentry.SubjectType) *AclEntryCreate {
|
||||
aec.mutation.SetSubjectType(at)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (aec *AclEntryCreate) SetSubjectID(i int) *AclEntryCreate {
|
||||
aec.mutation.SetSubjectID(i)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetNillableSubjectID sets the "subject_id" field if the given value is not nil.
|
||||
func (aec *AclEntryCreate) SetNillableSubjectID(i *int) *AclEntryCreate {
|
||||
if i != nil {
|
||||
aec.SetSubjectID(*i)
|
||||
}
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (aec *AclEntryCreate) SetPermissions(bs *boolset.BooleanSet) *AclEntryCreate {
|
||||
aec.mutation.SetPermissions(bs)
|
||||
return aec
|
||||
}
|
||||
|
||||
// SetFile sets the "file" edge to the File entity.
|
||||
func (aec *AclEntryCreate) SetFile(f *File) *AclEntryCreate {
|
||||
return aec.SetFileID(f.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AclEntryMutation object of the builder.
|
||||
func (aec *AclEntryCreate) Mutation() *AclEntryMutation {
|
||||
return aec.mutation
|
||||
}
|
||||
|
||||
// Save creates the AclEntry in the database.
|
||||
func (aec *AclEntryCreate) Save(ctx context.Context) (*AclEntry, error) {
|
||||
if err := aec.defaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return withHooks(ctx, aec.sqlSave, aec.mutation, aec.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (aec *AclEntryCreate) SaveX(ctx context.Context) *AclEntry {
|
||||
v, err := aec.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (aec *AclEntryCreate) Exec(ctx context.Context) error {
|
||||
_, err := aec.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aec *AclEntryCreate) ExecX(ctx context.Context) {
|
||||
if err := aec.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (aec *AclEntryCreate) defaults() error {
|
||||
if _, ok := aec.mutation.CreatedAt(); !ok {
|
||||
if aclentry.DefaultCreatedAt == nil {
|
||||
return fmt.Errorf("ent: uninitialized aclentry.DefaultCreatedAt (forgotten import ent/runtime?)")
|
||||
}
|
||||
v := aclentry.DefaultCreatedAt()
|
||||
aec.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := aec.mutation.UpdatedAt(); !ok {
|
||||
if aclentry.DefaultUpdatedAt == nil {
|
||||
return fmt.Errorf("ent: uninitialized aclentry.DefaultUpdatedAt (forgotten import ent/runtime?)")
|
||||
}
|
||||
v := aclentry.DefaultUpdatedAt()
|
||||
aec.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (aec *AclEntryCreate) check() error {
|
||||
if _, ok := aec.mutation.CreatedAt(); !ok {
|
||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "AclEntry.created_at"`)}
|
||||
}
|
||||
if _, ok := aec.mutation.UpdatedAt(); !ok {
|
||||
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "AclEntry.updated_at"`)}
|
||||
}
|
||||
if _, ok := aec.mutation.FileID(); !ok {
|
||||
return &ValidationError{Name: "file_id", err: errors.New(`ent: missing required field "AclEntry.file_id"`)}
|
||||
}
|
||||
if _, ok := aec.mutation.SubjectType(); !ok {
|
||||
return &ValidationError{Name: "subject_type", err: errors.New(`ent: missing required field "AclEntry.subject_type"`)}
|
||||
}
|
||||
if v, ok := aec.mutation.SubjectType(); ok {
|
||||
if err := aclentry.SubjectTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "subject_type", err: fmt.Errorf(`ent: validator failed for field "AclEntry.subject_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := aec.mutation.Permissions(); !ok {
|
||||
return &ValidationError{Name: "permissions", err: errors.New(`ent: missing required field "AclEntry.permissions"`)}
|
||||
}
|
||||
if _, ok := aec.mutation.FileID(); !ok {
|
||||
return &ValidationError{Name: "file", err: errors.New(`ent: missing required edge "AclEntry.file"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (aec *AclEntryCreate) sqlSave(ctx context.Context) (*AclEntry, error) {
|
||||
if err := aec.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_node, _spec := aec.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, aec.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)
|
||||
aec.mutation.id = &_node.ID
|
||||
aec.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (aec *AclEntryCreate) createSpec() (*AclEntry, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &AclEntry{config: aec.config}
|
||||
_spec = sqlgraph.NewCreateSpec(aclentry.Table, sqlgraph.NewFieldSpec(aclentry.FieldID, field.TypeInt))
|
||||
)
|
||||
|
||||
if id, ok := aec.mutation.ID(); ok {
|
||||
_node.ID = id
|
||||
id64 := int64(id)
|
||||
_spec.ID.Value = id64
|
||||
}
|
||||
|
||||
_spec.OnConflict = aec.conflict
|
||||
if value, ok := aec.mutation.CreatedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldCreatedAt, field.TypeTime, value)
|
||||
_node.CreatedAt = value
|
||||
}
|
||||
if value, ok := aec.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldUpdatedAt, field.TypeTime, value)
|
||||
_node.UpdatedAt = value
|
||||
}
|
||||
if value, ok := aec.mutation.DeletedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldDeletedAt, field.TypeTime, value)
|
||||
_node.DeletedAt = &value
|
||||
}
|
||||
if value, ok := aec.mutation.SubjectType(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectType, field.TypeEnum, value)
|
||||
_node.SubjectType = value
|
||||
}
|
||||
if value, ok := aec.mutation.SubjectID(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectID, field.TypeInt, value)
|
||||
_node.SubjectID = value
|
||||
}
|
||||
if value, ok := aec.mutation.Permissions(); ok {
|
||||
_spec.SetField(aclentry.FieldPermissions, field.TypeBytes, value)
|
||||
_node.Permissions = value
|
||||
}
|
||||
if nodes := aec.mutation.FileIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: aclentry.FileTable,
|
||||
Columns: []string{aclentry.FileColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(file.FieldID, field.TypeInt),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_node.FileID = 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.AclEntry.Create().
|
||||
// SetCreatedAt(v).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.AclEntryUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (aec *AclEntryCreate) OnConflict(opts ...sql.ConflictOption) *AclEntryUpsertOne {
|
||||
aec.conflict = opts
|
||||
return &AclEntryUpsertOne{
|
||||
create: aec,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (aec *AclEntryCreate) OnConflictColumns(columns ...string) *AclEntryUpsertOne {
|
||||
aec.conflict = append(aec.conflict, sql.ConflictColumns(columns...))
|
||||
return &AclEntryUpsertOne{
|
||||
create: aec,
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// AclEntryUpsertOne is the builder for "upsert"-ing
|
||||
// one AclEntry node.
|
||||
AclEntryUpsertOne struct {
|
||||
create *AclEntryCreate
|
||||
}
|
||||
|
||||
// AclEntryUpsert is the "OnConflict" setter.
|
||||
AclEntryUpsert struct {
|
||||
*sql.UpdateSet
|
||||
}
|
||||
)
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AclEntryUpsert) SetUpdatedAt(v time.Time) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldUpdatedAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdateUpdatedAt() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldUpdatedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (u *AclEntryUpsert) SetDeletedAt(v time.Time) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldDeletedAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdateDeletedAt() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldDeletedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||
func (u *AclEntryUpsert) ClearDeletedAt() *AclEntryUpsert {
|
||||
u.SetNull(aclentry.FieldDeletedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (u *AclEntryUpsert) SetFileID(v int) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldFileID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateFileID sets the "file_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdateFileID() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldFileID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (u *AclEntryUpsert) SetSubjectType(v aclentry.SubjectType) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldSubjectType, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateSubjectType sets the "subject_type" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdateSubjectType() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldSubjectType)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (u *AclEntryUpsert) SetSubjectID(v int) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldSubjectID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateSubjectID sets the "subject_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdateSubjectID() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldSubjectID)
|
||||
return u
|
||||
}
|
||||
|
||||
// AddSubjectID adds v to the "subject_id" field.
|
||||
func (u *AclEntryUpsert) AddSubjectID(v int) *AclEntryUpsert {
|
||||
u.Add(aclentry.FieldSubjectID, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// ClearSubjectID clears the value of the "subject_id" field.
|
||||
func (u *AclEntryUpsert) ClearSubjectID() *AclEntryUpsert {
|
||||
u.SetNull(aclentry.FieldSubjectID)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (u *AclEntryUpsert) SetPermissions(v *boolset.BooleanSet) *AclEntryUpsert {
|
||||
u.Set(aclentry.FieldPermissions, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdatePermissions sets the "permissions" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsert) UpdatePermissions() *AclEntryUpsert {
|
||||
u.SetExcluded(aclentry.FieldPermissions)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AclEntryUpsertOne) UpdateNewValues() *AclEntryUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(aclentry.FieldCreatedAt)
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AclEntryUpsertOne) Ignore() *AclEntryUpsertOne {
|
||||
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 *AclEntryUpsertOne) DoNothing() *AclEntryUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AclEntryCreate.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AclEntryUpsertOne) Update(set func(*AclEntryUpsert)) *AclEntryUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AclEntryUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AclEntryUpsertOne) SetUpdatedAt(v time.Time) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdateUpdatedAt() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (u *AclEntryUpsertOne) SetDeletedAt(v time.Time) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetDeletedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdateDeletedAt() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateDeletedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||
func (u *AclEntryUpsertOne) ClearDeletedAt() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.ClearDeletedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (u *AclEntryUpsertOne) SetFileID(v int) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetFileID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateFileID sets the "file_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdateFileID() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateFileID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (u *AclEntryUpsertOne) SetSubjectType(v aclentry.SubjectType) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetSubjectType(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSubjectType sets the "subject_type" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdateSubjectType() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateSubjectType()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (u *AclEntryUpsertOne) SetSubjectID(v int) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetSubjectID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddSubjectID adds v to the "subject_id" field.
|
||||
func (u *AclEntryUpsertOne) AddSubjectID(v int) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.AddSubjectID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSubjectID sets the "subject_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdateSubjectID() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateSubjectID()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearSubjectID clears the value of the "subject_id" field.
|
||||
func (u *AclEntryUpsertOne) ClearSubjectID() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.ClearSubjectID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (u *AclEntryUpsertOne) SetPermissions(v *boolset.BooleanSet) *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetPermissions(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatePermissions sets the "permissions" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertOne) UpdatePermissions() *AclEntryUpsertOne {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdatePermissions()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AclEntryUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AclEntryCreate.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AclEntryUpsertOne) 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 *AclEntryUpsertOne) 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 *AclEntryUpsertOne) IDX(ctx context.Context) int {
|
||||
id, err := u.ID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func (m *AclEntryCreate) SetRawID(t int) *AclEntryCreate {
|
||||
m.mutation.SetRawID(t)
|
||||
return m
|
||||
}
|
||||
|
||||
// AclEntryCreateBulk is the builder for creating many AclEntry entities in bulk.
|
||||
type AclEntryCreateBulk struct {
|
||||
config
|
||||
err error
|
||||
builders []*AclEntryCreate
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// Save creates the AclEntry entities in the database.
|
||||
func (aecb *AclEntryCreateBulk) Save(ctx context.Context) ([]*AclEntry, error) {
|
||||
if aecb.err != nil {
|
||||
return nil, aecb.err
|
||||
}
|
||||
specs := make([]*sqlgraph.CreateSpec, len(aecb.builders))
|
||||
nodes := make([]*AclEntry, len(aecb.builders))
|
||||
mutators := make([]Mutator, len(aecb.builders))
|
||||
for i := range aecb.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := aecb.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*AclEntryMutation)
|
||||
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, aecb.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
spec.OnConflict = aecb.conflict
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, aecb.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, aecb.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (aecb *AclEntryCreateBulk) SaveX(ctx context.Context) []*AclEntry {
|
||||
v, err := aecb.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (aecb *AclEntryCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := aecb.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aecb *AclEntryCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := aecb.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.AclEntry.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.AclEntryUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (aecb *AclEntryCreateBulk) OnConflict(opts ...sql.ConflictOption) *AclEntryUpsertBulk {
|
||||
aecb.conflict = opts
|
||||
return &AclEntryUpsertBulk{
|
||||
create: aecb,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (aecb *AclEntryCreateBulk) OnConflictColumns(columns ...string) *AclEntryUpsertBulk {
|
||||
aecb.conflict = append(aecb.conflict, sql.ConflictColumns(columns...))
|
||||
return &AclEntryUpsertBulk{
|
||||
create: aecb,
|
||||
}
|
||||
}
|
||||
|
||||
// AclEntryUpsertBulk is the builder for "upsert"-ing
|
||||
// a bulk of AclEntry nodes.
|
||||
type AclEntryUpsertBulk struct {
|
||||
create *AclEntryCreateBulk
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that
|
||||
// were set on create. Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *AclEntryUpsertBulk) UpdateNewValues() *AclEntryUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
for _, b := range u.create.builders {
|
||||
if _, exists := b.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(aclentry.FieldCreatedAt)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.AclEntry.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *AclEntryUpsertBulk) Ignore() *AclEntryUpsertBulk {
|
||||
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 *AclEntryUpsertBulk) DoNothing() *AclEntryUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the AclEntryCreateBulk.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *AclEntryUpsertBulk) Update(set func(*AclEntryUpsert)) *AclEntryUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&AclEntryUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *AclEntryUpsertBulk) SetUpdatedAt(v time.Time) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdateUpdatedAt() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (u *AclEntryUpsertBulk) SetDeletedAt(v time.Time) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetDeletedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdateDeletedAt() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateDeletedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||
func (u *AclEntryUpsertBulk) ClearDeletedAt() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.ClearDeletedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (u *AclEntryUpsertBulk) SetFileID(v int) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetFileID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateFileID sets the "file_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdateFileID() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateFileID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (u *AclEntryUpsertBulk) SetSubjectType(v aclentry.SubjectType) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetSubjectType(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSubjectType sets the "subject_type" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdateSubjectType() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateSubjectType()
|
||||
})
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (u *AclEntryUpsertBulk) SetSubjectID(v int) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetSubjectID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// AddSubjectID adds v to the "subject_id" field.
|
||||
func (u *AclEntryUpsertBulk) AddSubjectID(v int) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.AddSubjectID(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateSubjectID sets the "subject_id" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdateSubjectID() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdateSubjectID()
|
||||
})
|
||||
}
|
||||
|
||||
// ClearSubjectID clears the value of the "subject_id" field.
|
||||
func (u *AclEntryUpsertBulk) ClearSubjectID() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.ClearSubjectID()
|
||||
})
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (u *AclEntryUpsertBulk) SetPermissions(v *boolset.BooleanSet) *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.SetPermissions(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatePermissions sets the "permissions" field to the value that was provided on create.
|
||||
func (u *AclEntryUpsertBulk) UpdatePermissions() *AclEntryUpsertBulk {
|
||||
return u.Update(func(s *AclEntryUpsert) {
|
||||
s.UpdatePermissions()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *AclEntryUpsertBulk) 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 AclEntryCreateBulk instead", i)
|
||||
}
|
||||
}
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for AclEntryCreateBulk.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *AclEntryUpsertBulk) 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/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
|
||||
)
|
||||
|
||||
// AclEntryDelete is the builder for deleting a AclEntry entity.
|
||||
type AclEntryDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AclEntryMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AclEntryDelete builder.
|
||||
func (aed *AclEntryDelete) Where(ps ...predicate.AclEntry) *AclEntryDelete {
|
||||
aed.mutation.Where(ps...)
|
||||
return aed
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (aed *AclEntryDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, aed.sqlExec, aed.mutation, aed.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aed *AclEntryDelete) ExecX(ctx context.Context) int {
|
||||
n, err := aed.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (aed *AclEntryDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(aclentry.Table, sqlgraph.NewFieldSpec(aclentry.FieldID, field.TypeInt))
|
||||
if ps := aed.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, aed.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
aed.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// AclEntryDeleteOne is the builder for deleting a single AclEntry entity.
|
||||
type AclEntryDeleteOne struct {
|
||||
aed *AclEntryDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AclEntryDelete builder.
|
||||
func (aedo *AclEntryDeleteOne) Where(ps ...predicate.AclEntry) *AclEntryDeleteOne {
|
||||
aedo.aed.mutation.Where(ps...)
|
||||
return aedo
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (aedo *AclEntryDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := aedo.aed.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{aclentry.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aedo *AclEntryDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := aedo.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,605 @@
|
||||
// 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/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/file"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
|
||||
)
|
||||
|
||||
// AclEntryQuery is the builder for querying AclEntry entities.
|
||||
type AclEntryQuery struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []aclentry.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.AclEntry
|
||||
withFile *FileQuery
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the AclEntryQuery builder.
|
||||
func (aeq *AclEntryQuery) Where(ps ...predicate.AclEntry) *AclEntryQuery {
|
||||
aeq.predicates = append(aeq.predicates, ps...)
|
||||
return aeq
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func (aeq *AclEntryQuery) Limit(limit int) *AclEntryQuery {
|
||||
aeq.ctx.Limit = &limit
|
||||
return aeq
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func (aeq *AclEntryQuery) Offset(offset int) *AclEntryQuery {
|
||||
aeq.ctx.Offset = &offset
|
||||
return aeq
|
||||
}
|
||||
|
||||
// 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 (aeq *AclEntryQuery) Unique(unique bool) *AclEntryQuery {
|
||||
aeq.ctx.Unique = &unique
|
||||
return aeq
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func (aeq *AclEntryQuery) Order(o ...aclentry.OrderOption) *AclEntryQuery {
|
||||
aeq.order = append(aeq.order, o...)
|
||||
return aeq
|
||||
}
|
||||
|
||||
// QueryFile chains the current query on the "file" edge.
|
||||
func (aeq *AclEntryQuery) QueryFile() *FileQuery {
|
||||
query := (&FileClient{config: aeq.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
|
||||
if err := aeq.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector := aeq.sqlQuery(ctx)
|
||||
if err := selector.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(aclentry.Table, aclentry.FieldID, selector),
|
||||
sqlgraph.To(file.Table, file.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, aclentry.FileTable, aclentry.FileColumn),
|
||||
)
|
||||
fromU = sqlgraph.SetNeighbors(aeq.driver.Dialect(), step)
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// First returns the first AclEntry entity from the query.
|
||||
// Returns a *NotFoundError when no AclEntry was found.
|
||||
func (aeq *AclEntryQuery) First(ctx context.Context) (*AclEntry, error) {
|
||||
nodes, err := aeq.Limit(1).All(setContextOp(ctx, aeq.ctx, "First"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{aclentry.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) FirstX(ctx context.Context) *AclEntry {
|
||||
node, err := aeq.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first AclEntry ID from the query.
|
||||
// Returns a *NotFoundError when no AclEntry ID was found.
|
||||
func (aeq *AclEntryQuery) FirstID(ctx context.Context) (id int, err error) {
|
||||
var ids []int
|
||||
if ids, err = aeq.Limit(1).IDs(setContextOp(ctx, aeq.ctx, "FirstID")); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{aclentry.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) FirstIDX(ctx context.Context) int {
|
||||
id, err := aeq.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single AclEntry entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one AclEntry entity is found.
|
||||
// Returns a *NotFoundError when no AclEntry entities are found.
|
||||
func (aeq *AclEntryQuery) Only(ctx context.Context) (*AclEntry, error) {
|
||||
nodes, err := aeq.Limit(2).All(setContextOp(ctx, aeq.ctx, "Only"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{aclentry.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{aclentry.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) OnlyX(ctx context.Context) *AclEntry {
|
||||
node, err := aeq.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only AclEntry ID in the query.
|
||||
// Returns a *NotSingularError when more than one AclEntry ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (aeq *AclEntryQuery) OnlyID(ctx context.Context) (id int, err error) {
|
||||
var ids []int
|
||||
if ids, err = aeq.Limit(2).IDs(setContextOp(ctx, aeq.ctx, "OnlyID")); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{aclentry.Label}
|
||||
default:
|
||||
err = &NotSingularError{aclentry.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) OnlyIDX(ctx context.Context) int {
|
||||
id, err := aeq.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of AclEntries.
|
||||
func (aeq *AclEntryQuery) All(ctx context.Context) ([]*AclEntry, error) {
|
||||
ctx = setContextOp(ctx, aeq.ctx, "All")
|
||||
if err := aeq.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*AclEntry, *AclEntryQuery]()
|
||||
return withInterceptors[[]*AclEntry](ctx, aeq, qr, aeq.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) AllX(ctx context.Context) []*AclEntry {
|
||||
nodes, err := aeq.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of AclEntry IDs.
|
||||
func (aeq *AclEntryQuery) IDs(ctx context.Context) (ids []int, err error) {
|
||||
if aeq.ctx.Unique == nil && aeq.path != nil {
|
||||
aeq.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, aeq.ctx, "IDs")
|
||||
if err = aeq.Select(aclentry.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) IDsX(ctx context.Context) []int {
|
||||
ids, err := aeq.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (aeq *AclEntryQuery) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, aeq.ctx, "Count")
|
||||
if err := aeq.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, aeq, querierCount[*AclEntryQuery](), aeq.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (aeq *AclEntryQuery) CountX(ctx context.Context) int {
|
||||
count, err := aeq.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (aeq *AclEntryQuery) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, aeq.ctx, "Exist")
|
||||
switch _, err := aeq.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 (aeq *AclEntryQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := aeq.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the AclEntryQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (aeq *AclEntryQuery) Clone() *AclEntryQuery {
|
||||
if aeq == nil {
|
||||
return nil
|
||||
}
|
||||
return &AclEntryQuery{
|
||||
config: aeq.config,
|
||||
ctx: aeq.ctx.Clone(),
|
||||
order: append([]aclentry.OrderOption{}, aeq.order...),
|
||||
inters: append([]Interceptor{}, aeq.inters...),
|
||||
predicates: append([]predicate.AclEntry{}, aeq.predicates...),
|
||||
withFile: aeq.withFile.Clone(),
|
||||
// clone intermediate query.
|
||||
sql: aeq.sql.Clone(),
|
||||
path: aeq.path,
|
||||
}
|
||||
}
|
||||
|
||||
// WithFile tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "file" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func (aeq *AclEntryQuery) WithFile(opts ...func(*FileQuery)) *AclEntryQuery {
|
||||
query := (&FileClient{config: aeq.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
aeq.withFile = query
|
||||
return aeq
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AclEntry.Query().
|
||||
// GroupBy(aclentry.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
func (aeq *AclEntryQuery) GroupBy(field string, fields ...string) *AclEntryGroupBy {
|
||||
aeq.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &AclEntryGroupBy{build: aeq}
|
||||
grbuild.flds = &aeq.ctx.Fields
|
||||
grbuild.label = aclentry.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.AclEntry.Query().
|
||||
// Select(aclentry.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
func (aeq *AclEntryQuery) Select(fields ...string) *AclEntrySelect {
|
||||
aeq.ctx.Fields = append(aeq.ctx.Fields, fields...)
|
||||
sbuild := &AclEntrySelect{AclEntryQuery: aeq}
|
||||
sbuild.label = aclentry.Label
|
||||
sbuild.flds, sbuild.scan = &aeq.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a AclEntrySelect configured with the given aggregations.
|
||||
func (aeq *AclEntryQuery) Aggregate(fns ...AggregateFunc) *AclEntrySelect {
|
||||
return aeq.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range aeq.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, aeq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, f := range aeq.ctx.Fields {
|
||||
if !aclentry.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if aeq.path != nil {
|
||||
prev, err := aeq.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aeq.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AclEntry, error) {
|
||||
var (
|
||||
nodes = []*AclEntry{}
|
||||
_spec = aeq.querySpec()
|
||||
loadedTypes = [1]bool{
|
||||
aeq.withFile != nil,
|
||||
}
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]any, error) {
|
||||
return (*AclEntry).scanValues(nil, columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []any) error {
|
||||
node := &AclEntry{config: aeq.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, aeq.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
if query := aeq.withFile; query != nil {
|
||||
if err := aeq.loadFile(ctx, query, nodes, nil,
|
||||
func(n *AclEntry, e *File) { n.Edges.File = e }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) loadFile(ctx context.Context, query *FileQuery, nodes []*AclEntry, init func(*AclEntry), assign func(*AclEntry, *File)) error {
|
||||
ids := make([]int, 0, len(nodes))
|
||||
nodeids := make(map[int][]*AclEntry)
|
||||
for i := range nodes {
|
||||
fk := nodes[i].FileID
|
||||
if _, ok := nodeids[fk]; !ok {
|
||||
ids = append(ids, fk)
|
||||
}
|
||||
nodeids[fk] = append(nodeids[fk], nodes[i])
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
query.Where(file.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 "file_id" returned %v`, n.ID)
|
||||
}
|
||||
for i := range nodes {
|
||||
assign(nodes[i], n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := aeq.querySpec()
|
||||
_spec.Node.Columns = aeq.ctx.Fields
|
||||
if len(aeq.ctx.Fields) > 0 {
|
||||
_spec.Unique = aeq.ctx.Unique != nil && *aeq.ctx.Unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, aeq.driver, _spec)
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := sqlgraph.NewQuerySpec(aclentry.Table, aclentry.Columns, sqlgraph.NewFieldSpec(aclentry.FieldID, field.TypeInt))
|
||||
_spec.From = aeq.sql
|
||||
if unique := aeq.ctx.Unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
} else if aeq.path != nil {
|
||||
_spec.Unique = true
|
||||
}
|
||||
if fields := aeq.ctx.Fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, aclentry.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != aclentry.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
if aeq.withFile != nil {
|
||||
_spec.Node.AddColumnOnce(aclentry.FieldFileID)
|
||||
}
|
||||
}
|
||||
if ps := aeq.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := aeq.ctx.Limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := aeq.ctx.Offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := aeq.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (aeq *AclEntryQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(aeq.driver.Dialect())
|
||||
t1 := builder.Table(aclentry.Table)
|
||||
columns := aeq.ctx.Fields
|
||||
if len(columns) == 0 {
|
||||
columns = aclentry.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if aeq.sql != nil {
|
||||
selector = aeq.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if aeq.ctx.Unique != nil && *aeq.ctx.Unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, p := range aeq.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range aeq.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := aeq.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 := aeq.ctx.Limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// AclEntryGroupBy is the group-by builder for AclEntry entities.
|
||||
type AclEntryGroupBy struct {
|
||||
selector
|
||||
build *AclEntryQuery
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (aegb *AclEntryGroupBy) Aggregate(fns ...AggregateFunc) *AclEntryGroupBy {
|
||||
aegb.fns = append(aegb.fns, fns...)
|
||||
return aegb
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (aegb *AclEntryGroupBy) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, aegb.build.ctx, "GroupBy")
|
||||
if err := aegb.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AclEntryQuery, *AclEntryGroupBy](ctx, aegb.build, aegb, aegb.build.inters, v)
|
||||
}
|
||||
|
||||
func (aegb *AclEntryGroupBy) sqlScan(ctx context.Context, root *AclEntryQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx).Select()
|
||||
aggregation := make([]string, 0, len(aegb.fns))
|
||||
for _, fn := range aegb.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(*aegb.flds)+len(aegb.fns))
|
||||
for _, f := range *aegb.flds {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
selector.GroupBy(selector.Columns(*aegb.flds...)...)
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := aegb.build.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
// AclEntrySelect is the builder for selecting fields of AclEntry entities.
|
||||
type AclEntrySelect struct {
|
||||
*AclEntryQuery
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func (aes *AclEntrySelect) Aggregate(fns ...AggregateFunc) *AclEntrySelect {
|
||||
aes.fns = append(aes.fns, fns...)
|
||||
return aes
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (aes *AclEntrySelect) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, aes.ctx, "Select")
|
||||
if err := aes.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*AclEntryQuery, *AclEntrySelect](ctx, aes.AclEntryQuery, aes, aes.inters, v)
|
||||
}
|
||||
|
||||
func (aes *AclEntrySelect) sqlScan(ctx context.Context, root *AclEntryQuery, v any) error {
|
||||
selector := root.sqlQuery(ctx)
|
||||
aggregation := make([]string, 0, len(aes.fns))
|
||||
for _, fn := range aes.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
switch n := len(*aes.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 := aes.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
@ -0,0 +1,542 @@
|
||||
// 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/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/file"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/predicate"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
// AclEntryUpdate is the builder for updating AclEntry entities.
|
||||
type AclEntryUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *AclEntryMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AclEntryUpdate builder.
|
||||
func (aeu *AclEntryUpdate) Where(ps ...predicate.AclEntry) *AclEntryUpdate {
|
||||
aeu.mutation.Where(ps...)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (aeu *AclEntryUpdate) SetUpdatedAt(t time.Time) *AclEntryUpdate {
|
||||
aeu.mutation.SetUpdatedAt(t)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (aeu *AclEntryUpdate) SetDeletedAt(t time.Time) *AclEntryUpdate {
|
||||
aeu.mutation.SetDeletedAt(t)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||
func (aeu *AclEntryUpdate) SetNillableDeletedAt(t *time.Time) *AclEntryUpdate {
|
||||
if t != nil {
|
||||
aeu.SetDeletedAt(*t)
|
||||
}
|
||||
return aeu
|
||||
}
|
||||
|
||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||
func (aeu *AclEntryUpdate) ClearDeletedAt() *AclEntryUpdate {
|
||||
aeu.mutation.ClearDeletedAt()
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (aeu *AclEntryUpdate) SetFileID(i int) *AclEntryUpdate {
|
||||
aeu.mutation.SetFileID(i)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetNillableFileID sets the "file_id" field if the given value is not nil.
|
||||
func (aeu *AclEntryUpdate) SetNillableFileID(i *int) *AclEntryUpdate {
|
||||
if i != nil {
|
||||
aeu.SetFileID(*i)
|
||||
}
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (aeu *AclEntryUpdate) SetSubjectType(at aclentry.SubjectType) *AclEntryUpdate {
|
||||
aeu.mutation.SetSubjectType(at)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetNillableSubjectType sets the "subject_type" field if the given value is not nil.
|
||||
func (aeu *AclEntryUpdate) SetNillableSubjectType(at *aclentry.SubjectType) *AclEntryUpdate {
|
||||
if at != nil {
|
||||
aeu.SetSubjectType(*at)
|
||||
}
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (aeu *AclEntryUpdate) SetSubjectID(i int) *AclEntryUpdate {
|
||||
aeu.mutation.ResetSubjectID()
|
||||
aeu.mutation.SetSubjectID(i)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetNillableSubjectID sets the "subject_id" field if the given value is not nil.
|
||||
func (aeu *AclEntryUpdate) SetNillableSubjectID(i *int) *AclEntryUpdate {
|
||||
if i != nil {
|
||||
aeu.SetSubjectID(*i)
|
||||
}
|
||||
return aeu
|
||||
}
|
||||
|
||||
// AddSubjectID adds i to the "subject_id" field.
|
||||
func (aeu *AclEntryUpdate) AddSubjectID(i int) *AclEntryUpdate {
|
||||
aeu.mutation.AddSubjectID(i)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// ClearSubjectID clears the value of the "subject_id" field.
|
||||
func (aeu *AclEntryUpdate) ClearSubjectID() *AclEntryUpdate {
|
||||
aeu.mutation.ClearSubjectID()
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (aeu *AclEntryUpdate) SetPermissions(bs *boolset.BooleanSet) *AclEntryUpdate {
|
||||
aeu.mutation.SetPermissions(bs)
|
||||
return aeu
|
||||
}
|
||||
|
||||
// SetFile sets the "file" edge to the File entity.
|
||||
func (aeu *AclEntryUpdate) SetFile(f *File) *AclEntryUpdate {
|
||||
return aeu.SetFileID(f.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AclEntryMutation object of the builder.
|
||||
func (aeu *AclEntryUpdate) Mutation() *AclEntryMutation {
|
||||
return aeu.mutation
|
||||
}
|
||||
|
||||
// ClearFile clears the "file" edge to the File entity.
|
||||
func (aeu *AclEntryUpdate) ClearFile() *AclEntryUpdate {
|
||||
aeu.mutation.ClearFile()
|
||||
return aeu
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (aeu *AclEntryUpdate) Save(ctx context.Context) (int, error) {
|
||||
if err := aeu.defaults(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withHooks(ctx, aeu.sqlSave, aeu.mutation, aeu.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (aeu *AclEntryUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := aeu.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (aeu *AclEntryUpdate) Exec(ctx context.Context) error {
|
||||
_, err := aeu.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aeu *AclEntryUpdate) ExecX(ctx context.Context) {
|
||||
if err := aeu.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (aeu *AclEntryUpdate) defaults() error {
|
||||
if _, ok := aeu.mutation.UpdatedAt(); !ok {
|
||||
if aclentry.UpdateDefaultUpdatedAt == nil {
|
||||
return fmt.Errorf("ent: uninitialized aclentry.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
||||
}
|
||||
v := aclentry.UpdateDefaultUpdatedAt()
|
||||
aeu.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (aeu *AclEntryUpdate) check() error {
|
||||
if v, ok := aeu.mutation.SubjectType(); ok {
|
||||
if err := aclentry.SubjectTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "subject_type", err: fmt.Errorf(`ent: validator failed for field "AclEntry.subject_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := aeu.mutation.FileID(); aeu.mutation.FileCleared() && !ok {
|
||||
return errors.New(`ent: clearing a required unique edge "AclEntry.file"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (aeu *AclEntryUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
||||
if err := aeu.check(); err != nil {
|
||||
return n, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(aclentry.Table, aclentry.Columns, sqlgraph.NewFieldSpec(aclentry.FieldID, field.TypeInt))
|
||||
if ps := aeu.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := aeu.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := aeu.mutation.DeletedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldDeletedAt, field.TypeTime, value)
|
||||
}
|
||||
if aeu.mutation.DeletedAtCleared() {
|
||||
_spec.ClearField(aclentry.FieldDeletedAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := aeu.mutation.SubjectType(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectType, field.TypeEnum, value)
|
||||
}
|
||||
if value, ok := aeu.mutation.SubjectID(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectID, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := aeu.mutation.AddedSubjectID(); ok {
|
||||
_spec.AddField(aclentry.FieldSubjectID, field.TypeInt, value)
|
||||
}
|
||||
if aeu.mutation.SubjectIDCleared() {
|
||||
_spec.ClearField(aclentry.FieldSubjectID, field.TypeInt)
|
||||
}
|
||||
if value, ok := aeu.mutation.Permissions(); ok {
|
||||
_spec.SetField(aclentry.FieldPermissions, field.TypeBytes, value)
|
||||
}
|
||||
if aeu.mutation.FileCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: aclentry.FileTable,
|
||||
Columns: []string{aclentry.FileColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(file.FieldID, field.TypeInt),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := aeu.mutation.FileIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: aclentry.FileTable,
|
||||
Columns: []string{aclentry.FileColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(file.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, aeu.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{aclentry.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
aeu.mutation.done = true
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// AclEntryUpdateOne is the builder for updating a single AclEntry entity.
|
||||
type AclEntryUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *AclEntryMutation
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetUpdatedAt(t time.Time) *AclEntryUpdateOne {
|
||||
aeuo.mutation.SetUpdatedAt(t)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetDeletedAt sets the "deleted_at" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetDeletedAt(t time.Time) *AclEntryUpdateOne {
|
||||
aeuo.mutation.SetDeletedAt(t)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
|
||||
func (aeuo *AclEntryUpdateOne) SetNillableDeletedAt(t *time.Time) *AclEntryUpdateOne {
|
||||
if t != nil {
|
||||
aeuo.SetDeletedAt(*t)
|
||||
}
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// ClearDeletedAt clears the value of the "deleted_at" field.
|
||||
func (aeuo *AclEntryUpdateOne) ClearDeletedAt() *AclEntryUpdateOne {
|
||||
aeuo.mutation.ClearDeletedAt()
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetFileID sets the "file_id" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetFileID(i int) *AclEntryUpdateOne {
|
||||
aeuo.mutation.SetFileID(i)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetNillableFileID sets the "file_id" field if the given value is not nil.
|
||||
func (aeuo *AclEntryUpdateOne) SetNillableFileID(i *int) *AclEntryUpdateOne {
|
||||
if i != nil {
|
||||
aeuo.SetFileID(*i)
|
||||
}
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetSubjectType sets the "subject_type" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetSubjectType(at aclentry.SubjectType) *AclEntryUpdateOne {
|
||||
aeuo.mutation.SetSubjectType(at)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetNillableSubjectType sets the "subject_type" field if the given value is not nil.
|
||||
func (aeuo *AclEntryUpdateOne) SetNillableSubjectType(at *aclentry.SubjectType) *AclEntryUpdateOne {
|
||||
if at != nil {
|
||||
aeuo.SetSubjectType(*at)
|
||||
}
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetSubjectID sets the "subject_id" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetSubjectID(i int) *AclEntryUpdateOne {
|
||||
aeuo.mutation.ResetSubjectID()
|
||||
aeuo.mutation.SetSubjectID(i)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetNillableSubjectID sets the "subject_id" field if the given value is not nil.
|
||||
func (aeuo *AclEntryUpdateOne) SetNillableSubjectID(i *int) *AclEntryUpdateOne {
|
||||
if i != nil {
|
||||
aeuo.SetSubjectID(*i)
|
||||
}
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// AddSubjectID adds i to the "subject_id" field.
|
||||
func (aeuo *AclEntryUpdateOne) AddSubjectID(i int) *AclEntryUpdateOne {
|
||||
aeuo.mutation.AddSubjectID(i)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// ClearSubjectID clears the value of the "subject_id" field.
|
||||
func (aeuo *AclEntryUpdateOne) ClearSubjectID() *AclEntryUpdateOne {
|
||||
aeuo.mutation.ClearSubjectID()
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetPermissions sets the "permissions" field.
|
||||
func (aeuo *AclEntryUpdateOne) SetPermissions(bs *boolset.BooleanSet) *AclEntryUpdateOne {
|
||||
aeuo.mutation.SetPermissions(bs)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// SetFile sets the "file" edge to the File entity.
|
||||
func (aeuo *AclEntryUpdateOne) SetFile(f *File) *AclEntryUpdateOne {
|
||||
return aeuo.SetFileID(f.ID)
|
||||
}
|
||||
|
||||
// Mutation returns the AclEntryMutation object of the builder.
|
||||
func (aeuo *AclEntryUpdateOne) Mutation() *AclEntryMutation {
|
||||
return aeuo.mutation
|
||||
}
|
||||
|
||||
// ClearFile clears the "file" edge to the File entity.
|
||||
func (aeuo *AclEntryUpdateOne) ClearFile() *AclEntryUpdateOne {
|
||||
aeuo.mutation.ClearFile()
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the AclEntryUpdate builder.
|
||||
func (aeuo *AclEntryUpdateOne) Where(ps ...predicate.AclEntry) *AclEntryUpdateOne {
|
||||
aeuo.mutation.Where(ps...)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (aeuo *AclEntryUpdateOne) Select(field string, fields ...string) *AclEntryUpdateOne {
|
||||
aeuo.fields = append([]string{field}, fields...)
|
||||
return aeuo
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated AclEntry entity.
|
||||
func (aeuo *AclEntryUpdateOne) Save(ctx context.Context) (*AclEntry, error) {
|
||||
if err := aeuo.defaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return withHooks(ctx, aeuo.sqlSave, aeuo.mutation, aeuo.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (aeuo *AclEntryUpdateOne) SaveX(ctx context.Context) *AclEntry {
|
||||
node, err := aeuo.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (aeuo *AclEntryUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := aeuo.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (aeuo *AclEntryUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := aeuo.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (aeuo *AclEntryUpdateOne) defaults() error {
|
||||
if _, ok := aeuo.mutation.UpdatedAt(); !ok {
|
||||
if aclentry.UpdateDefaultUpdatedAt == nil {
|
||||
return fmt.Errorf("ent: uninitialized aclentry.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
|
||||
}
|
||||
v := aclentry.UpdateDefaultUpdatedAt()
|
||||
aeuo.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (aeuo *AclEntryUpdateOne) check() error {
|
||||
if v, ok := aeuo.mutation.SubjectType(); ok {
|
||||
if err := aclentry.SubjectTypeValidator(v); err != nil {
|
||||
return &ValidationError{Name: "subject_type", err: fmt.Errorf(`ent: validator failed for field "AclEntry.subject_type": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := aeuo.mutation.FileID(); aeuo.mutation.FileCleared() && !ok {
|
||||
return errors.New(`ent: clearing a required unique edge "AclEntry.file"`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (aeuo *AclEntryUpdateOne) sqlSave(ctx context.Context) (_node *AclEntry, err error) {
|
||||
if err := aeuo.check(); err != nil {
|
||||
return _node, err
|
||||
}
|
||||
_spec := sqlgraph.NewUpdateSpec(aclentry.Table, aclentry.Columns, sqlgraph.NewFieldSpec(aclentry.FieldID, field.TypeInt))
|
||||
id, ok := aeuo.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AclEntry.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := aeuo.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, aclentry.FieldID)
|
||||
for _, f := range fields {
|
||||
if !aclentry.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != aclentry.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := aeuo.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := aeuo.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldUpdatedAt, field.TypeTime, value)
|
||||
}
|
||||
if value, ok := aeuo.mutation.DeletedAt(); ok {
|
||||
_spec.SetField(aclentry.FieldDeletedAt, field.TypeTime, value)
|
||||
}
|
||||
if aeuo.mutation.DeletedAtCleared() {
|
||||
_spec.ClearField(aclentry.FieldDeletedAt, field.TypeTime)
|
||||
}
|
||||
if value, ok := aeuo.mutation.SubjectType(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectType, field.TypeEnum, value)
|
||||
}
|
||||
if value, ok := aeuo.mutation.SubjectID(); ok {
|
||||
_spec.SetField(aclentry.FieldSubjectID, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := aeuo.mutation.AddedSubjectID(); ok {
|
||||
_spec.AddField(aclentry.FieldSubjectID, field.TypeInt, value)
|
||||
}
|
||||
if aeuo.mutation.SubjectIDCleared() {
|
||||
_spec.ClearField(aclentry.FieldSubjectID, field.TypeInt)
|
||||
}
|
||||
if value, ok := aeuo.mutation.Permissions(); ok {
|
||||
_spec.SetField(aclentry.FieldPermissions, field.TypeBytes, value)
|
||||
}
|
||||
if aeuo.mutation.FileCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: aclentry.FileTable,
|
||||
Columns: []string{aclentry.FileColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(file.FieldID, field.TypeInt),
|
||||
},
|
||||
}
|
||||
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
|
||||
}
|
||||
if nodes := aeuo.mutation.FileIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
Inverse: true,
|
||||
Table: aclentry.FileTable,
|
||||
Columns: []string{aclentry.FileColumn},
|
||||
Bidi: false,
|
||||
Target: &sqlgraph.EdgeTarget{
|
||||
IDSpec: sqlgraph.NewFieldSpec(file.FieldID, field.TypeInt),
|
||||
},
|
||||
}
|
||||
for _, k := range nodes {
|
||||
edge.Target.Nodes = append(edge.Target.Nodes, k)
|
||||
}
|
||||
_spec.Edges.Add = append(_spec.Edges.Add, edge)
|
||||
}
|
||||
_node = &AclEntry{config: aeuo.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, aeuo.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{aclentry.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
aeuo.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,54 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/schema/edge"
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
// AclEntry holds the schema definition for per-file access control entries.
|
||||
// Each row grants a capability bitmask (read/create/update/delete) on a file
|
||||
// or directory to a subject: a specific user, a user group, anonymous
|
||||
// visitors, or every other authenticated user.
|
||||
type AclEntry struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
// Fields of the AclEntry.
|
||||
func (AclEntry) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int("file_id"),
|
||||
field.Enum("subject_type").
|
||||
Values("user", "group", "anonymous", "everyone"),
|
||||
field.Int("subject_id").
|
||||
Optional(),
|
||||
field.Bytes("permissions").GoType(&boolset.BooleanSet{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Edges of the AclEntry.
|
||||
func (AclEntry) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("file", File.Type).
|
||||
Ref("acl_entries").
|
||||
Field("file_id").
|
||||
Unique().
|
||||
Required(),
|
||||
}
|
||||
}
|
||||
|
||||
// Indexes of the AclEntry.
|
||||
func (AclEntry) Indexes() []ent.Index {
|
||||
return []ent.Index{
|
||||
index.Fields("file_id", "subject_type", "subject_id").
|
||||
Unique(),
|
||||
}
|
||||
}
|
||||
|
||||
func (AclEntry) Mixin() []ent.Mixin {
|
||||
return []ent.Mixin{
|
||||
CommonMixin{},
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,300 @@
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
DialogContent,
|
||||
IconButton,
|
||||
Skeleton,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { deleteAclEntry, getAclEntries, searchAclSubjects, upsertAclEntry } from "../../../../api/api.ts";
|
||||
import { AclEntry, AclPermissionKey, AclSubject, AclSubjectType } from "../../../../api/explorer.ts";
|
||||
import { closeAclDialog } from "../../../../redux/globalStateSlice.ts";
|
||||
import { useAppDispatch, useAppSelector } from "../../../../redux/hooks.ts";
|
||||
import AutoHeight from "../../../Common/AutoHeight.tsx";
|
||||
import {
|
||||
DenseAutocomplete,
|
||||
DenseFilledTextField,
|
||||
NoWrapTableCell,
|
||||
StyledTableContainerPaper,
|
||||
} from "../../../Common/StyledComponents.tsx";
|
||||
import DraggableDialog from "../../../Dialogs/DraggableDialog.tsx";
|
||||
import Dismiss from "../../../Icons/Dismiss.tsx";
|
||||
import Globe from "../../../Icons/Globe.tsx";
|
||||
import PeopleTeam from "../../../Icons/PeopleTeam.tsx";
|
||||
import PersonOutlined from "../../../Icons/PersonOutlined.tsx";
|
||||
import PersonStar from "../../../Icons/PersonStar.tsx";
|
||||
|
||||
const permissionOrder: AclPermissionKey[] = ["read", "create", "update", "delete"];
|
||||
|
||||
interface PendingSubject {
|
||||
type: AclSubjectType;
|
||||
id: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const AclDialog = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [entries, setEntries] = useState<AclEntry[] | undefined>(undefined);
|
||||
const [pending, setPending] = useState<number[]>([]);
|
||||
const [subjectOptions, setSubjectOptions] = useState<PendingSubject[]>([]);
|
||||
const [keyword, setKeyword] = useState("");
|
||||
|
||||
const open = useAppSelector((state) => state.globalState.aclDialogOpen);
|
||||
const target = useAppSelector((state) => state.globalState.aclDialogFile);
|
||||
|
||||
const uri = target?.path;
|
||||
|
||||
const generalSubject = useCallback(
|
||||
(type: "anonymous" | "everyone"): PendingSubject => ({
|
||||
type,
|
||||
id: 0,
|
||||
label: t(`fileManager.acl${type === "anonymous" ? "Anonymous" : "Everyone"}`),
|
||||
}),
|
||||
[t],
|
||||
);
|
||||
|
||||
const subjectLabel = useCallback(
|
||||
(e: AclEntry) => {
|
||||
if (e.subject_type === "anonymous" || e.subject_type === "everyone") {
|
||||
return t(`fileManager.acl${e.subject_type === "anonymous" ? "Anonymous" : "Everyone"}`);
|
||||
}
|
||||
return e.subject_name || `#${e.subject_id}`;
|
||||
},
|
||||
[t],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (open && uri) {
|
||||
setEntries(undefined);
|
||||
dispatch(getAclEntries(uri)).then((res) => setEntries(res));
|
||||
}
|
||||
}, [open, uri, dispatch]);
|
||||
|
||||
// Search selectable subjects; anonymous/everyone are always offered when not
|
||||
// already present on the file.
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
const handle = setTimeout(() => {
|
||||
const fixed: PendingSubject[] = ["anonymous", "everyone"]
|
||||
.filter((ty) => !entries?.some((e) => e.subject_type === ty))
|
||||
.map((ty) => generalSubject(ty as "anonymous" | "everyone"))
|
||||
.filter((s) => keyword == "" || s.label.toLowerCase().includes(keyword.toLowerCase()));
|
||||
dispatch(searchAclSubjects(keyword))
|
||||
.then((res: AclSubject[]) => {
|
||||
const dynamic = (res || [])
|
||||
.filter((s) => !entries?.some((e) => e.subject_type === s.type && e.subject_id === s.id))
|
||||
.map((s) => ({
|
||||
type: s.type as AclSubjectType,
|
||||
id: s.id,
|
||||
label: s.type === "user" ? s.name : `${s.name} (${t("fileManager.aclGroup")})`,
|
||||
}));
|
||||
setSubjectOptions([...dynamic, ...fixed]);
|
||||
})
|
||||
.catch(() => setSubjectOptions(fixed));
|
||||
}, 300);
|
||||
return () => clearTimeout(handle);
|
||||
}, [keyword, open, entries, dispatch, generalSubject, t]);
|
||||
|
||||
const togglePermission = useCallback(
|
||||
(entry: AclEntry, perm: AclPermissionKey) => {
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
const next = entry.permissions.includes(perm)
|
||||
? entry.permissions.filter((p) => p !== perm)
|
||||
: [...entry.permissions, perm];
|
||||
setPending((p) => [...p, entry.id]);
|
||||
dispatch(
|
||||
upsertAclEntry({
|
||||
uri,
|
||||
subject_type: entry.subject_type,
|
||||
subject_id: entry.subject_id,
|
||||
permissions: next,
|
||||
}),
|
||||
)
|
||||
.then((res) => {
|
||||
setEntries((prev) =>
|
||||
prev?.map((e) => (e.id === entry.id ? { ...e, permissions: res.permissions } : e)),
|
||||
);
|
||||
})
|
||||
.finally(() => setPending((p) => p.filter((id) => id !== entry.id)));
|
||||
},
|
||||
[uri, dispatch],
|
||||
);
|
||||
|
||||
const removeEntry = useCallback(
|
||||
(entry: AclEntry) => {
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
setPending((p) => [...p, entry.id]);
|
||||
dispatch(deleteAclEntry(uri, entry.id))
|
||||
.then(() => setEntries((prev) => prev?.filter((e) => e.id !== entry.id)))
|
||||
.finally(() => setPending((p) => p.filter((id) => id !== entry.id)));
|
||||
},
|
||||
[uri, dispatch],
|
||||
);
|
||||
|
||||
const addSubject = useCallback(
|
||||
(subject: PendingSubject | null) => {
|
||||
if (!subject || !uri) {
|
||||
return;
|
||||
}
|
||||
setPending((p) => [...p, -1]);
|
||||
dispatch(
|
||||
upsertAclEntry({
|
||||
uri,
|
||||
subject_type: subject.type,
|
||||
subject_id: subject.id,
|
||||
permissions: ["read"],
|
||||
}),
|
||||
)
|
||||
.then((res) => {
|
||||
setEntries((prev) => [...(prev ?? []), { ...res, subject_name: subject.label }]);
|
||||
setKeyword("");
|
||||
})
|
||||
.finally(() => setPending((p) => p.filter((id) => id !== -1)));
|
||||
},
|
||||
[uri, dispatch],
|
||||
);
|
||||
|
||||
const subjectIcon = useMemo(
|
||||
() => ({
|
||||
user: <PersonOutlined fontSize="small" />,
|
||||
group: <PeopleTeam fontSize="small" />,
|
||||
anonymous: <PersonStar fontSize="small" />,
|
||||
everyone: <Globe fontSize="small" />,
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<DraggableDialog
|
||||
title={t("application:fileManager.permissions")}
|
||||
loading={entries === undefined}
|
||||
dialogProps={{
|
||||
open: open ?? false,
|
||||
onClose: () => dispatch(closeAclDialog()),
|
||||
fullWidth: true,
|
||||
maxWidth: "md",
|
||||
}}
|
||||
>
|
||||
<DialogContent>
|
||||
<AutoHeight>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
||||
{t("fileManager.aclDes", { name: target?.name })}
|
||||
</Typography>
|
||||
<DenseAutocomplete
|
||||
options={subjectOptions}
|
||||
inputValue={keyword}
|
||||
onInputChange={(_, v) => setKeyword(v)}
|
||||
getOptionLabel={(o) => (o as PendingSubject).label}
|
||||
onChange={(_, v) => addSubject(v as PendingSubject | null)}
|
||||
value={null}
|
||||
blurOnSelect
|
||||
sx={{ mb: 2 }}
|
||||
renderOption={(props, option) => {
|
||||
const o = option as PendingSubject;
|
||||
return (
|
||||
<li {...props} key={`${o.type}:${o.id}`}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
{subjectIcon[o.type]}
|
||||
{o.label}
|
||||
</Box>
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<DenseFilledTextField
|
||||
{...params}
|
||||
placeholder={t("application:fileManager.typeToSearch")}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<TableContainer component={StyledTableContainerPaper}>
|
||||
<Table sx={{ width: "100%" }} size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<NoWrapTableCell>{t("fileManager.aclSubject")}</NoWrapTableCell>
|
||||
{permissionOrder.map((p) => (
|
||||
<TableCell key={p} align="center" padding="checkbox">
|
||||
{t(`fileManager.aclPerm_${p}`)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell padding="checkbox" />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{entries === undefined && (
|
||||
<TableRow>
|
||||
<NoWrapTableCell>
|
||||
<Skeleton variant="text" width={140} />
|
||||
</NoWrapTableCell>
|
||||
{permissionOrder.map((p) => (
|
||||
<TableCell key={p} align="center" padding="checkbox">
|
||||
<Skeleton variant="circular" width={18} height={18} sx={{ mx: "auto" }} />
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell padding="checkbox" />
|
||||
</TableRow>
|
||||
)}
|
||||
{entries?.map((e) => (
|
||||
<TableRow key={e.id} hover>
|
||||
<NoWrapTableCell component="th" scope="row">
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
{subjectIcon[e.subject_type]}
|
||||
{subjectLabel(e)}
|
||||
</Box>
|
||||
</NoWrapTableCell>
|
||||
{permissionOrder.map((p) => (
|
||||
<TableCell key={p} align="center" padding="checkbox">
|
||||
<Checkbox
|
||||
size="small"
|
||||
checked={e.permissions.includes(p)}
|
||||
disabled={pending.includes(e.id)}
|
||||
onChange={() => togglePermission(e, p)}
|
||||
/>
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell padding="checkbox" align="right">
|
||||
<IconButton
|
||||
size="small"
|
||||
disabled={pending.includes(e.id)}
|
||||
onClick={() => removeEntry(e)}
|
||||
>
|
||||
<Dismiss fontSize="small" />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
{entries && entries.length === 0 && (
|
||||
<Box sx={{ p: 1, width: "100%", textAlign: "center" }}>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t("application:setting.listEmpty")}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</TableContainer>
|
||||
</AutoHeight>
|
||||
</DialogContent>
|
||||
</DraggableDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default AclDialog;
|
||||
@ -0,0 +1,156 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/conf"
|
||||
)
|
||||
|
||||
type (
|
||||
AclClient interface {
|
||||
TxOperator
|
||||
// List returns all ACL entries for a file, ordered by subject type.
|
||||
List(ctx context.Context, fileID int) ([]*ent.AclEntry, error)
|
||||
// Upsert creates or updates the entry for (file, subject).
|
||||
Upsert(ctx context.Context, params *UpsertAclEntryParams) (*ent.AclEntry, error)
|
||||
// Delete removes an ACL entry scoped to the given file.
|
||||
Delete(ctx context.Context, fileID, id int) error
|
||||
// EffectivePermissions unions the permission bits of all entries on
|
||||
// fileID matching the acting user. Anonymous users (id 0) only match
|
||||
// the anonymous tier; authenticated users match their explicit user
|
||||
// and group rows plus the everyone tier. Returns nil when no entry
|
||||
// matches — callers then fall back to share-level defaults.
|
||||
EffectivePermissions(ctx context.Context, fileID int, user *ent.User) (*boolset.BooleanSet, error)
|
||||
}
|
||||
|
||||
UpsertAclEntryParams struct {
|
||||
FileID int
|
||||
SubjectType aclentry.SubjectType
|
||||
SubjectID int
|
||||
Permissions *boolset.BooleanSet
|
||||
}
|
||||
)
|
||||
|
||||
func NewAclClient(client *ent.Client, dbType conf.DBType) AclClient {
|
||||
return &aclClient{
|
||||
client: client,
|
||||
maxSQlParam: sqlParamLimit(dbType),
|
||||
}
|
||||
}
|
||||
|
||||
type aclClient struct {
|
||||
maxSQlParam int
|
||||
client *ent.Client
|
||||
}
|
||||
|
||||
func (c *aclClient) SetClient(newClient *ent.Client) TxOperator {
|
||||
return &aclClient{client: newClient, maxSQlParam: c.maxSQlParam}
|
||||
}
|
||||
|
||||
func (c *aclClient) GetClient() *ent.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *aclClient) List(ctx context.Context, fileID int) ([]*ent.AclEntry, error) {
|
||||
return c.client.AclEntry.Query().
|
||||
Where(aclentry.FileID(fileID)).
|
||||
Order(aclentry.BySubjectType(), aclentry.BySubjectID()).
|
||||
All(ctx)
|
||||
}
|
||||
|
||||
func (c *aclClient) Upsert(ctx context.Context, params *UpsertAclEntryParams) (*ent.AclEntry, error) {
|
||||
if params.Permissions == nil {
|
||||
params.Permissions = &boolset.BooleanSet{}
|
||||
}
|
||||
|
||||
id, err := c.client.AclEntry.Create().
|
||||
SetFileID(params.FileID).
|
||||
SetSubjectType(params.SubjectType).
|
||||
SetSubjectID(params.SubjectID).
|
||||
SetPermissions(params.Permissions).
|
||||
OnConflictColumns(aclentry.FieldFileID, aclentry.FieldSubjectType, aclentry.FieldSubjectID).
|
||||
UpdateNewValues().
|
||||
ID(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upsert ACL entry: %w", err)
|
||||
}
|
||||
|
||||
return c.client.AclEntry.Get(ctx, id)
|
||||
}
|
||||
|
||||
func (c *aclClient) Delete(ctx context.Context, fileID, id int) error {
|
||||
affected, err := c.client.AclEntry.Delete().
|
||||
Where(aclentry.ID(id), aclentry.FileID(fileID)).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete ACL entry: %w", err)
|
||||
}
|
||||
if affected == 0 {
|
||||
return &ent.NotFoundError{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *aclClient) EffectivePermissions(ctx context.Context, fileID int, user *ent.User) (*boolset.BooleanSet, error) {
|
||||
entries, err := c.client.AclEntry.Query().
|
||||
Where(aclentry.FileID(fileID)).
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query ACL entries: %w", err)
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if IsAnonymousUser(user) {
|
||||
for _, e := range entries {
|
||||
if e.SubjectType == aclentry.SubjectTypeAnonymous {
|
||||
if e.Permissions == nil {
|
||||
return &boolset.BooleanSet{}, nil
|
||||
}
|
||||
return e.Permissions, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
groupID := 0
|
||||
if group := user.Edges.Group; group != nil {
|
||||
groupID = group.ID
|
||||
}
|
||||
|
||||
res := &boolset.BooleanSet{}
|
||||
matched := false
|
||||
for _, e := range entries {
|
||||
hit := false
|
||||
switch e.SubjectType {
|
||||
case aclentry.SubjectTypeEveryone:
|
||||
hit = true
|
||||
case aclentry.SubjectTypeUser:
|
||||
hit = e.SubjectID == user.ID
|
||||
case aclentry.SubjectTypeGroup:
|
||||
hit = groupID > 0 && e.SubjectID == groupID
|
||||
}
|
||||
if !hit {
|
||||
continue
|
||||
}
|
||||
matched = true
|
||||
if e.Permissions == nil {
|
||||
continue
|
||||
}
|
||||
for i := 0; i <= int(types.AclPermDelete); i++ {
|
||||
if e.Permissions.Enabled(i) {
|
||||
boolset.Set(i, true, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !matched {
|
||||
return nil, nil
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
@ -0,0 +1,154 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/enttest"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/conf"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func aclFixture(t *testing.T, client *ent.Client) (*ent.User, *ent.Group, *ent.File) {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
group := client.Group.Create().SetName("g").SetPermissions(&boolset.BooleanSet{}).SaveX(ctx)
|
||||
user := client.User.Create().SetEmail("u@example.com").SetNick("u").SetGroup(group).SaveX(ctx)
|
||||
file := client.File.Create().SetName("dir").SetType(int(types.FileTypeFolder)).SetOwner(user).SaveX(ctx)
|
||||
user.SetGroup(group)
|
||||
return user, group, file
|
||||
}
|
||||
|
||||
func aclEntry(t *testing.T, client *ent.Client, fileID int, st aclentry.SubjectType, sid int, perms ...types.AclPermission) *ent.AclEntry {
|
||||
t.Helper()
|
||||
bs := &boolset.BooleanSet{}
|
||||
for _, p := range perms {
|
||||
boolset.Set(int(p), true, bs)
|
||||
}
|
||||
return client.AclEntry.Create().
|
||||
SetFileID(fileID).
|
||||
SetSubjectType(st).
|
||||
SetSubjectID(sid).
|
||||
SetPermissions(bs).
|
||||
SaveX(context.Background())
|
||||
}
|
||||
|
||||
func TestAclUpsertAndList(t *testing.T) {
|
||||
client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared")
|
||||
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
||||
ctx := context.Background()
|
||||
_, _, file := aclFixture(t, client)
|
||||
c := NewAclClient(client, conf.SQLiteDB)
|
||||
|
||||
bs := &boolset.BooleanSet{}
|
||||
boolset.Set(int(types.AclPermRead), true, bs)
|
||||
e, err := c.Upsert(ctx, &UpsertAclEntryParams{
|
||||
FileID: file.ID, SubjectType: aclentry.SubjectTypeUser, SubjectID: 7, Permissions: bs,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, e.ID)
|
||||
|
||||
// Second upsert on same (file, subject) updates rather than duplicating.
|
||||
boolset.Set(int(types.AclPermDelete), true, bs)
|
||||
e2, err := c.Upsert(ctx, &UpsertAclEntryParams{
|
||||
FileID: file.ID, SubjectType: aclentry.SubjectTypeUser, SubjectID: 7, Permissions: bs,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, e.ID, e2.ID)
|
||||
|
||||
entries, err := c.List(ctx, file.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries, 1)
|
||||
require.True(t, entries[0].Permissions.Enabled(int(types.AclPermDelete)))
|
||||
|
||||
require.NoError(t, c.Delete(ctx, file.ID, e.ID))
|
||||
entries, err = c.List(ctx, file.ID)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, entries)
|
||||
|
||||
// Delete of a missing row reports not found.
|
||||
require.Error(t, c.Delete(ctx, file.ID, e.ID))
|
||||
}
|
||||
|
||||
func TestAclEffectivePermissionsAnonymous(t *testing.T) {
|
||||
client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared")
|
||||
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
||||
ctx := context.Background()
|
||||
_, _, file := aclFixture(t, client)
|
||||
c := NewAclClient(client, conf.SQLiteDB)
|
||||
anon := &ent.User{ID: 0}
|
||||
|
||||
// No rows at all -> nil (fall back to share defaults).
|
||||
res, err := c.EffectivePermissions(ctx, file.ID, anon)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, res)
|
||||
|
||||
// An anonymous row applies to anonymous visitors; other tiers do not.
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeEveryone, 0, types.AclPermRead)
|
||||
res, err = c.EffectivePermissions(ctx, file.ID, anon)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, res)
|
||||
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeAnonymous, 0, types.AclPermCreate)
|
||||
res, err = c.EffectivePermissions(ctx, file.ID, anon)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.True(t, res.Enabled(int(types.AclPermCreate)))
|
||||
require.False(t, res.Enabled(int(types.AclPermRead)))
|
||||
}
|
||||
|
||||
func TestAclEffectivePermissionsUnion(t *testing.T) {
|
||||
client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared")
|
||||
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
||||
ctx := context.Background()
|
||||
user, group, file := aclFixture(t, client)
|
||||
c := NewAclClient(client, conf.SQLiteDB)
|
||||
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeEveryone, 0, types.AclPermRead)
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeGroup, group.ID, types.AclPermCreate)
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeUser, user.ID, types.AclPermDelete)
|
||||
// Unrelated rows must not leak in.
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeUser, user.ID+99, types.AclPermUpdate)
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeGroup, group.ID+99, types.AclPermUpdate)
|
||||
|
||||
res, err := c.EffectivePermissions(ctx, file.ID, user)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.True(t, res.Enabled(int(types.AclPermRead)))
|
||||
require.True(t, res.Enabled(int(types.AclPermCreate)))
|
||||
require.True(t, res.Enabled(int(types.AclPermDelete)))
|
||||
require.False(t, res.Enabled(int(types.AclPermUpdate)))
|
||||
}
|
||||
|
||||
func TestAclEffectivePermissionsNoMatchIsNil(t *testing.T) {
|
||||
client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared")
|
||||
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
||||
ctx := context.Background()
|
||||
user, _, file := aclFixture(t, client)
|
||||
c := NewAclClient(client, conf.SQLiteDB)
|
||||
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeUser, user.ID+99, types.AclPermRead)
|
||||
res, err := c.EffectivePermissions(ctx, file.ID, user)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, res)
|
||||
}
|
||||
|
||||
func TestAclEffectivePermissionsExplicitEmptyRevokes(t *testing.T) {
|
||||
client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared")
|
||||
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
||||
ctx := context.Background()
|
||||
user, _, file := aclFixture(t, client)
|
||||
c := NewAclClient(client, conf.SQLiteDB)
|
||||
|
||||
// An everyone row with zero bits = explicit revocation for all
|
||||
// authenticated visitors; distinct from nil (no match).
|
||||
aclEntry(t, client, file.ID, aclentry.SubjectTypeEveryone, 0)
|
||||
res, err := c.EffectivePermissions(ctx, file.ID, user)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.False(t, res.Enabled(int(types.AclPermRead)))
|
||||
}
|
||||
@ -0,0 +1,240 @@
|
||||
package explorer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/aclentry"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
// AclEntryResponse is one row in the Permissions dialog.
|
||||
type AclEntryResponse struct {
|
||||
ID int `json:"id"`
|
||||
SubjectType string `json:"subject_type"`
|
||||
SubjectID int `json:"subject_id"`
|
||||
SubjectName string `json:"subject_name"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
// AclSubjectResponse is a selectable subject in the Permissions dialog.
|
||||
type AclSubjectResponse struct {
|
||||
Type string `json:"type"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type (
|
||||
// AclListService lists ACL entries of a file.
|
||||
AclListService struct {
|
||||
Uri string `form:"uri" binding:"required"`
|
||||
}
|
||||
AclListParamCtx struct{}
|
||||
|
||||
// AclUpsertService creates or updates an ACL entry.
|
||||
AclUpsertService struct {
|
||||
Uri string `json:"uri" binding:"required"`
|
||||
SubjectType string `json:"subject_type" binding:"required,oneof=user group anonymous everyone"`
|
||||
SubjectID int `json:"subject_id"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
AclUpsertParamCtx struct{}
|
||||
|
||||
// AclDeleteService removes an ACL entry.
|
||||
AclDeleteService struct {
|
||||
Uri string `form:"uri" binding:"required"`
|
||||
ID int `form:"id" binding:"required,min=1"`
|
||||
}
|
||||
AclDeleteParamCtx struct{}
|
||||
|
||||
// AclSubjectSearchService resolves selectable subjects for the dialog.
|
||||
AclSubjectSearchService struct {
|
||||
Keyword string `form:"keyword"`
|
||||
}
|
||||
AclSubjectSearchParamCtx struct{}
|
||||
)
|
||||
|
||||
func aclPermissionsToSet(perms []string) (*boolset.BooleanSet, error) {
|
||||
bs := &boolset.BooleanSet{}
|
||||
nameToBit := lo.Invert(types.AclPermissionList)
|
||||
for _, p := range perms {
|
||||
bit, ok := nameToBit[p]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown permission %q", p)
|
||||
}
|
||||
boolset.Set(int(bit), true, bs)
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func aclSetToPermissions(bs *boolset.BooleanSet) []string {
|
||||
res := []string{}
|
||||
for bit, name := range types.AclPermissionList {
|
||||
if bs != nil && bs.Enabled(int(bit)) {
|
||||
res = append(res, name)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ownedAclFile resolves the target file and enforces that the acting user
|
||||
// owns it and their group may manage explicit permissions.
|
||||
func ownedAclFile(c *gin.Context, uriRaw string) (int, error) {
|
||||
user := inventory.UserFromContext(c)
|
||||
uri, err := fs.NewUriFromString(uriRaw)
|
||||
if err != nil {
|
||||
return 0, serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
|
||||
}
|
||||
|
||||
m := manager.NewFileManager(dependency.FromContext(c), user)
|
||||
defer m.Recycle()
|
||||
|
||||
file, err := m.Get(c, uri)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to get file: %w", err)
|
||||
}
|
||||
if file.OwnerID() != user.ID {
|
||||
return 0, serializer.NewError(serializer.CodeNoPermissionErr, "Only the owner can manage permissions", nil)
|
||||
}
|
||||
|
||||
if user.Edges.Group == nil || user.Edges.Group.Permissions == nil ||
|
||||
!user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionSetExplicitUser)) {
|
||||
return 0, serializer.NewError(serializer.CodeNoPermissionErr, "Permission management is not enabled for your group", nil)
|
||||
}
|
||||
|
||||
return file.ID(), nil
|
||||
}
|
||||
|
||||
func (s *AclListService) Get(c *gin.Context) ([]*AclEntryResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileID, err := ownedAclFile(c, s.Uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries, err := dep.AclClient().List(c, fileID)
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list permissions", err)
|
||||
}
|
||||
|
||||
// Resolve subject display names.
|
||||
names := map[string]string{}
|
||||
for _, e := range entries {
|
||||
key := fmt.Sprintf("%s:%d", e.SubjectType, e.SubjectID)
|
||||
switch e.SubjectType {
|
||||
case aclentry.SubjectTypeUser:
|
||||
if u, err := dep.UserClient().GetByID(c, e.SubjectID); err == nil {
|
||||
names[key] = u.Email
|
||||
}
|
||||
case aclentry.SubjectTypeGroup:
|
||||
if g, err := dep.GroupClient().GetByID(c, e.SubjectID); err == nil {
|
||||
names[key] = g.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lo.Map(entries, func(e *ent.AclEntry, _ int) *AclEntryResponse {
|
||||
name := names[fmt.Sprintf("%s:%d", e.SubjectType, e.SubjectID)]
|
||||
if e.SubjectType == aclentry.SubjectTypeAnonymous {
|
||||
name = "anonymous"
|
||||
} else if e.SubjectType == aclentry.SubjectTypeEveryone {
|
||||
name = "everyone"
|
||||
}
|
||||
return &AclEntryResponse{
|
||||
ID: e.ID,
|
||||
SubjectType: string(e.SubjectType),
|
||||
SubjectID: e.SubjectID,
|
||||
SubjectName: name,
|
||||
Permissions: aclSetToPermissions(e.Permissions),
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *AclUpsertService) Update(c *gin.Context) (*AclEntryResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileID, err := ownedAclFile(c, s.Uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
perms, err := aclPermissionsToSet(s.Permissions)
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid permissions", err)
|
||||
}
|
||||
|
||||
subjectType := aclentry.SubjectType(s.SubjectType)
|
||||
if (subjectType == aclentry.SubjectTypeAnonymous || subjectType == aclentry.SubjectTypeEveryone) && s.SubjectID != 0 {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "General access entries must not carry a subject id", nil)
|
||||
}
|
||||
if (subjectType == aclentry.SubjectTypeUser || subjectType == aclentry.SubjectTypeGroup) && s.SubjectID <= 0 {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Subject id is required", nil)
|
||||
}
|
||||
|
||||
e, err := dep.AclClient().Upsert(c, &inventory.UpsertAclEntryParams{
|
||||
FileID: fileID,
|
||||
SubjectType: subjectType,
|
||||
SubjectID: s.SubjectID,
|
||||
Permissions: perms,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to save permission", err)
|
||||
}
|
||||
|
||||
return &AclEntryResponse{
|
||||
ID: e.ID,
|
||||
SubjectType: string(e.SubjectType),
|
||||
SubjectID: e.SubjectID,
|
||||
Permissions: aclSetToPermissions(e.Permissions),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *AclDeleteService) Delete(c *gin.Context) error {
|
||||
dep := dependency.FromContext(c)
|
||||
fileID, err := ownedAclFile(c, s.Uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dep.AclClient().Delete(c, fileID, s.ID); err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to delete permission", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AclSubjectSearchService) Get(c *gin.Context) ([]*AclSubjectResponse, error) {
|
||||
user := inventory.UserFromContext(c)
|
||||
if user.Edges.Group == nil || user.Edges.Group.Permissions == nil ||
|
||||
!user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionSetExplicitUser)) {
|
||||
return nil, serializer.NewError(serializer.CodeNoPermissionErr, "Permission management is not enabled for your group", nil)
|
||||
}
|
||||
|
||||
dep := dependency.FromContext(c)
|
||||
res := []*AclSubjectResponse{}
|
||||
|
||||
// Exact email match only — user enumeration by prefix is not exposed.
|
||||
if s.Keyword != "" {
|
||||
if u, err := dep.UserClient().GetByEmail(c, s.Keyword); err == nil {
|
||||
res = append(res, &AclSubjectResponse{Type: "user", ID: u.ID, Name: u.Email})
|
||||
}
|
||||
}
|
||||
|
||||
groups, err := dep.GroupClient().ListAll(c)
|
||||
if err == nil {
|
||||
for _, g := range groups {
|
||||
if s.Keyword == "" || strings.Contains(strings.ToLower(g.Name), strings.ToLower(s.Keyword)) {
|
||||
res = append(res, &AclSubjectResponse{Type: "group", ID: g.ID, Name: g.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
Loading…
Reference in new issue