固化七月迭代审计治理进展以隔离线上热修
Constraint: 切换 main 前必须保存当前七月分支全部项目进展,套餐生效提案仅属于 Iteration/7-11。 Rejected: 将七月套餐修复直接移植到 main | 两个分支的可靠投递架构不同。 Confidence: medium Scope-risk: broad Directive: 不得将本提交整体 cherry-pick 到 main;main 套餐热修必须基于其纯 Asynq 代码独立实施。 Tested: git diff --check;openspec validate fix-package-activation-starvation --strict。 Not-tested: 按用户要求未运行自动化测试;go build ./... 因当前审计改造中的 Enterprise 模型字面量和 role.recordFailure 参数类型错误未通过。
This commit is contained in:
@@ -2,7 +2,9 @@ package enterprise
|
||||
|
||||
import (
|
||||
"context"
|
||||
stderrors "errors"
|
||||
|
||||
accessauditapp "github.com/break/junhong_cmp_fiber/internal/application/accessaudit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
@@ -12,6 +14,7 @@ import (
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
@@ -19,14 +22,23 @@ type Service struct {
|
||||
enterpriseStore *postgres.EnterpriseStore
|
||||
shopStore *postgres.ShopStore
|
||||
accountStore *postgres.AccountStore
|
||||
accessAudit accessauditapp.Writer
|
||||
}
|
||||
|
||||
func New(db *gorm.DB, enterpriseStore *postgres.EnterpriseStore, shopStore *postgres.ShopStore, accountStore *postgres.AccountStore) *Service {
|
||||
// New 创建企业生命周期服务。
|
||||
func New(
|
||||
db *gorm.DB,
|
||||
enterpriseStore *postgres.EnterpriseStore,
|
||||
shopStore *postgres.ShopStore,
|
||||
accountStore *postgres.AccountStore,
|
||||
accessAudit accessauditapp.Writer,
|
||||
) *Service {
|
||||
return &Service{
|
||||
db: db,
|
||||
enterpriseStore: enterpriseStore,
|
||||
shopStore: shopStore,
|
||||
accountStore: accountStore,
|
||||
accessAudit: accessAudit,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,52 +47,71 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateEnterpriseReq) (*dt
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
if s.db == nil || s.accessAudit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
||||
}
|
||||
|
||||
enterprise := &model.Enterprise{
|
||||
EnterpriseName: req.EnterpriseName, EnterpriseCode: req.EnterpriseCode, OwnerShopID: req.OwnerShopID,
|
||||
LegalPerson: req.LegalPerson, ContactName: req.ContactName, ContactPhone: req.ContactPhone,
|
||||
BusinessLicense: req.BusinessLicense, Province: req.Province, City: req.City,
|
||||
District: req.District, Address: req.Address, Status: constants.StatusEnabled,
|
||||
}
|
||||
enterprise.Creator = currentUserID
|
||||
enterprise.Updater = currentUserID
|
||||
if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeEnterprise {
|
||||
err := errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeAgent && req.OwnerShopID == nil {
|
||||
err := errors.New(errors.CodeForbidden, "代理账号不能创建平台主管企业")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.EnterpriseCode != "" {
|
||||
existing, _ := s.enterpriseStore.GetByCode(ctx, req.EnterpriseCode)
|
||||
if existing != nil {
|
||||
return nil, errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
||||
err := errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
existingAccount, _ := s.accountStore.GetByPhone(ctx, req.LoginPhone)
|
||||
if existingAccount != nil {
|
||||
return nil, errors.New(errors.CodePhoneExists, "手机号已被使用")
|
||||
err := errors.New(errors.CodePhoneExists, "手机号已被使用")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ownerShop *model.Shop
|
||||
if req.OwnerShopID != nil {
|
||||
_, err := s.shopStore.GetByID(ctx, *req.OwnerShopID)
|
||||
if err := middleware.CanManageShop(ctx, *req.OwnerShopID); err != nil {
|
||||
err = errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
var err error
|
||||
ownerShop, err = s.shopStore.GetByID(ctx, *req.OwnerShopID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.CodeShopNotFound, "归属店铺不存在或无效")
|
||||
err = errors.New(errors.CodeShopNotFound, "归属店铺不存在或无效")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
||||
appErr := errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, ownerShop, nil, appErr)
|
||||
return nil, appErr
|
||||
}
|
||||
|
||||
var enterprise *model.Enterprise
|
||||
var account *model.Account
|
||||
|
||||
err = s.db.Transaction(func(tx *gorm.DB) error {
|
||||
enterprise = &model.Enterprise{
|
||||
EnterpriseName: req.EnterpriseName,
|
||||
EnterpriseCode: req.EnterpriseCode,
|
||||
OwnerShopID: req.OwnerShopID,
|
||||
LegalPerson: req.LegalPerson,
|
||||
ContactName: req.ContactName,
|
||||
ContactPhone: req.ContactPhone,
|
||||
BusinessLicense: req.BusinessLicense,
|
||||
Province: req.Province,
|
||||
City: req.City,
|
||||
District: req.District,
|
||||
Address: req.Address,
|
||||
Status: constants.StatusEnabled,
|
||||
}
|
||||
enterprise.Creator = currentUserID
|
||||
enterprise.Updater = currentUserID
|
||||
|
||||
if err := tx.WithContext(ctx).Create(enterprise).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建企业失败")
|
||||
}
|
||||
@@ -100,18 +131,27 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateEnterpriseReq) (*dt
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建企业账号失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
||||
ActionCode: constants.AuditActionEnterpriseCreated, Summary: "创建企业", OperatorID: currentUserID,
|
||||
Enterprise: enterprise, Shop: ownerShop,
|
||||
Accounts: []accessauditapp.AccountChange{{
|
||||
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
||||
AfterData: map[string]any{"status": account.Status, "credentials_configured": true},
|
||||
}},
|
||||
AfterData: enterpriseProfileData(enterprise),
|
||||
})
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
failureEnterprise := *enterprise
|
||||
failureEnterprise.ID = 0
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", &failureEnterprise, ownerShop, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownerShopName := ""
|
||||
if enterprise.OwnerShopID != nil {
|
||||
if shop, err := s.shopStore.GetByID(ctx, *enterprise.OwnerShopID); err == nil {
|
||||
ownerShopName = shop.ShopName
|
||||
}
|
||||
if ownerShop != nil {
|
||||
ownerShopName = ownerShop.ShopName
|
||||
}
|
||||
|
||||
return &dto.CreateEnterpriseResp{
|
||||
@@ -140,28 +180,205 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateEnterpriseReq) (*dt
|
||||
|
||||
// Update 更新企业信息
|
||||
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateEnterpriseRequest) (*model.Enterprise, error) {
|
||||
// 获取当前用户 ID
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
if s.db == nil || s.accessAudit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
||||
}
|
||||
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
||||
return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
}
|
||||
|
||||
// 查询企业
|
||||
var enterprise *model.Enterprise
|
||||
var before *model.Enterprise
|
||||
var ownerShop *model.Shop
|
||||
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
locked, err := lockEnterprise(ctx, tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
beforeValue := *locked
|
||||
before = &beforeValue
|
||||
enterprise = locked
|
||||
ownerShop = loadEnterpriseOwnerShop(tx, locked.OwnerShopID)
|
||||
if req.EnterpriseCode != nil && *req.EnterpriseCode != locked.EnterpriseCode {
|
||||
var count int64
|
||||
if err := tx.Model(&model.Enterprise{}).Where("enterprise_code = ? AND id <> ?", *req.EnterpriseCode, id).Count(&count).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "检查企业编号失败")
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
||||
}
|
||||
locked.EnterpriseCode = *req.EnterpriseCode
|
||||
}
|
||||
applyEnterpriseUpdate(locked, req)
|
||||
locked.Updater = currentUserID
|
||||
if err := tx.Save(locked).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "更新企业失败")
|
||||
}
|
||||
if !enterpriseProfileChanged(before, locked) {
|
||||
return nil
|
||||
}
|
||||
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
||||
ActionCode: constants.AuditActionEnterpriseUpdated, Summary: "更新企业基础资料", OperatorID: currentUserID,
|
||||
Enterprise: locked, Shop: ownerShop,
|
||||
BeforeData: enterpriseProfileData(before), AfterData: enterpriseProfileData(locked),
|
||||
}); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "写入企业更新审计失败")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if before != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseUpdated, "更新企业基础资料失败", before, ownerShop, nil, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return enterprise, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
if s.db == nil || s.accessAudit == nil {
|
||||
return errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
||||
}
|
||||
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
||||
return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
}
|
||||
|
||||
var before *model.Enterprise
|
||||
var ownerShop *model.Shop
|
||||
var accounts []*model.Account
|
||||
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
enterprise, err := lockEnterprise(ctx, tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
beforeValue := *enterprise
|
||||
before = &beforeValue
|
||||
ownerShop = loadEnterpriseOwnerShop(tx, enterprise.OwnerShopID)
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("enterprise_id = ?", id).Find(&accounts).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询企业账号失败")
|
||||
}
|
||||
enterprise.Status = status
|
||||
enterprise.Updater = currentUserID
|
||||
if err := tx.Save(enterprise).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新企业状态失败")
|
||||
}
|
||||
|
||||
if err := tx.Model(&model.Account{}).
|
||||
Where("enterprise_id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"updater": currentUserID,
|
||||
}).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "同步更新企业账号状态失败")
|
||||
}
|
||||
if before.Status == status {
|
||||
return nil
|
||||
}
|
||||
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
||||
for _, account := range accounts {
|
||||
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
||||
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
||||
BeforeData: map[string]any{"status": account.Status}, AfterData: map[string]any{"status": status},
|
||||
})
|
||||
}
|
||||
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
||||
ActionCode: constants.AuditActionEnterpriseStatusUpdated, Summary: "更新企业状态", OperatorID: currentUserID,
|
||||
Enterprise: enterprise, Shop: ownerShop, Accounts: accountChanges,
|
||||
BeforeData: map[string]any{"status": before.Status}, AfterData: map[string]any{"status": status},
|
||||
}); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "写入企业状态审计失败")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if before != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionEnterpriseStatusUpdated, "更新企业状态失败", before, ownerShop, accounts, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdatePassword(ctx context.Context, id uint, password string) error {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
if s.db == nil || s.accessAudit == nil {
|
||||
return errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
||||
}
|
||||
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
||||
return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
}
|
||||
enterprise, err := s.enterpriseStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
||||
return errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
||||
}
|
||||
var ownerShop *model.Shop
|
||||
if enterprise.OwnerShopID != nil {
|
||||
ownerShop, _ = s.shopStore.GetByID(ctx, *enterprise.OwnerShopID)
|
||||
}
|
||||
|
||||
// 检查企业编号唯一性(如果修改了编号)
|
||||
if req.EnterpriseCode != nil && *req.EnterpriseCode != enterprise.EnterpriseCode {
|
||||
existing, err := s.enterpriseStore.GetByCode(ctx, *req.EnterpriseCode)
|
||||
if err == nil && existing != nil && existing.ID != id {
|
||||
return nil, errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
appErr := errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
||||
s.recordFailure(ctx, constants.AuditActionEnterprisePasswordUpdated, "更新企业账号密码失败", enterprise, ownerShop, nil, appErr)
|
||||
return appErr
|
||||
}
|
||||
|
||||
var accounts []*model.Account
|
||||
err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
enterprise, err = lockEnterprise(ctx, tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enterprise.EnterpriseCode = *req.EnterpriseCode
|
||||
ownerShop = loadEnterpriseOwnerShop(tx, enterprise.OwnerShopID)
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("enterprise_id = ?", id).Find(&accounts).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询企业账号失败")
|
||||
}
|
||||
if err := tx.Model(&model.Account{}).Where("enterprise_id = ?", id).Updates(map[string]interface{}{
|
||||
"password": string(hashedPassword), "updater": currentUserID,
|
||||
}).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "更新企业账号密码失败")
|
||||
}
|
||||
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
||||
for _, account := range accounts {
|
||||
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
||||
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
||||
BeforeData: map[string]any{"credentials_configured": account.Password != ""},
|
||||
AfterData: map[string]any{"credentials_configured": true, "state": "changed"},
|
||||
})
|
||||
}
|
||||
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
||||
ActionCode: constants.AuditActionEnterprisePasswordUpdated, Summary: "更新企业账号密码", OperatorID: currentUserID,
|
||||
Enterprise: enterprise, Shop: ownerShop, Accounts: accountChanges,
|
||||
BeforeData: map[string]any{"credentials_configured": len(accounts) > 0},
|
||||
AfterData: map[string]any{"credentials_configured": len(accounts) > 0, "state": "changed"},
|
||||
}); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "写入企业改密审计失败")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if enterprise != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionEnterprisePasswordUpdated, "更新企业账号密码失败", enterprise, ownerShop, accounts, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新字段
|
||||
func applyEnterpriseUpdate(enterprise *model.Enterprise, req *dto.UpdateEnterpriseRequest) {
|
||||
if req.EnterpriseName != nil {
|
||||
enterprise.EnterpriseName = *req.EnterpriseName
|
||||
}
|
||||
@@ -189,69 +406,81 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateEnterprise
|
||||
if req.Address != nil {
|
||||
enterprise.Address = *req.Address
|
||||
}
|
||||
|
||||
enterprise.Updater = currentUserID
|
||||
|
||||
if err := s.enterpriseStore.Update(ctx, enterprise); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return enterprise, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
func enterpriseProfileData(enterprise *model.Enterprise) map[string]any {
|
||||
return map[string]any{
|
||||
"enterprise_name": enterprise.EnterpriseName, "enterprise_code": enterprise.EnterpriseCode,
|
||||
"owner_shop_id": enterprise.OwnerShopID, "legal_person": enterprise.LegalPerson,
|
||||
"contact_name": enterprise.ContactName, "contact_phone": enterprise.ContactPhone,
|
||||
"business_license": enterprise.BusinessLicense, "province": enterprise.Province,
|
||||
"city": enterprise.City, "district": enterprise.District, "address": enterprise.Address,
|
||||
"status": enterprise.Status,
|
||||
}
|
||||
}
|
||||
|
||||
enterprise, err := s.enterpriseStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
||||
func enterpriseProfileChanged(before, after *model.Enterprise) bool {
|
||||
return before.EnterpriseName != after.EnterpriseName || before.EnterpriseCode != after.EnterpriseCode ||
|
||||
before.LegalPerson != after.LegalPerson || before.ContactName != after.ContactName ||
|
||||
before.ContactPhone != after.ContactPhone || before.BusinessLicense != after.BusinessLicense ||
|
||||
before.Province != after.Province || before.City != after.City || before.District != after.District ||
|
||||
before.Address != after.Address
|
||||
}
|
||||
|
||||
func lockEnterprise(ctx context.Context, tx *gorm.DB, id uint) (*model.Enterprise, error) {
|
||||
var enterprise model.Enterprise
|
||||
query := middleware.ApplyOwnerShopFilter(ctx, tx.WithContext(ctx).Where("id = ?", id))
|
||||
if err := query.Clauses(clause.Locking{Strength: "UPDATE"}).First(&enterprise).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询企业失败")
|
||||
}
|
||||
return &enterprise, nil
|
||||
}
|
||||
|
||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||
enterprise.Status = status
|
||||
enterprise.Updater = currentUserID
|
||||
if err := tx.WithContext(ctx).Save(enterprise).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新企业状态失败")
|
||||
}
|
||||
|
||||
if err := tx.WithContext(ctx).Model(&model.Account{}).
|
||||
Where("enterprise_id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"updater": currentUserID,
|
||||
}).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "同步更新企业账号状态失败")
|
||||
}
|
||||
|
||||
func loadEnterpriseOwnerShop(tx *gorm.DB, ownerShopID *uint) *model.Shop {
|
||||
if ownerShopID == nil {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
var shop model.Shop
|
||||
if err := tx.Unscoped().First(&shop, *ownerShopID).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
return &shop
|
||||
}
|
||||
|
||||
func (s *Service) UpdatePassword(ctx context.Context, id uint, password string) error {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
func (s *Service) recordFailure(
|
||||
ctx context.Context,
|
||||
actionCode, summary string,
|
||||
enterprise *model.Enterprise,
|
||||
ownerShop *model.Shop,
|
||||
accounts []*model.Account,
|
||||
originalErr error,
|
||||
) {
|
||||
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
||||
for _, account := range accounts {
|
||||
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
||||
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
||||
})
|
||||
}
|
||||
accessauditapp.RecordFailure(ctx, s.db, s.accessAudit, accessauditapp.ChangeAudit{
|
||||
ActionCode: actionCode, Summary: summary, Result: enterpriseAuditFailureResult(originalErr),
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx), Enterprise: enterprise, Shop: ownerShop,
|
||||
Accounts: accountChanges, SubjectVisibility: constants.AuditSubjectInternalOnly,
|
||||
}, originalErr)
|
||||
}
|
||||
|
||||
_, err := s.enterpriseStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
||||
func enterpriseAuditFailureResult(err error) string {
|
||||
var appErr *errors.AppError
|
||||
if stderrors.As(err, &appErr) {
|
||||
switch appErr.Code {
|
||||
case errors.CodeForbidden, errors.CodeInvalidParam, errors.CodeNotFound, errors.CodeEnterpriseNotFound,
|
||||
errors.CodeEnterpriseCodeExists, errors.CodePhoneExists, errors.CodeShopNotFound:
|
||||
return constants.AuditResultDenied
|
||||
}
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
||||
}
|
||||
|
||||
return s.db.WithContext(ctx).Model(&model.Account{}).
|
||||
Where("enterprise_id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"password": string(hashedPassword),
|
||||
"updater": currentUserID,
|
||||
}).Error
|
||||
return constants.AuditResultFailed
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id uint) (*model.Enterprise, error) {
|
||||
|
||||
Reference in New Issue
Block a user