From 4018d04a5ffd18744de21973ddada702032b73c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Dvo=C5=99=C3=A1k?= <150935816+Dvorinka@users.noreply.github.com> Date: Sun, 20 Sep 2026 00:06:37 +0200 Subject: [PATCH] feat: abuse report queue with public submission and admin review (#185) Visitors can report shares or users from the share page more-menu; the public endpoint is IP rate-limited and captcha-gated via the new abuse_captcha setting (default on). Admins review the queue at /admin/abuse with resolve/dismiss transitions and an optional reversible share block that expires the link rather than deleting it. Submissions emit report_abuse activity events. Authored By: TDvorak Generated with [Devin](https://devin.ai) Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- application/dependency/dependency.go | 12 + ent/abusereport.go | 219 +++ ent/abusereport/abusereport.go | 148 ++ ent/abusereport/where.go | 740 ++++++++++ ent/abusereport_create.go | 1205 +++++++++++++++++ ent/abusereport_delete.go | 88 ++ ent/abusereport_query.go | 526 +++++++ ent/abusereport_update.go | 680 ++++++++++ ent/client.go | 169 ++- ent/ent.go | 2 + ent/hook/hook.go | 12 + ent/intercept/intercept.go | 30 + ent/internal/schema.go | 2 +- ent/migrate/schema.go | 34 + ent/mutation.go | 1069 +++++++++++++++ ent/mutationhelper.go | 6 + ent/predicate/predicate.go | 3 + ent/runtime/runtime.go | 24 + ent/schema/abusereport.go | 47 + ent/tx.go | 5 +- frontend/public/locales/en-US/dashboard.json | 23 +- frontend/public/locales/zh-CN/dashboard.json | 23 +- frontend/src/api/api.ts | 53 + frontend/src/api/dashboard.ts | 35 + frontend/src/api/site.ts | 1 + .../component/Admin/Abuse/AbuseReportList.tsx | 285 ++++ frontend/src/component/Admin/AdminBundle.tsx | 2 + .../Admin/Settings/Captcha/Captcha.tsx | 18 + .../component/FileManager/Dialogs/Dialogs.tsx | 2 + .../Dialogs/ReportAbuse/ReportAbuseDialog.tsx | 127 ++ .../FileManager/TopBar/MoreActionMenu.tsx | 24 +- frontend/src/redux/globalStateSlice.ts | 18 + frontend/src/router/index.tsx | 7 + inventory/abusereport.go | 97 ++ inventory/abusereport_test.go | 63 + inventory/setting.go | 1 + inventory/share.go | 7 + inventory/types/abuse.go | 21 + pkg/setting/provider.go | 6 + routers/controllers/admin.go | 20 + routers/controllers/share.go | 10 + routers/router.go | 34 +- service/abuse/report.go | 78 ++ service/admin/abuse.go | 114 ++ service/basic/site.go | 4 + 45 files changed, 6071 insertions(+), 23 deletions(-) create mode 100644 ent/abusereport.go create mode 100644 ent/abusereport/abusereport.go create mode 100644 ent/abusereport/where.go create mode 100644 ent/abusereport_create.go create mode 100644 ent/abusereport_delete.go create mode 100644 ent/abusereport_query.go create mode 100644 ent/abusereport_update.go create mode 100644 ent/schema/abusereport.go create mode 100644 frontend/src/component/Admin/Abuse/AbuseReportList.tsx create mode 100644 frontend/src/component/FileManager/Dialogs/ReportAbuse/ReportAbuseDialog.tsx create mode 100644 inventory/abusereport.go create mode 100644 inventory/abusereport_test.go create mode 100644 inventory/types/abuse.go create mode 100644 service/abuse/report.go create mode 100644 service/admin/abuse.go diff --git a/application/dependency/dependency.go b/application/dependency/dependency.go index 35fdeea3..d1f1ebf9 100644 --- a/application/dependency/dependency.go +++ b/application/dependency/dependency.go @@ -112,6 +112,8 @@ type Dep interface { VasClient() inventory.VasClient // ActivityClient Get a singleton inventory.ActivityClient instance for the audit event store. ActivityClient() inventory.ActivityClient + // AbuseReportClient Get a singleton inventory.AbuseReportClient instance for the abuse review queue. + AbuseReportClient() inventory.AbuseReportClient // TaskClient Get a singleton inventory.TaskClient instance for access DB task store. TaskClient() inventory.TaskClient // ForkWithLogger create a shallow copy of dependency with a new correlated logger, used as per-request dep. @@ -171,6 +173,7 @@ type dependency struct { aclClient inventory.AclClient vasClient inventory.VasClient activityClient inventory.ActivityClient + abuseReportClient inventory.AbuseReportClient settingProvider setting.Provider userClient inventory.UserClient groupClient inventory.GroupClient @@ -858,6 +861,15 @@ func (d *dependency) ActivityClient() inventory.ActivityClient { return d.activityClient } +func (d *dependency) AbuseReportClient() inventory.AbuseReportClient { + if d.abuseReportClient != nil { + return d.abuseReportClient + } + + d.abuseReportClient = inventory.NewAbuseReportClient(d.DBClient()) + return d.abuseReportClient +} + func (d *dependency) TaskClient() inventory.TaskClient { if d.taskClient != nil { return d.taskClient diff --git a/ent/abusereport.go b/ent/abusereport.go new file mode 100644 index 00000000..3ab3ee91 --- /dev/null +++ b/ent/abusereport.go @@ -0,0 +1,219 @@ +// 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/abusereport" +) + +// AbuseReport is the model entity for the AbuseReport schema. +type AbuseReport 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"` + // ReporterID holds the value of the "reporter_id" field. + ReporterID int `json:"reporter_id,omitempty"` + // ReporterEmail holds the value of the "reporter_email" field. + ReporterEmail string `json:"reporter_email,omitempty"` + // TargetType holds the value of the "target_type" field. + TargetType string `json:"target_type,omitempty"` + // TargetID holds the value of the "target_id" field. + TargetID int `json:"target_id,omitempty"` + // Reason holds the value of the "reason" field. + Reason int `json:"reason,omitempty"` + // Description holds the value of the "description" field. + Description string `json:"description,omitempty"` + // Status holds the value of the "status" field. + Status string `json:"status,omitempty"` + // AdminNote holds the value of the "admin_note" field. + AdminNote string `json:"admin_note,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*AbuseReport) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case abusereport.FieldID, abusereport.FieldReporterID, abusereport.FieldTargetID, abusereport.FieldReason: + values[i] = new(sql.NullInt64) + case abusereport.FieldReporterEmail, abusereport.FieldTargetType, abusereport.FieldDescription, abusereport.FieldStatus, abusereport.FieldAdminNote: + values[i] = new(sql.NullString) + case abusereport.FieldCreatedAt, abusereport.FieldUpdatedAt, abusereport.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 AbuseReport fields. +func (ar *AbuseReport) 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 abusereport.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + ar.ID = int(value.Int64) + case abusereport.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 { + ar.CreatedAt = value.Time + } + case abusereport.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 { + ar.UpdatedAt = value.Time + } + case abusereport.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 { + ar.DeletedAt = new(time.Time) + *ar.DeletedAt = value.Time + } + case abusereport.FieldReporterID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field reporter_id", values[i]) + } else if value.Valid { + ar.ReporterID = int(value.Int64) + } + case abusereport.FieldReporterEmail: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field reporter_email", values[i]) + } else if value.Valid { + ar.ReporterEmail = value.String + } + case abusereport.FieldTargetType: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field target_type", values[i]) + } else if value.Valid { + ar.TargetType = value.String + } + case abusereport.FieldTargetID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field target_id", values[i]) + } else if value.Valid { + ar.TargetID = int(value.Int64) + } + case abusereport.FieldReason: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field reason", values[i]) + } else if value.Valid { + ar.Reason = int(value.Int64) + } + case abusereport.FieldDescription: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field description", values[i]) + } else if value.Valid { + ar.Description = value.String + } + case abusereport.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + ar.Status = value.String + } + case abusereport.FieldAdminNote: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field admin_note", values[i]) + } else if value.Valid { + ar.AdminNote = value.String + } + default: + ar.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the AbuseReport. +// This includes values selected through modifiers, order, etc. +func (ar *AbuseReport) Value(name string) (ent.Value, error) { + return ar.selectValues.Get(name) +} + +// Update returns a builder for updating this AbuseReport. +// Note that you need to call AbuseReport.Unwrap() before calling this method if this AbuseReport +// was returned from a transaction, and the transaction was committed or rolled back. +func (ar *AbuseReport) Update() *AbuseReportUpdateOne { + return NewAbuseReportClient(ar.config).UpdateOne(ar) +} + +// Unwrap unwraps the AbuseReport 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 (ar *AbuseReport) Unwrap() *AbuseReport { + _tx, ok := ar.config.driver.(*txDriver) + if !ok { + panic("ent: AbuseReport is not a transactional entity") + } + ar.config.driver = _tx.drv + return ar +} + +// String implements the fmt.Stringer. +func (ar *AbuseReport) String() string { + var builder strings.Builder + builder.WriteString("AbuseReport(") + builder.WriteString(fmt.Sprintf("id=%v, ", ar.ID)) + builder.WriteString("created_at=") + builder.WriteString(ar.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(ar.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + if v := ar.DeletedAt; v != nil { + builder.WriteString("deleted_at=") + builder.WriteString(v.Format(time.ANSIC)) + } + builder.WriteString(", ") + builder.WriteString("reporter_id=") + builder.WriteString(fmt.Sprintf("%v", ar.ReporterID)) + builder.WriteString(", ") + builder.WriteString("reporter_email=") + builder.WriteString(ar.ReporterEmail) + builder.WriteString(", ") + builder.WriteString("target_type=") + builder.WriteString(ar.TargetType) + builder.WriteString(", ") + builder.WriteString("target_id=") + builder.WriteString(fmt.Sprintf("%v", ar.TargetID)) + builder.WriteString(", ") + builder.WriteString("reason=") + builder.WriteString(fmt.Sprintf("%v", ar.Reason)) + builder.WriteString(", ") + builder.WriteString("description=") + builder.WriteString(ar.Description) + builder.WriteString(", ") + builder.WriteString("status=") + builder.WriteString(ar.Status) + builder.WriteString(", ") + builder.WriteString("admin_note=") + builder.WriteString(ar.AdminNote) + builder.WriteByte(')') + return builder.String() +} + +// AbuseReports is a parsable slice of AbuseReport. +type AbuseReports []*AbuseReport diff --git a/ent/abusereport/abusereport.go b/ent/abusereport/abusereport.go new file mode 100644 index 00000000..b8d50b0a --- /dev/null +++ b/ent/abusereport/abusereport.go @@ -0,0 +1,148 @@ +// Code generated by ent, DO NOT EDIT. + +package abusereport + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the abusereport type in the database. + Label = "abuse_report" + // 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" + // FieldReporterID holds the string denoting the reporter_id field in the database. + FieldReporterID = "reporter_id" + // FieldReporterEmail holds the string denoting the reporter_email field in the database. + FieldReporterEmail = "reporter_email" + // FieldTargetType holds the string denoting the target_type field in the database. + FieldTargetType = "target_type" + // FieldTargetID holds the string denoting the target_id field in the database. + FieldTargetID = "target_id" + // FieldReason holds the string denoting the reason field in the database. + FieldReason = "reason" + // FieldDescription holds the string denoting the description field in the database. + FieldDescription = "description" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldAdminNote holds the string denoting the admin_note field in the database. + FieldAdminNote = "admin_note" + // Table holds the table name of the abusereport in the database. + Table = "abuse_reports" +) + +// Columns holds all SQL columns for abusereport fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldReporterID, + FieldReporterEmail, + FieldTargetType, + FieldTargetID, + FieldReason, + FieldDescription, + FieldStatus, + FieldAdminNote, +} + +// 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 + // DefaultStatus holds the default value on creation for the "status" field. + DefaultStatus string +) + +// OrderOption defines the ordering options for the AbuseReport 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() +} + +// ByReporterID orders the results by the reporter_id field. +func ByReporterID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldReporterID, opts...).ToFunc() +} + +// ByReporterEmail orders the results by the reporter_email field. +func ByReporterEmail(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldReporterEmail, opts...).ToFunc() +} + +// ByTargetType orders the results by the target_type field. +func ByTargetType(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTargetType, opts...).ToFunc() +} + +// ByTargetID orders the results by the target_id field. +func ByTargetID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTargetID, opts...).ToFunc() +} + +// ByReason orders the results by the reason field. +func ByReason(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldReason, opts...).ToFunc() +} + +// ByDescription orders the results by the description field. +func ByDescription(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDescription, opts...).ToFunc() +} + +// ByStatus orders the results by the status field. +func ByStatus(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStatus, opts...).ToFunc() +} + +// ByAdminNote orders the results by the admin_note field. +func ByAdminNote(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldAdminNote, opts...).ToFunc() +} diff --git a/ent/abusereport/where.go b/ent/abusereport/where.go new file mode 100644 index 00000000..3bf6157b --- /dev/null +++ b/ent/abusereport/where.go @@ -0,0 +1,740 @@ +// Code generated by ent, DO NOT EDIT. + +package abusereport + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.AbuseReport { + return predicate.AbuseReport(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.AbuseReport { + return predicate.AbuseReport(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.AbuseReport { + return predicate.AbuseReport(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.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldDeletedAt, v)) +} + +// ReporterID applies equality check predicate on the "reporter_id" field. It's identical to ReporterIDEQ. +func ReporterID(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReporterID, v)) +} + +// ReporterEmail applies equality check predicate on the "reporter_email" field. It's identical to ReporterEmailEQ. +func ReporterEmail(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReporterEmail, v)) +} + +// TargetType applies equality check predicate on the "target_type" field. It's identical to TargetTypeEQ. +func TargetType(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldTargetType, v)) +} + +// TargetID applies equality check predicate on the "target_id" field. It's identical to TargetIDEQ. +func TargetID(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldTargetID, v)) +} + +// Reason applies equality check predicate on the "reason" field. It's identical to ReasonEQ. +func Reason(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReason, v)) +} + +// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ. +func Description(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldDescription, v)) +} + +// Status applies equality check predicate on the "status" field. It's identical to StatusEQ. +func Status(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldStatus, v)) +} + +// AdminNote applies equality check predicate on the "admin_note" field. It's identical to AdminNoteEQ. +func AdminNote(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldAdminNote, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotNull(FieldDeletedAt)) +} + +// ReporterIDEQ applies the EQ predicate on the "reporter_id" field. +func ReporterIDEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReporterID, v)) +} + +// ReporterIDNEQ applies the NEQ predicate on the "reporter_id" field. +func ReporterIDNEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldReporterID, v)) +} + +// ReporterIDIn applies the In predicate on the "reporter_id" field. +func ReporterIDIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldReporterID, vs...)) +} + +// ReporterIDNotIn applies the NotIn predicate on the "reporter_id" field. +func ReporterIDNotIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldReporterID, vs...)) +} + +// ReporterIDGT applies the GT predicate on the "reporter_id" field. +func ReporterIDGT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldReporterID, v)) +} + +// ReporterIDGTE applies the GTE predicate on the "reporter_id" field. +func ReporterIDGTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldReporterID, v)) +} + +// ReporterIDLT applies the LT predicate on the "reporter_id" field. +func ReporterIDLT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldReporterID, v)) +} + +// ReporterIDLTE applies the LTE predicate on the "reporter_id" field. +func ReporterIDLTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldReporterID, v)) +} + +// ReporterIDIsNil applies the IsNil predicate on the "reporter_id" field. +func ReporterIDIsNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIsNull(FieldReporterID)) +} + +// ReporterIDNotNil applies the NotNil predicate on the "reporter_id" field. +func ReporterIDNotNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotNull(FieldReporterID)) +} + +// ReporterEmailEQ applies the EQ predicate on the "reporter_email" field. +func ReporterEmailEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReporterEmail, v)) +} + +// ReporterEmailNEQ applies the NEQ predicate on the "reporter_email" field. +func ReporterEmailNEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldReporterEmail, v)) +} + +// ReporterEmailIn applies the In predicate on the "reporter_email" field. +func ReporterEmailIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldReporterEmail, vs...)) +} + +// ReporterEmailNotIn applies the NotIn predicate on the "reporter_email" field. +func ReporterEmailNotIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldReporterEmail, vs...)) +} + +// ReporterEmailGT applies the GT predicate on the "reporter_email" field. +func ReporterEmailGT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldReporterEmail, v)) +} + +// ReporterEmailGTE applies the GTE predicate on the "reporter_email" field. +func ReporterEmailGTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldReporterEmail, v)) +} + +// ReporterEmailLT applies the LT predicate on the "reporter_email" field. +func ReporterEmailLT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldReporterEmail, v)) +} + +// ReporterEmailLTE applies the LTE predicate on the "reporter_email" field. +func ReporterEmailLTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldReporterEmail, v)) +} + +// ReporterEmailContains applies the Contains predicate on the "reporter_email" field. +func ReporterEmailContains(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContains(FieldReporterEmail, v)) +} + +// ReporterEmailHasPrefix applies the HasPrefix predicate on the "reporter_email" field. +func ReporterEmailHasPrefix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasPrefix(FieldReporterEmail, v)) +} + +// ReporterEmailHasSuffix applies the HasSuffix predicate on the "reporter_email" field. +func ReporterEmailHasSuffix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasSuffix(FieldReporterEmail, v)) +} + +// ReporterEmailIsNil applies the IsNil predicate on the "reporter_email" field. +func ReporterEmailIsNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIsNull(FieldReporterEmail)) +} + +// ReporterEmailNotNil applies the NotNil predicate on the "reporter_email" field. +func ReporterEmailNotNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotNull(FieldReporterEmail)) +} + +// ReporterEmailEqualFold applies the EqualFold predicate on the "reporter_email" field. +func ReporterEmailEqualFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEqualFold(FieldReporterEmail, v)) +} + +// ReporterEmailContainsFold applies the ContainsFold predicate on the "reporter_email" field. +func ReporterEmailContainsFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContainsFold(FieldReporterEmail, v)) +} + +// TargetTypeEQ applies the EQ predicate on the "target_type" field. +func TargetTypeEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldTargetType, v)) +} + +// TargetTypeNEQ applies the NEQ predicate on the "target_type" field. +func TargetTypeNEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldTargetType, v)) +} + +// TargetTypeIn applies the In predicate on the "target_type" field. +func TargetTypeIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldTargetType, vs...)) +} + +// TargetTypeNotIn applies the NotIn predicate on the "target_type" field. +func TargetTypeNotIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldTargetType, vs...)) +} + +// TargetTypeGT applies the GT predicate on the "target_type" field. +func TargetTypeGT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldTargetType, v)) +} + +// TargetTypeGTE applies the GTE predicate on the "target_type" field. +func TargetTypeGTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldTargetType, v)) +} + +// TargetTypeLT applies the LT predicate on the "target_type" field. +func TargetTypeLT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldTargetType, v)) +} + +// TargetTypeLTE applies the LTE predicate on the "target_type" field. +func TargetTypeLTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldTargetType, v)) +} + +// TargetTypeContains applies the Contains predicate on the "target_type" field. +func TargetTypeContains(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContains(FieldTargetType, v)) +} + +// TargetTypeHasPrefix applies the HasPrefix predicate on the "target_type" field. +func TargetTypeHasPrefix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasPrefix(FieldTargetType, v)) +} + +// TargetTypeHasSuffix applies the HasSuffix predicate on the "target_type" field. +func TargetTypeHasSuffix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasSuffix(FieldTargetType, v)) +} + +// TargetTypeEqualFold applies the EqualFold predicate on the "target_type" field. +func TargetTypeEqualFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEqualFold(FieldTargetType, v)) +} + +// TargetTypeContainsFold applies the ContainsFold predicate on the "target_type" field. +func TargetTypeContainsFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContainsFold(FieldTargetType, v)) +} + +// TargetIDEQ applies the EQ predicate on the "target_id" field. +func TargetIDEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldTargetID, v)) +} + +// TargetIDNEQ applies the NEQ predicate on the "target_id" field. +func TargetIDNEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldTargetID, v)) +} + +// TargetIDIn applies the In predicate on the "target_id" field. +func TargetIDIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldTargetID, vs...)) +} + +// TargetIDNotIn applies the NotIn predicate on the "target_id" field. +func TargetIDNotIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldTargetID, vs...)) +} + +// TargetIDGT applies the GT predicate on the "target_id" field. +func TargetIDGT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldTargetID, v)) +} + +// TargetIDGTE applies the GTE predicate on the "target_id" field. +func TargetIDGTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldTargetID, v)) +} + +// TargetIDLT applies the LT predicate on the "target_id" field. +func TargetIDLT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldTargetID, v)) +} + +// TargetIDLTE applies the LTE predicate on the "target_id" field. +func TargetIDLTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldTargetID, v)) +} + +// ReasonEQ applies the EQ predicate on the "reason" field. +func ReasonEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldReason, v)) +} + +// ReasonNEQ applies the NEQ predicate on the "reason" field. +func ReasonNEQ(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldReason, v)) +} + +// ReasonIn applies the In predicate on the "reason" field. +func ReasonIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldReason, vs...)) +} + +// ReasonNotIn applies the NotIn predicate on the "reason" field. +func ReasonNotIn(vs ...int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldReason, vs...)) +} + +// ReasonGT applies the GT predicate on the "reason" field. +func ReasonGT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldReason, v)) +} + +// ReasonGTE applies the GTE predicate on the "reason" field. +func ReasonGTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldReason, v)) +} + +// ReasonLT applies the LT predicate on the "reason" field. +func ReasonLT(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldReason, v)) +} + +// ReasonLTE applies the LTE predicate on the "reason" field. +func ReasonLTE(v int) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldReason, v)) +} + +// DescriptionEQ applies the EQ predicate on the "description" field. +func DescriptionEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldDescription, v)) +} + +// DescriptionNEQ applies the NEQ predicate on the "description" field. +func DescriptionNEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldDescription, v)) +} + +// DescriptionIn applies the In predicate on the "description" field. +func DescriptionIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldDescription, vs...)) +} + +// DescriptionNotIn applies the NotIn predicate on the "description" field. +func DescriptionNotIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldDescription, vs...)) +} + +// DescriptionGT applies the GT predicate on the "description" field. +func DescriptionGT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldDescription, v)) +} + +// DescriptionGTE applies the GTE predicate on the "description" field. +func DescriptionGTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldDescription, v)) +} + +// DescriptionLT applies the LT predicate on the "description" field. +func DescriptionLT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldDescription, v)) +} + +// DescriptionLTE applies the LTE predicate on the "description" field. +func DescriptionLTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldDescription, v)) +} + +// DescriptionContains applies the Contains predicate on the "description" field. +func DescriptionContains(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContains(FieldDescription, v)) +} + +// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field. +func DescriptionHasPrefix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasPrefix(FieldDescription, v)) +} + +// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field. +func DescriptionHasSuffix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasSuffix(FieldDescription, v)) +} + +// DescriptionIsNil applies the IsNil predicate on the "description" field. +func DescriptionIsNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIsNull(FieldDescription)) +} + +// DescriptionNotNil applies the NotNil predicate on the "description" field. +func DescriptionNotNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotNull(FieldDescription)) +} + +// DescriptionEqualFold applies the EqualFold predicate on the "description" field. +func DescriptionEqualFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEqualFold(FieldDescription, v)) +} + +// DescriptionContainsFold applies the ContainsFold predicate on the "description" field. +func DescriptionContainsFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContainsFold(FieldDescription, v)) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldStatus, v)) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldStatus, v)) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldStatus, vs...)) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldStatus, vs...)) +} + +// StatusGT applies the GT predicate on the "status" field. +func StatusGT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldStatus, v)) +} + +// StatusGTE applies the GTE predicate on the "status" field. +func StatusGTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldStatus, v)) +} + +// StatusLT applies the LT predicate on the "status" field. +func StatusLT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldStatus, v)) +} + +// StatusLTE applies the LTE predicate on the "status" field. +func StatusLTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldStatus, v)) +} + +// StatusContains applies the Contains predicate on the "status" field. +func StatusContains(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContains(FieldStatus, v)) +} + +// StatusHasPrefix applies the HasPrefix predicate on the "status" field. +func StatusHasPrefix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasPrefix(FieldStatus, v)) +} + +// StatusHasSuffix applies the HasSuffix predicate on the "status" field. +func StatusHasSuffix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasSuffix(FieldStatus, v)) +} + +// StatusEqualFold applies the EqualFold predicate on the "status" field. +func StatusEqualFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEqualFold(FieldStatus, v)) +} + +// StatusContainsFold applies the ContainsFold predicate on the "status" field. +func StatusContainsFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContainsFold(FieldStatus, v)) +} + +// AdminNoteEQ applies the EQ predicate on the "admin_note" field. +func AdminNoteEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEQ(FieldAdminNote, v)) +} + +// AdminNoteNEQ applies the NEQ predicate on the "admin_note" field. +func AdminNoteNEQ(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNEQ(FieldAdminNote, v)) +} + +// AdminNoteIn applies the In predicate on the "admin_note" field. +func AdminNoteIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIn(FieldAdminNote, vs...)) +} + +// AdminNoteNotIn applies the NotIn predicate on the "admin_note" field. +func AdminNoteNotIn(vs ...string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotIn(FieldAdminNote, vs...)) +} + +// AdminNoteGT applies the GT predicate on the "admin_note" field. +func AdminNoteGT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGT(FieldAdminNote, v)) +} + +// AdminNoteGTE applies the GTE predicate on the "admin_note" field. +func AdminNoteGTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldGTE(FieldAdminNote, v)) +} + +// AdminNoteLT applies the LT predicate on the "admin_note" field. +func AdminNoteLT(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLT(FieldAdminNote, v)) +} + +// AdminNoteLTE applies the LTE predicate on the "admin_note" field. +func AdminNoteLTE(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldLTE(FieldAdminNote, v)) +} + +// AdminNoteContains applies the Contains predicate on the "admin_note" field. +func AdminNoteContains(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContains(FieldAdminNote, v)) +} + +// AdminNoteHasPrefix applies the HasPrefix predicate on the "admin_note" field. +func AdminNoteHasPrefix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasPrefix(FieldAdminNote, v)) +} + +// AdminNoteHasSuffix applies the HasSuffix predicate on the "admin_note" field. +func AdminNoteHasSuffix(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldHasSuffix(FieldAdminNote, v)) +} + +// AdminNoteIsNil applies the IsNil predicate on the "admin_note" field. +func AdminNoteIsNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldIsNull(FieldAdminNote)) +} + +// AdminNoteNotNil applies the NotNil predicate on the "admin_note" field. +func AdminNoteNotNil() predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldNotNull(FieldAdminNote)) +} + +// AdminNoteEqualFold applies the EqualFold predicate on the "admin_note" field. +func AdminNoteEqualFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldEqualFold(FieldAdminNote, v)) +} + +// AdminNoteContainsFold applies the ContainsFold predicate on the "admin_note" field. +func AdminNoteContainsFold(v string) predicate.AbuseReport { + return predicate.AbuseReport(sql.FieldContainsFold(FieldAdminNote, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.AbuseReport) predicate.AbuseReport { + return predicate.AbuseReport(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.AbuseReport) predicate.AbuseReport { + return predicate.AbuseReport(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.AbuseReport) predicate.AbuseReport { + return predicate.AbuseReport(sql.NotPredicates(p)) +} diff --git a/ent/abusereport_create.go b/ent/abusereport_create.go new file mode 100644 index 00000000..9fcfd623 --- /dev/null +++ b/ent/abusereport_create.go @@ -0,0 +1,1205 @@ +// 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/abusereport" +) + +// AbuseReportCreate is the builder for creating a AbuseReport entity. +type AbuseReportCreate struct { + config + mutation *AbuseReportMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (arc *AbuseReportCreate) SetCreatedAt(t time.Time) *AbuseReportCreate { + arc.mutation.SetCreatedAt(t) + return arc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableCreatedAt(t *time.Time) *AbuseReportCreate { + if t != nil { + arc.SetCreatedAt(*t) + } + return arc +} + +// SetUpdatedAt sets the "updated_at" field. +func (arc *AbuseReportCreate) SetUpdatedAt(t time.Time) *AbuseReportCreate { + arc.mutation.SetUpdatedAt(t) + return arc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableUpdatedAt(t *time.Time) *AbuseReportCreate { + if t != nil { + arc.SetUpdatedAt(*t) + } + return arc +} + +// SetDeletedAt sets the "deleted_at" field. +func (arc *AbuseReportCreate) SetDeletedAt(t time.Time) *AbuseReportCreate { + arc.mutation.SetDeletedAt(t) + return arc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableDeletedAt(t *time.Time) *AbuseReportCreate { + if t != nil { + arc.SetDeletedAt(*t) + } + return arc +} + +// SetReporterID sets the "reporter_id" field. +func (arc *AbuseReportCreate) SetReporterID(i int) *AbuseReportCreate { + arc.mutation.SetReporterID(i) + return arc +} + +// SetNillableReporterID sets the "reporter_id" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableReporterID(i *int) *AbuseReportCreate { + if i != nil { + arc.SetReporterID(*i) + } + return arc +} + +// SetReporterEmail sets the "reporter_email" field. +func (arc *AbuseReportCreate) SetReporterEmail(s string) *AbuseReportCreate { + arc.mutation.SetReporterEmail(s) + return arc +} + +// SetNillableReporterEmail sets the "reporter_email" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableReporterEmail(s *string) *AbuseReportCreate { + if s != nil { + arc.SetReporterEmail(*s) + } + return arc +} + +// SetTargetType sets the "target_type" field. +func (arc *AbuseReportCreate) SetTargetType(s string) *AbuseReportCreate { + arc.mutation.SetTargetType(s) + return arc +} + +// SetTargetID sets the "target_id" field. +func (arc *AbuseReportCreate) SetTargetID(i int) *AbuseReportCreate { + arc.mutation.SetTargetID(i) + return arc +} + +// SetReason sets the "reason" field. +func (arc *AbuseReportCreate) SetReason(i int) *AbuseReportCreate { + arc.mutation.SetReason(i) + return arc +} + +// SetDescription sets the "description" field. +func (arc *AbuseReportCreate) SetDescription(s string) *AbuseReportCreate { + arc.mutation.SetDescription(s) + return arc +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableDescription(s *string) *AbuseReportCreate { + if s != nil { + arc.SetDescription(*s) + } + return arc +} + +// SetStatus sets the "status" field. +func (arc *AbuseReportCreate) SetStatus(s string) *AbuseReportCreate { + arc.mutation.SetStatus(s) + return arc +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableStatus(s *string) *AbuseReportCreate { + if s != nil { + arc.SetStatus(*s) + } + return arc +} + +// SetAdminNote sets the "admin_note" field. +func (arc *AbuseReportCreate) SetAdminNote(s string) *AbuseReportCreate { + arc.mutation.SetAdminNote(s) + return arc +} + +// SetNillableAdminNote sets the "admin_note" field if the given value is not nil. +func (arc *AbuseReportCreate) SetNillableAdminNote(s *string) *AbuseReportCreate { + if s != nil { + arc.SetAdminNote(*s) + } + return arc +} + +// Mutation returns the AbuseReportMutation object of the builder. +func (arc *AbuseReportCreate) Mutation() *AbuseReportMutation { + return arc.mutation +} + +// Save creates the AbuseReport in the database. +func (arc *AbuseReportCreate) Save(ctx context.Context) (*AbuseReport, error) { + if err := arc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, arc.sqlSave, arc.mutation, arc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (arc *AbuseReportCreate) SaveX(ctx context.Context) *AbuseReport { + v, err := arc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (arc *AbuseReportCreate) Exec(ctx context.Context) error { + _, err := arc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (arc *AbuseReportCreate) ExecX(ctx context.Context) { + if err := arc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (arc *AbuseReportCreate) defaults() error { + if _, ok := arc.mutation.CreatedAt(); !ok { + if abusereport.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized abusereport.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := abusereport.DefaultCreatedAt() + arc.mutation.SetCreatedAt(v) + } + if _, ok := arc.mutation.UpdatedAt(); !ok { + if abusereport.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized abusereport.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := abusereport.DefaultUpdatedAt() + arc.mutation.SetUpdatedAt(v) + } + if _, ok := arc.mutation.Status(); !ok { + v := abusereport.DefaultStatus + arc.mutation.SetStatus(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (arc *AbuseReportCreate) check() error { + if _, ok := arc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "AbuseReport.created_at"`)} + } + if _, ok := arc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "AbuseReport.updated_at"`)} + } + if _, ok := arc.mutation.TargetType(); !ok { + return &ValidationError{Name: "target_type", err: errors.New(`ent: missing required field "AbuseReport.target_type"`)} + } + if _, ok := arc.mutation.TargetID(); !ok { + return &ValidationError{Name: "target_id", err: errors.New(`ent: missing required field "AbuseReport.target_id"`)} + } + if _, ok := arc.mutation.Reason(); !ok { + return &ValidationError{Name: "reason", err: errors.New(`ent: missing required field "AbuseReport.reason"`)} + } + if _, ok := arc.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "AbuseReport.status"`)} + } + return nil +} + +func (arc *AbuseReportCreate) sqlSave(ctx context.Context) (*AbuseReport, error) { + if err := arc.check(); err != nil { + return nil, err + } + _node, _spec := arc.createSpec() + if err := sqlgraph.CreateNode(ctx, arc.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) + arc.mutation.id = &_node.ID + arc.mutation.done = true + return _node, nil +} + +func (arc *AbuseReportCreate) createSpec() (*AbuseReport, *sqlgraph.CreateSpec) { + var ( + _node = &AbuseReport{config: arc.config} + _spec = sqlgraph.NewCreateSpec(abusereport.Table, sqlgraph.NewFieldSpec(abusereport.FieldID, field.TypeInt)) + ) + + if id, ok := arc.mutation.ID(); ok { + _node.ID = id + id64 := int64(id) + _spec.ID.Value = id64 + } + + _spec.OnConflict = arc.conflict + if value, ok := arc.mutation.CreatedAt(); ok { + _spec.SetField(abusereport.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := arc.mutation.UpdatedAt(); ok { + _spec.SetField(abusereport.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := arc.mutation.DeletedAt(); ok { + _spec.SetField(abusereport.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = &value + } + if value, ok := arc.mutation.ReporterID(); ok { + _spec.SetField(abusereport.FieldReporterID, field.TypeInt, value) + _node.ReporterID = value + } + if value, ok := arc.mutation.ReporterEmail(); ok { + _spec.SetField(abusereport.FieldReporterEmail, field.TypeString, value) + _node.ReporterEmail = value + } + if value, ok := arc.mutation.TargetType(); ok { + _spec.SetField(abusereport.FieldTargetType, field.TypeString, value) + _node.TargetType = value + } + if value, ok := arc.mutation.TargetID(); ok { + _spec.SetField(abusereport.FieldTargetID, field.TypeInt, value) + _node.TargetID = value + } + if value, ok := arc.mutation.Reason(); ok { + _spec.SetField(abusereport.FieldReason, field.TypeInt, value) + _node.Reason = value + } + if value, ok := arc.mutation.Description(); ok { + _spec.SetField(abusereport.FieldDescription, field.TypeString, value) + _node.Description = value + } + if value, ok := arc.mutation.Status(); ok { + _spec.SetField(abusereport.FieldStatus, field.TypeString, value) + _node.Status = value + } + if value, ok := arc.mutation.AdminNote(); ok { + _spec.SetField(abusereport.FieldAdminNote, field.TypeString, value) + _node.AdminNote = value + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.AbuseReport.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.AbuseReportUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (arc *AbuseReportCreate) OnConflict(opts ...sql.ConflictOption) *AbuseReportUpsertOne { + arc.conflict = opts + return &AbuseReportUpsertOne{ + create: arc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (arc *AbuseReportCreate) OnConflictColumns(columns ...string) *AbuseReportUpsertOne { + arc.conflict = append(arc.conflict, sql.ConflictColumns(columns...)) + return &AbuseReportUpsertOne{ + create: arc, + } +} + +type ( + // AbuseReportUpsertOne is the builder for "upsert"-ing + // one AbuseReport node. + AbuseReportUpsertOne struct { + create *AbuseReportCreate + } + + // AbuseReportUpsert is the "OnConflict" setter. + AbuseReportUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *AbuseReportUpsert) SetUpdatedAt(v time.Time) *AbuseReportUpsert { + u.Set(abusereport.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateUpdatedAt() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldUpdatedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *AbuseReportUpsert) SetDeletedAt(v time.Time) *AbuseReportUpsert { + u.Set(abusereport.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateDeletedAt() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *AbuseReportUpsert) ClearDeletedAt() *AbuseReportUpsert { + u.SetNull(abusereport.FieldDeletedAt) + return u +} + +// SetReporterID sets the "reporter_id" field. +func (u *AbuseReportUpsert) SetReporterID(v int) *AbuseReportUpsert { + u.Set(abusereport.FieldReporterID, v) + return u +} + +// UpdateReporterID sets the "reporter_id" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateReporterID() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldReporterID) + return u +} + +// AddReporterID adds v to the "reporter_id" field. +func (u *AbuseReportUpsert) AddReporterID(v int) *AbuseReportUpsert { + u.Add(abusereport.FieldReporterID, v) + return u +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (u *AbuseReportUpsert) ClearReporterID() *AbuseReportUpsert { + u.SetNull(abusereport.FieldReporterID) + return u +} + +// SetReporterEmail sets the "reporter_email" field. +func (u *AbuseReportUpsert) SetReporterEmail(v string) *AbuseReportUpsert { + u.Set(abusereport.FieldReporterEmail, v) + return u +} + +// UpdateReporterEmail sets the "reporter_email" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateReporterEmail() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldReporterEmail) + return u +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (u *AbuseReportUpsert) ClearReporterEmail() *AbuseReportUpsert { + u.SetNull(abusereport.FieldReporterEmail) + return u +} + +// SetTargetType sets the "target_type" field. +func (u *AbuseReportUpsert) SetTargetType(v string) *AbuseReportUpsert { + u.Set(abusereport.FieldTargetType, v) + return u +} + +// UpdateTargetType sets the "target_type" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateTargetType() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldTargetType) + return u +} + +// SetTargetID sets the "target_id" field. +func (u *AbuseReportUpsert) SetTargetID(v int) *AbuseReportUpsert { + u.Set(abusereport.FieldTargetID, v) + return u +} + +// UpdateTargetID sets the "target_id" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateTargetID() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldTargetID) + return u +} + +// AddTargetID adds v to the "target_id" field. +func (u *AbuseReportUpsert) AddTargetID(v int) *AbuseReportUpsert { + u.Add(abusereport.FieldTargetID, v) + return u +} + +// SetReason sets the "reason" field. +func (u *AbuseReportUpsert) SetReason(v int) *AbuseReportUpsert { + u.Set(abusereport.FieldReason, v) + return u +} + +// UpdateReason sets the "reason" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateReason() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldReason) + return u +} + +// AddReason adds v to the "reason" field. +func (u *AbuseReportUpsert) AddReason(v int) *AbuseReportUpsert { + u.Add(abusereport.FieldReason, v) + return u +} + +// SetDescription sets the "description" field. +func (u *AbuseReportUpsert) SetDescription(v string) *AbuseReportUpsert { + u.Set(abusereport.FieldDescription, v) + return u +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateDescription() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldDescription) + return u +} + +// ClearDescription clears the value of the "description" field. +func (u *AbuseReportUpsert) ClearDescription() *AbuseReportUpsert { + u.SetNull(abusereport.FieldDescription) + return u +} + +// SetStatus sets the "status" field. +func (u *AbuseReportUpsert) SetStatus(v string) *AbuseReportUpsert { + u.Set(abusereport.FieldStatus, v) + return u +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateStatus() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldStatus) + return u +} + +// SetAdminNote sets the "admin_note" field. +func (u *AbuseReportUpsert) SetAdminNote(v string) *AbuseReportUpsert { + u.Set(abusereport.FieldAdminNote, v) + return u +} + +// UpdateAdminNote sets the "admin_note" field to the value that was provided on create. +func (u *AbuseReportUpsert) UpdateAdminNote() *AbuseReportUpsert { + u.SetExcluded(abusereport.FieldAdminNote) + return u +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (u *AbuseReportUpsert) ClearAdminNote() *AbuseReportUpsert { + u.SetNull(abusereport.FieldAdminNote) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *AbuseReportUpsertOne) UpdateNewValues() *AbuseReportUpsertOne { + 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(abusereport.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *AbuseReportUpsertOne) Ignore() *AbuseReportUpsertOne { + 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 *AbuseReportUpsertOne) DoNothing() *AbuseReportUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the AbuseReportCreate.OnConflict +// documentation for more info. +func (u *AbuseReportUpsertOne) Update(set func(*AbuseReportUpsert)) *AbuseReportUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&AbuseReportUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *AbuseReportUpsertOne) SetUpdatedAt(v time.Time) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateUpdatedAt() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *AbuseReportUpsertOne) SetDeletedAt(v time.Time) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateDeletedAt() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *AbuseReportUpsertOne) ClearDeletedAt() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearDeletedAt() + }) +} + +// SetReporterID sets the "reporter_id" field. +func (u *AbuseReportUpsertOne) SetReporterID(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReporterID(v) + }) +} + +// AddReporterID adds v to the "reporter_id" field. +func (u *AbuseReportUpsertOne) AddReporterID(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.AddReporterID(v) + }) +} + +// UpdateReporterID sets the "reporter_id" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateReporterID() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReporterID() + }) +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (u *AbuseReportUpsertOne) ClearReporterID() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearReporterID() + }) +} + +// SetReporterEmail sets the "reporter_email" field. +func (u *AbuseReportUpsertOne) SetReporterEmail(v string) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReporterEmail(v) + }) +} + +// UpdateReporterEmail sets the "reporter_email" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateReporterEmail() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReporterEmail() + }) +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (u *AbuseReportUpsertOne) ClearReporterEmail() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearReporterEmail() + }) +} + +// SetTargetType sets the "target_type" field. +func (u *AbuseReportUpsertOne) SetTargetType(v string) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetTargetType(v) + }) +} + +// UpdateTargetType sets the "target_type" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateTargetType() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateTargetType() + }) +} + +// SetTargetID sets the "target_id" field. +func (u *AbuseReportUpsertOne) SetTargetID(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetTargetID(v) + }) +} + +// AddTargetID adds v to the "target_id" field. +func (u *AbuseReportUpsertOne) AddTargetID(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.AddTargetID(v) + }) +} + +// UpdateTargetID sets the "target_id" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateTargetID() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateTargetID() + }) +} + +// SetReason sets the "reason" field. +func (u *AbuseReportUpsertOne) SetReason(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReason(v) + }) +} + +// AddReason adds v to the "reason" field. +func (u *AbuseReportUpsertOne) AddReason(v int) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.AddReason(v) + }) +} + +// UpdateReason sets the "reason" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateReason() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReason() + }) +} + +// SetDescription sets the "description" field. +func (u *AbuseReportUpsertOne) SetDescription(v string) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetDescription(v) + }) +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateDescription() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateDescription() + }) +} + +// ClearDescription clears the value of the "description" field. +func (u *AbuseReportUpsertOne) ClearDescription() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearDescription() + }) +} + +// SetStatus sets the "status" field. +func (u *AbuseReportUpsertOne) SetStatus(v string) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateStatus() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateStatus() + }) +} + +// SetAdminNote sets the "admin_note" field. +func (u *AbuseReportUpsertOne) SetAdminNote(v string) *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.SetAdminNote(v) + }) +} + +// UpdateAdminNote sets the "admin_note" field to the value that was provided on create. +func (u *AbuseReportUpsertOne) UpdateAdminNote() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateAdminNote() + }) +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (u *AbuseReportUpsertOne) ClearAdminNote() *AbuseReportUpsertOne { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearAdminNote() + }) +} + +// Exec executes the query. +func (u *AbuseReportUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for AbuseReportCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *AbuseReportUpsertOne) 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 *AbuseReportUpsertOne) 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 *AbuseReportUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +func (m *AbuseReportCreate) SetRawID(t int) *AbuseReportCreate { + m.mutation.SetRawID(t) + return m +} + +// AbuseReportCreateBulk is the builder for creating many AbuseReport entities in bulk. +type AbuseReportCreateBulk struct { + config + err error + builders []*AbuseReportCreate + conflict []sql.ConflictOption +} + +// Save creates the AbuseReport entities in the database. +func (arcb *AbuseReportCreateBulk) Save(ctx context.Context) ([]*AbuseReport, error) { + if arcb.err != nil { + return nil, arcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(arcb.builders)) + nodes := make([]*AbuseReport, len(arcb.builders)) + mutators := make([]Mutator, len(arcb.builders)) + for i := range arcb.builders { + func(i int, root context.Context) { + builder := arcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AbuseReportMutation) + 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, arcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = arcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, arcb.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, arcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (arcb *AbuseReportCreateBulk) SaveX(ctx context.Context) []*AbuseReport { + v, err := arcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (arcb *AbuseReportCreateBulk) Exec(ctx context.Context) error { + _, err := arcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (arcb *AbuseReportCreateBulk) ExecX(ctx context.Context) { + if err := arcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.AbuseReport.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.AbuseReportUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (arcb *AbuseReportCreateBulk) OnConflict(opts ...sql.ConflictOption) *AbuseReportUpsertBulk { + arcb.conflict = opts + return &AbuseReportUpsertBulk{ + create: arcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (arcb *AbuseReportCreateBulk) OnConflictColumns(columns ...string) *AbuseReportUpsertBulk { + arcb.conflict = append(arcb.conflict, sql.ConflictColumns(columns...)) + return &AbuseReportUpsertBulk{ + create: arcb, + } +} + +// AbuseReportUpsertBulk is the builder for "upsert"-ing +// a bulk of AbuseReport nodes. +type AbuseReportUpsertBulk struct { + create *AbuseReportCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *AbuseReportUpsertBulk) UpdateNewValues() *AbuseReportUpsertBulk { + 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(abusereport.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.AbuseReport.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *AbuseReportUpsertBulk) Ignore() *AbuseReportUpsertBulk { + 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 *AbuseReportUpsertBulk) DoNothing() *AbuseReportUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the AbuseReportCreateBulk.OnConflict +// documentation for more info. +func (u *AbuseReportUpsertBulk) Update(set func(*AbuseReportUpsert)) *AbuseReportUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&AbuseReportUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *AbuseReportUpsertBulk) SetUpdatedAt(v time.Time) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateUpdatedAt() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *AbuseReportUpsertBulk) SetDeletedAt(v time.Time) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateDeletedAt() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *AbuseReportUpsertBulk) ClearDeletedAt() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearDeletedAt() + }) +} + +// SetReporterID sets the "reporter_id" field. +func (u *AbuseReportUpsertBulk) SetReporterID(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReporterID(v) + }) +} + +// AddReporterID adds v to the "reporter_id" field. +func (u *AbuseReportUpsertBulk) AddReporterID(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.AddReporterID(v) + }) +} + +// UpdateReporterID sets the "reporter_id" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateReporterID() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReporterID() + }) +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (u *AbuseReportUpsertBulk) ClearReporterID() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearReporterID() + }) +} + +// SetReporterEmail sets the "reporter_email" field. +func (u *AbuseReportUpsertBulk) SetReporterEmail(v string) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReporterEmail(v) + }) +} + +// UpdateReporterEmail sets the "reporter_email" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateReporterEmail() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReporterEmail() + }) +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (u *AbuseReportUpsertBulk) ClearReporterEmail() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearReporterEmail() + }) +} + +// SetTargetType sets the "target_type" field. +func (u *AbuseReportUpsertBulk) SetTargetType(v string) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetTargetType(v) + }) +} + +// UpdateTargetType sets the "target_type" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateTargetType() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateTargetType() + }) +} + +// SetTargetID sets the "target_id" field. +func (u *AbuseReportUpsertBulk) SetTargetID(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetTargetID(v) + }) +} + +// AddTargetID adds v to the "target_id" field. +func (u *AbuseReportUpsertBulk) AddTargetID(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.AddTargetID(v) + }) +} + +// UpdateTargetID sets the "target_id" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateTargetID() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateTargetID() + }) +} + +// SetReason sets the "reason" field. +func (u *AbuseReportUpsertBulk) SetReason(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetReason(v) + }) +} + +// AddReason adds v to the "reason" field. +func (u *AbuseReportUpsertBulk) AddReason(v int) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.AddReason(v) + }) +} + +// UpdateReason sets the "reason" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateReason() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateReason() + }) +} + +// SetDescription sets the "description" field. +func (u *AbuseReportUpsertBulk) SetDescription(v string) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetDescription(v) + }) +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateDescription() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateDescription() + }) +} + +// ClearDescription clears the value of the "description" field. +func (u *AbuseReportUpsertBulk) ClearDescription() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearDescription() + }) +} + +// SetStatus sets the "status" field. +func (u *AbuseReportUpsertBulk) SetStatus(v string) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateStatus() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateStatus() + }) +} + +// SetAdminNote sets the "admin_note" field. +func (u *AbuseReportUpsertBulk) SetAdminNote(v string) *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.SetAdminNote(v) + }) +} + +// UpdateAdminNote sets the "admin_note" field to the value that was provided on create. +func (u *AbuseReportUpsertBulk) UpdateAdminNote() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.UpdateAdminNote() + }) +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (u *AbuseReportUpsertBulk) ClearAdminNote() *AbuseReportUpsertBulk { + return u.Update(func(s *AbuseReportUpsert) { + s.ClearAdminNote() + }) +} + +// Exec executes the query. +func (u *AbuseReportUpsertBulk) 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 AbuseReportCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for AbuseReportCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *AbuseReportUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/abusereport_delete.go b/ent/abusereport_delete.go new file mode 100644 index 00000000..ccb8e153 --- /dev/null +++ b/ent/abusereport_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// AbuseReportDelete is the builder for deleting a AbuseReport entity. +type AbuseReportDelete struct { + config + hooks []Hook + mutation *AbuseReportMutation +} + +// Where appends a list predicates to the AbuseReportDelete builder. +func (ard *AbuseReportDelete) Where(ps ...predicate.AbuseReport) *AbuseReportDelete { + ard.mutation.Where(ps...) + return ard +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ard *AbuseReportDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, ard.sqlExec, ard.mutation, ard.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (ard *AbuseReportDelete) ExecX(ctx context.Context) int { + n, err := ard.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ard *AbuseReportDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(abusereport.Table, sqlgraph.NewFieldSpec(abusereport.FieldID, field.TypeInt)) + if ps := ard.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ard.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + ard.mutation.done = true + return affected, err +} + +// AbuseReportDeleteOne is the builder for deleting a single AbuseReport entity. +type AbuseReportDeleteOne struct { + ard *AbuseReportDelete +} + +// Where appends a list predicates to the AbuseReportDelete builder. +func (ardo *AbuseReportDeleteOne) Where(ps ...predicate.AbuseReport) *AbuseReportDeleteOne { + ardo.ard.mutation.Where(ps...) + return ardo +} + +// Exec executes the deletion query. +func (ardo *AbuseReportDeleteOne) Exec(ctx context.Context) error { + n, err := ardo.ard.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{abusereport.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ardo *AbuseReportDeleteOne) ExecX(ctx context.Context) { + if err := ardo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/abusereport_query.go b/ent/abusereport_query.go new file mode 100644 index 00000000..728d3e7d --- /dev/null +++ b/ent/abusereport_query.go @@ -0,0 +1,526 @@ +// 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/abusereport" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// AbuseReportQuery is the builder for querying AbuseReport entities. +type AbuseReportQuery struct { + config + ctx *QueryContext + order []abusereport.OrderOption + inters []Interceptor + predicates []predicate.AbuseReport + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the AbuseReportQuery builder. +func (arq *AbuseReportQuery) Where(ps ...predicate.AbuseReport) *AbuseReportQuery { + arq.predicates = append(arq.predicates, ps...) + return arq +} + +// Limit the number of records to be returned by this query. +func (arq *AbuseReportQuery) Limit(limit int) *AbuseReportQuery { + arq.ctx.Limit = &limit + return arq +} + +// Offset to start from. +func (arq *AbuseReportQuery) Offset(offset int) *AbuseReportQuery { + arq.ctx.Offset = &offset + return arq +} + +// 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 (arq *AbuseReportQuery) Unique(unique bool) *AbuseReportQuery { + arq.ctx.Unique = &unique + return arq +} + +// Order specifies how the records should be ordered. +func (arq *AbuseReportQuery) Order(o ...abusereport.OrderOption) *AbuseReportQuery { + arq.order = append(arq.order, o...) + return arq +} + +// First returns the first AbuseReport entity from the query. +// Returns a *NotFoundError when no AbuseReport was found. +func (arq *AbuseReportQuery) First(ctx context.Context) (*AbuseReport, error) { + nodes, err := arq.Limit(1).All(setContextOp(ctx, arq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{abusereport.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (arq *AbuseReportQuery) FirstX(ctx context.Context) *AbuseReport { + node, err := arq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first AbuseReport ID from the query. +// Returns a *NotFoundError when no AbuseReport ID was found. +func (arq *AbuseReportQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = arq.Limit(1).IDs(setContextOp(ctx, arq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{abusereport.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (arq *AbuseReportQuery) FirstIDX(ctx context.Context) int { + id, err := arq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single AbuseReport entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one AbuseReport entity is found. +// Returns a *NotFoundError when no AbuseReport entities are found. +func (arq *AbuseReportQuery) Only(ctx context.Context) (*AbuseReport, error) { + nodes, err := arq.Limit(2).All(setContextOp(ctx, arq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{abusereport.Label} + default: + return nil, &NotSingularError{abusereport.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (arq *AbuseReportQuery) OnlyX(ctx context.Context) *AbuseReport { + node, err := arq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only AbuseReport ID in the query. +// Returns a *NotSingularError when more than one AbuseReport ID is found. +// Returns a *NotFoundError when no entities are found. +func (arq *AbuseReportQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = arq.Limit(2).IDs(setContextOp(ctx, arq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{abusereport.Label} + default: + err = &NotSingularError{abusereport.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (arq *AbuseReportQuery) OnlyIDX(ctx context.Context) int { + id, err := arq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of AbuseReports. +func (arq *AbuseReportQuery) All(ctx context.Context) ([]*AbuseReport, error) { + ctx = setContextOp(ctx, arq.ctx, "All") + if err := arq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*AbuseReport, *AbuseReportQuery]() + return withInterceptors[[]*AbuseReport](ctx, arq, qr, arq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (arq *AbuseReportQuery) AllX(ctx context.Context) []*AbuseReport { + nodes, err := arq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of AbuseReport IDs. +func (arq *AbuseReportQuery) IDs(ctx context.Context) (ids []int, err error) { + if arq.ctx.Unique == nil && arq.path != nil { + arq.Unique(true) + } + ctx = setContextOp(ctx, arq.ctx, "IDs") + if err = arq.Select(abusereport.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (arq *AbuseReportQuery) IDsX(ctx context.Context) []int { + ids, err := arq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (arq *AbuseReportQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, arq.ctx, "Count") + if err := arq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, arq, querierCount[*AbuseReportQuery](), arq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (arq *AbuseReportQuery) CountX(ctx context.Context) int { + count, err := arq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (arq *AbuseReportQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, arq.ctx, "Exist") + switch _, err := arq.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 (arq *AbuseReportQuery) ExistX(ctx context.Context) bool { + exist, err := arq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the AbuseReportQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (arq *AbuseReportQuery) Clone() *AbuseReportQuery { + if arq == nil { + return nil + } + return &AbuseReportQuery{ + config: arq.config, + ctx: arq.ctx.Clone(), + order: append([]abusereport.OrderOption{}, arq.order...), + inters: append([]Interceptor{}, arq.inters...), + predicates: append([]predicate.AbuseReport{}, arq.predicates...), + // clone intermediate query. + sql: arq.sql.Clone(), + path: arq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.AbuseReport.Query(). +// GroupBy(abusereport.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (arq *AbuseReportQuery) GroupBy(field string, fields ...string) *AbuseReportGroupBy { + arq.ctx.Fields = append([]string{field}, fields...) + grbuild := &AbuseReportGroupBy{build: arq} + grbuild.flds = &arq.ctx.Fields + grbuild.label = abusereport.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.AbuseReport.Query(). +// Select(abusereport.FieldCreatedAt). +// Scan(ctx, &v) +func (arq *AbuseReportQuery) Select(fields ...string) *AbuseReportSelect { + arq.ctx.Fields = append(arq.ctx.Fields, fields...) + sbuild := &AbuseReportSelect{AbuseReportQuery: arq} + sbuild.label = abusereport.Label + sbuild.flds, sbuild.scan = &arq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a AbuseReportSelect configured with the given aggregations. +func (arq *AbuseReportQuery) Aggregate(fns ...AggregateFunc) *AbuseReportSelect { + return arq.Select().Aggregate(fns...) +} + +func (arq *AbuseReportQuery) prepareQuery(ctx context.Context) error { + for _, inter := range arq.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, arq); err != nil { + return err + } + } + } + for _, f := range arq.ctx.Fields { + if !abusereport.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if arq.path != nil { + prev, err := arq.path(ctx) + if err != nil { + return err + } + arq.sql = prev + } + return nil +} + +func (arq *AbuseReportQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AbuseReport, error) { + var ( + nodes = []*AbuseReport{} + _spec = arq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*AbuseReport).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &AbuseReport{config: arq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, arq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (arq *AbuseReportQuery) sqlCount(ctx context.Context) (int, error) { + _spec := arq.querySpec() + _spec.Node.Columns = arq.ctx.Fields + if len(arq.ctx.Fields) > 0 { + _spec.Unique = arq.ctx.Unique != nil && *arq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, arq.driver, _spec) +} + +func (arq *AbuseReportQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(abusereport.Table, abusereport.Columns, sqlgraph.NewFieldSpec(abusereport.FieldID, field.TypeInt)) + _spec.From = arq.sql + if unique := arq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if arq.path != nil { + _spec.Unique = true + } + if fields := arq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, abusereport.FieldID) + for i := range fields { + if fields[i] != abusereport.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := arq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := arq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := arq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := arq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (arq *AbuseReportQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(arq.driver.Dialect()) + t1 := builder.Table(abusereport.Table) + columns := arq.ctx.Fields + if len(columns) == 0 { + columns = abusereport.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if arq.sql != nil { + selector = arq.sql + selector.Select(selector.Columns(columns...)...) + } + if arq.ctx.Unique != nil && *arq.ctx.Unique { + selector.Distinct() + } + for _, p := range arq.predicates { + p(selector) + } + for _, p := range arq.order { + p(selector) + } + if offset := arq.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 := arq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// AbuseReportGroupBy is the group-by builder for AbuseReport entities. +type AbuseReportGroupBy struct { + selector + build *AbuseReportQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (argb *AbuseReportGroupBy) Aggregate(fns ...AggregateFunc) *AbuseReportGroupBy { + argb.fns = append(argb.fns, fns...) + return argb +} + +// Scan applies the selector query and scans the result into the given value. +func (argb *AbuseReportGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, argb.build.ctx, "GroupBy") + if err := argb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*AbuseReportQuery, *AbuseReportGroupBy](ctx, argb.build, argb, argb.build.inters, v) +} + +func (argb *AbuseReportGroupBy) sqlScan(ctx context.Context, root *AbuseReportQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(argb.fns)) + for _, fn := range argb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*argb.flds)+len(argb.fns)) + for _, f := range *argb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*argb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := argb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// AbuseReportSelect is the builder for selecting fields of AbuseReport entities. +type AbuseReportSelect struct { + *AbuseReportQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ars *AbuseReportSelect) Aggregate(fns ...AggregateFunc) *AbuseReportSelect { + ars.fns = append(ars.fns, fns...) + return ars +} + +// Scan applies the selector query and scans the result into the given value. +func (ars *AbuseReportSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ars.ctx, "Select") + if err := ars.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*AbuseReportQuery, *AbuseReportSelect](ctx, ars.AbuseReportQuery, ars, ars.inters, v) +} + +func (ars *AbuseReportSelect) sqlScan(ctx context.Context, root *AbuseReportQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ars.fns)) + for _, fn := range ars.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ars.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 := ars.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/abusereport_update.go b/ent/abusereport_update.go new file mode 100644 index 00000000..7d709b8e --- /dev/null +++ b/ent/abusereport_update.go @@ -0,0 +1,680 @@ +// 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/abusereport" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// AbuseReportUpdate is the builder for updating AbuseReport entities. +type AbuseReportUpdate struct { + config + hooks []Hook + mutation *AbuseReportMutation +} + +// Where appends a list predicates to the AbuseReportUpdate builder. +func (aru *AbuseReportUpdate) Where(ps ...predicate.AbuseReport) *AbuseReportUpdate { + aru.mutation.Where(ps...) + return aru +} + +// SetUpdatedAt sets the "updated_at" field. +func (aru *AbuseReportUpdate) SetUpdatedAt(t time.Time) *AbuseReportUpdate { + aru.mutation.SetUpdatedAt(t) + return aru +} + +// SetDeletedAt sets the "deleted_at" field. +func (aru *AbuseReportUpdate) SetDeletedAt(t time.Time) *AbuseReportUpdate { + aru.mutation.SetDeletedAt(t) + return aru +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableDeletedAt(t *time.Time) *AbuseReportUpdate { + if t != nil { + aru.SetDeletedAt(*t) + } + return aru +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (aru *AbuseReportUpdate) ClearDeletedAt() *AbuseReportUpdate { + aru.mutation.ClearDeletedAt() + return aru +} + +// SetReporterID sets the "reporter_id" field. +func (aru *AbuseReportUpdate) SetReporterID(i int) *AbuseReportUpdate { + aru.mutation.ResetReporterID() + aru.mutation.SetReporterID(i) + return aru +} + +// SetNillableReporterID sets the "reporter_id" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableReporterID(i *int) *AbuseReportUpdate { + if i != nil { + aru.SetReporterID(*i) + } + return aru +} + +// AddReporterID adds i to the "reporter_id" field. +func (aru *AbuseReportUpdate) AddReporterID(i int) *AbuseReportUpdate { + aru.mutation.AddReporterID(i) + return aru +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (aru *AbuseReportUpdate) ClearReporterID() *AbuseReportUpdate { + aru.mutation.ClearReporterID() + return aru +} + +// SetReporterEmail sets the "reporter_email" field. +func (aru *AbuseReportUpdate) SetReporterEmail(s string) *AbuseReportUpdate { + aru.mutation.SetReporterEmail(s) + return aru +} + +// SetNillableReporterEmail sets the "reporter_email" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableReporterEmail(s *string) *AbuseReportUpdate { + if s != nil { + aru.SetReporterEmail(*s) + } + return aru +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (aru *AbuseReportUpdate) ClearReporterEmail() *AbuseReportUpdate { + aru.mutation.ClearReporterEmail() + return aru +} + +// SetTargetType sets the "target_type" field. +func (aru *AbuseReportUpdate) SetTargetType(s string) *AbuseReportUpdate { + aru.mutation.SetTargetType(s) + return aru +} + +// SetNillableTargetType sets the "target_type" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableTargetType(s *string) *AbuseReportUpdate { + if s != nil { + aru.SetTargetType(*s) + } + return aru +} + +// SetTargetID sets the "target_id" field. +func (aru *AbuseReportUpdate) SetTargetID(i int) *AbuseReportUpdate { + aru.mutation.ResetTargetID() + aru.mutation.SetTargetID(i) + return aru +} + +// SetNillableTargetID sets the "target_id" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableTargetID(i *int) *AbuseReportUpdate { + if i != nil { + aru.SetTargetID(*i) + } + return aru +} + +// AddTargetID adds i to the "target_id" field. +func (aru *AbuseReportUpdate) AddTargetID(i int) *AbuseReportUpdate { + aru.mutation.AddTargetID(i) + return aru +} + +// SetReason sets the "reason" field. +func (aru *AbuseReportUpdate) SetReason(i int) *AbuseReportUpdate { + aru.mutation.ResetReason() + aru.mutation.SetReason(i) + return aru +} + +// SetNillableReason sets the "reason" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableReason(i *int) *AbuseReportUpdate { + if i != nil { + aru.SetReason(*i) + } + return aru +} + +// AddReason adds i to the "reason" field. +func (aru *AbuseReportUpdate) AddReason(i int) *AbuseReportUpdate { + aru.mutation.AddReason(i) + return aru +} + +// SetDescription sets the "description" field. +func (aru *AbuseReportUpdate) SetDescription(s string) *AbuseReportUpdate { + aru.mutation.SetDescription(s) + return aru +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableDescription(s *string) *AbuseReportUpdate { + if s != nil { + aru.SetDescription(*s) + } + return aru +} + +// ClearDescription clears the value of the "description" field. +func (aru *AbuseReportUpdate) ClearDescription() *AbuseReportUpdate { + aru.mutation.ClearDescription() + return aru +} + +// SetStatus sets the "status" field. +func (aru *AbuseReportUpdate) SetStatus(s string) *AbuseReportUpdate { + aru.mutation.SetStatus(s) + return aru +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableStatus(s *string) *AbuseReportUpdate { + if s != nil { + aru.SetStatus(*s) + } + return aru +} + +// SetAdminNote sets the "admin_note" field. +func (aru *AbuseReportUpdate) SetAdminNote(s string) *AbuseReportUpdate { + aru.mutation.SetAdminNote(s) + return aru +} + +// SetNillableAdminNote sets the "admin_note" field if the given value is not nil. +func (aru *AbuseReportUpdate) SetNillableAdminNote(s *string) *AbuseReportUpdate { + if s != nil { + aru.SetAdminNote(*s) + } + return aru +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (aru *AbuseReportUpdate) ClearAdminNote() *AbuseReportUpdate { + aru.mutation.ClearAdminNote() + return aru +} + +// Mutation returns the AbuseReportMutation object of the builder. +func (aru *AbuseReportUpdate) Mutation() *AbuseReportMutation { + return aru.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (aru *AbuseReportUpdate) Save(ctx context.Context) (int, error) { + if err := aru.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, aru.sqlSave, aru.mutation, aru.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (aru *AbuseReportUpdate) SaveX(ctx context.Context) int { + affected, err := aru.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (aru *AbuseReportUpdate) Exec(ctx context.Context) error { + _, err := aru.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (aru *AbuseReportUpdate) ExecX(ctx context.Context) { + if err := aru.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (aru *AbuseReportUpdate) defaults() error { + if _, ok := aru.mutation.UpdatedAt(); !ok { + if abusereport.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized abusereport.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := abusereport.UpdateDefaultUpdatedAt() + aru.mutation.SetUpdatedAt(v) + } + return nil +} + +func (aru *AbuseReportUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := sqlgraph.NewUpdateSpec(abusereport.Table, abusereport.Columns, sqlgraph.NewFieldSpec(abusereport.FieldID, field.TypeInt)) + if ps := aru.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := aru.mutation.UpdatedAt(); ok { + _spec.SetField(abusereport.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := aru.mutation.DeletedAt(); ok { + _spec.SetField(abusereport.FieldDeletedAt, field.TypeTime, value) + } + if aru.mutation.DeletedAtCleared() { + _spec.ClearField(abusereport.FieldDeletedAt, field.TypeTime) + } + if value, ok := aru.mutation.ReporterID(); ok { + _spec.SetField(abusereport.FieldReporterID, field.TypeInt, value) + } + if value, ok := aru.mutation.AddedReporterID(); ok { + _spec.AddField(abusereport.FieldReporterID, field.TypeInt, value) + } + if aru.mutation.ReporterIDCleared() { + _spec.ClearField(abusereport.FieldReporterID, field.TypeInt) + } + if value, ok := aru.mutation.ReporterEmail(); ok { + _spec.SetField(abusereport.FieldReporterEmail, field.TypeString, value) + } + if aru.mutation.ReporterEmailCleared() { + _spec.ClearField(abusereport.FieldReporterEmail, field.TypeString) + } + if value, ok := aru.mutation.TargetType(); ok { + _spec.SetField(abusereport.FieldTargetType, field.TypeString, value) + } + if value, ok := aru.mutation.TargetID(); ok { + _spec.SetField(abusereport.FieldTargetID, field.TypeInt, value) + } + if value, ok := aru.mutation.AddedTargetID(); ok { + _spec.AddField(abusereport.FieldTargetID, field.TypeInt, value) + } + if value, ok := aru.mutation.Reason(); ok { + _spec.SetField(abusereport.FieldReason, field.TypeInt, value) + } + if value, ok := aru.mutation.AddedReason(); ok { + _spec.AddField(abusereport.FieldReason, field.TypeInt, value) + } + if value, ok := aru.mutation.Description(); ok { + _spec.SetField(abusereport.FieldDescription, field.TypeString, value) + } + if aru.mutation.DescriptionCleared() { + _spec.ClearField(abusereport.FieldDescription, field.TypeString) + } + if value, ok := aru.mutation.Status(); ok { + _spec.SetField(abusereport.FieldStatus, field.TypeString, value) + } + if value, ok := aru.mutation.AdminNote(); ok { + _spec.SetField(abusereport.FieldAdminNote, field.TypeString, value) + } + if aru.mutation.AdminNoteCleared() { + _spec.ClearField(abusereport.FieldAdminNote, field.TypeString) + } + if n, err = sqlgraph.UpdateNodes(ctx, aru.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{abusereport.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + aru.mutation.done = true + return n, nil +} + +// AbuseReportUpdateOne is the builder for updating a single AbuseReport entity. +type AbuseReportUpdateOne struct { + config + fields []string + hooks []Hook + mutation *AbuseReportMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (aruo *AbuseReportUpdateOne) SetUpdatedAt(t time.Time) *AbuseReportUpdateOne { + aruo.mutation.SetUpdatedAt(t) + return aruo +} + +// SetDeletedAt sets the "deleted_at" field. +func (aruo *AbuseReportUpdateOne) SetDeletedAt(t time.Time) *AbuseReportUpdateOne { + aruo.mutation.SetDeletedAt(t) + return aruo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableDeletedAt(t *time.Time) *AbuseReportUpdateOne { + if t != nil { + aruo.SetDeletedAt(*t) + } + return aruo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (aruo *AbuseReportUpdateOne) ClearDeletedAt() *AbuseReportUpdateOne { + aruo.mutation.ClearDeletedAt() + return aruo +} + +// SetReporterID sets the "reporter_id" field. +func (aruo *AbuseReportUpdateOne) SetReporterID(i int) *AbuseReportUpdateOne { + aruo.mutation.ResetReporterID() + aruo.mutation.SetReporterID(i) + return aruo +} + +// SetNillableReporterID sets the "reporter_id" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableReporterID(i *int) *AbuseReportUpdateOne { + if i != nil { + aruo.SetReporterID(*i) + } + return aruo +} + +// AddReporterID adds i to the "reporter_id" field. +func (aruo *AbuseReportUpdateOne) AddReporterID(i int) *AbuseReportUpdateOne { + aruo.mutation.AddReporterID(i) + return aruo +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (aruo *AbuseReportUpdateOne) ClearReporterID() *AbuseReportUpdateOne { + aruo.mutation.ClearReporterID() + return aruo +} + +// SetReporterEmail sets the "reporter_email" field. +func (aruo *AbuseReportUpdateOne) SetReporterEmail(s string) *AbuseReportUpdateOne { + aruo.mutation.SetReporterEmail(s) + return aruo +} + +// SetNillableReporterEmail sets the "reporter_email" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableReporterEmail(s *string) *AbuseReportUpdateOne { + if s != nil { + aruo.SetReporterEmail(*s) + } + return aruo +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (aruo *AbuseReportUpdateOne) ClearReporterEmail() *AbuseReportUpdateOne { + aruo.mutation.ClearReporterEmail() + return aruo +} + +// SetTargetType sets the "target_type" field. +func (aruo *AbuseReportUpdateOne) SetTargetType(s string) *AbuseReportUpdateOne { + aruo.mutation.SetTargetType(s) + return aruo +} + +// SetNillableTargetType sets the "target_type" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableTargetType(s *string) *AbuseReportUpdateOne { + if s != nil { + aruo.SetTargetType(*s) + } + return aruo +} + +// SetTargetID sets the "target_id" field. +func (aruo *AbuseReportUpdateOne) SetTargetID(i int) *AbuseReportUpdateOne { + aruo.mutation.ResetTargetID() + aruo.mutation.SetTargetID(i) + return aruo +} + +// SetNillableTargetID sets the "target_id" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableTargetID(i *int) *AbuseReportUpdateOne { + if i != nil { + aruo.SetTargetID(*i) + } + return aruo +} + +// AddTargetID adds i to the "target_id" field. +func (aruo *AbuseReportUpdateOne) AddTargetID(i int) *AbuseReportUpdateOne { + aruo.mutation.AddTargetID(i) + return aruo +} + +// SetReason sets the "reason" field. +func (aruo *AbuseReportUpdateOne) SetReason(i int) *AbuseReportUpdateOne { + aruo.mutation.ResetReason() + aruo.mutation.SetReason(i) + return aruo +} + +// SetNillableReason sets the "reason" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableReason(i *int) *AbuseReportUpdateOne { + if i != nil { + aruo.SetReason(*i) + } + return aruo +} + +// AddReason adds i to the "reason" field. +func (aruo *AbuseReportUpdateOne) AddReason(i int) *AbuseReportUpdateOne { + aruo.mutation.AddReason(i) + return aruo +} + +// SetDescription sets the "description" field. +func (aruo *AbuseReportUpdateOne) SetDescription(s string) *AbuseReportUpdateOne { + aruo.mutation.SetDescription(s) + return aruo +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableDescription(s *string) *AbuseReportUpdateOne { + if s != nil { + aruo.SetDescription(*s) + } + return aruo +} + +// ClearDescription clears the value of the "description" field. +func (aruo *AbuseReportUpdateOne) ClearDescription() *AbuseReportUpdateOne { + aruo.mutation.ClearDescription() + return aruo +} + +// SetStatus sets the "status" field. +func (aruo *AbuseReportUpdateOne) SetStatus(s string) *AbuseReportUpdateOne { + aruo.mutation.SetStatus(s) + return aruo +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableStatus(s *string) *AbuseReportUpdateOne { + if s != nil { + aruo.SetStatus(*s) + } + return aruo +} + +// SetAdminNote sets the "admin_note" field. +func (aruo *AbuseReportUpdateOne) SetAdminNote(s string) *AbuseReportUpdateOne { + aruo.mutation.SetAdminNote(s) + return aruo +} + +// SetNillableAdminNote sets the "admin_note" field if the given value is not nil. +func (aruo *AbuseReportUpdateOne) SetNillableAdminNote(s *string) *AbuseReportUpdateOne { + if s != nil { + aruo.SetAdminNote(*s) + } + return aruo +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (aruo *AbuseReportUpdateOne) ClearAdminNote() *AbuseReportUpdateOne { + aruo.mutation.ClearAdminNote() + return aruo +} + +// Mutation returns the AbuseReportMutation object of the builder. +func (aruo *AbuseReportUpdateOne) Mutation() *AbuseReportMutation { + return aruo.mutation +} + +// Where appends a list predicates to the AbuseReportUpdate builder. +func (aruo *AbuseReportUpdateOne) Where(ps ...predicate.AbuseReport) *AbuseReportUpdateOne { + aruo.mutation.Where(ps...) + return aruo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (aruo *AbuseReportUpdateOne) Select(field string, fields ...string) *AbuseReportUpdateOne { + aruo.fields = append([]string{field}, fields...) + return aruo +} + +// Save executes the query and returns the updated AbuseReport entity. +func (aruo *AbuseReportUpdateOne) Save(ctx context.Context) (*AbuseReport, error) { + if err := aruo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, aruo.sqlSave, aruo.mutation, aruo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (aruo *AbuseReportUpdateOne) SaveX(ctx context.Context) *AbuseReport { + node, err := aruo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (aruo *AbuseReportUpdateOne) Exec(ctx context.Context) error { + _, err := aruo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (aruo *AbuseReportUpdateOne) ExecX(ctx context.Context) { + if err := aruo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (aruo *AbuseReportUpdateOne) defaults() error { + if _, ok := aruo.mutation.UpdatedAt(); !ok { + if abusereport.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized abusereport.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := abusereport.UpdateDefaultUpdatedAt() + aruo.mutation.SetUpdatedAt(v) + } + return nil +} + +func (aruo *AbuseReportUpdateOne) sqlSave(ctx context.Context) (_node *AbuseReport, err error) { + _spec := sqlgraph.NewUpdateSpec(abusereport.Table, abusereport.Columns, sqlgraph.NewFieldSpec(abusereport.FieldID, field.TypeInt)) + id, ok := aruo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AbuseReport.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := aruo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, abusereport.FieldID) + for _, f := range fields { + if !abusereport.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != abusereport.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := aruo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := aruo.mutation.UpdatedAt(); ok { + _spec.SetField(abusereport.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := aruo.mutation.DeletedAt(); ok { + _spec.SetField(abusereport.FieldDeletedAt, field.TypeTime, value) + } + if aruo.mutation.DeletedAtCleared() { + _spec.ClearField(abusereport.FieldDeletedAt, field.TypeTime) + } + if value, ok := aruo.mutation.ReporterID(); ok { + _spec.SetField(abusereport.FieldReporterID, field.TypeInt, value) + } + if value, ok := aruo.mutation.AddedReporterID(); ok { + _spec.AddField(abusereport.FieldReporterID, field.TypeInt, value) + } + if aruo.mutation.ReporterIDCleared() { + _spec.ClearField(abusereport.FieldReporterID, field.TypeInt) + } + if value, ok := aruo.mutation.ReporterEmail(); ok { + _spec.SetField(abusereport.FieldReporterEmail, field.TypeString, value) + } + if aruo.mutation.ReporterEmailCleared() { + _spec.ClearField(abusereport.FieldReporterEmail, field.TypeString) + } + if value, ok := aruo.mutation.TargetType(); ok { + _spec.SetField(abusereport.FieldTargetType, field.TypeString, value) + } + if value, ok := aruo.mutation.TargetID(); ok { + _spec.SetField(abusereport.FieldTargetID, field.TypeInt, value) + } + if value, ok := aruo.mutation.AddedTargetID(); ok { + _spec.AddField(abusereport.FieldTargetID, field.TypeInt, value) + } + if value, ok := aruo.mutation.Reason(); ok { + _spec.SetField(abusereport.FieldReason, field.TypeInt, value) + } + if value, ok := aruo.mutation.AddedReason(); ok { + _spec.AddField(abusereport.FieldReason, field.TypeInt, value) + } + if value, ok := aruo.mutation.Description(); ok { + _spec.SetField(abusereport.FieldDescription, field.TypeString, value) + } + if aruo.mutation.DescriptionCleared() { + _spec.ClearField(abusereport.FieldDescription, field.TypeString) + } + if value, ok := aruo.mutation.Status(); ok { + _spec.SetField(abusereport.FieldStatus, field.TypeString, value) + } + if value, ok := aruo.mutation.AdminNote(); ok { + _spec.SetField(abusereport.FieldAdminNote, field.TypeString, value) + } + if aruo.mutation.AdminNoteCleared() { + _spec.ClearField(abusereport.FieldAdminNote, field.TypeString) + } + _node = &AbuseReport{config: aruo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, aruo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{abusereport.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + aruo.mutation.done = true + return _node, nil +} diff --git a/ent/client.go b/ent/client.go index 5e0a7033..d0cc1d68 100644 --- a/ent/client.go +++ b/ent/client.go @@ -15,6 +15,7 @@ import ( "entgo.io/ent/dialect" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" "github.com/cloudreve/Cloudreve/v4/ent/aclentry" "github.com/cloudreve/Cloudreve/v4/ent/activityevent" "github.com/cloudreve/Cloudreve/v4/ent/credittxn" @@ -46,6 +47,8 @@ type Client struct { config // Schema is the client for creating, migrating and dropping schema. Schema *migrate.Schema + // AbuseReport is the client for interacting with the AbuseReport builders. + AbuseReport *AbuseReportClient // AclEntry is the client for interacting with the AclEntry builders. AclEntry *AclEntryClient // ActivityEvent is the client for interacting with the ActivityEvent builders. @@ -101,6 +104,7 @@ func NewClient(opts ...Option) *Client { func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) + c.AbuseReport = NewAbuseReportClient(c.config) c.AclEntry = NewAclEntryClient(c.config) c.ActivityEvent = NewActivityEventClient(c.config) c.CreditTxn = NewCreditTxnClient(c.config) @@ -215,6 +219,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { return &Tx{ ctx: ctx, config: cfg, + AbuseReport: NewAbuseReportClient(cfg), AclEntry: NewAclEntryClient(cfg), ActivityEvent: NewActivityEventClient(cfg), CreditTxn: NewCreditTxnClient(cfg), @@ -256,6 +261,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) return &Tx{ ctx: ctx, config: cfg, + AbuseReport: NewAbuseReportClient(cfg), AclEntry: NewAclEntryClient(cfg), ActivityEvent: NewActivityEventClient(cfg), CreditTxn: NewCreditTxnClient(cfg), @@ -284,7 +290,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) // Debug returns a new debug-client. It's used to get verbose logging on specific operations. // // client.Debug(). -// AclEntry. +// AbuseReport. // Query(). // Count(ctx) func (c *Client) Debug() *Client { @@ -307,10 +313,10 @@ func (c *Client) Close() error { // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ - c.AclEntry, c.ActivityEvent, c.CreditTxn, c.DavAccount, c.DirectLink, c.Entity, - c.File, c.FsEvent, c.GiftCode, c.Group, c.InvitationCode, c.Metadata, c.Node, - c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, c.StoragePolicy, - c.Task, c.User, c.UserGrant, + c.AbuseReport, c.AclEntry, c.ActivityEvent, c.CreditTxn, c.DavAccount, + c.DirectLink, c.Entity, c.File, c.FsEvent, c.GiftCode, c.Group, + c.InvitationCode, c.Metadata, c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, + c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.UserGrant, } { n.Use(hooks...) } @@ -320,10 +326,10 @@ func (c *Client) Use(hooks ...Hook) { // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ - c.AclEntry, c.ActivityEvent, c.CreditTxn, c.DavAccount, c.DirectLink, c.Entity, - c.File, c.FsEvent, c.GiftCode, c.Group, c.InvitationCode, c.Metadata, c.Node, - c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, c.StoragePolicy, - c.Task, c.User, c.UserGrant, + c.AbuseReport, c.AclEntry, c.ActivityEvent, c.CreditTxn, c.DavAccount, + c.DirectLink, c.Entity, c.File, c.FsEvent, c.GiftCode, c.Group, + c.InvitationCode, c.Metadata, c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, + c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, c.UserGrant, } { n.Intercept(interceptors...) } @@ -332,6 +338,8 @@ func (c *Client) Intercept(interceptors ...Interceptor) { // Mutate implements the ent.Mutator interface. func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { switch m := m.(type) { + case *AbuseReportMutation: + return c.AbuseReport.mutate(ctx, m) case *AclEntryMutation: return c.AclEntry.mutate(ctx, m) case *ActivityEventMutation: @@ -381,6 +389,141 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { } } +// AbuseReportClient is a client for the AbuseReport schema. +type AbuseReportClient struct { + config +} + +// NewAbuseReportClient returns a client for the AbuseReport from the given config. +func NewAbuseReportClient(c config) *AbuseReportClient { + return &AbuseReportClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `abusereport.Hooks(f(g(h())))`. +func (c *AbuseReportClient) Use(hooks ...Hook) { + c.hooks.AbuseReport = append(c.hooks.AbuseReport, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `abusereport.Intercept(f(g(h())))`. +func (c *AbuseReportClient) Intercept(interceptors ...Interceptor) { + c.inters.AbuseReport = append(c.inters.AbuseReport, interceptors...) +} + +// Create returns a builder for creating a AbuseReport entity. +func (c *AbuseReportClient) Create() *AbuseReportCreate { + mutation := newAbuseReportMutation(c.config, OpCreate) + return &AbuseReportCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of AbuseReport entities. +func (c *AbuseReportClient) CreateBulk(builders ...*AbuseReportCreate) *AbuseReportCreateBulk { + return &AbuseReportCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *AbuseReportClient) MapCreateBulk(slice any, setFunc func(*AbuseReportCreate, int)) *AbuseReportCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &AbuseReportCreateBulk{err: fmt.Errorf("calling to AbuseReportClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*AbuseReportCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &AbuseReportCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for AbuseReport. +func (c *AbuseReportClient) Update() *AbuseReportUpdate { + mutation := newAbuseReportMutation(c.config, OpUpdate) + return &AbuseReportUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *AbuseReportClient) UpdateOne(ar *AbuseReport) *AbuseReportUpdateOne { + mutation := newAbuseReportMutation(c.config, OpUpdateOne, withAbuseReport(ar)) + return &AbuseReportUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *AbuseReportClient) UpdateOneID(id int) *AbuseReportUpdateOne { + mutation := newAbuseReportMutation(c.config, OpUpdateOne, withAbuseReportID(id)) + return &AbuseReportUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for AbuseReport. +func (c *AbuseReportClient) Delete() *AbuseReportDelete { + mutation := newAbuseReportMutation(c.config, OpDelete) + return &AbuseReportDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *AbuseReportClient) DeleteOne(ar *AbuseReport) *AbuseReportDeleteOne { + return c.DeleteOneID(ar.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *AbuseReportClient) DeleteOneID(id int) *AbuseReportDeleteOne { + builder := c.Delete().Where(abusereport.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &AbuseReportDeleteOne{builder} +} + +// Query returns a query builder for AbuseReport. +func (c *AbuseReportClient) Query() *AbuseReportQuery { + return &AbuseReportQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeAbuseReport}, + inters: c.Interceptors(), + } +} + +// Get returns a AbuseReport entity by its id. +func (c *AbuseReportClient) Get(ctx context.Context, id int) (*AbuseReport, error) { + return c.Query().Where(abusereport.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *AbuseReportClient) GetX(ctx context.Context, id int) *AbuseReport { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *AbuseReportClient) Hooks() []Hook { + hooks := c.hooks.AbuseReport + return append(hooks[:len(hooks):len(hooks)], abusereport.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *AbuseReportClient) Interceptors() []Interceptor { + inters := c.inters.AbuseReport + return append(inters[:len(inters):len(inters)], abusereport.Interceptors[:]...) +} + +func (c *AbuseReportClient) mutate(ctx context.Context, m *AbuseReportMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&AbuseReportCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&AbuseReportUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&AbuseReportUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&AbuseReportDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown AbuseReport mutation op: %q", m.Op()) + } +} + // AclEntryClient is a client for the AclEntry schema. type AclEntryClient struct { config @@ -4121,14 +4264,14 @@ func (c *UserGrantClient) mutate(ctx context.Context, m *UserGrantMutation) (Val // hooks and interceptors per client, for fast access. type ( hooks struct { - AclEntry, ActivityEvent, CreditTxn, DavAccount, DirectLink, Entity, File, - FsEvent, GiftCode, Group, InvitationCode, Metadata, Node, OAuthClient, + AbuseReport, AclEntry, ActivityEvent, CreditTxn, DavAccount, DirectLink, Entity, + File, FsEvent, GiftCode, Group, InvitationCode, Metadata, Node, OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, User, UserGrant []ent.Hook } inters struct { - AclEntry, ActivityEvent, CreditTxn, DavAccount, DirectLink, Entity, File, - FsEvent, GiftCode, Group, InvitationCode, Metadata, Node, OAuthClient, + AbuseReport, AclEntry, ActivityEvent, CreditTxn, DavAccount, DirectLink, Entity, + File, FsEvent, GiftCode, Group, InvitationCode, Metadata, Node, OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, User, UserGrant []ent.Interceptor } diff --git a/ent/ent.go b/ent/ent.go index dad5a523..d9e3adb3 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" "github.com/cloudreve/Cloudreve/v4/ent/aclentry" "github.com/cloudreve/Cloudreve/v4/ent/activityevent" "github.com/cloudreve/Cloudreve/v4/ent/credittxn" @@ -94,6 +95,7 @@ var ( func checkColumn(table, column string) error { initCheck.Do(func() { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ + abusereport.Table: abusereport.ValidColumn, aclentry.Table: aclentry.ValidColumn, activityevent.Table: activityevent.ValidColumn, credittxn.Table: credittxn.ValidColumn, diff --git a/ent/hook/hook.go b/ent/hook/hook.go index eb4b808d..a9a93cb3 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -9,6 +9,18 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent" ) +// The AbuseReportFunc type is an adapter to allow the use of ordinary +// function as AbuseReport mutator. +type AbuseReportFunc func(context.Context, *ent.AbuseReportMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f AbuseReportFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.AbuseReportMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AbuseReportMutation", m) +} + // The AclEntryFunc type is an adapter to allow the use of ordinary // function as AclEntry mutator. type AclEntryFunc func(context.Context, *ent.AclEntryMutation) (ent.Value, error) diff --git a/ent/intercept/intercept.go b/ent/intercept/intercept.go index 01114c87..6b0a71d2 100644 --- a/ent/intercept/intercept.go +++ b/ent/intercept/intercept.go @@ -8,6 +8,7 @@ import ( "entgo.io/ent/dialect/sql" "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" "github.com/cloudreve/Cloudreve/v4/ent/aclentry" "github.com/cloudreve/Cloudreve/v4/ent/activityevent" "github.com/cloudreve/Cloudreve/v4/ent/credittxn" @@ -89,6 +90,33 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error { return f(ctx, query) } +// The AbuseReportFunc type is an adapter to allow the use of ordinary function as a Querier. +type AbuseReportFunc func(context.Context, *ent.AbuseReportQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f AbuseReportFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.AbuseReportQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.AbuseReportQuery", q) +} + +// The TraverseAbuseReport type is an adapter to allow the use of ordinary function as Traverser. +type TraverseAbuseReport func(context.Context, *ent.AbuseReportQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseAbuseReport) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseAbuseReport) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.AbuseReportQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.AbuseReportQuery", q) +} + // The AclEntryFunc type is an adapter to allow the use of ordinary function as a Querier. type AclEntryFunc func(context.Context, *ent.AclEntryQuery) (ent.Value, error) @@ -686,6 +714,8 @@ func (f TraverseUserGrant) Traverse(ctx context.Context, q ent.Query) error { // NewQuery returns the generic Query interface for the given typed query. func NewQuery(q ent.Query) (Query, error) { switch q := q.(type) { + case *ent.AbuseReportQuery: + return &query[*ent.AbuseReportQuery, predicate.AbuseReport, abusereport.OrderOption]{typ: ent.TypeAbuseReport, tq: q}, nil case *ent.AclEntryQuery: return &query[*ent.AclEntryQuery, predicate.AclEntry, aclentry.OrderOption]{typ: ent.TypeAclEntry, tq: q}, nil case *ent.ActivityEventQuery: diff --git a/ent/internal/schema.go b/ent/internal/schema.go index 43f9b5e6..967b89e1 100644 --- a/ent/internal/schema.go +++ b/ent/internal/schema.go @@ -6,4 +6,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"AclEntry\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"acl_entries\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subject_type\",\"type\":{\"Type\":6,\"Ident\":\"aclentry.SubjectType\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"user\",\"V\":\"user\"},{\"N\":\"group\",\"V\":\"group\"},{\"N\":\"anonymous\",\"V\":\"anonymous\"},{\"N\":\"everyone\",\"V\":\"everyone\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subject_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"subject_type\",\"subject_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"ActivityEvent\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"actor_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ip\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"cid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"share_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"extra\",\"type\":{\"Type\":3,\"Ident\":\"map[string]interface {}\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"map[string]interface {}\",\"Kind\":21,\"PkgPath\":\"\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"created_at\"]},{\"fields\":[\"type\",\"created_at\"]},{\"fields\":[\"file_id\",\"created_at\"]},{\"fields\":[\"actor_id\",\"created_at\"]},{\"fields\":[\"share_id\",\"created_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"CreditTxn\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"credit_txns\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"credittxn.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"purchase\",\"V\":\"purchase\"},{\"N\":\"gift\",\"V\":\"gift\"},{\"N\":\"share_income\",\"V\":\"share_income\"},{\"N\":\"adjust\",\"V\":\"adjust\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ref\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"des\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"user_id\",\"created_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"acl_entries\",\"type\":\"AclEntry\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"created_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"GiftCode\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"redeemer\",\"type\":\"User\",\"field\":\"used_by_id\",\"ref_name\":\"redeemed_codes\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"code\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"giftcode.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"points\",\"V\":\"points\"},{\"N\":\"storage\",\"V\":\"storage\"},{\"N\":\"group\",\"V\":\"group\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"duration\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_by_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"des\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true},{\"name\":\"allowed_policies\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"InvitationCode\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"code\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_uses\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthClient\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"guid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"homepage_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2048,\"optional\":true,\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"redirect_uris\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.OAuthClientProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"OAuthClientProps\",\"Ident\":\"types.OAuthClientProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_enabled\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":true,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"oauth_grants\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"client\",\"type\":\"OAuthClient\",\"field\":\"client_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"client_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"client_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"allowed_groups\",\"type\":\"Group\",\"ref_name\":\"allowed_policies\",\"inverse\":true},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"storagepolicy.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"creator_ip\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":45,\"optional\":true,\"validators\":1,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hidden\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"oauth_grants\",\"type\":\"OAuthGrant\"},{\"name\":\"credit_txns\",\"type\":\"CreditTxn\"},{\"name\":\"redeemed_codes\",\"type\":\"GiftCode\"},{\"name\":\"grants\",\"type\":\"UserGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ban_expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ban_reason\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_login\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0},\"comment\":\"Time of the last successful sign-in\"},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credits\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"UserGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"usergrant.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"storage\",\"V\":\"storage\"},{\"N\":\"group\",\"V\":\"group\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"prev_group_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"user_id\",\"type\"]},{\"fields\":[\"expires_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" +const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"AbuseReport\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"reporter_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reporter_email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"target_type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"target_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reason\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":\"open\",\"default_kind\":24,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"admin_note\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"status\",\"created_at\"]},{\"fields\":[\"target_type\",\"target_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"AclEntry\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"acl_entries\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subject_type\",\"type\":{\"Type\":6,\"Ident\":\"aclentry.SubjectType\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"user\",\"V\":\"user\"},{\"N\":\"group\",\"V\":\"group\"},{\"N\":\"anonymous\",\"V\":\"anonymous\"},{\"N\":\"everyone\",\"V\":\"everyone\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subject_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"subject_type\",\"subject_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"ActivityEvent\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"actor_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ip\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"cid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"share_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"extra\",\"type\":{\"Type\":3,\"Ident\":\"map[string]interface {}\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"map[string]interface {}\",\"Kind\":21,\"PkgPath\":\"\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"created_at\"]},{\"fields\":[\"type\",\"created_at\"]},{\"fields\":[\"file_id\",\"created_at\"]},{\"fields\":[\"actor_id\",\"created_at\"]},{\"fields\":[\"share_id\",\"created_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"CreditTxn\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"credit_txns\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"credittxn.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"purchase\",\"V\":\"purchase\"},{\"N\":\"gift\",\"V\":\"gift\"},{\"N\":\"share_income\",\"V\":\"share_income\"},{\"N\":\"adjust\",\"V\":\"adjust\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ref\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"des\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"user_id\",\"created_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"acl_entries\",\"type\":\"AclEntry\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"created_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"GiftCode\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"redeemer\",\"type\":\"User\",\"field\":\"used_by_id\",\"ref_name\":\"redeemed_codes\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"code\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"giftcode.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"points\",\"V\":\"points\"},{\"N\":\"storage\",\"V\":\"storage\"},{\"N\":\"group\",\"V\":\"group\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"duration\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_by_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"des\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true},{\"name\":\"allowed_policies\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"InvitationCode\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"code\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_uses\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"used_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthClient\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"guid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"homepage_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2048,\"optional\":true,\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"redirect_uris\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.OAuthClientProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"OAuthClientProps\",\"Ident\":\"types.OAuthClientProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_enabled\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":true,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"oauth_grants\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"client\",\"type\":\"OAuthClient\",\"field\":\"client_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"client_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"client_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"allowed_groups\",\"type\":\"Group\",\"ref_name\":\"allowed_policies\",\"inverse\":true},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"storagepolicy.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"creator_ip\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":45,\"optional\":true,\"validators\":1,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hidden\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"oauth_grants\",\"type\":\"OAuthGrant\"},{\"name\":\"credit_txns\",\"type\":\"CreditTxn\"},{\"name\":\"redeemed_codes\",\"type\":\"GiftCode\"},{\"name\":\"grants\",\"type\":\"UserGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ban_expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"ban_reason\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_login\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0},\"comment\":\"Time of the last successful sign-in\"},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credits\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"UserGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"usergrant.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"storage\",\"V\":\"storage\"},{\"N\":\"group\",\"V\":\"group\"}],\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"amount\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"prev_group_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"user_id\",\"type\"]},{\"fields\":[\"expires_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index f44c99aa..83095b96 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -8,6 +8,39 @@ import ( ) var ( + // AbuseReportsColumns holds the columns for the "abuse_reports" table. + AbuseReportsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "reporter_id", Type: field.TypeInt, Nullable: true}, + {Name: "reporter_email", Type: field.TypeString, Nullable: true}, + {Name: "target_type", Type: field.TypeString}, + {Name: "target_id", Type: field.TypeInt}, + {Name: "reason", Type: field.TypeInt}, + {Name: "description", Type: field.TypeString, Nullable: true}, + {Name: "status", Type: field.TypeString, Default: "open"}, + {Name: "admin_note", Type: field.TypeString, Nullable: true}, + } + // AbuseReportsTable holds the schema information for the "abuse_reports" table. + AbuseReportsTable = &schema.Table{ + Name: "abuse_reports", + Columns: AbuseReportsColumns, + PrimaryKey: []*schema.Column{AbuseReportsColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "abusereport_status_created_at", + Unique: false, + Columns: []*schema.Column{AbuseReportsColumns[10], AbuseReportsColumns[1]}, + }, + { + Name: "abusereport_target_type_target_id", + Unique: false, + Columns: []*schema.Column{AbuseReportsColumns[6], AbuseReportsColumns[7]}, + }, + }, + } // ACLEntriesColumns holds the columns for the "acl_entries" table. ACLEntriesColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -756,6 +789,7 @@ var ( } // Tables holds all the tables in the schema. Tables = []*schema.Table{ + AbuseReportsTable, ACLEntriesTable, ActivityEventsTable, CreditTxnsTable, diff --git a/ent/mutation.go b/ent/mutation.go index 944f35e8..6a17493a 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -11,6 +11,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" "github.com/cloudreve/Cloudreve/v4/ent/aclentry" "github.com/cloudreve/Cloudreve/v4/ent/activityevent" "github.com/cloudreve/Cloudreve/v4/ent/credittxn" @@ -49,6 +50,7 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. + TypeAbuseReport = "AbuseReport" TypeAclEntry = "AclEntry" TypeActivityEvent = "ActivityEvent" TypeCreditTxn = "CreditTxn" @@ -73,6 +75,1073 @@ const ( TypeUserGrant = "UserGrant" ) +// AbuseReportMutation represents an operation that mutates the AbuseReport nodes in the graph. +type AbuseReportMutation struct { + config + op Op + typ string + id *int + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + reporter_id *int + addreporter_id *int + reporter_email *string + target_type *string + target_id *int + addtarget_id *int + reason *int + addreason *int + description *string + status *string + admin_note *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*AbuseReport, error) + predicates []predicate.AbuseReport +} + +var _ ent.Mutation = (*AbuseReportMutation)(nil) + +// abusereportOption allows management of the mutation configuration using functional options. +type abusereportOption func(*AbuseReportMutation) + +// newAbuseReportMutation creates new mutation for the AbuseReport entity. +func newAbuseReportMutation(c config, op Op, opts ...abusereportOption) *AbuseReportMutation { + m := &AbuseReportMutation{ + config: c, + op: op, + typ: TypeAbuseReport, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withAbuseReportID sets the ID field of the mutation. +func withAbuseReportID(id int) abusereportOption { + return func(m *AbuseReportMutation) { + var ( + err error + once sync.Once + value *AbuseReport + ) + m.oldValue = func(ctx context.Context) (*AbuseReport, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().AbuseReport.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withAbuseReport sets the old AbuseReport of the mutation. +func withAbuseReport(node *AbuseReport) abusereportOption { + return func(m *AbuseReportMutation) { + m.oldValue = func(context.Context) (*AbuseReport, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m AbuseReportMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m AbuseReportMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *AbuseReportMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *AbuseReportMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().AbuseReport.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *AbuseReportMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *AbuseReportMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *AbuseReportMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *AbuseReportMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *AbuseReportMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *AbuseReportMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *AbuseReportMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *AbuseReportMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldDeletedAt(ctx context.Context) (v *time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *AbuseReportMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[abusereport.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *AbuseReportMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[abusereport.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *AbuseReportMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, abusereport.FieldDeletedAt) +} + +// SetReporterID sets the "reporter_id" field. +func (m *AbuseReportMutation) SetReporterID(i int) { + m.reporter_id = &i + m.addreporter_id = nil +} + +// ReporterID returns the value of the "reporter_id" field in the mutation. +func (m *AbuseReportMutation) ReporterID() (r int, exists bool) { + v := m.reporter_id + if v == nil { + return + } + return *v, true +} + +// OldReporterID returns the old "reporter_id" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldReporterID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldReporterID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldReporterID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldReporterID: %w", err) + } + return oldValue.ReporterID, nil +} + +// AddReporterID adds i to the "reporter_id" field. +func (m *AbuseReportMutation) AddReporterID(i int) { + if m.addreporter_id != nil { + *m.addreporter_id += i + } else { + m.addreporter_id = &i + } +} + +// AddedReporterID returns the value that was added to the "reporter_id" field in this mutation. +func (m *AbuseReportMutation) AddedReporterID() (r int, exists bool) { + v := m.addreporter_id + if v == nil { + return + } + return *v, true +} + +// ClearReporterID clears the value of the "reporter_id" field. +func (m *AbuseReportMutation) ClearReporterID() { + m.reporter_id = nil + m.addreporter_id = nil + m.clearedFields[abusereport.FieldReporterID] = struct{}{} +} + +// ReporterIDCleared returns if the "reporter_id" field was cleared in this mutation. +func (m *AbuseReportMutation) ReporterIDCleared() bool { + _, ok := m.clearedFields[abusereport.FieldReporterID] + return ok +} + +// ResetReporterID resets all changes to the "reporter_id" field. +func (m *AbuseReportMutation) ResetReporterID() { + m.reporter_id = nil + m.addreporter_id = nil + delete(m.clearedFields, abusereport.FieldReporterID) +} + +// SetReporterEmail sets the "reporter_email" field. +func (m *AbuseReportMutation) SetReporterEmail(s string) { + m.reporter_email = &s +} + +// ReporterEmail returns the value of the "reporter_email" field in the mutation. +func (m *AbuseReportMutation) ReporterEmail() (r string, exists bool) { + v := m.reporter_email + if v == nil { + return + } + return *v, true +} + +// OldReporterEmail returns the old "reporter_email" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldReporterEmail(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldReporterEmail is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldReporterEmail requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldReporterEmail: %w", err) + } + return oldValue.ReporterEmail, nil +} + +// ClearReporterEmail clears the value of the "reporter_email" field. +func (m *AbuseReportMutation) ClearReporterEmail() { + m.reporter_email = nil + m.clearedFields[abusereport.FieldReporterEmail] = struct{}{} +} + +// ReporterEmailCleared returns if the "reporter_email" field was cleared in this mutation. +func (m *AbuseReportMutation) ReporterEmailCleared() bool { + _, ok := m.clearedFields[abusereport.FieldReporterEmail] + return ok +} + +// ResetReporterEmail resets all changes to the "reporter_email" field. +func (m *AbuseReportMutation) ResetReporterEmail() { + m.reporter_email = nil + delete(m.clearedFields, abusereport.FieldReporterEmail) +} + +// SetTargetType sets the "target_type" field. +func (m *AbuseReportMutation) SetTargetType(s string) { + m.target_type = &s +} + +// TargetType returns the value of the "target_type" field in the mutation. +func (m *AbuseReportMutation) TargetType() (r string, exists bool) { + v := m.target_type + if v == nil { + return + } + return *v, true +} + +// OldTargetType returns the old "target_type" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldTargetType(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTargetType is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTargetType requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTargetType: %w", err) + } + return oldValue.TargetType, nil +} + +// ResetTargetType resets all changes to the "target_type" field. +func (m *AbuseReportMutation) ResetTargetType() { + m.target_type = nil +} + +// SetTargetID sets the "target_id" field. +func (m *AbuseReportMutation) SetTargetID(i int) { + m.target_id = &i + m.addtarget_id = nil +} + +// TargetID returns the value of the "target_id" field in the mutation. +func (m *AbuseReportMutation) TargetID() (r int, exists bool) { + v := m.target_id + if v == nil { + return + } + return *v, true +} + +// OldTargetID returns the old "target_id" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldTargetID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTargetID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTargetID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTargetID: %w", err) + } + return oldValue.TargetID, nil +} + +// AddTargetID adds i to the "target_id" field. +func (m *AbuseReportMutation) AddTargetID(i int) { + if m.addtarget_id != nil { + *m.addtarget_id += i + } else { + m.addtarget_id = &i + } +} + +// AddedTargetID returns the value that was added to the "target_id" field in this mutation. +func (m *AbuseReportMutation) AddedTargetID() (r int, exists bool) { + v := m.addtarget_id + if v == nil { + return + } + return *v, true +} + +// ResetTargetID resets all changes to the "target_id" field. +func (m *AbuseReportMutation) ResetTargetID() { + m.target_id = nil + m.addtarget_id = nil +} + +// SetReason sets the "reason" field. +func (m *AbuseReportMutation) SetReason(i int) { + m.reason = &i + m.addreason = nil +} + +// Reason returns the value of the "reason" field in the mutation. +func (m *AbuseReportMutation) Reason() (r int, exists bool) { + v := m.reason + if v == nil { + return + } + return *v, true +} + +// OldReason returns the old "reason" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldReason(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldReason is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldReason requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldReason: %w", err) + } + return oldValue.Reason, nil +} + +// AddReason adds i to the "reason" field. +func (m *AbuseReportMutation) AddReason(i int) { + if m.addreason != nil { + *m.addreason += i + } else { + m.addreason = &i + } +} + +// AddedReason returns the value that was added to the "reason" field in this mutation. +func (m *AbuseReportMutation) AddedReason() (r int, exists bool) { + v := m.addreason + if v == nil { + return + } + return *v, true +} + +// ResetReason resets all changes to the "reason" field. +func (m *AbuseReportMutation) ResetReason() { + m.reason = nil + m.addreason = nil +} + +// SetDescription sets the "description" field. +func (m *AbuseReportMutation) SetDescription(s string) { + m.description = &s +} + +// Description returns the value of the "description" field in the mutation. +func (m *AbuseReportMutation) Description() (r string, exists bool) { + v := m.description + if v == nil { + return + } + return *v, true +} + +// OldDescription returns the old "description" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldDescription(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDescription is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDescription requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDescription: %w", err) + } + return oldValue.Description, nil +} + +// ClearDescription clears the value of the "description" field. +func (m *AbuseReportMutation) ClearDescription() { + m.description = nil + m.clearedFields[abusereport.FieldDescription] = struct{}{} +} + +// DescriptionCleared returns if the "description" field was cleared in this mutation. +func (m *AbuseReportMutation) DescriptionCleared() bool { + _, ok := m.clearedFields[abusereport.FieldDescription] + return ok +} + +// ResetDescription resets all changes to the "description" field. +func (m *AbuseReportMutation) ResetDescription() { + m.description = nil + delete(m.clearedFields, abusereport.FieldDescription) +} + +// SetStatus sets the "status" field. +func (m *AbuseReportMutation) SetStatus(s string) { + m.status = &s +} + +// Status returns the value of the "status" field in the mutation. +func (m *AbuseReportMutation) Status() (r string, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldStatus(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *AbuseReportMutation) ResetStatus() { + m.status = nil +} + +// SetAdminNote sets the "admin_note" field. +func (m *AbuseReportMutation) SetAdminNote(s string) { + m.admin_note = &s +} + +// AdminNote returns the value of the "admin_note" field in the mutation. +func (m *AbuseReportMutation) AdminNote() (r string, exists bool) { + v := m.admin_note + if v == nil { + return + } + return *v, true +} + +// OldAdminNote returns the old "admin_note" field's value of the AbuseReport entity. +// If the AbuseReport object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AbuseReportMutation) OldAdminNote(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAdminNote is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAdminNote requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAdminNote: %w", err) + } + return oldValue.AdminNote, nil +} + +// ClearAdminNote clears the value of the "admin_note" field. +func (m *AbuseReportMutation) ClearAdminNote() { + m.admin_note = nil + m.clearedFields[abusereport.FieldAdminNote] = struct{}{} +} + +// AdminNoteCleared returns if the "admin_note" field was cleared in this mutation. +func (m *AbuseReportMutation) AdminNoteCleared() bool { + _, ok := m.clearedFields[abusereport.FieldAdminNote] + return ok +} + +// ResetAdminNote resets all changes to the "admin_note" field. +func (m *AbuseReportMutation) ResetAdminNote() { + m.admin_note = nil + delete(m.clearedFields, abusereport.FieldAdminNote) +} + +// Where appends a list predicates to the AbuseReportMutation builder. +func (m *AbuseReportMutation) Where(ps ...predicate.AbuseReport) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the AbuseReportMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *AbuseReportMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.AbuseReport, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *AbuseReportMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *AbuseReportMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (AbuseReport). +func (m *AbuseReportMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *AbuseReportMutation) Fields() []string { + fields := make([]string, 0, 11) + if m.created_at != nil { + fields = append(fields, abusereport.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, abusereport.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, abusereport.FieldDeletedAt) + } + if m.reporter_id != nil { + fields = append(fields, abusereport.FieldReporterID) + } + if m.reporter_email != nil { + fields = append(fields, abusereport.FieldReporterEmail) + } + if m.target_type != nil { + fields = append(fields, abusereport.FieldTargetType) + } + if m.target_id != nil { + fields = append(fields, abusereport.FieldTargetID) + } + if m.reason != nil { + fields = append(fields, abusereport.FieldReason) + } + if m.description != nil { + fields = append(fields, abusereport.FieldDescription) + } + if m.status != nil { + fields = append(fields, abusereport.FieldStatus) + } + if m.admin_note != nil { + fields = append(fields, abusereport.FieldAdminNote) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *AbuseReportMutation) Field(name string) (ent.Value, bool) { + switch name { + case abusereport.FieldCreatedAt: + return m.CreatedAt() + case abusereport.FieldUpdatedAt: + return m.UpdatedAt() + case abusereport.FieldDeletedAt: + return m.DeletedAt() + case abusereport.FieldReporterID: + return m.ReporterID() + case abusereport.FieldReporterEmail: + return m.ReporterEmail() + case abusereport.FieldTargetType: + return m.TargetType() + case abusereport.FieldTargetID: + return m.TargetID() + case abusereport.FieldReason: + return m.Reason() + case abusereport.FieldDescription: + return m.Description() + case abusereport.FieldStatus: + return m.Status() + case abusereport.FieldAdminNote: + return m.AdminNote() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *AbuseReportMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case abusereport.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case abusereport.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case abusereport.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case abusereport.FieldReporterID: + return m.OldReporterID(ctx) + case abusereport.FieldReporterEmail: + return m.OldReporterEmail(ctx) + case abusereport.FieldTargetType: + return m.OldTargetType(ctx) + case abusereport.FieldTargetID: + return m.OldTargetID(ctx) + case abusereport.FieldReason: + return m.OldReason(ctx) + case abusereport.FieldDescription: + return m.OldDescription(ctx) + case abusereport.FieldStatus: + return m.OldStatus(ctx) + case abusereport.FieldAdminNote: + return m.OldAdminNote(ctx) + } + return nil, fmt.Errorf("unknown AbuseReport field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *AbuseReportMutation) SetField(name string, value ent.Value) error { + switch name { + case abusereport.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case abusereport.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case abusereport.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case abusereport.FieldReporterID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetReporterID(v) + return nil + case abusereport.FieldReporterEmail: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetReporterEmail(v) + return nil + case abusereport.FieldTargetType: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTargetType(v) + return nil + case abusereport.FieldTargetID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTargetID(v) + return nil + case abusereport.FieldReason: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetReason(v) + return nil + case abusereport.FieldDescription: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDescription(v) + return nil + case abusereport.FieldStatus: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case abusereport.FieldAdminNote: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAdminNote(v) + return nil + } + return fmt.Errorf("unknown AbuseReport field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *AbuseReportMutation) AddedFields() []string { + var fields []string + if m.addreporter_id != nil { + fields = append(fields, abusereport.FieldReporterID) + } + if m.addtarget_id != nil { + fields = append(fields, abusereport.FieldTargetID) + } + if m.addreason != nil { + fields = append(fields, abusereport.FieldReason) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *AbuseReportMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case abusereport.FieldReporterID: + return m.AddedReporterID() + case abusereport.FieldTargetID: + return m.AddedTargetID() + case abusereport.FieldReason: + return m.AddedReason() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *AbuseReportMutation) AddField(name string, value ent.Value) error { + switch name { + case abusereport.FieldReporterID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddReporterID(v) + return nil + case abusereport.FieldTargetID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddTargetID(v) + return nil + case abusereport.FieldReason: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddReason(v) + return nil + } + return fmt.Errorf("unknown AbuseReport numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *AbuseReportMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(abusereport.FieldDeletedAt) { + fields = append(fields, abusereport.FieldDeletedAt) + } + if m.FieldCleared(abusereport.FieldReporterID) { + fields = append(fields, abusereport.FieldReporterID) + } + if m.FieldCleared(abusereport.FieldReporterEmail) { + fields = append(fields, abusereport.FieldReporterEmail) + } + if m.FieldCleared(abusereport.FieldDescription) { + fields = append(fields, abusereport.FieldDescription) + } + if m.FieldCleared(abusereport.FieldAdminNote) { + fields = append(fields, abusereport.FieldAdminNote) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *AbuseReportMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *AbuseReportMutation) ClearField(name string) error { + switch name { + case abusereport.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case abusereport.FieldReporterID: + m.ClearReporterID() + return nil + case abusereport.FieldReporterEmail: + m.ClearReporterEmail() + return nil + case abusereport.FieldDescription: + m.ClearDescription() + return nil + case abusereport.FieldAdminNote: + m.ClearAdminNote() + return nil + } + return fmt.Errorf("unknown AbuseReport nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *AbuseReportMutation) ResetField(name string) error { + switch name { + case abusereport.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case abusereport.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case abusereport.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case abusereport.FieldReporterID: + m.ResetReporterID() + return nil + case abusereport.FieldReporterEmail: + m.ResetReporterEmail() + return nil + case abusereport.FieldTargetType: + m.ResetTargetType() + return nil + case abusereport.FieldTargetID: + m.ResetTargetID() + return nil + case abusereport.FieldReason: + m.ResetReason() + return nil + case abusereport.FieldDescription: + m.ResetDescription() + return nil + case abusereport.FieldStatus: + m.ResetStatus() + return nil + case abusereport.FieldAdminNote: + m.ResetAdminNote() + return nil + } + return fmt.Errorf("unknown AbuseReport field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *AbuseReportMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *AbuseReportMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *AbuseReportMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *AbuseReportMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *AbuseReportMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *AbuseReportMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *AbuseReportMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown AbuseReport unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *AbuseReportMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown AbuseReport edge %s", name) +} + // AclEntryMutation represents an operation that mutates the AclEntry nodes in the graph. type AclEntryMutation struct { config diff --git a/ent/mutationhelper.go b/ent/mutationhelper.go index 01e415fe..535d2fed 100644 --- a/ent/mutationhelper.go +++ b/ent/mutationhelper.go @@ -4,6 +4,12 @@ package ent // SetUpdatedAt sets the "updated_at" field. +func (m *AbuseReportMutation) SetRawID(t int) { + m.id = &t +} + +// SetUpdatedAt sets the "updated_at" field. + func (m *AclEntryMutation) SetRawID(t int) { m.id = &t } diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index 6d075a20..98ec45fb 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -6,6 +6,9 @@ import ( "entgo.io/ent/dialect/sql" ) +// AbuseReport is the predicate function for abusereport builders. +type AbuseReport func(*sql.Selector) + // AclEntry is the predicate function for aclentry builders. type AclEntry func(*sql.Selector) diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go index 2b404521..b2c1ba07 100644 --- a/ent/runtime/runtime.go +++ b/ent/runtime/runtime.go @@ -5,6 +5,7 @@ package runtime import ( "time" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" "github.com/cloudreve/Cloudreve/v4/ent/aclentry" "github.com/cloudreve/Cloudreve/v4/ent/activityevent" "github.com/cloudreve/Cloudreve/v4/ent/credittxn" @@ -35,6 +36,29 @@ import ( // (default values, validators, hooks and policies) and stitches it // to their package variables. func init() { + abusereportMixin := schema.AbuseReport{}.Mixin() + abusereportMixinHooks0 := abusereportMixin[0].Hooks() + abusereport.Hooks[0] = abusereportMixinHooks0[0] + abusereportMixinInters0 := abusereportMixin[0].Interceptors() + abusereport.Interceptors[0] = abusereportMixinInters0[0] + abusereportMixinFields0 := abusereportMixin[0].Fields() + _ = abusereportMixinFields0 + abusereportFields := schema.AbuseReport{}.Fields() + _ = abusereportFields + // abusereportDescCreatedAt is the schema descriptor for created_at field. + abusereportDescCreatedAt := abusereportMixinFields0[0].Descriptor() + // abusereport.DefaultCreatedAt holds the default value on creation for the created_at field. + abusereport.DefaultCreatedAt = abusereportDescCreatedAt.Default.(func() time.Time) + // abusereportDescUpdatedAt is the schema descriptor for updated_at field. + abusereportDescUpdatedAt := abusereportMixinFields0[1].Descriptor() + // abusereport.DefaultUpdatedAt holds the default value on creation for the updated_at field. + abusereport.DefaultUpdatedAt = abusereportDescUpdatedAt.Default.(func() time.Time) + // abusereport.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + abusereport.UpdateDefaultUpdatedAt = abusereportDescUpdatedAt.UpdateDefault.(func() time.Time) + // abusereportDescStatus is the schema descriptor for status field. + abusereportDescStatus := abusereportFields[6].Descriptor() + // abusereport.DefaultStatus holds the default value on creation for the status field. + abusereport.DefaultStatus = abusereportDescStatus.Default.(string) aclentryMixin := schema.AclEntry{}.Mixin() aclentryMixinHooks0 := aclentryMixin[0].Hooks() aclentry.Hooks[0] = aclentryMixinHooks0[0] diff --git a/ent/schema/abusereport.go b/ent/schema/abusereport.go new file mode 100644 index 00000000..1d5a6fdf --- /dev/null +++ b/ent/schema/abusereport.go @@ -0,0 +1,47 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// AbuseReport holds one user-submitted abuse report against a share or a +// user. Target references are plain IDs (no edges) so reports survive +// deletion of the reported share or user. +type AbuseReport struct { + ent.Schema +} + +// Fields of the AbuseReport. +func (AbuseReport) Fields() []ent.Field { + return []ent.Field{ + field.Int("reporter_id"). + Optional(), + field.String("reporter_email"). + Optional(), + field.String("target_type"), + field.Int("target_id"), + field.Int("reason"), + field.String("description"). + Optional(), + field.String("status"). + Default("open"), + field.String("admin_note"). + Optional(), + } +} + +// Indexes of the AbuseReport. +func (AbuseReport) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("status", "created_at"), + index.Fields("target_type", "target_id"), + } +} + +func (AbuseReport) Mixin() []ent.Mixin { + return []ent.Mixin{ + CommonMixin{}, + } +} diff --git a/ent/tx.go b/ent/tx.go index 73b83083..8455fdac 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -14,6 +14,8 @@ import ( // Tx is a transactional client that is created by calling Client.Tx(). type Tx struct { config + // AbuseReport is the client for interacting with the AbuseReport builders. + AbuseReport *AbuseReportClient // AclEntry is the client for interacting with the AclEntry builders. AclEntry *AclEntryClient // ActivityEvent is the client for interacting with the ActivityEvent builders. @@ -189,6 +191,7 @@ func (tx *Tx) Client() *Client { } func (tx *Tx) init() { + tx.AbuseReport = NewAbuseReportClient(tx.config) tx.AclEntry = NewAclEntryClient(tx.config) tx.ActivityEvent = NewActivityEventClient(tx.config) tx.CreditTxn = NewCreditTxnClient(tx.config) @@ -220,7 +223,7 @@ func (tx *Tx) init() { // of them in order to commit or rollback the transaction. // // If a closed transaction is embedded in one of the generated entities, and the entity -// applies a query, for example: AclEntry.QueryXXX(), the query will be executed +// applies a query, for example: AbuseReport.QueryXXX(), the query will be executed // through the driver which created this transaction. // // Note that txDriver is not goroutine safe. diff --git a/frontend/public/locales/en-US/dashboard.json b/frontend/public/locales/en-US/dashboard.json index ae6ef0b8..151d2296 100644 --- a/frontend/public/locales/en-US/dashboard.json +++ b/frontend/public/locales/en-US/dashboard.json @@ -1892,6 +1892,27 @@ "reporterID": "Reporter user ID", "reportedUserID": "Reported user ID", "shareID": "Shared ID", - "reason": "Reason" + "reason": "Reason", + "target": "Target", + "statusLabel": "Status", + "reportedAt": "Reported at", + "actions": "Actions", + "resolve": "Resolve", + "dismiss": "Dismiss", + "adminNote": "Admin note", + "blockShare": "Block the shared link", + "noReports": "No abuse reports", + "reviewSuccess": "Report updated.", + "status": { + "open": "Open", + "resolved": "Resolved", + "dismissed": "Dismissed", + "all": "All" + }, + "markAs": { + "resolved": "Resolve report", + "dismissed": "Dismiss report", + "open": "Reopen report" + } } } \ No newline at end of file diff --git a/frontend/public/locales/zh-CN/dashboard.json b/frontend/public/locales/zh-CN/dashboard.json index 4f75d629..a0beaa07 100644 --- a/frontend/public/locales/zh-CN/dashboard.json +++ b/frontend/public/locales/zh-CN/dashboard.json @@ -1891,6 +1891,27 @@ "reporterID": "举报者用户 ID", "reportedUserID": "举报对象用户 ID", "shareID": "分享 ID", - "reason": "原因" + "reason": "原因", + "target": "举报对象", + "statusLabel": "状态", + "reportedAt": "举报时间", + "actions": "操作", + "resolve": "标记已处理", + "dismiss": "忽略", + "adminNote": "管理员备注", + "blockShare": "封禁此分享链接", + "noReports": "没有举报记录", + "reviewSuccess": "举报已更新。", + "status": { + "open": "待处理", + "resolved": "已处理", + "dismissed": "已忽略", + "all": "全部" + }, + "markAs": { + "resolved": "标记为已处理", + "dismissed": "忽略此举报", + "open": "重新打开举报" + } } } \ No newline at end of file diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts index 590ffe41..59903988 100644 --- a/frontend/src/api/api.ts +++ b/frontend/src/api/api.ts @@ -3,6 +3,9 @@ import { EncryptedBlob } from "../component/Uploader/core/uploader/encrypt/blob. import i18n from "../i18n.ts"; import { ActivityEventListResponse, + AbuseReportListResponse, + ReportAbuseService, + UpdateAbuseReportService, AdjustCreditService, AdminListGroupResponse, AdminListService, @@ -2726,6 +2729,56 @@ export function getFileActivity(uri: string, page: number, pageSize: number): Th }; } +export function sendReportAbuse(args: ReportAbuseService): ThunkResponse { + return async (dispatch, _getState) => { + return await dispatch( + send( + "/abuse/report", + { method: "POST", data: args }, + { + ...defaultOpts, + }, + ), + ); + }; +} + +export function adminListAbuseReports(args: { + page: number; + pageSize: number; + status?: string; +}): ThunkResponse { + return async (dispatch, _getState) => { + const params = new URLSearchParams({ page: String(args.page), page_size: String(args.pageSize) }); + if (args.status) { + params.set("status", args.status); + } + return await dispatch( + send( + `/admin/abuse?${params.toString()}`, + { method: "GET" }, + { + ...defaultOpts, + }, + ), + ); + }; +} + +export function adminUpdateAbuseReport(id: string, args: UpdateAbuseReportService): ThunkResponse { + return async (dispatch, _getState) => { + return await dispatch( + send( + `/admin/abuse/${id}`, + { method: "PATCH", data: args }, + { + ...defaultOpts, + }, + ), + ); + }; +} + export function adminAdjustCredit(args: AdjustCreditService): ThunkResponse { return async (dispatch, _getState) => { return await dispatch( diff --git a/frontend/src/api/dashboard.ts b/frontend/src/api/dashboard.ts index 41bad198..962c1e92 100644 --- a/frontend/src/api/dashboard.ts +++ b/frontend/src/api/dashboard.ts @@ -685,3 +685,38 @@ export interface AdjustCreditService { delta: number; des?: string; } + +export type AbuseTargetType = "share" | "user"; +export type AbuseReportStatus = "open" | "resolved" | "dismissed"; + +export interface AbuseReport { + id: string; + reporter_id?: string; + reporter_email?: string; + target_type: AbuseTargetType; + target_id: string; + reason: number; + description: string; + status: AbuseReportStatus; + admin_note: string; + created_at: number; +} + +export interface AbuseReportListResponse { + reports: AbuseReport[]; + total: number; +} + +export interface ReportAbuseService { + target_type: AbuseTargetType; + target: string; + reason: number; + description?: string; + [x: string]: unknown; +} + +export interface UpdateAbuseReportService { + status: AbuseReportStatus; + admin_note?: string; + block_share?: boolean; +} diff --git a/frontend/src/api/site.ts b/frontend/src/api/site.ts index a3d57804..caf9e8a2 100644 --- a/frontend/src/api/site.ts +++ b/frontend/src/api/site.ts @@ -33,6 +33,7 @@ export interface SiteConfig { sso_display_name?: string; sso_auto_redirect?: boolean; download_cdn_routes?: { name: string; url: string }[]; + abuse_captcha?: boolean; logo?: string; logo_light?: string; tos_url?: string; diff --git a/frontend/src/component/Admin/Abuse/AbuseReportList.tsx b/frontend/src/component/Admin/Abuse/AbuseReportList.tsx new file mode 100644 index 00000000..05d42173 --- /dev/null +++ b/frontend/src/component/Admin/Abuse/AbuseReportList.tsx @@ -0,0 +1,285 @@ +import { + Box, + Button, + Chip, + Collapse, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + FormControlLabel, + IconButton, + Stack, + Switch, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TextField, + useMediaQuery, + useTheme, +} from "@mui/material"; +import { KeyboardArrowDown, KeyboardArrowUp } from "@mui/icons-material"; +import { enqueueSnackbar } from "notistack"; +import { useQueryState } from "nuqs"; +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { adminListAbuseReports, adminUpdateAbuseReport } from "../../../api/api"; +import { AbuseReport, AbuseReportStatus } from "../../../api/dashboard"; +import { useAppDispatch } from "../../../redux/hooks"; +import { DefaultCloseAction } from "../../Common/Snackbar/snackbar"; +import { DenseSelect, StyledTableContainerPaper } from "../../Common/StyledComponents"; +import { SquareMenuItem } from "../../FileManager/ContextMenu/ContextMenu"; +import PageContainer from "../../Pages/PageContainer"; +import PageHeader from "../../Pages/PageHeader"; +import TablePagination from "../Common/TablePagination"; +import { PageQuery, PageSizeQuery } from "../StoragePolicy/StoragePolicySetting"; + +export const StatusQuery = "status"; + +const statusColor = (status: AbuseReportStatus): "warning" | "success" | "default" => { + switch (status) { + case "open": + return "warning"; + case "resolved": + return "success"; + default: + return "default"; + } +}; + +const ReviewDialog = ({ + report, + status, + onClose, + onDone, +}: { + report?: AbuseReport; + status: AbuseReportStatus; + onClose: () => void; + onDone: () => void; +}) => { + const { t } = useTranslation("dashboard"); + const dispatch = useAppDispatch(); + const [note, setNote] = useState(""); + const [blockShare, setBlockShare] = useState(false); + const [loading, setLoading] = useState(false); + + useEffect(() => { + setNote(""); + setBlockShare(false); + }, [report, status]); + + const onSubmit = () => { + if (!report) { + return; + } + setLoading(true); + dispatch( + adminUpdateAbuseReport(report.id, { + status, + admin_note: note || undefined, + block_share: blockShare, + }), + ) + .then(() => { + enqueueSnackbar({ + message: t("abuseReport.reviewSuccess"), + variant: "success", + action: DefaultCloseAction, + }); + onDone(); + }) + .finally(() => setLoading(false)); + }; + + return ( + + {t(`abuseReport.markAs.${status}`)} + + setNote(e.target.value)} + inputProps={{ maxLength: 2000 }} + sx={{ mt: 1 }} + /> + {report?.target_type === "share" && ( + setBlockShare(e.target.checked)} />} + label={t("abuseReport.blockShare")} + /> + )} + + + + + + + ); +}; + +const ReportRow = ({ report, onReview }: { report: AbuseReport; onReview: (status: AbuseReportStatus) => void }) => { + const { t } = useTranslation("dashboard"); + const [open, setOpen] = useState(false); + const reasonOptions = t("application:vas.reportReasonOptions", { returnObjects: true }) as string[]; + + return ( + <> + + + setOpen(!open)}> + {open ? : } + + + + {report.target_type === "share" + ? `${t("abuseReport.shareID")} #${report.target_id}` + : `${t("abuseReport.reportedUserID")} #${report.target_id}`} + + {reasonOptions[report.reason] ?? report.reason} + {report.reporter_email || report.reporter_id || "-"} + + + + {new Date(report.created_at * 1000).toLocaleString()} + + {report.status === "open" && ( + + + + + )} + + + + + + + {report.description && ( + {report.description} + )} + {report.admin_note && ( + + {t("abuseReport.adminNote")}: {report.admin_note} + + )} + + + + + + ); +}; + +const AbuseReportList = () => { + const { t } = useTranslation("dashboard"); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const dispatch = useAppDispatch(); + const [loading, setLoading] = useState(true); + const [reports, setReports] = useState([]); + const [count, setCount] = useState(0); + const [page, setPage] = useQueryState(PageQuery, { defaultValue: "1" }); + const [pageSize, setPageSize] = useQueryState(PageSizeQuery, { defaultValue: "25" }); + const [status, setStatus] = useQueryState(StatusQuery, { defaultValue: "open" }); + const [review, setReview] = useState<{ report: AbuseReport; status: AbuseReportStatus } | undefined>(undefined); + + const pageInt = parseInt(page) ?? 1; + const pageSizeInt = parseInt(pageSize) ?? 25; + + const load = () => { + setLoading(true); + dispatch(adminListAbuseReports({ page: pageInt, pageSize: pageSizeInt, status: status || undefined })) + .then((res) => { + setReports(res.reports); + setCount(res.total); + }) + .finally(() => setLoading(false)); + }; + + useEffect(load, [page, pageSize, status]); + + return ( + + + + { + setStatus(e.target.value as string); + setPage("1"); + }} + sx={{ minWidth: 180 }} + > + {t("abuseReport.status.open")} + {t("abuseReport.status.resolved")} + {t("abuseReport.status.dismissed")} + {t("abuseReport.status.all")} + + + + + + + + {t("abuseReport.target")} + {t("abuseReport.reason")} + {t("abuseReport.reporter")} + {t("abuseReport.statusLabel")} + {t("abuseReport.reportedAt")} + {t("abuseReport.actions")} + + + + {reports.map((report) => ( + setReview({ report, status: s })} + /> + ))} + {!loading && reports.length === 0 && ( + + + {t("abuseReport.noReports")} + + + )} + +
+
+ setPageSize(size.toString())} + onChange={(_e, value) => setPage(value.toString())} + /> + setReview(undefined)} + onDone={() => { + setReview(undefined); + load(); + }} + /> +
+ ); +}; + +export default AbuseReportList; diff --git a/frontend/src/component/Admin/AdminBundle.tsx b/frontend/src/component/Admin/AdminBundle.tsx index 6e29b760..e0252118 100644 --- a/frontend/src/component/Admin/AdminBundle.tsx +++ b/frontend/src/component/Admin/AdminBundle.tsx @@ -1,3 +1,4 @@ +import AbuseReportList from "./Abuse/AbuseReportList"; import EntitySetting from "./Entity/EntitySetting"; import EventList from "./Event/EventList"; import FileSetting from "./File/FileSetting"; @@ -18,6 +19,7 @@ import TaskList from "./Task/TaskList"; import UserSetting from "./User/UserSetting"; export { + AbuseReportList, EditGroup, EditNode, EditOAuthClient, diff --git a/frontend/src/component/Admin/Settings/Captcha/Captcha.tsx b/frontend/src/component/Admin/Settings/Captcha/Captcha.tsx index e14a0118..e2771f3e 100644 --- a/frontend/src/component/Admin/Settings/Captcha/Captcha.tsx +++ b/frontend/src/component/Admin/Settings/Captcha/Captcha.tsx @@ -79,6 +79,24 @@ const Captcha = () => { {t("settings.captchaForResetDes")} + + + + setSettings({ + abuse_captcha: e.target.checked ? "1" : "0", + }) + } + /> + } + label={t("settings.captchaForAbuseReport")} + /> + {t("settings.captchaForAbuseReportDes")} + + diff --git a/frontend/src/component/FileManager/Dialogs/Dialogs.tsx b/frontend/src/component/FileManager/Dialogs/Dialogs.tsx index b38bbce0..9887af8b 100644 --- a/frontend/src/component/FileManager/Dialogs/Dialogs.tsx +++ b/frontend/src/component/FileManager/Dialogs/Dialogs.tsx @@ -12,6 +12,7 @@ import ManageShares from "./Share/ManageShares.tsx"; import StoragePolicy from "./StoragePolicy.tsx"; import AclDialog from "./Acl/AclDialog.tsx"; import ActivityDialog from "./Activity/ActivityDialog.tsx"; +import ReportAbuseDialog from "./ReportAbuse/ReportAbuseDialog.tsx"; import AnnouncementDialog from "./AnnouncementDialog.tsx"; import StaleVersionConfirm from "./StaleVersionConfirm.tsx"; import SaveAs from "./SaveAs.tsx"; @@ -65,6 +66,7 @@ const Dialogs = () => { + diff --git a/frontend/src/component/FileManager/Dialogs/ReportAbuse/ReportAbuseDialog.tsx b/frontend/src/component/FileManager/Dialogs/ReportAbuse/ReportAbuseDialog.tsx new file mode 100644 index 00000000..744d7aaf --- /dev/null +++ b/frontend/src/component/FileManager/Dialogs/ReportAbuse/ReportAbuseDialog.tsx @@ -0,0 +1,127 @@ +import { LoadingButton } from "@mui/lab"; +import { + DialogActions, + DialogContent, + FormControl, + InputLabel, + ListItemText, + TextField, + Typography, +} from "@mui/material"; +import { enqueueSnackbar } from "notistack"; +import { useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { sendReportAbuse } from "../../../../api/api.ts"; +import { closeReportAbuseDialog } from "../../../../redux/globalStateSlice.ts"; +import { useAppDispatch, useAppSelector } from "../../../../redux/hooks.ts"; +import { Captcha, CaptchaParams } from "../../../Common/Captcha/Captcha.tsx"; +import { DenseSelect } from "../../../Common/StyledComponents.tsx"; +import { DefaultCloseAction } from "../../../Common/Snackbar/snackbar.tsx"; +import DraggableDialog from "../../../Dialogs/DraggableDialog.tsx"; +import { SquareMenuItem } from "../../ContextMenu/ContextMenu.tsx"; + +const ReportAbuseDialog = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const open = useAppSelector((state) => state.globalState.reportAbuseDialogOpen); + const targetType = useAppSelector((state) => state.globalState.reportAbuseTargetType); + const target = useAppSelector((state) => state.globalState.reportAbuseTarget); + const captchaEnabled = useAppSelector((state) => state.siteConfig.basic.config.abuse_captcha); + + const reasonOptions = t("application:vas.reportReasonOptions", { returnObjects: true }) as string[]; + + const [reason, setReason] = useState(0); + const [description, setDescription] = useState(""); + const [loading, setLoading] = useState(false); + const [captchaGen, setCaptchaGen] = useState(0); + const captchaState = useRef({}); + + useEffect(() => { + if (open) { + setReason(0); + setDescription(""); + captchaState.current = {}; + } + }, [open]); + + const onClose = () => dispatch(closeReportAbuseDialog()); + + const onSubmit = () => { + if (!targetType || !target) { + return; + } + setLoading(true); + dispatch( + sendReportAbuse({ + target_type: targetType as "share" | "user", + target, + reason, + description: description || undefined, + ...captchaState.current, + }), + ) + .then(() => { + enqueueSnackbar({ + message: t("application:vas.reportAbuseSuccess"), + variant: "success", + action: DefaultCloseAction, + }); + onClose(); + }) + .catch(() => { + setCaptchaGen((g) => g + 1); + }) + .finally(() => setLoading(false)); + }; + + return ( + + + + {t("application:vas.reportTarget")}: {target} + + + {t("application:vas.reportReason")} + setReason(parseInt(e.target.value as string))} + > + {reasonOptions.map((r, i) => ( + + {r} + + ))} + + + setDescription(e.target.value)} + inputProps={{ maxLength: 2000 }} + /> + {captchaEnabled && (captchaState.current = s)} generation={captchaGen} />} + + + + {t("common:ok")} + + + + ); +}; + +export default ReportAbuseDialog; diff --git a/frontend/src/component/FileManager/TopBar/MoreActionMenu.tsx b/frontend/src/component/FileManager/TopBar/MoreActionMenu.tsx index 2a4fe23f..ac82094b 100644 --- a/frontend/src/component/FileManager/TopBar/MoreActionMenu.tsx +++ b/frontend/src/component/FileManager/TopBar/MoreActionMenu.tsx @@ -3,6 +3,7 @@ import { usePopupState } from "material-ui-popup-state/hooks"; import { useCallback, useContext } from "react"; import { useTranslation } from "react-i18next"; import { clearSelected } from "../../../redux/fileManagerSlice.ts"; +import { setReportAbuseDialog } from "../../../redux/globalStateSlice.ts"; import { useAppDispatch, useAppSelector } from "../../../redux/hooks.ts"; import { NavigatorCapability } from "../../../api/explorer.ts"; import { downloadAll } from "../../../redux/thunks/download.ts"; @@ -10,7 +11,7 @@ import { createShareShortcut, isMacbook } from "../../../redux/thunks/file.ts"; import { inverseSelection, pinCurrentView, refreshFileList, selectAll } from "../../../redux/thunks/filemanager.ts"; import SessionManager from "../../../session"; import Boolset from "../../../util/boolset.ts"; -import { Filesystem } from "../../../util/uri.ts"; +import CrUri, { Filesystem } from "../../../util/uri.ts"; import { KeyIndicator } from "../../Frame/NavBar/SearchBar.tsx"; import ArrowSync from "../../Icons/ArrowSync.tsx"; import Border from "../../Icons/Border.tsx"; @@ -19,6 +20,7 @@ import BorderInside from "../../Icons/BorderInside.tsx"; import CloudDownloadOutlined from "../../Icons/CloudDownloadOutlined.tsx"; import FolderLink from "../../Icons/FolderLink.tsx"; import PinOutlined from "../../Icons/PinOutlined.tsx"; +import WarningOutlined from "../../Icons/WarningOutlined.tsx"; import { DenseDivider, SquareMenu, SquareMenuItem } from "../ContextMenu/ContextMenu.tsx"; import { FmIndexContext } from "../FmIndexContext.tsx"; @@ -26,6 +28,7 @@ const MoreActionMenu = ({ onClose, ...rest }: MenuProps) => { const { t } = useTranslation(); const fmIndex = useContext(FmIndexContext); const fs = useAppSelector((state) => state.fileManager[fmIndex].current_fs); + const path = useAppSelector((state) => state.fileManager[fmIndex].path); const parentCapability = useAppSelector((state) => state.fileManager[fmIndex].list?.parent?.capability); const canDownloadAll = new Boolset(parentCapability).enabled(NavigatorCapability.download_file); const dispatch = useAppDispatch(); @@ -73,6 +76,17 @@ const MoreActionMenu = ({ onClose, ...rest }: MenuProps) => { dispatch(downloadAll(fmIndex)); }, [dispatch, onClose, fmIndex]); + const onReportClicked = useCallback(() => { + onClose && onClose({}, "escapeKeyDown"); + if (!path) { + return; + } + const shareId = new CrUri(path).id(); + if (shareId) { + dispatch(setReportAbuseDialog({ open: true, targetType: "share", target: shareId })); + } + }, [dispatch, onClose, path]); + return ( { {t("application:fileManager.downloadAll")} )} + {fs == Filesystem.share && ( + + + + + {t("application:vas.report")} + + )} {isLogin && } diff --git a/frontend/src/redux/globalStateSlice.ts b/frontend/src/redux/globalStateSlice.ts index a91789f6..f16a123f 100644 --- a/frontend/src/redux/globalStateSlice.ts +++ b/frontend/src/redux/globalStateSlice.ts @@ -164,6 +164,11 @@ export interface GlobalStateSlice { activityDialogOpen?: boolean; activityDialogFile?: FileResponse; + // Report abuse dialog + reportAbuseDialogOpen?: boolean; + reportAbuseTargetType?: string; + reportAbuseTarget?: string; + // Stale version action dialog staleVersionDialogOpen?: boolean; staleVersionUri?: string; @@ -824,6 +829,17 @@ export const globalStateSlice = createSlice({ closeActivityDialog: (state) => { state.activityDialogOpen = false; }, + setReportAbuseDialog: ( + state, + action: PayloadAction<{ open: boolean; targetType: string; target: string }>, + ) => { + state.reportAbuseDialogOpen = action.payload.open; + state.reportAbuseTargetType = action.payload.targetType; + state.reportAbuseTarget = action.payload.target; + }, + closeReportAbuseDialog: (state) => { + state.reportAbuseDialogOpen = false; + }, setImageViewer: (state, action: PayloadAction) => { state.imageViewer = action.payload; }, @@ -957,6 +973,8 @@ export const { closeAclDialog, setActivityDialog, closeActivityDialog, + setReportAbuseDialog, + closeReportAbuseDialog, setVersionControlDialog, closeVersionControlDialog, closeSidebar, diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 65d22c7a..a22989c4 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -221,6 +221,13 @@ export const router = createBrowserRouter([ return { Component: EventList }; }, }, + { + path: "abuse", + async lazy() { + let { AbuseReportList } = await import("../component/Admin/AdminBundle.tsx"); + return { Component: AbuseReportList }; + }, + }, { path: "filesystem", async lazy() { diff --git a/inventory/abusereport.go b/inventory/abusereport.go new file mode 100644 index 00000000..af15aeb0 --- /dev/null +++ b/inventory/abusereport.go @@ -0,0 +1,97 @@ +package inventory + +import ( + "context" + + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/ent/abusereport" +) + +type ( + // AbuseReportClient persists abuse reports for the admin review queue. + AbuseReportClient interface { + TxOperator + // Create inserts a new open report. + Create(ctx context.Context, params *CreateAbuseReportParams) (*ent.AbuseReport, error) + // List returns a page of reports plus the filtered total. + List(ctx context.Context, args *ListAbuseReportArgs) (*ListAbuseReportResult, error) + // SetStatus updates status/admin note of one report. + SetStatus(ctx context.Context, id int, status, adminNote string) (*ent.AbuseReport, error) + } + + CreateAbuseReportParams struct { + ReporterID int + ReporterEmail string + TargetType string + TargetID int + Reason int + Description string + } + + ListAbuseReportArgs struct { + *PaginationArgs + Status string + } + + ListAbuseReportResult struct { + Reports []*ent.AbuseReport + Total int + } + + abuseReportClient struct { + client *ent.Client + } +) + +// NewAbuseReportClient creates an AbuseReportClient. +func NewAbuseReportClient(client *ent.Client) AbuseReportClient { + return &abuseReportClient{client: client} +} + +func (c *abuseReportClient) SetClient(newClient *ent.Client) TxOperator { + return &abuseReportClient{client: newClient} +} + +func (c *abuseReportClient) GetClient() *ent.Client { + return c.client +} + +func (c *abuseReportClient) Create(ctx context.Context, params *CreateAbuseReportParams) (*ent.AbuseReport, error) { + return c.client.AbuseReport.Create(). + SetReporterID(params.ReporterID). + SetReporterEmail(params.ReporterEmail). + SetTargetType(params.TargetType). + SetTargetID(params.TargetID). + SetReason(params.Reason). + SetDescription(params.Description). + Save(ctx) +} + +func (c *abuseReportClient) List(ctx context.Context, args *ListAbuseReportArgs) (*ListAbuseReportResult, error) { + q := c.client.AbuseReport.Query().Order(ent.Desc(abusereport.FieldCreatedAt)) + if args.Status != "" { + q = q.Where(abusereport.StatusEQ(args.Status)) + } + + total, err := q.Clone().Count(ctx) + if err != nil { + return nil, err + } + + reports, err := q. + Offset(args.Page * args.PageSize). + Limit(args.PageSize). + All(ctx) + if err != nil { + return nil, err + } + + return &ListAbuseReportResult{Reports: reports, Total: total}, nil +} + +func (c *abuseReportClient) SetStatus(ctx context.Context, id int, status, adminNote string) (*ent.AbuseReport, error) { + return c.client.AbuseReport.UpdateOneID(id). + SetStatus(status). + SetAdminNote(adminNote). + Save(ctx) +} diff --git a/inventory/abusereport_test.go b/inventory/abusereport_test.go new file mode 100644 index 00000000..3673174b --- /dev/null +++ b/inventory/abusereport_test.go @@ -0,0 +1,63 @@ +package inventory + +import ( + "context" + "testing" + + "github.com/cloudreve/Cloudreve/v4/ent/enttest" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/stretchr/testify/require" +) + +func TestAbuseReportCreateListSetStatus(t *testing.T) { + client := enttest.Open(t, "sqlite3", "file:"+t.Name()+"?mode=memory&cache=shared") + defer client.Close() + c := NewAbuseReportClient(client) + ctx := context.Background() + + r1, err := c.Create(ctx, &CreateAbuseReportParams{ + ReporterID: 3, + ReporterEmail: "reporter@example.com", + TargetType: types.AbuseTargetShare, + TargetID: 11, + Reason: types.AbuseReasonCopyright, + Description: "pirated content", + }) + require.NoError(t, err) + require.Equal(t, types.AbuseStatusOpen, r1.Status) + + _, err = c.Create(ctx, &CreateAbuseReportParams{ + TargetType: types.AbuseTargetUser, + TargetID: 5, + Reason: types.AbuseReasonSpam, + }) + require.NoError(t, err) + + all, err := c.List(ctx, &ListAbuseReportArgs{ + PaginationArgs: &PaginationArgs{Page: 0, PageSize: 10}, + }) + require.NoError(t, err) + require.Equal(t, 2, all.Total) + require.Len(t, all.Reports, 2) + // Newest first. + require.Equal(t, types.AbuseTargetUser, all.Reports[0].TargetType) + + openOnly, err := c.List(ctx, &ListAbuseReportArgs{ + PaginationArgs: &PaginationArgs{Page: 0, PageSize: 10}, + Status: types.AbuseStatusOpen, + }) + require.NoError(t, err) + require.Equal(t, 2, openOnly.Total) + + updated, err := c.SetStatus(ctx, r1.ID, types.AbuseStatusResolved, "share expired") + require.NoError(t, err) + require.Equal(t, types.AbuseStatusResolved, updated.Status) + require.Equal(t, "share expired", updated.AdminNote) + + openOnly, err = c.List(ctx, &ListAbuseReportArgs{ + PaginationArgs: &PaginationArgs{Page: 0, PageSize: 10}, + Status: types.AbuseStatusOpen, + }) + require.NoError(t, err) + require.Equal(t, 1, openOnly.Total) +} diff --git a/inventory/setting.go b/inventory/setting.go index 0b6a048a..407f184a 100644 --- a/inventory/setting.go +++ b/inventory/setting.go @@ -542,6 +542,7 @@ var DefaultSettings = map[string]string{ "reg_captcha": `0`, "email_active": `0`, "forget_captcha": `0`, + "abuse_captcha": `1`, "gravatar_server": `https://www.gravatar.com/`, "defaultTheme": `#1976d2`, "theme_options": `{"#1976d2":{"light":{"palette":{"primary":{"main":"#1976d2","light":"#42a5f5","dark":"#1565c0"},"secondary":{"main":"#9c27b0","light":"#ba68c8","dark":"#7b1fa2"}}},"dark":{"palette":{"primary":{"main":"#90caf9","light":"#e3f2fd","dark":"#42a5f5"},"secondary":{"main":"#ce93d8","light":"#f3e5f5","dark":"#ab47bc"}}}},"#3f51b5":{"light":{"palette":{"primary":{"main":"#3f51b5"},"secondary":{"main":"#f50057"}}},"dark":{"palette":{"primary":{"main":"#9fa8da"},"secondary":{"main":"#ff4081"}}}}}`, diff --git a/inventory/share.go b/inventory/share.go index 8ff5e0a5..771493ae 100644 --- a/inventory/share.go +++ b/inventory/share.go @@ -57,6 +57,8 @@ type ( List(ctx context.Context, args *ListShareArgs) (*ListShareResult, error) // CountByTimeRange counts the number of shares created in the given time range. CountByTimeRange(ctx context.Context, start, end *time.Time) (int, error) + // Expire marks the share expired immediately (admin moderation block). + Expire(ctx context.Context, id int) error } CreateShareParams struct { @@ -206,6 +208,11 @@ func (c *shareClient) Delete(ctx context.Context, shareId int) error { return c.client.Share.DeleteOneID(shareId).Exec(ctx) } +// Expire marks the share expired immediately (admin moderation block). +func (c *shareClient) Expire(ctx context.Context, id int) error { + return c.client.Share.UpdateOneID(id).SetExpires(time.Now()).Exec(ctx) +} + // Viewed increments the view count of the share. func (c *shareClient) Viewed(ctx context.Context, share *ent.Share) error { _, err := c.client.Share.UpdateOneID(share.ID).AddViews(1).Save(ctx) diff --git a/inventory/types/abuse.go b/inventory/types/abuse.go new file mode 100644 index 00000000..3b83a1f6 --- /dev/null +++ b/inventory/types/abuse.go @@ -0,0 +1,21 @@ +package types + +// Abuse report target and status constants. +const ( + AbuseTargetShare = "share" + AbuseTargetUser = "user" + + AbuseStatusOpen = "open" + AbuseStatusResolved = "resolved" + AbuseStatusDismissed = "dismissed" +) + +// Abuse reasons, matching the frontend reportReasonOptions order. +const ( + AbuseReasonCopyright = iota + AbuseReasonHarmful + AbuseReasonSpam + AbuseReasonOther + + AbuseReasonMax = AbuseReasonOther +) diff --git a/pkg/setting/provider.go b/pkg/setting/provider.go index bbdfe23d..cc09e3f7 100644 --- a/pkg/setting/provider.go +++ b/pkg/setting/provider.go @@ -35,6 +35,8 @@ type ( LoginCaptchaEnabled(ctx context.Context) bool // ForgotPasswordCaptchaEnabled returns true if forgot password captcha is enabled. ForgotPasswordCaptchaEnabled(ctx context.Context) bool + // AbuseCaptchaEnabled returns true if abuse reports require captcha. + AbuseCaptchaEnabled(ctx context.Context) bool // CaptchaType returns the type of captcha used. CaptchaType(ctx context.Context) CaptchaType // ReCaptcha returns the Google reCaptcha settings. @@ -926,6 +928,10 @@ func (s *settingProvider) ForgotPasswordCaptchaEnabled(ctx context.Context) bool return s.getBoolean(ctx, "forget_captcha", false) } +func (s *settingProvider) AbuseCaptchaEnabled(ctx context.Context) bool { + return s.getBoolean(ctx, "abuse_captcha", true) +} + func (s *settingProvider) AuthnEnabled(ctx context.Context) bool { return s.getBoolean(ctx, "authn_enabled", false) } diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index db3871e8..048a0491 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -342,6 +342,26 @@ func AdminListEvents(c *gin.Context) { c.JSON(200, serializer.Response{Data: res}) } +// AdminListAbuseReports lists the abuse report queue. +func AdminListAbuseReports(c *gin.Context) { + service := ParametersFromContext[*admin.AbuseListService](c, admin.AbuseListParamCtx{}) + res, err := service.List(c) + if respondErr(c, err) { + return + } + c.JSON(200, serializer.Response{Data: res}) +} + +// AdminUpdateAbuseReport updates a report and optionally blocks the share. +func AdminUpdateAbuseReport(c *gin.Context) { + service := ParametersFromContext[*admin.AbuseUpdateService](c, admin.AbuseUpdateParamCtx{}) + res, err := service.Update(c) + if respondErr(c, err) { + return + } + c.JSON(200, serializer.Response{Data: res}) +} + // func AdminHashIDEncode(c *gin.Context) { // service := ParametersFromContext[*admin.HashIDService](c, admin.HashIDParamCtx{}) // resp, err := service.Encode(c) diff --git a/routers/controllers/share.go b/routers/controllers/share.go index 479d0eb9..eac89258 100644 --- a/routers/controllers/share.go +++ b/routers/controllers/share.go @@ -3,6 +3,7 @@ package controllers import ( "github.com/cloudreve/Cloudreve/v4/pkg/hashid" "github.com/cloudreve/Cloudreve/v4/pkg/serializer" + "github.com/cloudreve/Cloudreve/v4/service/abuse" "github.com/cloudreve/Cloudreve/v4/service/share" "github.com/gin-gonic/gin" "net/http" @@ -80,3 +81,12 @@ func ShareRedirect(c *gin.Context) { service := ParametersFromContext[*share.ShortLinkRedirectService](c, share.ShortLinkRedirectParamCtx{}) c.Redirect(http.StatusFound, service.RedirectTo(c)) } + +// ReportAbuse accepts an abuse report against a share or user. +func ReportAbuse(c *gin.Context) { + service := ParametersFromContext[*abuse.ReportService](c, abuse.ReportParamCtx{}) + if err := service.Create(c); respondErr(c, err) { + return + } + c.JSON(200, serializer.Response{}) +} diff --git a/routers/router.go b/routers/router.go index eacbd538..047149af 100644 --- a/routers/router.go +++ b/routers/router.go @@ -16,6 +16,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/pkg/logging" "github.com/cloudreve/Cloudreve/v4/pkg/webdav" "github.com/cloudreve/Cloudreve/v4/routers/controllers" + abusesvc "github.com/cloudreve/Cloudreve/v4/service/abuse" adminsvc "github.com/cloudreve/Cloudreve/v4/service/admin" "github.com/cloudreve/Cloudreve/v4/service/basic" "github.com/cloudreve/Cloudreve/v4/service/explorer" @@ -962,11 +963,19 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { // middleware.CheckShareUnlocked(), // controllers.PreviewShareReadme, //) - //// 举报分享 - //share.POST("report/:id", - // middleware.CheckShareUnlocked(), - // controllers.ReportShare, - //) + } + + // 举报滥用 + abuse := v4.Group("abuse") + { + abuse.POST("report", + middleware.RateLimitByIP("abuse_report", 10, time.Hour), + middleware.CaptchaRequired(func(c *gin.Context) bool { + return dep.SettingProvider().AbuseCaptchaEnabled(c) + }), + controllers.FromJSON[abusesvc.ReportService](abusesvc.ReportParamCtx{}), + controllers.ReportAbuse, + ) } // 需要登录保护的 @@ -1324,6 +1333,21 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine { ) } + abuse := admin.Group("abuse", middleware.AdminSection(types.GroupPermissionAdminReports)) + { + // 列出举报 + abuse.GET("", + controllers.FromQuery[adminsvc.AbuseListService](adminsvc.AbuseListParamCtx{}), + controllers.AdminListAbuseReports, + ) + // 更新举报状态 + abuse.PATCH(":id", + middleware.HashID(hashid.AuditLogID), + controllers.FromJSON[adminsvc.AbuseUpdateService](adminsvc.AbuseUpdateParamCtx{}), + controllers.AdminUpdateAbuseReport, + ) + } + file := admin.Group("file", middleware.AdminSection(types.GroupPermissionAdminFiles)) { // 列出文件 diff --git a/service/abuse/report.go b/service/abuse/report.go new file mode 100644 index 00000000..26a5a9c6 --- /dev/null +++ b/service/abuse/report.go @@ -0,0 +1,78 @@ +package abuse + +import ( + "github.com/cloudreve/Cloudreve/v4/application/dependency" + "github.com/cloudreve/Cloudreve/v4/inventory" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/activity" + "github.com/cloudreve/Cloudreve/v4/pkg/hashid" + "github.com/cloudreve/Cloudreve/v4/pkg/serializer" + "github.com/gin-gonic/gin" +) + +type ( + // ReportService accepts an abuse report from any visitor. CAPTCHA and + // rate limiting are enforced by route middleware. + ReportService struct { + TargetType string `json:"target_type" binding:"required,oneof=share user"` + Target string `json:"target" binding:"required"` + Reason int `json:"reason" binding:"min=0"` + Description string `json:"description" binding:"max=2000"` + } + ReportParamCtx struct{} +) + +// Create validates the target, stores the report, and emits report_abuse. +func (s *ReportService) Create(c *gin.Context) error { + dep := dependency.FromContext(c) + if s.Reason > types.AbuseReasonMax { + return serializer.NewError(serializer.CodeParamErr, "Invalid reason", nil) + } + + params := &inventory.CreateAbuseReportParams{ + TargetType: s.TargetType, + Reason: s.Reason, + Description: s.Description, + } + if u := inventory.UserFromContext(c); u != nil && !inventory.IsAnonymousUser(u) { + params.ReporterID = u.ID + params.ReporterEmail = u.Email + } + + var opts []activity.Opt + switch s.TargetType { + case types.AbuseTargetShare: + shareID, err := dep.HashIDEncoder().Decode(s.Target, hashid.ShareID) + if err != nil { + return serializer.NewError(serializer.CodeParamErr, "Invalid share", err) + } + if _, err := dep.ShareClient().GetByID(c, shareID); err != nil { + return serializer.NewError(serializer.CodeNotFound, "Share not found", err) + } + params.TargetID = shareID + opts = append(opts, activity.Share(shareID)) + case types.AbuseTargetUser: + uid, err := dep.HashIDEncoder().Decode(s.Target, hashid.UserID) + if err != nil { + return serializer.NewError(serializer.CodeParamErr, "Invalid user", err) + } + if _, err := dep.UserClient().GetByID(c, uid); err != nil { + return serializer.NewError(serializer.CodeNotFound, "User not found", err) + } + params.TargetID = uid + } + + report, err := dep.AbuseReportClient().Create(c, params) + if err != nil { + return serializer.NewError(serializer.CodeDBError, "Failed to submit report", err) + } + + opts = append(opts, activity.Extra(map[string]any{ + "report_id": report.ID, + "target_type": s.TargetType, + "reason": s.Reason, + })) + activity.Record(c, dep.SettingProvider(), dep.ActivityClient(), types.EventReportAbuse, opts...) + + return nil +} diff --git a/service/admin/abuse.go b/service/admin/abuse.go new file mode 100644 index 00000000..e14cd6eb --- /dev/null +++ b/service/admin/abuse.go @@ -0,0 +1,114 @@ +package admin + +import ( + "github.com/cloudreve/Cloudreve/v4/application/dependency" + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/inventory" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/hashid" + "github.com/cloudreve/Cloudreve/v4/pkg/serializer" + "github.com/gin-gonic/gin" +) + +type ( + // AbuseListService pages the abuse report queue. + AbuseListService struct { + Page int `form:"page" binding:"required,min=0"` + PageSize int `form:"page_size" binding:"required,min=1,max=100"` + Status string `form:"status" binding:"omitempty,oneof=open resolved dismissed"` + } + AbuseListParamCtx struct{} + + // AbuseReport is one queue entry. + AbuseReport struct { + ID string `json:"id"` + ReporterID string `json:"reporter_id,omitempty"` + ReporterEmail string `json:"reporter_email,omitempty"` + TargetType string `json:"target_type"` + TargetID string `json:"target_id"` + Reason int `json:"reason"` + Description string `json:"description"` + Status string `json:"status"` + AdminNote string `json:"admin_note"` + CreatedAt int64 `json:"created_at"` + } + + AbuseListResponse struct { + Reports []*AbuseReport `json:"reports"` + Total int `json:"total"` + } + + // AbuseUpdateService updates one report; block_share additionally expires + // the reported share. + AbuseUpdateService struct { + Status string `json:"status" binding:"required,oneof=open resolved dismissed"` + AdminNote string `json:"admin_note" binding:"max=2000"` + BlockShare bool `json:"block_share"` + } + AbuseUpdateParamCtx struct{} +) + +func (s *AbuseListService) List(c *gin.Context) (*AbuseListResponse, error) { + dep := dependency.FromContext(c) + res, err := dep.AbuseReportClient().List(c, &inventory.ListAbuseReportArgs{ + PaginationArgs: &inventory.PaginationArgs{ + UseCursorPagination: false, + Page: s.Page, + PageSize: s.PageSize, + }, + Status: s.Status, + }) + if err != nil { + return nil, serializer.NewError(serializer.CodeDBError, "Failed to list reports", err) + } + + return BuildAbuseListResponse(res, dep.HashIDEncoder()), nil +} + +func BuildAbuseListResponse(res *inventory.ListAbuseReportResult, hasher hashid.Encoder) *AbuseListResponse { + reports := make([]*AbuseReport, 0, len(res.Reports)) + for _, r := range res.Reports { + reports = append(reports, BuildAbuseReport(r, hasher)) + } + return &AbuseListResponse{Reports: reports, Total: res.Total} +} + +func BuildAbuseReport(r *ent.AbuseReport, hasher hashid.Encoder) *AbuseReport { + res := &AbuseReport{ + ID: hashid.EncodeAuditLogID(hasher, r.ID), + ReporterEmail: r.ReporterEmail, + TargetType: r.TargetType, + Reason: r.Reason, + Description: r.Description, + Status: r.Status, + AdminNote: r.AdminNote, + CreatedAt: r.CreatedAt.Unix(), + } + if r.ReporterID > 0 { + res.ReporterID = hashid.EncodeUserID(hasher, r.ReporterID) + } + if r.TargetType == types.AbuseTargetShare { + res.TargetID = hashid.EncodeShareID(hasher, r.TargetID) + } else { + res.TargetID = hashid.EncodeUserID(hasher, r.TargetID) + } + return res +} + +func (s *AbuseUpdateService) Update(c *gin.Context) (*AbuseReport, error) { + dep := dependency.FromContext(c) + reportID := hashid.FromContext(c) + + report, err := dep.AbuseReportClient().SetStatus(c, reportID, s.Status, s.AdminNote) + if err != nil { + return nil, serializer.NewError(serializer.CodeDBError, "Failed to update report", err) + } + + if s.BlockShare && report.TargetType == types.AbuseTargetShare { + if err := dep.ShareClient().Expire(c, report.TargetID); err != nil { + return nil, serializer.NewError(serializer.CodeDBError, "Failed to block share", err) + } + } + + return BuildAbuseReport(report, dep.HashIDEncoder()), nil +} diff --git a/service/basic/site.go b/service/basic/site.go index 04b037d6..e444a3e2 100644 --- a/service/basic/site.go +++ b/service/basic/site.go @@ -54,6 +54,9 @@ type SiteConfig struct { // can offer a download-route picker (#2987). DownloadCDNRoutes []setting.CDNRoute `json:"download_cdn_routes,omitempty"` + // AbuseCaptcha controls whether the report-abuse dialog shows captcha. + AbuseCaptcha bool `json:"abuse_captcha,omitempty"` + // Explorer section Icons string `json:"icons,omitempty"` EmojiPreset string `json:"emoji_preset,omitempty"` @@ -234,6 +237,7 @@ func (s *GetSettingService) GetSiteConfig(c *gin.Context) (*SiteConfig, error) { ShareDefaultPrivate: shareDefaults.PrivateByDefault, DefaultShareLinksInProfile: string(shareDefaults.LinksInProfile), DownloadCDNRoutes: settings.DownloadCDNRoutes(c), + AbuseCaptcha: settings.AbuseCaptchaEnabled(c), }, nil }