Skip to content

Commit 7ada0c4

Browse files
models/tests: Transition validators and add MIME type support
- Changed `BeforeValidator` to `AfterValidator` in `_internal.py` to improve validation reliability and sequencing. - Added support for `application/pem-certificate-chain` MIME type for PEM credentials to widen compatibility with certificate formats. - Updated tests to ensure validation handles `pem-certificate-chain` MIME type for both certificates and private keys. - Introduced `test_sign_payload_accepts_logo_tuple_sequence` to verify the logo field supports tuple sequences in payloads. Assisted-by: Codex
1 parent 6426620 commit 7ada0c4

2 files changed

Lines changed: 72 additions & 5 deletions

File tree

src/pdfrest/models/_internal.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,7 @@ class PdfSignPayload(BaseModel):
10651065
serialization_alias="pfx_credential_id",
10661066
),
10671067
BeforeValidator(_ensure_list),
1068-
BeforeValidator(
1068+
AfterValidator(
10691069
_allowed_mime_types(
10701070
"application/x-pkcs12",
10711071
"application/pkcs12",
@@ -1085,7 +1085,7 @@ class PdfSignPayload(BaseModel):
10851085
serialization_alias="pfx_passphrase_id",
10861086
),
10871087
BeforeValidator(_ensure_list),
1088-
BeforeValidator(
1088+
AfterValidator(
10891089
_allowed_mime_types(
10901090
"text/plain",
10911091
"application/octet-stream",
@@ -1104,13 +1104,14 @@ class PdfSignPayload(BaseModel):
11041104
serialization_alias="certificate_id",
11051105
),
11061106
BeforeValidator(_ensure_list),
1107-
BeforeValidator(
1107+
AfterValidator(
11081108
# DER cert/key uploads are frequently tagged as x509-ca-cert (or octet-stream
11091109
# in some environments), so we intentionally keep this allowlist broad.
11101110
_allowed_mime_types(
11111111
"application/pkix-cert",
11121112
"application/x-x509-ca-cert",
11131113
"application/x-pem-file",
1114+
"application/pem-certificate-chain",
11141115
"application/octet-stream",
11151116
error_msg="Certificate must be a .pem or .der file",
11161117
)
@@ -1127,13 +1128,14 @@ class PdfSignPayload(BaseModel):
11271128
serialization_alias="private_key_id",
11281129
),
11291130
BeforeValidator(_ensure_list),
1130-
BeforeValidator(
1131+
AfterValidator(
11311132
# Keep parity with provider/browser MIME detection for DER private keys.
11321133
_allowed_mime_types(
11331134
"application/pkix-cert",
11341135
"application/x-x509-ca-cert",
11351136
"application/pkcs8",
11361137
"application/x-pem-file",
1138+
"application/pem-certificate-chain",
11371139
"application/octet-stream",
11381140
error_msg="Private key must be a .pem or .der file",
11391141
)
@@ -1150,7 +1152,7 @@ class PdfSignPayload(BaseModel):
11501152
serialization_alias="logo_id",
11511153
),
11521154
BeforeValidator(_ensure_list),
1153-
BeforeValidator(
1155+
AfterValidator(
11541156
_allowed_mime_types(
11551157
"image/jpeg",
11561158
"image/png",

tests/test_sign_pdf.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,68 @@ def test_sign_payload_accepts_x509_ca_cert_mime_for_der_credentials() -> None:
444444
assert payload.private_key is not None
445445
assert payload.certificate[0].type == "application/x-x509-ca-cert"
446446
assert payload.private_key[0].type == "application/x-x509-ca-cert"
447+
448+
449+
def test_sign_payload_accepts_pem_certificate_chain_mime_for_pem_credentials() -> None:
450+
input_pdf = make_pdf_file(str(PdfRestFileID.generate()))
451+
certificate_file = PdfRestFile.model_validate(
452+
build_file_info_payload(
453+
str(PdfRestFileID.generate()),
454+
"certificate.pem",
455+
"application/pem-certificate-chain",
456+
)
457+
)
458+
private_key_file = PdfRestFile.model_validate(
459+
build_file_info_payload(
460+
str(PdfRestFileID.generate()),
461+
"private_key.pem",
462+
"application/pem-certificate-chain",
463+
)
464+
)
465+
466+
payload = PdfSignPayload.model_validate(
467+
{
468+
"files": [input_pdf],
469+
"signature_configuration": {
470+
"type": "new",
471+
"name": "sig",
472+
"location": make_signature_location(),
473+
},
474+
"credentials": {
475+
"certificate": certificate_file,
476+
"private_key": private_key_file,
477+
},
478+
}
479+
)
480+
481+
assert payload.certificate is not None
482+
assert payload.private_key is not None
483+
assert payload.certificate[0].type == "application/pem-certificate-chain"
484+
assert payload.private_key[0].type == "application/pem-certificate-chain"
485+
486+
487+
def test_sign_payload_accepts_logo_tuple_sequence() -> None:
488+
input_pdf = make_pdf_file(str(PdfRestFileID.generate()))
489+
certificate_file = make_certificate_file(str(PdfRestFileID.generate()))
490+
private_key_file = make_private_key_file(str(PdfRestFileID.generate()))
491+
logo_file = make_logo_file(str(PdfRestFileID.generate()))
492+
493+
payload = PdfSignPayload.model_validate(
494+
{
495+
"files": [input_pdf],
496+
"signature_configuration": {
497+
"type": "new",
498+
"name": "sig",
499+
"location": make_signature_location(),
500+
},
501+
"credentials": {
502+
"certificate": certificate_file,
503+
"private_key": private_key_file,
504+
},
505+
"logo": (logo_file,),
506+
}
507+
)
508+
509+
assert payload.logo is not None
510+
assert len(payload.logo) == 1
511+
assert payload.logo[0].id == logo_file.id

0 commit comments

Comments
 (0)