@@ -0,0 +1,74 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"data-terminal-cloud/internal/deviceauth"
|
||||
"data-terminal-cloud/internal/devicereset"
|
||||
"data-terminal-cloud/internal/idempotency"
|
||||
)
|
||||
|
||||
type DeviceFactoryResetService interface {
|
||||
Reset(context.Context, deviceauth.Identity, string, string, []byte, devicereset.Input) (devicereset.Response, bool, error)
|
||||
}
|
||||
|
||||
func DeviceFactoryResetHandler(service DeviceFactoryResetService) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Header().Set("Cache-Control", "no-store")
|
||||
writer.Header().Set("Pragma", "no-cache")
|
||||
identity, ok := deviceauth.FromContext(request.Context())
|
||||
if !ok {
|
||||
WriteError(writer, request, http.StatusUnauthorized, "DEVICE_AUTHENTICATION_FAILED", "设备身份验证失败")
|
||||
return
|
||||
}
|
||||
key := strings.TrimSpace(request.Header.Get("Idempotency-Key"))
|
||||
if len(key) < 16 || len(key) > 128 {
|
||||
WriteError(writer, request, http.StatusBadRequest, "VALIDATION_FAILED", "缺少有效的重复请求识别码")
|
||||
return
|
||||
}
|
||||
rawBody, err := io.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
WriteError(writer, request, http.StatusBadRequest, "INVALID_REQUEST_BODY", "请求正文无法读取")
|
||||
return
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(rawBody))
|
||||
decoder.DisallowUnknownFields()
|
||||
var input devicereset.Input
|
||||
if err := decoder.Decode(&input); err != nil || ensureJSONEOF(decoder) != nil || devicereset.Validate(input) != nil {
|
||||
WriteError(writer, request, http.StatusBadRequest, "VALIDATION_FAILED", "设备恢复出厂参数不正确")
|
||||
return
|
||||
}
|
||||
response, replayed, err := service.Reset(request.Context(), identity, key, RequestID(request.Context()), rawBody, input)
|
||||
if replayed {
|
||||
writer.Header().Set("Idempotency-Replayed", "true")
|
||||
}
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, devicereset.ErrPendingTranscripts):
|
||||
WriteError(writer, request, http.StatusConflict, "DEVICE_RESET_PENDING_TRANSCRIPTS", "设备仍有未上传的聊天记录")
|
||||
case errors.Is(err, devicereset.ErrFirmwareInProgress):
|
||||
WriteError(writer, request, http.StatusConflict, "DEVICE_RESET_FIRMWARE_IN_PROGRESS", "设备正在升级固件,暂时不能恢复出厂")
|
||||
case errors.Is(err, devicereset.ErrResetCounterConflict):
|
||||
WriteError(writer, request, http.StatusConflict, "DEVICE_RESET_COUNTER_CONFLICT", "设备重置计数器不是递增值")
|
||||
case errors.Is(err, devicereset.ErrStateConflict):
|
||||
WriteError(writer, request, http.StatusConflict, "DEVICE_RESET_STATE_CONFLICT", "当前设备状态不允许恢复出厂")
|
||||
case errors.Is(err, idempotency.ErrKeyConflict):
|
||||
WriteError(writer, request, http.StatusConflict, "IDEMPOTENCY_KEY_CONFLICT", "重复请求识别码已用于不同的请求")
|
||||
case errors.Is(err, idempotency.ErrInProgress):
|
||||
WriteAPIError(writer, request, http.StatusConflict, Error{Code: "IDEMPOTENCY_IN_PROGRESS", Message: "相同恢复出厂请求仍在处理中", Retryable: true})
|
||||
case errors.Is(err, devicereset.ErrInvalid):
|
||||
WriteError(writer, request, http.StatusBadRequest, "VALIDATION_FAILED", "设备恢复出厂参数不正确")
|
||||
default:
|
||||
WriteAPIError(writer, request, http.StatusServiceUnavailable, Error{Code: "DEVICE_RESET_FAILED", Message: "设备恢复出厂暂时失败", Retryable: true})
|
||||
}
|
||||
return
|
||||
}
|
||||
WriteJSON(writer, request, http.StatusOK, response)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user