feat(auth,prompt-rule): add password change with session revocation and scope prompt rules by brand
Frontend CI / Frontend (push) Successful in 3m8s
Backend CI / Backend (push) Successful in 14m48s

Add self-service password change that re-hashes the credential and bumps a
per-user session version so all existing access/refresh tokens are rejected.
Session version is tracked in Redis with an in-memory fallback and enforced in
middleware and refresh.

Scope prompt rules and rule groups to a brand: new brand_id column (migrated to
a "未归属" fallback brand for existing rows), brand-filtered queries/indexes, and
brand-aware admin-web tabs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 18:09:53 +08:00
parent 9f9e4f8e19
commit e045e00fbf
41 changed files with 1135 additions and 167 deletions
+18 -18
View File
@@ -152,42 +152,42 @@ func invalidateBrandCaches(ctx context.Context, c sharedcache.Cache, tenantID, b
invalidateWorkspaceCaches(ctx, c, tenantID)
}
func promptRuleGroupsCacheKey(tenantID int64) string {
return fmt.Sprintf("prompt_rule:groups:%d", tenantID)
func promptRuleGroupsCacheKey(tenantID, brandID int64) string {
return fmt.Sprintf("prompt_rule:groups:%d:%d", tenantID, brandID)
}
func promptRuleSimpleCacheKey(tenantID int64) string {
return fmt.Sprintf("prompt_rule:simple:%d", tenantID)
func promptRuleSimpleCacheKey(tenantID, brandID int64) string {
return fmt.Sprintf("prompt_rule:simple:%d:%d", tenantID, brandID)
}
func promptRuleDetailCachePrefix(tenantID int64) string {
return fmt.Sprintf("prompt_rule:detail:%d:", tenantID)
func promptRuleDetailCachePrefix(tenantID, brandID int64) string {
return fmt.Sprintf("prompt_rule:detail:%d:%d:", tenantID, brandID)
}
func promptRuleDetailCacheKey(tenantID, ruleID int64) string {
return fmt.Sprintf("%s%d", promptRuleDetailCachePrefix(tenantID), ruleID)
func promptRuleDetailCacheKey(tenantID, brandID, ruleID int64) string {
return fmt.Sprintf("%s%d", promptRuleDetailCachePrefix(tenantID, brandID), ruleID)
}
func promptRuleListCachePrefix(tenantID int64) string {
return fmt.Sprintf("prompt_rule:list:%d:", tenantID)
func promptRuleListCachePrefix(tenantID, brandID int64) string {
return fmt.Sprintf("prompt_rule:list:%d:%d:", tenantID, brandID)
}
func promptRuleListCacheKey(tenantID int64, params interface{}) string {
return promptRuleListCachePrefix(tenantID) + digestCacheKey(params)
func promptRuleListCacheKey(tenantID, brandID int64, params interface{}) string {
return promptRuleListCachePrefix(tenantID, brandID) + digestCacheKey(params)
}
func articleListCachePrefix(tenantID int64) string {
return fmt.Sprintf("article:list:%d:", tenantID)
}
func invalidatePromptRuleCaches(ctx context.Context, c sharedcache.Cache, tenantID int64, ruleID *int64) {
deleteCacheKey(ctx, c, promptRuleGroupsCacheKey(tenantID))
deleteCacheKey(ctx, c, promptRuleSimpleCacheKey(tenantID))
deleteCachePrefix(ctx, c, promptRuleListCachePrefix(tenantID))
func invalidatePromptRuleCaches(ctx context.Context, c sharedcache.Cache, tenantID, brandID int64, ruleID *int64) {
deleteCacheKey(ctx, c, promptRuleGroupsCacheKey(tenantID, brandID))
deleteCacheKey(ctx, c, promptRuleSimpleCacheKey(tenantID, brandID))
deleteCachePrefix(ctx, c, promptRuleListCachePrefix(tenantID, brandID))
if ruleID != nil && *ruleID > 0 {
deleteCacheKey(ctx, c, promptRuleDetailCacheKey(tenantID, *ruleID))
deleteCacheKey(ctx, c, promptRuleDetailCacheKey(tenantID, brandID, *ruleID))
} else {
deleteCachePrefix(ctx, c, promptRuleDetailCachePrefix(tenantID))
deleteCachePrefix(ctx, c, promptRuleDetailCachePrefix(tenantID, brandID))
}
deleteCachePrefix(ctx, c, scheduleTaskListCachePrefix(tenantID))
deleteCachePrefix(ctx, c, scheduleTaskDetailCachePrefix(tenantID))