fix(exports): 更新导出逻辑以移除自动用户ID转换

- 删除从 URL 参数 userId 和 current_user_id 自动转换为 creator_in 的逻辑
- 更新相关注释,明确 current_user_id 仅用于记录导出任务的 owner,不用于数据过滤
- 强调用户需手动选择 creator 进行过滤,提升数据过滤的安全性和灵活性
This commit is contained in:
zhouyonggao 2025-12-19 02:24:54 +08:00
parent fca0e70115
commit ccb12da7f3
2 changed files with 21 additions and 55 deletions

View File

@ -102,40 +102,8 @@ func (a *ExportsAPI) create(w http.ResponseWriter, r *http.Request) {
}
// merge permission scope into filters to enforce boundary
p.Filters = mergePermissionIntoFilters(p.Datasource, main, p.Permission, p.Filters)
// support multiple userId in query: e.g., userId=15,25 → filters.creator_in
{
uidStr := r.URL.Query().Get("userId")
if uidStr != "" {
parts := strings.Split(uidStr, ",")
ids := make([]interface{}, 0, len(parts))
for _, s := range parts {
s = strings.TrimSpace(s)
if s == "" {
continue
}
if n, err := strconv.ParseUint(s, 10, 64); err == nil {
ids = append(ids, n)
}
}
if len(ids) > 0 {
// 如果传递了 plan_id_eq 或 reseller_id_eq不设置 creator_in适用于所有数据源
skipCreator := false
if main == "order" || main == "order_info" {
if v, ok := p.Filters["plan_id_eq"]; ok && v != nil && v != "" && v != 0 {
skipCreator = true
}
if v, ok := p.Filters["reseller_id_eq"]; ok && v != nil && v != "" && v != 0 {
skipCreator = true
}
}
if !skipCreator {
if _, exists := p.Filters["creator_in"]; !exists {
p.Filters["creator_in"] = ids
}
}
}
}
}
// 注意:不再从 URL 参数 userId 或 current_user_id 自动转换为 creator_in 过滤
// current_user_id 仅用于记录导出任务的 owner不用于数据过滤
// support multiple merchantId in query: e.g., merchantId=1,2,3 → filters.merchant_id_in
{
midStr := r.URL.Query().Get("merchantId")
@ -1658,7 +1626,7 @@ func mergePermissionIntoFilters(ds, main string, perm map[string]interface{}, fi
if hasNonEmptyIDs(filters["creator_in"]) {
return filters
}
// try known keys
// try known keys (明确排除 current_user_id它仅用于记录 owner不用于数据过滤)
{
candidates := []string{"creator_in", "creator_ids", "user_ids", "user_id_in", "user_id", "owner_id"}
ids := []interface{}{}
@ -1666,6 +1634,10 @@ func mergePermissionIntoFilters(ds, main string, perm map[string]interface{}, fi
if perm == nil {
break
}
// 明确排除 current_user_id 字段(即使不在 candidates 列表中,也显式检查以确保安全)
if k == "current_user_id" {
continue
}
if v, ok := perm[k]; ok {
ids = normalizeIDs(v)
if len(ids) > 0 {
@ -1674,9 +1646,14 @@ func mergePermissionIntoFilters(ds, main string, perm map[string]interface{}, fi
}
}
// also check filters incoming alternative keys and normalize into creator_in
// 明确排除 current_user_id 字段
if len(ids) == 0 {
alt := []string{"creator_ids", "user_ids", "user_id_in", "user_id", "owner_id"}
for _, k := range alt {
// 明确排除 current_user_id 字段
if k == "current_user_id" {
continue
}
if v, ok := filters[k]; ok {
ids = normalizeIDs(v)
if len(ids) > 0 {
@ -1685,6 +1662,11 @@ func mergePermissionIntoFilters(ds, main string, perm map[string]interface{}, fi
}
}
}
// 额外检查:如果 permission 或 filters 中直接有 current_user_id明确排除它
if perm != nil {
delete(perm, "current_user_id")
}
delete(filters, "current_user_id")
if len(ids) > 0 {
filters["creator_in"] = ids
}

View File

@ -666,32 +666,16 @@ const app = createApp({
if (state.exportForm.datasource === 'marketing') {
loadCreators();
const userId = Api.getUserId();
if (userId) {
const parts = String(userId).split(',').map(s => s.trim()).filter(Boolean);
if (parts.length === 1) {
// 单个用户 ID同时设置 creatorId 和 creatorIds
state.exportForm.creatorId = Number(parts[0]);
state.exportForm.creatorIds = [Number(parts[0])];
} else {
// 多个用户 ID只设置 creatorIds
state.exportForm.creatorId = null;
state.exportForm.creatorIds = parts.map(Number);
}
}
// 注意:不再自动从 current_user_id 设置 creatorId/creatorIds
// 用户需要手动选择 creator 进行过滤
}
if (state.exportForm.datasource === 'ymt') {
await loadYmtCreators();
await loadYmtMerchants();
await loadYmtActivities();
const userId = Api.getUserId();
if (userId) {
const first = String(userId).split(',').map(s => s.trim()).filter(Boolean)[0];
if (first) {
state.exportForm.ymtCreatorId = Number(first);
}
}
// 注意:不再自动从 current_user_id 设置 ymtCreatorId
// 用户需要手动选择 creator 进行过滤
}
if (!state.exportForm.dateRange?.length) {