136 lines
3.8 KiB
Go
136 lines
3.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"vctp/internal/secrets"
|
|
)
|
|
|
|
func newEncryptTestHandler() (*Handler, *secrets.Secrets) {
|
|
logger := newTestLogger()
|
|
key := []byte("0123456789abcdef0123456789abcdef")
|
|
secret := secrets.New(logger, key)
|
|
return &Handler{
|
|
Logger: logger,
|
|
Secret: secret,
|
|
}, secret
|
|
}
|
|
|
|
func decodeResponse(t *testing.T, rr *httptest.ResponseRecorder) map[string]string {
|
|
t.Helper()
|
|
var resp map[string]string
|
|
if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil {
|
|
t.Fatalf("failed to decode response body %q: %v", rr.Body.String(), err)
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func TestEncryptDataRejectsWrongMethod(t *testing.T) {
|
|
h, _ := newEncryptTestHandler()
|
|
req := httptest.NewRequest(http.MethodGet, "/api/encrypt", nil)
|
|
rr := httptest.NewRecorder()
|
|
|
|
h.EncryptData(rr, req)
|
|
|
|
if rr.Code != http.StatusMethodNotAllowed {
|
|
t.Fatalf("expected %d, got %d", http.StatusMethodNotAllowed, rr.Code)
|
|
}
|
|
resp := decodeResponse(t, rr)
|
|
if resp["status"] != "ERROR" {
|
|
t.Fatalf("expected status ERROR, got %#v", resp)
|
|
}
|
|
}
|
|
|
|
func TestEncryptDataRejectsInvalidJSON(t *testing.T) {
|
|
h, _ := newEncryptTestHandler()
|
|
req := httptest.NewRequest(http.MethodPost, "/api/encrypt", strings.NewReader("{"))
|
|
rr := httptest.NewRecorder()
|
|
|
|
h.EncryptData(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
resp := decodeResponse(t, rr)
|
|
if resp["status"] != "ERROR" {
|
|
t.Fatalf("expected status ERROR, got %#v", resp)
|
|
}
|
|
}
|
|
|
|
func TestEncryptDataAcceptsPlaintextField(t *testing.T) {
|
|
h, secret := newEncryptTestHandler()
|
|
req := httptest.NewRequest(http.MethodPost, "/api/encrypt", strings.NewReader(`{"plaintext":"super-secret"}`))
|
|
rr := httptest.NewRecorder()
|
|
|
|
h.EncryptData(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("expected %d, got %d", http.StatusOK, rr.Code)
|
|
}
|
|
resp := decodeResponse(t, rr)
|
|
if resp["status"] != "OK" {
|
|
t.Fatalf("expected status OK, got %#v", resp)
|
|
}
|
|
if resp["ciphertext"] == "" || resp["prefixed"] == "" {
|
|
t.Fatalf("expected ciphertext+prefixed fields, got %#v", resp)
|
|
}
|
|
if !strings.HasPrefix(resp["prefixed"], encryptedValuePrefixV1) {
|
|
t.Fatalf("expected prefixed value with %q, got %q", encryptedValuePrefixV1, resp["prefixed"])
|
|
}
|
|
if !strings.EqualFold(resp["message"], resp["ciphertext"]) {
|
|
t.Fatalf("expected message to mirror ciphertext, got %#v", resp)
|
|
}
|
|
plain, err := secret.Decrypt(resp["ciphertext"])
|
|
if err != nil {
|
|
t.Fatalf("unable to decrypt ciphertext response: %v", err)
|
|
}
|
|
if string(plain) != "super-secret" {
|
|
t.Fatalf("unexpected decrypted value %q", string(plain))
|
|
}
|
|
}
|
|
|
|
func TestEncryptDataAcceptsLegacyValueField(t *testing.T) {
|
|
h, secret := newEncryptTestHandler()
|
|
body := bytes.NewBufferString(`{"value":"legacy-input"}`)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/encrypt", body)
|
|
rr := httptest.NewRecorder()
|
|
|
|
h.EncryptData(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("expected %d, got %d", http.StatusOK, rr.Code)
|
|
}
|
|
resp := decodeResponse(t, rr)
|
|
cipherText := resp["ciphertext"]
|
|
if cipherText == "" {
|
|
t.Fatalf("expected ciphertext in response, got %#v", resp)
|
|
}
|
|
plain, err := secret.Decrypt(cipherText)
|
|
if err != nil {
|
|
t.Fatalf("unable to decrypt ciphertext response: %v", err)
|
|
}
|
|
if string(plain) != "legacy-input" {
|
|
t.Fatalf("unexpected decrypted value %q", string(plain))
|
|
}
|
|
}
|
|
|
|
func TestEncryptDataRejectsMissingPayloadValue(t *testing.T) {
|
|
h, _ := newEncryptTestHandler()
|
|
req := httptest.NewRequest(http.MethodPost, "/api/encrypt", strings.NewReader(`{}`))
|
|
rr := httptest.NewRecorder()
|
|
|
|
h.EncryptData(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
resp := decodeResponse(t, rr)
|
|
if resp["status"] != "ERROR" {
|
|
t.Fatalf("expected status ERROR, got %#v", resp)
|
|
}
|
|
}
|