fix(platform-admin): correct organization and contact display
This commit is contained in:
@@ -135,13 +135,20 @@ func isCreatedResponseField(key string) bool {
|
||||
}
|
||||
|
||||
func ProtectPreciseLocation(ctx *gin.Context, model, value any) any {
|
||||
maskPersonalName := reflect.TypeOf(model) == reflect.TypeOf(&models.UserAccount{}) ||
|
||||
reflect.TypeOf(model) == reflect.TypeOf(&models.StaffAccount{})
|
||||
maskDisplayName := reflect.TypeOf(model) == reflect.TypeOf(&models.PlatformAccount{})
|
||||
ProtectPublicFields(value, maskPersonalName, maskDisplayName, HasPreciseLocationScope(ctx))
|
||||
retainPlatformPersonalData := canViewPlatformPersonalData(ctx)
|
||||
maskPersonalName := !retainPlatformPersonalData && (reflect.TypeOf(model) == reflect.TypeOf(&models.UserAccount{}) ||
|
||||
reflect.TypeOf(model) == reflect.TypeOf(&models.StaffAccount{}))
|
||||
maskDisplayName := !retainPlatformPersonalData && reflect.TypeOf(model) == reflect.TypeOf(&models.PlatformAccount{})
|
||||
protectPublicFields(value, maskPersonalName, maskDisplayName, HasPreciseLocationScope(ctx), retainPlatformPersonalData)
|
||||
return value
|
||||
}
|
||||
|
||||
// canViewPlatformPersonalData 仅允许已通过平台总后台鉴权和菜单校验的请求查看姓名与主手机号明文。
|
||||
func canViewPlatformPersonalData(ctx *gin.Context) bool {
|
||||
claims, err := middleware.ParseAuth(ctx)
|
||||
return err == nil && claims.Client == "platform_admin"
|
||||
}
|
||||
|
||||
var sensitiveResponseFields = map[string]bool{
|
||||
"avatar": true, "address": true, "credential_no": true,
|
||||
"evidence_uri": true, "evidence_url": true, "file_uri": true,
|
||||
@@ -152,12 +159,18 @@ var sensitiveResponseFields = map[string]bool{
|
||||
}
|
||||
|
||||
func ProtectPublicFields(value any, maskPersonalName, maskDisplayName, retainCoordinates bool) {
|
||||
protectPublicFields(value, maskPersonalName, maskDisplayName, retainCoordinates, false)
|
||||
}
|
||||
|
||||
func protectPublicFields(value any, maskPersonalName, maskDisplayName, retainCoordinates, retainPrimaryPhone bool) {
|
||||
switch data := value.(type) {
|
||||
case map[string]any:
|
||||
if phone, ok := data["phone"].(string); ok && phone != "" {
|
||||
data["phone_masked"] = MaskPhone(phone)
|
||||
if !retainPrimaryPhone {
|
||||
if phone, ok := data["phone"].(string); ok && phone != "" {
|
||||
data["phone_masked"] = MaskPhone(phone)
|
||||
}
|
||||
delete(data, "phone")
|
||||
}
|
||||
delete(data, "phone")
|
||||
for _, key := range []string{"contact_phone", "recipient_phone"} {
|
||||
if phone, ok := data[key].(string); ok && phone != "" {
|
||||
data[key+"_masked"] = MaskPhone(phone)
|
||||
@@ -194,11 +207,11 @@ func ProtectPublicFields(value any, maskPersonalName, maskDisplayName, retainCoo
|
||||
delete(data, "latitude")
|
||||
}
|
||||
for _, item := range data {
|
||||
ProtectPublicFields(item, maskPersonalName, maskDisplayName, retainCoordinates)
|
||||
protectPublicFields(item, maskPersonalName, maskDisplayName, retainCoordinates, retainPrimaryPhone)
|
||||
}
|
||||
case []any:
|
||||
for _, item := range data {
|
||||
ProtectPublicFields(item, maskPersonalName, maskDisplayName, retainCoordinates)
|
||||
protectPublicFields(item, maskPersonalName, maskDisplayName, retainCoordinates, retainPrimaryPhone)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
@@ -143,6 +145,55 @@ func TestPublicFieldProtectionMasksGasorderContacts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlatformAdminResourceResponseRetainsNamesAndPrimaryPhone(t *testing.T) {
|
||||
ctx, _ := gin.CreateTestContext(nil)
|
||||
ctx.Set("Auth", &types.JwtClaims{Client: "platform_admin"})
|
||||
|
||||
user := map[string]any{
|
||||
"name": "张三", "real_name": "张三", "phone": "13800138000",
|
||||
"address": "敏感地址", "contact_phone": "13900139000",
|
||||
}
|
||||
ProtectPreciseLocation(ctx, &models.UserAccount{}, user)
|
||||
if user["name"] != "张三" || user["real_name"] != "张三" || user["phone"] != "13800138000" {
|
||||
t.Fatalf("platform personal data was masked: %#v", user)
|
||||
}
|
||||
if _, exists := user["phone_masked"]; exists {
|
||||
t.Fatalf("platform response contains an unexpected phone mask: %#v", user)
|
||||
}
|
||||
if _, exists := user["address"]; exists {
|
||||
t.Fatalf("platform exception exposed an address: %#v", user)
|
||||
}
|
||||
if user["contact_phone_masked"] != "139****9000" {
|
||||
t.Fatalf("order contact phone was not kept masked: %#v", user)
|
||||
}
|
||||
|
||||
account := map[string]any{"display_name": "平台主管", "phone": "13700137000"}
|
||||
ProtectPreciseLocation(ctx, &models.PlatformAccount{}, account)
|
||||
if account["display_name"] != "平台主管" || account["phone"] != "13700137000" {
|
||||
t.Fatalf("platform account data was masked: %#v", account)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPlatformResourceResponseStillMasksNamesAndPhone(t *testing.T) {
|
||||
ctx, _ := gin.CreateTestContext(nil)
|
||||
ctx.Set("Auth", &types.JwtClaims{Client: "user_app"})
|
||||
value := map[string]any{"name": "张三", "real_name": "张三", "phone": "13800138000"}
|
||||
|
||||
ProtectPreciseLocation(ctx, &models.UserAccount{}, value)
|
||||
if _, exists := value["name"]; exists {
|
||||
t.Fatalf("non-platform response exposed a name: %#v", value)
|
||||
}
|
||||
if _, exists := value["real_name"]; exists {
|
||||
t.Fatalf("non-platform response exposed a real name: %#v", value)
|
||||
}
|
||||
if _, exists := value["phone"]; exists {
|
||||
t.Fatalf("non-platform response exposed a phone: %#v", value)
|
||||
}
|
||||
if value["name_masked"] != "张*" || value["phone_masked"] != "138****8000" {
|
||||
t.Fatalf("non-platform response masks are incorrect: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceRelationOptionalEmptyIdentityClearsRelation(t *testing.T) {
|
||||
values, err := ResolveResourceRelations(
|
||||
map[string]any{"warehouse_identity": ""},
|
||||
|
||||
Reference in New Issue
Block a user