安全与可靠性: 修复配额并发、投票事务、密码授权与导出完整性
This commit is contained in:
@@ -20,6 +20,8 @@ import (
|
||||
|
||||
var FeatureControls FeatureControlsStore
|
||||
|
||||
var ErrFeatureQuotaReached = errors.New("功能收集配额已满")
|
||||
|
||||
var _ FeatureControlsStore = (*featureControls)(nil)
|
||||
|
||||
// 受控功能标识(feature_controls.feature 取值)。
|
||||
@@ -517,6 +519,21 @@ func (db *featureControls) IncrementQuota(ctx context.Context, userID uint, feat
|
||||
// 于是计数比真实行数少,箱主的「已收集 7/10」永远偏低,达到上限后仍能继续收,
|
||||
// 而重置计数也校准不回来(重置是把计数清零,与实际行数更脱节)。
|
||||
// 现在内容 store 把这一步放进自己的事务里,任一步失败整体回滚,计数天然对齐。
|
||||
func reserveFeatureQuotaTx(tx *gorm.DB, userID uint, feature string) error {
|
||||
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(DefaultFeatureControl(userID, feature)).Error; err != nil {
|
||||
return errors.Wrap(err, "initialize feature quota")
|
||||
}
|
||||
var fc FeatureControl
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("user_id = ? AND feature = ?", userID, feature).First(&fc).Error; err != nil {
|
||||
return errors.Wrap(err, "lock feature quota")
|
||||
}
|
||||
if fc.QuotaLimit > 0 && fc.QuotaCount >= fc.QuotaLimit {
|
||||
return ErrFeatureQuotaReached
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func incrementQuotaTx(tx *gorm.DB, userID uint, feature string, delta int64) error {
|
||||
if delta == 0 {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user