Files

67 lines
3.0 KiB
Go
Raw Permalink Normal View History

package onboarding
import (
"context"
"data-terminal-cloud/internal/devicebinding"
"data-terminal-cloud/internal/devicereset"
"data-terminal-cloud/internal/idempotency"
"errors"
)
// This is a DEVREQ1 adapter for the existing reset transaction, not an owner
// authorization shortcut. The account must release ownership before reset.
func (s *Service) DeviceResetState(ctx context.Context, d Device) (map[string]any, error) {
if !deviceAllowed(d) || d.Mode != "physical_confirm" {
return nil, errAccess
}
if err := devicebinding.RequireUnboundForReset(ctx, s.pool, d.ID); err != nil {
return nil, resetError(err)
}
var counter int64
if err := s.pool.QueryRow(ctx, `SELECT factory_reset_counter FROM device WHERE id=$1 AND tenant_id=$2`, d.ID, d.TenantID).Scan(&counter); err != nil {
return nil, err
}
return map[string]any{"reset_counter": counter, "binding_generation": d.Generation}, nil
}
func (s *Service) DeviceFactoryReset(ctx context.Context, d Device, requestID string, raw []byte, in devicereset.Input) (devicereset.Response, error) {
if !deviceAllowed(d) || d.Mode != "physical_confirm" {
return devicereset.Response{}, errAccess
}
service, err := devicereset.NewService(s.pool, idempotency.NewExecutor(s.pool), s.audit)
if err != nil {
return devicereset.Response{}, err
}
// The reset ID lives in the signed and persisted body. HTTP requests may use
// fresh nonce/request IDs while retrying an uncertain result after a reboot.
response, _, err := service.Reset(ctx, controlIdentity(d), "factory-reset:"+in.ResetID, requestID, raw, in)
return response, resetError(err)
}
func resetError(err error) error {
switch {
case err == nil:
return nil
case errors.Is(err, devicebinding.ErrConfirmationRequired):
return fail(409, "DEVICE_RESET_AUTHORIZATION_REQUIRED", "请先由当前账号授权解绑,再恢复出厂")
case errors.Is(err, devicereset.ErrCallInProgress):
return fail(409, "DEVICE_RESET_CALL_IN_PROGRESS", "设备正在通话,请结束后再恢复出厂")
case errors.Is(err, devicereset.ErrFirmwareInProgress):
return fail(409, "DEVICE_RESET_FIRMWARE_IN_PROGRESS", "设备正在升级,暂时不能恢复出厂")
case errors.Is(err, devicereset.ErrPendingTranscripts):
return fail(409, "DEVICE_RESET_PENDING_TRANSCRIPTS", "设备仍有未上传的聊天记录")
case errors.Is(err, devicereset.ErrResetCounterConflict):
return fail(409, "DEVICE_RESET_COUNTER_CONFLICT", "设备重置计数器已变化")
case errors.Is(err, devicereset.ErrStateConflict):
return fail(409, "DEVICE_RESET_STATE_CONFLICT", "设备状态已变化,请重新确认")
case errors.Is(err, devicereset.ErrInvalid):
return fail(400, "INVALID_RESET_REQUEST", "设备重置参数不正确")
case errors.Is(err, idempotency.ErrKeyConflict):
return fail(409, "IDEMPOTENCY_KEY_CONFLICT", "同一重置请求不能修改内容")
case errors.Is(err, idempotency.ErrInProgress):
return fail(409, "IDEMPOTENCY_IN_PROGRESS", "设备重置请求仍在处理中")
default:
return err
}
}