177 lines
4.8 KiB
Go
177 lines
4.8 KiB
Go
package provisioning
|
|
|
|
import (
|
|
"encoding/csv"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/go-admin-team/go-admin-core/sdk/api"
|
|
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
|
|
"git.ilapage.cn/ila/yovision/Sense/server/app/sense/quota"
|
|
)
|
|
|
|
type API struct{ api.Api }
|
|
|
|
func (e *API) service(c *gin.Context) (*Service, error) {
|
|
service := &Service{}
|
|
if err := e.MakeContext(c).MakeOrm().MakeService(&service.Service).Errors; err != nil {
|
|
return nil, err
|
|
}
|
|
return service, nil
|
|
}
|
|
|
|
func (e *API) List(c *gin.Context) {
|
|
service, err := e.service(c)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
request := BatchPageRequest{}
|
|
if err = e.MakeContext(c).Bind(&request).Errors; err != nil {
|
|
e.Error(http.StatusBadRequest, err, "查询条件格式不正确")
|
|
return
|
|
}
|
|
list, count, err := service.ListBatches(&request)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
e.PageOK(list, int(count), request.GetPageIndex(), request.GetPageSize(), "查询成功")
|
|
}
|
|
|
|
func (e *API) Get(c *gin.Context) {
|
|
service, err := e.service(c)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
response, err := service.GetBatch(c.Param("id"))
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
e.OK(response, "查询成功")
|
|
}
|
|
|
|
func (e *API) Create(c *gin.Context) {
|
|
service, err := e.service(c)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
request := CreateBatchRequest{CreateBy: user.GetUserId(c)}
|
|
if err = bindStrictJSON(c, &request); err != nil {
|
|
e.Error(http.StatusBadRequest, err, "导入内容格式不正确")
|
|
return
|
|
}
|
|
response, err := service.CreateBatch(request)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
e.OK(response, "批次已导入并完成预校验")
|
|
}
|
|
|
|
func (e *API) Execute(c *gin.Context) { e.execute(c, false, "") }
|
|
func (e *API) RetryFailed(c *gin.Context) { e.execute(c, true, "") }
|
|
func (e *API) RetryItem(c *gin.Context) { e.execute(c, true, c.Param("itemId")) }
|
|
|
|
func (e *API) execute(c *gin.Context, retryFailed bool, itemID string) {
|
|
service, err := e.service(c)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
request := ExecuteRequest{UpdateBy: user.GetUserId(c)}
|
|
defer func() { clearCredentials(request.Credentials) }()
|
|
if err = bindStrictJSON(c, &request); err != nil {
|
|
e.Error(http.StatusBadRequest, err, "执行内容格式不正确")
|
|
return
|
|
}
|
|
response, err := service.Execute(c.Request.Context(), c.Param("id"), itemID, retryFailed, request)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
e.OK(response, "批量开通处理完成")
|
|
}
|
|
|
|
func (e *API) Export(c *gin.Context) {
|
|
service, err := e.service(c)
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
batch, err := service.GetBatch(c.Param("id"))
|
|
if err != nil {
|
|
e.writeError(err)
|
|
return
|
|
}
|
|
c.Header("Content-Type", "text/csv; charset=utf-8")
|
|
c.Header("Content-Disposition", "attachment; filename=provisioning-"+batch.ID+".csv")
|
|
c.Status(http.StatusOK)
|
|
writer := csv.NewWriter(c.Writer)
|
|
if err = writer.Write([]string{"line_number", "name", "location", "address", "status", "failure_code", "detail", "device_id"}); err != nil {
|
|
e.Logger.Error(err)
|
|
return
|
|
}
|
|
for _, item := range batch.Items {
|
|
if err = writer.Write([]string{strconv.Itoa(item.LineNumber), item.Name, item.Location, item.Address, item.Status, item.FailureCode, item.Detail, item.DeviceID}); err != nil {
|
|
e.Logger.Error(err)
|
|
return
|
|
}
|
|
}
|
|
writer.Flush()
|
|
if err = writer.Error(); err != nil {
|
|
e.Logger.Error(err)
|
|
}
|
|
}
|
|
|
|
func (e *API) writeError(err error) {
|
|
switch {
|
|
case errors.Is(err, ErrInvalidRequest):
|
|
e.Error(http.StatusBadRequest, err, err.Error())
|
|
case errors.Is(err, ErrBatchNotFound), errors.Is(err, ErrItemNotFound):
|
|
e.Error(http.StatusNotFound, err, err.Error())
|
|
case errors.Is(err, quota.ErrExceeded):
|
|
e.Error(http.StatusConflict, err, "当前配额已满,无法继续批量开通")
|
|
case errors.Is(err, quota.ErrUnavailable):
|
|
e.Error(http.StatusServiceUnavailable, err, "配额配置不可读取,已拒绝批量开通写入")
|
|
default:
|
|
e.Error(http.StatusInternalServerError, err, "批量开通操作失败")
|
|
}
|
|
}
|
|
|
|
func bindStrictJSON(c *gin.Context, target any) error {
|
|
if !strings.HasPrefix(strings.ToLower(strings.TrimSpace(c.GetHeader("Content-Type"))), "application/json") {
|
|
return errors.New("content type must be application/json")
|
|
}
|
|
decoder := json.NewDecoder(http.MaxBytesReader(c.Writer, c.Request.Body, 2<<20))
|
|
decoder.DisallowUnknownFields()
|
|
if err := decoder.Decode(target); err != nil {
|
|
return err
|
|
}
|
|
if err := decoder.Decode(&struct{}{}); !errors.Is(err, io.EOF) {
|
|
if err == nil {
|
|
return errors.New("request body must contain one JSON object")
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func clearCredentials(values []CredentialInput) {
|
|
for index := range values {
|
|
values[index].ONVIFUsername = ""
|
|
values[index].ONVIFPassword = ""
|
|
values[index].RTSPUsername = ""
|
|
values[index].RTSPPassword = ""
|
|
}
|
|
}
|