Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/partnership cb function #46

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions pyas2lib/as2.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,26 +513,41 @@ def _decompress_data(self, payload):

return False, payload

def parse(self, raw_content, find_org_cb, find_partner_cb, find_message_cb=None):
def parse(
self,
raw_content,
find_org_cb=None,
find_partner_cb=None,
find_message_cb=None,
find_org_partner_cb=None,
):
"""Function parses the RAW AS2 message; decrypts, verifies and
decompresses it and extracts the payload.

:param raw_content:
A byte string of the received HTTP headers followed by the body.

:param find_org_cb:
A callback the returns an Organization object if exists. The
as2-to header value is passed as an argument to it.
A conditional callback the returns an Organization object if exists. The
as2-to header value is passed as an argument to it. Must be provided
when find_partner_cb is provided and find_org_partner_cb is None

:param find_partner_cb:
A callback the returns an Partner object if exists. The
as2-from header value is passed as an argument to it.
An conditional callback the returns an Partner object if exists. The
as2-from header value is passed as an argument to it. Must be provided
when find_org_cb is provided and find_org_partner_cb is None.

:param find_message_cb:
An optional callback the returns an Message object if exists in
order to check for duplicates. The message id and partner id is
passed as arguments to it.

:param find_org_partner_cb:
A conditional callback that return Organization object and
Partner object if exist. The as2-to and as2-from header value
are passed as an argument to it. Must be provided
when find_org_cb and find_org_partner_cb is None.

:return:
A three element tuple containing (status, (exception, traceback)
, mdn). The status is a string indicating the status of the
Expand All @@ -541,6 +556,18 @@ def parse(self, raw_content, find_org_cb, find_partner_cb, find_message_cb=None)
the partner did not request it.
"""

# Validate passed arguments
if not any(
[
find_org_cb and find_partner_cb and not find_org_partner_cb,
find_org_partner_cb and not find_partner_cb and not find_org_cb,
]
):
raise TypeError(
"Incorrect arguments passed: either find_org_cb and find_partner_cb "
"or only find_org_partner_cb must be passed."
)

# Parse the raw MIME message and extract its content and headers
status, detailed_status, exception, mdn = "processed", None, (None, None), None
self.payload = parse_mime(raw_content)
Expand All @@ -554,12 +581,17 @@ def parse(self, raw_content, find_org_cb, find_partner_cb, find_message_cb=None)
try:
# Get the organization and partner for this transmission
org_id = unquote_as2name(as2_headers["as2-to"])
self.receiver = find_org_cb(org_id)
partner_id = unquote_as2name(as2_headers["as2-from"])

if find_org_partner_cb:
self.receiver, self.sender = find_org_partner_cb(org_id, partner_id)
else:
self.receiver = find_org_cb(org_id)
self.sender = find_partner_cb(partner_id)

if not self.receiver:
raise PartnerNotFound(f"Unknown AS2 organization with id {org_id}")

partner_id = unquote_as2name(as2_headers["as2-from"])
self.sender = find_partner_cb(partner_id)
if not self.sender:
raise PartnerNotFound(f"Unknown AS2 partner with id {partner_id}")

Expand Down
27 changes: 27 additions & 0 deletions pyas2lib/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,35 @@ def test_encrypted_signed_compressed_message(self):
self.assertEqual(out_message.mic, in_message.mic)
self.assertEqual(self.test_data.splitlines(), in_message.content.splitlines())

def test_encrypted_signed_message_partnership(self):
"""Test Encrypted Signed Uncompressed Message with Partnership"""

# Build an As2 message to be transmitted to partner
self.partner.sign = True
self.partner.encrypt = True
out_message = as2.Message(self.org, self.partner)
out_message.build(self.test_data)
raw_out_message = out_message.headers_str + b"\r\n" + out_message.content

# Parse the generated AS2 message as the partner
in_message = as2.Message()
status, _, _ = in_message.parse(
raw_out_message,
find_org_partner_cb=self.find_org_partner,
)

# Compare the mic contents of the input and output messages
self.assertEqual(status, "processed")
self.assertTrue(in_message.signed)
self.assertTrue(in_message.encrypted)
self.assertEqual(out_message.mic, in_message.mic)
self.assertEqual(self.test_data.splitlines(), in_message.content.splitlines())

def find_org(self, as2_id):
return self.org

def find_partner(self, as2_id):
return self.partner

def find_org_partner(self, as2_org, as2_partner):
return self.org, self.partner