固定生产商管理员角色
新建生产商时由服务端固定写入 admin,编辑时忽略并禁止修改角色。平台页面将 admin 只读显示为‘生产商管理员’,历史未知角色保持原值,不修改数据库或历史数据。补充后端回归测试、操作日志和项目文档。
This commit is contained in:
@@ -11,6 +11,9 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// producerAdminRoleCode 是生产商账户当前唯一支持的角色编码。
|
||||
const producerAdminRoleCode = "admin"
|
||||
|
||||
type producerAccountCreateRequest struct {
|
||||
ProducerCode string `json:"producer_code" binding:"required,max=64"`
|
||||
Name string `json:"name" binding:"required,max=128"`
|
||||
@@ -21,7 +24,7 @@ type producerAccountCreateRequest struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
DisplayName string `json:"display_name" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"` // 兼容旧客户端,服务端固定使用 admin。
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
@@ -32,7 +35,7 @@ type producerAccountUpdateRequest struct {
|
||||
Phone string `json:"phone" binding:"max=32"`
|
||||
Address string `json:"address" binding:"max=255"`
|
||||
DisplayName string `json:"display_name" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"` // 兼容旧客户端,更新时不采纳。
|
||||
Password string `json:"password"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -97,6 +100,37 @@ func restoreProducerAccountAddresses(response any, producers []models.ProducerAc
|
||||
return response
|
||||
}
|
||||
|
||||
// newProducerAccount 构造平台创建的生产商账户,并固定为生产商管理员角色。
|
||||
func newProducerAccount(request producerAccountCreateRequest, passwordHash string) models.ProducerAccount {
|
||||
return models.ProducerAccount{
|
||||
Entity: common.NewEntity(common.StatusEnable),
|
||||
ProducerCode: strings.TrimSpace(request.ProducerCode),
|
||||
Name: strings.TrimSpace(request.Name),
|
||||
CreditCode: strings.TrimSpace(request.CreditCode),
|
||||
Principal: strings.TrimSpace(request.Principal),
|
||||
Phone: strings.TrimSpace(request.Phone),
|
||||
Address: strings.TrimSpace(request.Address),
|
||||
Username: strings.TrimSpace(request.Username),
|
||||
DisplayName: strings.TrimSpace(request.DisplayName),
|
||||
PasswordHash: passwordHash,
|
||||
RoleCode: producerAdminRoleCode,
|
||||
Remark: request.Remark,
|
||||
}
|
||||
}
|
||||
|
||||
// producerAccountUpdateValues 生成生产商更新白名单值,刻意忽略客户端角色编码。
|
||||
func producerAccountUpdateValues(request producerAccountUpdateRequest) gin.H {
|
||||
return gin.H{
|
||||
"name": strings.TrimSpace(request.Name),
|
||||
"credit_code": strings.TrimSpace(request.CreditCode),
|
||||
"principal": strings.TrimSpace(request.Principal),
|
||||
"phone": strings.TrimSpace(request.Phone),
|
||||
"address": strings.TrimSpace(request.Address),
|
||||
"display_name": strings.TrimSpace(request.DisplayName),
|
||||
"remark": request.Remark,
|
||||
}
|
||||
}
|
||||
|
||||
func CreateProducerAccount(ctx *gin.Context) {
|
||||
var request producerAccountCreateRequest
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.IsValidAccountPassword(request.Password) {
|
||||
@@ -108,11 +142,7 @@ func CreateProducerAccount(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
roleCode := strings.TrimSpace(request.RoleCode)
|
||||
if roleCode == "" {
|
||||
roleCode = "admin"
|
||||
}
|
||||
data := models.ProducerAccount{Entity: common.NewEntity(common.StatusEnable), ProducerCode: strings.TrimSpace(request.ProducerCode), Name: strings.TrimSpace(request.Name), CreditCode: strings.TrimSpace(request.CreditCode), Principal: strings.TrimSpace(request.Principal), Phone: strings.TrimSpace(request.Phone), Address: strings.TrimSpace(request.Address), Username: strings.TrimSpace(request.Username), DisplayName: strings.TrimSpace(request.DisplayName), PasswordHash: hash, RoleCode: roleCode, Remark: request.Remark}
|
||||
data := newProducerAccount(request, hash)
|
||||
if err := impl.DBService.Create(&data).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
@@ -126,7 +156,7 @@ func UpdateProducerAccount(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
values := gin.H{"name": strings.TrimSpace(request.Name), "credit_code": strings.TrimSpace(request.CreditCode), "principal": strings.TrimSpace(request.Principal), "phone": strings.TrimSpace(request.Phone), "address": strings.TrimSpace(request.Address), "display_name": strings.TrimSpace(request.DisplayName), "role_code": strings.TrimSpace(request.RoleCode), "remark": request.Remark}
|
||||
values := producerAccountUpdateValues(request)
|
||||
if request.Password != "" {
|
||||
if !common.IsValidAccountPassword(request.Password) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
@@ -139,7 +169,7 @@ func UpdateProducerAccount(ctx *gin.Context) {
|
||||
}
|
||||
values["password_hash"] = hash
|
||||
}
|
||||
common.UpdateAllowedByIdentity(ctx, &models.ProducerAccount{}, values, []string{"name", "credit_code", "principal", "phone", "address", "display_name", "role_code", "remark", "password_hash"})
|
||||
common.UpdateAllowedByIdentity(ctx, &models.ProducerAccount{}, values, []string{"name", "credit_code", "principal", "phone", "address", "display_name", "remark", "password_hash"})
|
||||
}
|
||||
|
||||
func DeleteProducerAccount(ctx *gin.Context) {
|
||||
|
||||
@@ -9,6 +9,27 @@ import (
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
)
|
||||
|
||||
// TestNewProducerAccountUsesAdminRole 验证客户端角色不会改变新生产商的管理员权限。
|
||||
func TestNewProducerAccountUsesAdminRole(t *testing.T) {
|
||||
producer := newProducerAccount(producerAccountCreateRequest{
|
||||
ProducerCode: " producer-1 ",
|
||||
Name: " 示例生产商 ",
|
||||
Username: " producer-admin ",
|
||||
RoleCode: "1",
|
||||
}, "password-hash")
|
||||
if producer.RoleCode != producerAdminRoleCode {
|
||||
t.Fatalf("生产商角色编码必须为 %q,实际为 %q", producerAdminRoleCode, producer.RoleCode)
|
||||
}
|
||||
}
|
||||
|
||||
// TestProducerAccountUpdateIgnoresRole 验证编辑生产商时不会写入客户端角色编码。
|
||||
func TestProducerAccountUpdateIgnoresRole(t *testing.T) {
|
||||
values := producerAccountUpdateValues(producerAccountUpdateRequest{Name: "生产商", RoleCode: "1"})
|
||||
if _, exists := values["role_code"]; exists {
|
||||
t.Fatalf("生产商更新值不应包含角色编码:%#v", values)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRestoreProducerAccountAddresses 验证生产商列表按原顺序恢复企业地址。
|
||||
func TestRestoreProducerAccountAddresses(t *testing.T) {
|
||||
response := []any{
|
||||
|
||||
Reference in New Issue
Block a user