fix(t234): log OCR result in diagnostics

This commit is contained in:
QiuSW
2026-07-29 11:32:10 +08:00
parent 38c090b3e7
commit 4cf2151d75
5 changed files with 109 additions and 11 deletions
@@ -154,9 +154,16 @@ func (manager *SessionManager) EnsureAuthenticated(ctx context.Context) error {
return domain.ErrFreightSourceProtocol
}
code, err := manager.recognizer.Recognize(ctx, image.Content, image.ContentType)
if err != nil || !validCaptchaCode(code) {
if err != nil {
manager.logOCRResultFailed()
return domain.ErrFreightSourceOCRInvalid
}
code = strings.TrimSpace(code)
if !validCaptchaCode(code) {
manager.logOCRResultInvalid()
return domain.ErrFreightSourceOCRInvalid
}
manager.logOCRResult(code)
_, err = manager.Login(ctx, status.CaptchaTicket, code)
if errors.Is(err, ErrLoginRejected) {
return domain.ErrFreightSourceLoginRejected
@@ -479,6 +486,30 @@ func (manager *SessionManager) logERPTransportFailure(request *http.Request) {
)
}
func (manager *SessionManager) logOCRResult(value string) {
if !manager.diagnosticsOn {
return
}
manager.diagnosticLog(
"erp_ocr_result value=" + strconv.Quote(value) +
" length=" + strconv.Itoa(len(value)),
)
}
func (manager *SessionManager) logOCRResultInvalid() {
if !manager.diagnosticsOn {
return
}
manager.diagnosticLog("erp_ocr_result class=invalid")
}
func (manager *SessionManager) logOCRResultFailed() {
if !manager.diagnosticsOn {
return
}
manager.diagnosticLog("erp_ocr_result class=failed")
}
func (manager *SessionManager) logERPResponsePreview(
request *http.Request,
response *http.Response,
@@ -252,6 +252,7 @@ func TestSessionManagerDiagnosticLogsAreRedacted(t *testing.T) {
"erp_request method=GET path=/api/p/code1",
"erp_response method=GET path=/api/p/code1 status=200",
"body=omitted_non_json",
`erp_ocr_result value="1234" length=4`,
"erp_request method=POST path=/am/auth/login",
"erp_response method=POST path=/am/auth/login status=200",
`"status":false`,
@@ -270,6 +271,67 @@ func TestSessionManagerDiagnosticLogsAreRedacted(t *testing.T) {
}
}
func TestSessionManagerDiagnosticLogsHideInvalidOCRResults(t *testing.T) {
testCases := []struct {
name string
recognizer *fixedRecognizer
wantEvent string
secret string
}{
{
name: "invalid text",
recognizer: &fixedRecognizer{code: "private\nOCR output"},
wantEvent: "erp_ocr_result class=invalid",
secret: "private",
},
{
name: "recognizer failure",
recognizer: &fixedRecognizer{err: errors.New("private OCR response")},
wantEvent: "erp_ocr_result class=failed",
secret: "private",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(
writer http.ResponseWriter,
request *http.Request,
) {
if request.URL.Path != CaptchaPath {
writer.WriteHeader(http.StatusNotFound)
return
}
writer.Header().Set("Content-Type", "image/png")
_, _ = writer.Write([]byte("private-captcha-image"))
}))
defer server.Close()
var events []string
manager, err := NewSessionManager(SessionConfig{
BaseURL: server.URL,
Username: "test-user",
Password: "test-password",
Timeout: time.Second,
AllowInsecureHTTP: true,
CaptchaRecognizer: testCase.recognizer,
DiagnosticLogger: func(event string) {
events = append(events, event)
},
})
if err != nil {
t.Fatalf("NewSessionManager() error = %v", err)
}
if err := manager.EnsureAuthenticated(context.Background()); !errors.Is(err, domain.ErrFreightSourceOCRInvalid) {
t.Fatalf("EnsureAuthenticated() error = %v", err)
}
actual := strings.Join(events, "\n")
if !strings.Contains(actual, testCase.wantEvent) || strings.Contains(actual, testCase.secret) ||
strings.Contains(actual, "private-captcha-image") || strings.Contains(actual, "test-password") {
t.Fatalf("diagnostic log = %s", actual)
}
})
}
}
type fixedRecognizer struct {
code string
err error