feat(auth): enforce vehicle grant time boundaries

This commit is contained in:
lingniu
2026-07-16 15:44:29 +08:00
parent a541d10c7b
commit 4688abadef
11 changed files with 580 additions and 35 deletions

View File

@@ -1,7 +1,9 @@
package platform
import (
"encoding/json"
"net/url"
"sort"
"strconv"
"strings"
)
@@ -455,6 +457,7 @@ func buildDailyMileageSQL(query url.Values) SQLQuery {
}
where, args = appendVINListFilter(where, args, "m.vin", query.Get("vins"))
where, args = appendVINListFilter(where, args, "m.vin", query.Get("scopeVins"))
where, args = appendVehicleDateScope(where, args, "m.vin", "m.stat_date", query.Get("scopeVehicleFrom"))
protocols := parseMileageProtocols(query.Get("protocols"))
if len(protocols) > 0 {
where, args = appendMileageProtocolFilter(where, args, "m.protocol", protocols)
@@ -517,6 +520,7 @@ func buildMileageSummarySQL(query url.Values) SQLQuery {
}
where, args = appendVINListFilter(where, args, "m.vin", query.Get("vins"))
where, args = appendVINListFilter(where, args, "m.vin", query.Get("scopeVins"))
where, args = appendVehicleDateScope(where, args, "m.vin", "m.stat_date", query.Get("scopeVehicleFrom"))
if protocols := parseMileageProtocols(query.Get("protocols")); len(protocols) > 0 {
where, args = appendMileageProtocolFilter(where, args, "m.protocol", protocols)
} else if protocol := strings.TrimSpace(query.Get("protocol")); protocol != "" {
@@ -552,6 +556,7 @@ func buildMileageStatisticsWhere(query url.Values) (string, []any) {
}
where, args = appendVINListFilter(where, args, "m.vin", query.Get("vins"))
where, args = appendVINListFilter(where, args, "m.vin", query.Get("scopeVins"))
where, args = appendVehicleDateScope(where, args, "m.vin", "m.stat_date", query.Get("scopeVehicleFrom"))
if protocols := parseMileageProtocols(query.Get("protocols")); len(protocols) > 0 {
where, args = appendMileageProtocolFilter(where, args, "m.protocol", protocols)
} else if protocol := strings.TrimSpace(query.Get("protocol")); protocol != "" {
@@ -700,6 +705,40 @@ func appendVINListFilter(where []string, args []any, column string, raw string)
return append(where, column+" IN ("+strings.Join(placeholders, ",")+")"), args
}
func appendVehicleDateScope(where []string, args []any, vinColumn, dateColumn, raw string) ([]string, []any) {
raw = strings.TrimSpace(raw)
if raw == "" {
return where, args
}
var parsed map[string]string
if err := json.Unmarshal([]byte(raw), &parsed); err != nil || len(parsed) == 0 {
return append(where, "1 = 0"), args
}
cutoffs := make(map[string]string, len(parsed))
for vin, cutoff := range parsed {
vin = strings.ToUpper(strings.TrimSpace(vin))
cutoff = strings.TrimSpace(cutoff)
if vin == "" || cutoff == "" {
continue
}
cutoffs[vin] = cutoff
}
if len(cutoffs) == 0 {
return append(where, "1 = 0"), args
}
vins := make([]string, 0, len(cutoffs))
for vin := range cutoffs {
vins = append(vins, vin)
}
sort.Strings(vins)
predicates := make([]string, 0, len(vins))
for _, vin := range vins {
predicates = append(predicates, "("+vinColumn+" = ? AND "+dateColumn+" >= ?)")
args = append(args, vin, cutoffs[vin])
}
return append(where, "("+strings.Join(predicates, " OR ")+")"), args
}
func buildLimitOffset(query url.Values) (int, int) {
return parseSQLPageSize(query.Get("limit"), 20), parsePositive(query.Get("offset"), 0)
}