Skip to content

Commit 19aeeaa

Browse files
authored
Merge pull request #169 from GitGuardian/feat/scan-create-incidents-location
Add optional location field to scan_and_create_incidents documents
2 parents 5aba2e5 + 341e3dd commit 19aeeaa

4 files changed

Lines changed: 65 additions & 6 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Added
2+
3+
- `scan_and_create_incidents`: documents now accept an optional `location` field containing an http/https URL identifying the origin of the document.

pygitguardian/client.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ def multi_content_scan(
545545

546546
def scan_and_create_incidents(
547547
self,
548-
documents: List[Dict[str, str]],
548+
documents: List[Dict[str, Any]],
549549
source_uuid: UUID,
550550
*,
551551
extra_headers: Optional[Dict[str, str]] = None,
@@ -557,8 +557,8 @@ def scan_and_create_incidents(
557557
character.
558558
559559
:param documents: List of dictionaries containing the keys document
560-
and, optionally, filename.
561-
example: [{"document":"example content","filename":"intro.py"}]
560+
and, optionally, filename and location.
561+
example: [{"document":"example content","filename":"intro.py","location":{"url":"https://example.com"}}]
562562
:param source_uuid: the source UUID that will be used to identify the custom source, for which
563563
incidents will be created
564564
:param extra_headers: additional headers to add to the request
@@ -587,8 +587,9 @@ def scan_and_create_incidents(
587587
"source_uuid": source_uuid,
588588
"documents": [
589589
{
590-
"filename": document["filename"],
591-
"document": document["document"],
590+
key: document[key]
591+
for key in ("filename", "document", "location")
592+
if document.get(key) is not None
592593
}
593594
for document in request_obj
594595
],

pygitguardian/models.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,14 @@
3737
)
3838

3939

40+
class DocumentLocationSchema(BaseSchema):
41+
url = fields.Url(required=True, schemes={"http", "https"})
42+
43+
4044
class DocumentSchema(BaseSchema):
4145
filename = fields.String(validate=validate.Length(max=256), allow_none=True)
4246
document = fields.String(required=True)
47+
location = fields.Nested(DocumentLocationSchema, allow_none=True, load_default=None)
4348

4449
@staticmethod
4550
def validate_size(document: Dict[str, Any], maximum_size: int) -> None:
@@ -84,15 +89,24 @@ class Document(Base):
8489
Attributes:
8590
filename (optional,str): filename for filename evaluation
8691
document (str): text content
92+
location (optional,dict): origin of the document, with a required http/https url key
8793
"""
8894

8995
SCHEMA = DocumentSchema()
9096

91-
def __init__(self, document: str, filename: Optional[str] = None, **kwargs: Any):
97+
def __init__(
98+
self,
99+
document: str,
100+
filename: Optional[str] = None,
101+
location: Optional[Dict[str, str]] = None,
102+
**kwargs: Any,
103+
):
92104
super().__init__()
93105
self.document = document
94106
if filename:
95107
self.filename = filename
108+
if location:
109+
self.location = location
96110

97111
def __repr__(self) -> str:
98112
return f"filename:{self.filename}, document:{self.document}"

tests/test_client.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,47 @@ def test_scan_and_create_incidents_payload_structure(client: GGClient):
698698
assert mock_response.call_count == 1
699699

700700

701+
@responses.activate
702+
def test_scan_and_create_incidents_payload_with_location(client: GGClient):
703+
"""
704+
GIVEN a ggclient
705+
WHEN calling scan_and_create_incidents with a document location
706+
THEN the location is included in the payload
707+
"""
708+
709+
location = {"url": "https://wiki.example.com/my-config-page"}
710+
documents = [{"filename": FILENAME, "document": DOCUMENT, "location": location}]
711+
source_uuid = "123e4567-e89b-12d3-a456-426614174000"
712+
713+
expected_payload = {
714+
"documents": [
715+
{
716+
"document": DOCUMENT,
717+
"filename": FILENAME,
718+
"location": location,
719+
}
720+
],
721+
"source_uuid": source_uuid,
722+
}
723+
724+
mock_response = responses.post(
725+
url=client._url_from_endpoint("scan/create-incidents", "v1"),
726+
status=200,
727+
match=[matchers.json_params_matcher(expected_payload)],
728+
json=[
729+
{
730+
"policy_break_count": 0,
731+
"policies": ["pol"],
732+
"policy_breaks": [],
733+
}
734+
],
735+
)
736+
737+
client.scan_and_create_incidents(documents, source_uuid)
738+
739+
assert mock_response.call_count == 1
740+
741+
701742
@responses.activate
702743
def test_retrieve_secret_incident(client: GGClient):
703744
"""

0 commit comments

Comments
 (0)