fix(platform): guard approval transitions

This commit is contained in:
2026-07-27 09:14:36 +08:00
parent dd23452e14
commit 553648169e
3 changed files with 102 additions and 4 deletions

View File

@@ -14,6 +14,8 @@ import (
"gorm.io/gorm"
)
var errApprovalNotProcessable = errors.New("approval is not processable")
func approvalValues(status, opinion, operatorIdentity string) map[string]any {
return map[string]any{
"status": status,
@@ -40,6 +42,10 @@ func ApproveAudit(ctx *gin.Context) {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
if request.Status != "approved" && request.Status != "rejected" {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
values := approvalValues(request.Status, request.Opinion, claims.Identity)
var approval models.AudApproval
@@ -47,6 +53,9 @@ func ApproveAudit(ctx *gin.Context) {
if err := transaction.Where("identity = ?", ctx.Param("identity")).First(&approval).Error; err != nil {
return err
}
if approval.Status != "pending" || approval.ApplicantIdentity == claims.Identity {
return errApprovalNotProcessable
}
before, err := json.Marshal(gin.H{
"status": approval.Status, "opinion": approval.Opinion,
"handler_identity": approval.HandlerIdentity, "handled_at": approval.HandledAt,
@@ -54,10 +63,10 @@ func ApproveAudit(ctx *gin.Context) {
if err != nil {
return err
}
if result := transaction.Model(&models.AudApproval{}).Where("identity = ?", approval.Identity).Updates(values); result.Error != nil {
if result := transaction.Model(&models.AudApproval{}).Where("identity = ? AND status = ?", approval.Identity, "pending").Updates(values); result.Error != nil {
return result.Error
} else if result.RowsAffected == 0 {
return gorm.ErrRecordNotFound
return errApprovalNotProcessable
}
after, err := json.Marshal(values)
if err != nil {
@@ -74,6 +83,10 @@ func ApproveAudit(ctx *gin.Context) {
}).Error
})
if err != nil {
if errors.Is(err, errApprovalNotProcessable) {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
if errors.Is(err, gorm.ErrRecordNotFound) {
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
return