Files

100 lines
3.8 KiB
Go
Raw Permalink Normal View History

// 功能描述:报修现场照片关联与本人受保护读取;不公开照片文件目录。
// 版本1.0.0。
package user
import (
"crypto/sha256"
"fmt"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/upload"
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"time"
)
// ticketPhotoRequest 记录添加时间,导入照片不冒充已验证的原始拍摄时间。
type ticketPhotoRequest struct {
URI string `json:"uri" binding:"required"`
AddedAt time.Time `json:"added_at" binding:"required"`
Source string `json:"source" binding:"required,oneof=camera gallery"`
}
func UploadTicketPhoto(ctx *gin.Context) {
account, ok := common.UserAccount(ctx)
if !ok {
return
}
upload.UploadTicketPhoto(ctx, account.Identity)
}
// UploadedTicketPhoto 恢复本人草稿照片,不接受其他账户或任意路径。
func UploadedTicketPhoto(ctx *gin.Context) {
account, ok := common.UserAccount(ctx)
if !ok {
return
}
upload.ServeOwnedTicketPhoto(ctx, account.Identity, ctx.Param("name"))
}
// saveTicketPhotos 与工单创建共用事务,任一图片不属于本人时全部回滚。
func saveTicketPhotos(tx *gorm.DB, ticket models.CsTicket, owner string, photos []ticketPhotoRequest) error {
seen := map[string]bool{}
for index, photo := range photos {
if seen[photo.URI] || !upload.OwnsTicketPhoto(owner, photo.URI) || photo.AddedAt.IsZero() || photo.AddedAt.After(time.Now().Add(5*time.Minute)) {
return errcode.ErrInvalidArgument
}
seen[photo.URI] = true
evidence := models.CsTicketEvidence{
Entity: common.NewEntity(common.StatusEnable), CsTicketID: ticket.ID, EvidenceType: "reported", MediaType: "image", FileURI: photo.URI,
CapturedAt: photo.AddedAt, ReceivedAt: time.Now(), Source: "user_" + photo.Source, IntegrityStatus: "capture_time_unknown", OperatorIdentity: owner,
RequestNo: fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("user-photo:%s:%d", ticket.Identity, index)))),
}
if err := tx.Create(&evidence).Error; err != nil {
return err
}
}
return nil
}
// ticketPhotosForList 一次查询本人列表涉及的证据只发布元数据与公开证据UUID。
func ticketPhotosForList(tickets []models.CsTicket) (map[uint64][]gin.H, error) {
result := map[uint64][]gin.H{}
ids := make([]uint64, 0, len(tickets))
for _, ticket := range tickets {
ids = append(ids, ticket.ID)
}
if len(ids) == 0 {
return result, nil
}
var photos []models.CsTicketEvidence
if err := impl.DBService.Where("cs_ticket_id IN ? AND evidence_type = ? AND status <> ?", ids, "reported", common.StatusArchived).Order("created_at asc").Find(&photos).Error; err != nil {
return nil, err
}
for _, photo := range photos {
result[photo.CsTicketID] = append(result[photo.CsTicketID], gin.H{"identity": photo.Identity, "added_at": photo.CapturedAt, "source": photo.Source, "integrity_status": photo.IntegrityStatus})
}
return result, nil
}
// TicketPhoto 不允许借工单UUID读取其他工单照片也不允许读取他人报修。
func TicketPhoto(ctx *gin.Context) {
account, ok := common.UserAccount(ctx)
if !ok {
return
}
var ticket models.CsTicket
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", ctx.Param("identity"), account.ID, common.StatusArchived).First(&ticket).Error != nil {
ctx.Status(404)
return
}
var photo models.CsTicketEvidence
if impl.DBService.Where("identity = ? AND cs_ticket_id = ? AND evidence_type = ? AND status <> ?", ctx.Param("photoIdentity"), ticket.ID, "reported", common.StatusArchived).First(&photo).Error != nil {
ctx.Status(404)
return
}
upload.ServeTicketPhoto(ctx, account.Identity, photo.FileURI)
}