lib/api/stash/stash_client/pdf_metadata_contract_test.go

389 lines
11 KiB
Go

package stash_client_test
import (
"context"
"encoding/json"
"net/http"
"net/url"
"os"
"path/filepath"
"reflect"
"regexp"
"runtime"
"strings"
"testing"
"time"
openapiruntime "github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"code.tnxs.net/vernonkeenan/lib/api/stash/stash_client/stash_pdf"
"code.tnxs.net/vernonkeenan/lib/api/stash/stash_models"
)
type pdfMetadataCaptureTransport struct {
operation *openapiruntime.ClientOperation
}
func (transport *pdfMetadataCaptureTransport) Submit(
operation *openapiruntime.ClientOperation,
) (any, error) {
return transport.SubmitContext(context.Background(), operation)
}
func (transport *pdfMetadataCaptureTransport) SubmitContext(
_ context.Context,
operation *openapiruntime.ClientOperation,
) (any, error) {
transport.operation = operation
switch operation.ID {
case "listPdfs":
return stash_pdf.NewListPdfsOK(), nil
case "getPdfs":
return stash_pdf.NewGetPdfsOK(), nil
default:
panic("unexpected generated Stash PDF operation: " + operation.ID)
}
}
type pdfMetadataRequest struct {
headers http.Header
query url.Values
path map[string]string
timeout time.Duration
}
func newPDFMetadataRequest() *pdfMetadataRequest {
return &pdfMetadataRequest{
headers: make(http.Header),
query: make(url.Values),
path: make(map[string]string),
}
}
func (request *pdfMetadataRequest) SetHeaderParam(name string, values ...string) error {
request.headers.Del(name)
for _, value := range values {
request.headers.Add(name, value)
}
return nil
}
func (request *pdfMetadataRequest) GetHeaderParams() http.Header {
return request.headers
}
func (request *pdfMetadataRequest) SetQueryParam(name string, values ...string) error {
request.query[name] = append([]string(nil), values...)
return nil
}
func (request *pdfMetadataRequest) SetFormParam(string, ...string) error {
return nil
}
func (request *pdfMetadataRequest) SetPathParam(name, value string) error {
request.path[name] = value
return nil
}
func (request *pdfMetadataRequest) GetQueryParams() url.Values {
return request.query
}
func (request *pdfMetadataRequest) SetFileParam(string, ...openapiruntime.NamedReadCloser) error {
return nil
}
func (request *pdfMetadataRequest) SetBodyParam(any) error {
return nil
}
func (request *pdfMetadataRequest) SetTimeout(timeout time.Duration) error {
request.timeout = timeout
return nil
}
func (request *pdfMetadataRequest) GetMethod() string {
return ""
}
func (request *pdfMetadataRequest) GetPath() string {
return ""
}
func (request *pdfMetadataRequest) GetBody() []byte {
return nil
}
func (request *pdfMetadataRequest) GetBodyParam() any {
return nil
}
func (request *pdfMetadataRequest) GetFileParam() map[string][]openapiruntime.NamedReadCloser {
return nil
}
func compoundPDFMetadataAuth(apiKey, session string) openapiruntime.ClientAuthInfoWriter {
return openapiruntime.ClientAuthInfoWriterFunc(
func(request openapiruntime.ClientRequest, _ strfmt.Registry) error {
if err := request.SetHeaderParam("X-API-Key", apiKey); err != nil {
return err
}
return request.SetHeaderParam("Cookie", "kvSession="+session)
},
)
}
func TestGeneratedPDFMetadataOperationContract(t *testing.T) {
auth := compoundPDFMetadataAuth("fixture-api-key", "fixture-session")
tests := []struct {
name string
wantID string
wantMethod string
wantPath string
call func(openapiruntime.ContextualTransport) error
}{
{
name: "list",
wantID: "listPdfs",
wantMethod: http.MethodGet,
wantPath: "/pdfs",
call: func(transport openapiruntime.ContextualTransport) error {
_, err := stash_pdf.New(transport, strfmt.Default).ListPdfs(
stash_pdf.NewListPdfsParams(), auth,
)
return err
},
},
{
name: "get",
wantID: "getPdfs",
wantMethod: http.MethodGet,
wantPath: "/pdfs/{pdfId}",
call: func(transport openapiruntime.ContextualTransport) error {
_, err := stash_pdf.New(transport, strfmt.Default).GetPdfs(
stash_pdf.NewGetPdfsParams().WithPdfID("pdf-fixture"), auth,
)
return err
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
transport := &pdfMetadataCaptureTransport{}
if err := test.call(transport); err != nil {
t.Fatalf("generated client operation failed: %v", err)
}
if transport.operation == nil {
t.Fatal("generated client did not submit an operation")
}
if transport.operation.ID != test.wantID {
t.Errorf("operation ID = %q, want %q", transport.operation.ID, test.wantID)
}
if transport.operation.Method != test.wantMethod {
t.Errorf("method = %q, want %q", transport.operation.Method, test.wantMethod)
}
if transport.operation.PathPattern != test.wantPath {
t.Errorf("path = %q, want %q", transport.operation.PathPattern, test.wantPath)
}
if transport.operation.AuthInfo == nil {
t.Fatal("generated operation discarded compound auth writer")
}
request := newPDFMetadataRequest()
if err := transport.operation.AuthInfo.AuthenticateRequest(request, strfmt.Default); err != nil {
t.Fatalf("authenticate request: %v", err)
}
if got := request.headers.Get("X-API-Key"); got != "fixture-api-key" {
t.Errorf("X-API-Key = %q, want fixture value", got)
}
if got := request.headers.Get("Cookie"); got != "kvSession=fixture-session" {
t.Errorf("Cookie = %q, want only kvSession", got)
}
if len(request.headers) != 2 {
t.Errorf("compound auth wrote unexpected headers: %v", request.headers)
}
})
}
}
func TestGeneratedPDFMetadataParameters(t *testing.T) {
limit, offset := int64(100), int64(10000)
listRequest := newPDFMetadataRequest()
if err := stash_pdf.NewListPdfsParams().
WithLimit(&limit).
WithOffset(&offset).
WriteToRequest(listRequest, strfmt.Default); err != nil {
t.Fatalf("write list params: %v", err)
}
if got := listRequest.query.Get("limit"); got != "100" {
t.Errorf("limit = %q, want 100", got)
}
if got := listRequest.query.Get("offset"); got != "10000" {
t.Errorf("offset = %q, want 10000", got)
}
getRequest := newPDFMetadataRequest()
if err := stash_pdf.NewGetPdfsParams().
WithPdfID("pdf-fixture").
WriteToRequest(getRequest, strfmt.Default); err != nil {
t.Fatalf("write get params: %v", err)
}
if got := getRequest.path["pdfId"]; got != "pdf-fixture" {
t.Errorf("pdfId = %q, want fixture value", got)
}
}
func TestPDFMetadataModelIsSanitized(t *testing.T) {
modelType := reflect.TypeOf(stash_models.Document{})
wantFields := map[string]string{
"Filename": "string",
"ID": "string",
"Title": "string",
"URI": "string",
}
if modelType.NumField() != len(wantFields) {
t.Fatalf("Document has %d fields, want %d", modelType.NumField(), len(wantFields))
}
for fieldName, wantType := range wantFields {
field, exists := modelType.FieldByName(fieldName)
if !exists {
t.Errorf("Document is missing %s", fieldName)
continue
}
if got := field.Type.String(); got != wantType {
t.Errorf("Document.%s type = %s, want %s", fieldName, got, wantType)
}
}
encoded, err := json.Marshal(stash_models.Document{
ID: "pdf-fixture",
Filename: "fixture.pdf",
Title: "Fixture",
URI: "/fixture.pdf",
})
if err != nil {
t.Fatalf("marshal Document: %v", err)
}
for _, forbidden := range []string{
"HTML", "PDF", "ParentID", "SagaType", "OwnerID", "CreatedByID", "TenantID",
} {
if strings.Contains(string(encoded), forbidden) {
t.Errorf("sanitized metadata encoded forbidden field %q: %s", forbidden, encoded)
}
}
}
func TestGeneratedPDFMetadataSurfaceIsReadOnly(t *testing.T) {
clientType := reflect.TypeOf((*stash_pdf.ClientService)(nil)).Elem()
for index := 0; index < clientType.NumMethod(); index++ {
method := clientType.Method(index).Name
for _, forbiddenPrefix := range []string{
"Post", "Put", "Patch", "Delete", "Create", "Render", "Update",
} {
if strings.HasPrefix(method, forbiddenPrefix) {
t.Errorf("Stash PDF metadata client exposes mutation method %s", method)
}
}
}
repoRoot := pdfMetadataRepoRoot(t)
removed := []string{
filepath.Join(repoRoot, "api", "stash", "stash_client", "stash_pdf", "post_pdfs_parameters.go"),
filepath.Join(repoRoot, "api", "stash", "stash_client", "stash_pdf", "post_pdfs_responses.go"),
filepath.Join(repoRoot, "api", "stash", "stash_models", "new_p_d_f.go"),
filepath.Join(repoRoot, "api", "stash", "stash_models", "p_d_f_request.go"),
filepath.Join(repoRoot, "api", "stash", "stash_models", "request_meta.go"),
}
for _, path := range removed {
if _, err := os.Stat(path); !os.IsNotExist(err) {
t.Errorf("legacy mutation artifact still exists: %s", path)
}
}
}
func TestPDFMetadataProjectionPinsCompoundAuthAndBounds(t *testing.T) {
specText := readPDFMetadataProjection(t)
required := []string{
"x-provider-pr: \"vernonkeenan/stash#16\"",
"x-provider-head: \"b2f5b4a6ae5ff507dfdc86bb7b9ee5a9bb924131\"",
"operationId: listPdfs",
"operationId: getPdfs",
"maximum: 100",
"maximum: 10000",
" - ApiKeyAuth: []\n kvSessionCookie: []",
}
for _, fragment := range required {
if !strings.Contains(specText, fragment) {
t.Errorf("client projection is missing %q", fragment)
}
}
for _, forbidden := range []string{
"\n post:", "\n put:", "\n patch:", "\n delete:",
"HTML:", "PDF:", "OwnerID:", "ParentID:", "SagaType:",
} {
if strings.Contains(specText, forbidden) {
t.Errorf("client projection exposes forbidden contract fragment %q", forbidden)
}
}
}
func TestGeneratedPDFMetadataSurfaceHasNoExternalBypassOrSecrets(t *testing.T) {
repoRoot := pdfMetadataRepoRoot(t)
target := filepath.Join(repoRoot, "api", "stash")
credentialLiteral := regexp.MustCompile(
`(?i)(api[_-]?key|password|secret)\s*[:=]\s*["'][^"']+["']`,
)
err := filepath.WalkDir(target, func(path string, entry os.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if entry.IsDir() || !strings.HasSuffix(path, ".go") ||
strings.HasSuffix(path, "_test.go") {
return nil
}
content, err := os.ReadFile(path)
if err != nil {
return err
}
lower := strings.ToLower(string(content))
for _, forbidden := range []string{
"salesforce", "sf-gate", "go-force", "private key-----",
"postpdf", "putpdf", "deletepdf", "renderpdf",
} {
if strings.Contains(lower, forbidden) {
t.Errorf("%s contains forbidden boundary %q", path, forbidden)
}
}
if credentialLiteral.Match(content) {
t.Errorf("%s contains a credential-shaped literal", path)
}
return nil
})
if err != nil {
t.Fatalf("scan generated Stash target: %v", err)
}
}
func pdfMetadataRepoRoot(t *testing.T) string {
t.Helper()
_, sourceFile, _, ok := runtime.Caller(0)
if !ok {
t.Fatal("resolve test source path")
}
return filepath.Clean(filepath.Join(filepath.Dir(sourceFile), "..", "..", ".."))
}
func readPDFMetadataProjection(t *testing.T) string {
t.Helper()
content, err := os.ReadFile(filepath.Join(
pdfMetadataRepoRoot(t), "swagger", "client", "stash-pdf-metadata.yaml",
))
if err != nil {
t.Fatalf("read Stash PDF metadata projection: %v", err)
}
return string(content)
}