Files
tokens-reef/backend/ent/schema/user.go
User d1bf033f24 refactor(sora): remove per-user storage quota fields and simplify quota service
- Remove SoraStorageQuotaBytes/SoraStorageUsedBytes from User/Group schema (Ent ORM)
- Regenerate ent code (-582 lines net reduction)
- Clean up stale references in sora_handler.go (4 sites) and service.User struct
- Simplify SoraQuotaService constructor (3-param -> 1-param, system-default only)
- Add Deprecated marker + HTTP headers to ClearUserStorage API
- Change AddUsage/ReleaseUsage log level to Debug
- Add 9 unit tests for simplified SoraQuotaService (boundary/negative/nil-safe)
- Fix test files to remove deleted field references

Code review: 8.0/10 overall rating, 0 critical issues remaining.
2026-04-18 10:12:37 +08:00

101 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package schema
import (
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
func (User) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "users"},
}
}
func (User) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.TimeMixin{},
mixins.SoftDeleteMixin{},
}
}
func (User) Fields() []ent.Field {
return []ent.Field{
// 唯一约束通过部分索引实现WHERE deleted_at IS NULL支持软删除后重用
// 见迁移文件 016_soft_delete_partial_unique_indexes.sql
field.String("email").
MaxLen(255).
NotEmpty(),
field.String("password_hash").
MaxLen(255).
NotEmpty(),
field.String("role").
MaxLen(20).
Default(domain.RoleUser),
field.Float("balance").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
Default(0),
field.Int("concurrency").
Default(5),
field.String("status").
MaxLen(20).
Default(domain.StatusActive),
// Optional profile fields (added later; default '' in DB migration)
field.String("username").
MaxLen(100).
Default(""),
// wechat field migrated to user_attribute_values (see migration 019)
field.String("notes").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Default(""),
// TOTP 双因素认证字段
field.String("totp_secret_encrypted").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Optional().
Nillable(),
field.Bool("totp_enabled").
Default(false),
field.Time("totp_enabled_at").
Optional().
Nillable(),
}
}
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("api_keys", APIKey.Type),
edge.To("redeem_codes", RedeemCode.Type),
edge.To("subscriptions", UserSubscription.Type),
edge.To("assigned_subscriptions", UserSubscription.Type),
edge.To("announcement_reads", AnnouncementRead.Type),
edge.To("allowed_groups", Group.Type).
Through("user_allowed_groups", UserAllowedGroup.Type),
edge.To("usage_logs", UsageLog.Type),
edge.To("attribute_values", UserAttributeValue.Type),
edge.To("promo_code_usages", PromoCodeUsage.Type),
edge.To("payment_orders", PaymentOrder.Type),
}
}
func (User) Indexes() []ent.Index {
return []ent.Index{
// email 字段已在 Fields() 中声明 Unique(),无需重复索引
index.Fields("status"),
index.Fields("deleted_at"),
}
}