89 lines
2.9 KiB
Go
89 lines
2.9 KiB
Go
|
|
package httpapi
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"io"
|
||
|
|
"log"
|
||
|
|
"net/http"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
|
||
|
|
"git.apinb.com/ops/license/internal/dashboard"
|
||
|
|
"git.apinb.com/ops/license/internal/issuance"
|
||
|
|
"git.apinb.com/ops/license/internal/subject"
|
||
|
|
)
|
||
|
|
|
||
|
|
type pagination struct {
|
||
|
|
Page int `json:"page"`
|
||
|
|
PageSize int `json:"page_size"`
|
||
|
|
Total int64 `json:"total"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeData(c *gin.Context, status int, data any) {
|
||
|
|
c.JSON(status, gin.H{"data": data})
|
||
|
|
}
|
||
|
|
|
||
|
|
func writePage(c *gin.Context, data any, page, pageSize int, total int64) {
|
||
|
|
c.JSON(http.StatusOK, gin.H{
|
||
|
|
"data": data,
|
||
|
|
"pagination": pagination{
|
||
|
|
Page: page,
|
||
|
|
PageSize: pageSize,
|
||
|
|
Total: total,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeBadRequest(c *gin.Context) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": "bad_request", "message": "请求格式不正确"})
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeError(c *gin.Context, err error) {
|
||
|
|
status := http.StatusInternalServerError
|
||
|
|
code := "internal_error"
|
||
|
|
message := "服务器内部错误"
|
||
|
|
|
||
|
|
switch {
|
||
|
|
case errors.Is(err, subject.ErrNotFound):
|
||
|
|
status, code, message = http.StatusNotFound, "subject_not_found", "授权对象不存在"
|
||
|
|
case errors.Is(err, issuance.ErrNotFound):
|
||
|
|
status, code, message = http.StatusNotFound, "licence_not_found", "签发记录不存在"
|
||
|
|
case errors.Is(err, subject.ErrDuplicate):
|
||
|
|
status, code, message = http.StatusConflict, "subject_duplicate", "授权对象已存在"
|
||
|
|
case errors.Is(err, subject.ErrHasLicences):
|
||
|
|
status, code, message = http.StatusConflict, "subject_has_licences", "该授权对象已有签发记录,不能修改或删除"
|
||
|
|
case errors.Is(err, subject.ErrInvalidInput):
|
||
|
|
status, code, message = http.StatusUnprocessableEntity, "invalid_subject", "授权对象字段不合法"
|
||
|
|
case errors.Is(err, issuance.ErrInvalidDates):
|
||
|
|
status, code, message = http.StatusUnprocessableEntity, "invalid_licence_dates", "许可证日期不合法"
|
||
|
|
case errors.Is(err, issuance.ErrInvalidQuota):
|
||
|
|
status, code, message = http.StatusUnprocessableEntity, "invalid_licence_quota", "许可证配额不合法"
|
||
|
|
case errors.Is(err, issuance.ErrPreviousMismatch):
|
||
|
|
status, code, message = http.StatusUnprocessableEntity, "previous_licence_mismatch", "续期来源与授权对象不匹配"
|
||
|
|
case errors.Is(err, issuance.ErrInvalidInput), errors.Is(err, dashboard.ErrInvalidInput):
|
||
|
|
status, code, message = http.StatusUnprocessableEntity, "invalid_issuance", "签发参数不合法"
|
||
|
|
}
|
||
|
|
|
||
|
|
if status == http.StatusInternalServerError {
|
||
|
|
log.Printf("HTTP internal error: %v", err)
|
||
|
|
}
|
||
|
|
c.JSON(status, gin.H{"code": code, "message": message})
|
||
|
|
}
|
||
|
|
|
||
|
|
func decodeJSON(c *gin.Context, destination any) error {
|
||
|
|
decoder := json.NewDecoder(c.Request.Body)
|
||
|
|
decoder.DisallowUnknownFields()
|
||
|
|
if err := decoder.Decode(destination); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
var trailing any
|
||
|
|
if err := decoder.Decode(&trailing); !errors.Is(err, io.EOF) {
|
||
|
|
if err == nil {
|
||
|
|
return errors.New("JSON 包含多个顶层值")
|
||
|
|
}
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|