Skip to content

Commit 255dadf

Browse files
committed
Add policyUUIDs to text scan endpoint
Also rename deprecated config field internally to policy
1 parent 62333c0 commit 255dadf

File tree

2 files changed

+124
-7
lines changed

2 files changed

+124
-7
lines changed

nightfall/api.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,51 @@ def scan_text(self, texts: List[str], detection_rules: Optional[List[DetectionRu
8484
if not detection_rule_uuids and not detection_rules:
8585
raise NightfallUserError("at least one of detection_rule_uuids or detection_rules required", 40001)
8686

87-
config = {}
87+
policy = {}
8888
if detection_rule_uuids:
89-
config["detectionRuleUUIDs"] = detection_rule_uuids
89+
policy["detectionRuleUUIDs"] = detection_rule_uuids
9090
if detection_rules:
91-
config["detectionRules"] = [d.as_dict() for d in detection_rules]
91+
policy["detectionRules"] = [d.as_dict() for d in detection_rules]
9292
if context_bytes:
93-
config["contextBytes"] = context_bytes
93+
policy["contextBytes"] = context_bytes
9494
if default_redaction_config:
95-
config["defaultRedactionConfig"] = default_redaction_config.as_dict()
95+
policy["defaultRedactionConfig"] = default_redaction_config.as_dict()
9696
request_body = {
9797
"payload": texts,
98-
"config": config
98+
"policy": policy
99+
}
100+
response = self._scan_text_v3(request_body)
101+
102+
_validate_response(response, 200)
103+
104+
parsed_response = response.json()
105+
106+
findings = [[Finding.from_dict(f) for f in item_findings] for item_findings in parsed_response["findings"]]
107+
return findings, parsed_response.get("redactedPayload")
108+
109+
110+
def scan_text_with_policies(self, texts: List[str], policy_uuids: List[str] = None) ->\
111+
Tuple[List[List[Finding]], List[str]]:
112+
"""Scan text with Nightfall.
113+
114+
This method takes the specified config and then makes
115+
one or more requests to the Nightfall API for scanning.
116+
The maximum supported length of policy_uuids is currently 1.
117+
118+
:param texts: List of strings to scan.
119+
:type texts: List[str]
120+
:param policy_uuids: List of policy UUIDs to scan each text with.
121+
These can be created in the Nightfall UI.
122+
:type policy_uuids: List[str] or None
123+
:returns: list of findings, list of redacted input texts
124+
"""
125+
126+
if not policy_uuids:
127+
raise NightfallUserError("policy_uuids may not be empty", 40001)
128+
129+
request_body = {
130+
"payload": texts,
131+
"policyUUIDs": policy_uuids
99132
}
100133
response = self._scan_text_v3(request_body)
101134

tests/test_api.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def test_scan_text():
224224
[
225225
"4916-6734-7572-5015 is my credit card number, 489-36-8350 ssn"
226226
],
227-
"config":
227+
"policy":
228228
{
229229
"detectionRules":
230230
[
@@ -332,6 +332,90 @@ def test_scan_text():
332332
assert len(redactions) == 1
333333
assert redactions[0] == "491👀-👀👀👀👀-👀👀👀👀-👀👀👀👀 is my credit card number, [REDACTED] ssn"
334334

335+
@responses.activate
336+
def test_scan_text_with_policies():
337+
nightfall = Nightfall("NF-NOT_REAL")
338+
responses.add(responses.POST, 'https://api.nightfall.ai/v3/scan',
339+
json={
340+
"findings":
341+
[
342+
[
343+
{
344+
"finding": "4916-6734-7572-5015",
345+
"redactedFinding": "491👀-👀👀👀👀-👀👀👀👀-👀👀👀👀",
346+
"afterContext": " is my cre",
347+
"detector":
348+
{
349+
"name": "Credit Card Number",
350+
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
351+
},
352+
"confidence": "VERY_LIKELY",
353+
"location":
354+
{
355+
"byteRange":
356+
{
357+
"start": 0,
358+
"end": 19
359+
},
360+
"codepointRange":
361+
{
362+
"start": 0,
363+
"end": 19
364+
}
365+
},
366+
"redactedLocation":
367+
{
368+
"byteRange":
369+
{
370+
"start": 0,
371+
"end": 19
372+
},
373+
"codepointRange":
374+
{
375+
"start": 0,
376+
"end": 19
377+
}
378+
},
379+
"matchedDetectionRuleUUIDs":
380+
["0d8efd7b-b87a-478b-984e-9cf5534a46bc"],
381+
"matchedDetectionRules":
382+
[]
383+
},
384+
]
385+
],
386+
"redactedPayload":
387+
[
388+
"491👀-👀👀👀👀-👀👀👀👀-👀👀👀👀 is my credit card number, [REDACTED] ssn"
389+
]
390+
})
391+
result, redactions = nightfall.scan_text_with_policies(
392+
["4916-6734-7572-5015 is my credit card number, 489-36-8350 ssn"],
393+
["2388f83f-cd31-4689-971b-4ee94f798281"]
394+
)
395+
396+
assert len(responses.calls) == 1
397+
assert responses.calls[0].request.headers.get("Authorization") == "Bearer NF-NOT_REAL"
398+
assert json.loads(responses.calls[0].request.body) == {
399+
"payload":
400+
[
401+
"4916-6734-7572-5015 is my credit card number, 489-36-8350 ssn"
402+
],
403+
"policyUUIDs": ["2388f83f-cd31-4689-971b-4ee94f798281"]
404+
}
405+
406+
assert len(result) == 1
407+
assert len(result[0]) == 1
408+
assert result[0][0] == Finding(
409+
"4916-6734-7572-5015",
410+
'491👀-👀👀👀👀-👀👀👀👀-👀👀👀👀',
411+
None, " is my cre",
412+
"Credit Card Number",
413+
result[0][0].detector_uuid,
414+
Confidence.VERY_LIKELY,
415+
Range(0, 19), Range(0, 19), "",
416+
["0d8efd7b-b87a-478b-984e-9cf5534a46bc"], [])
417+
assert len(redactions) == 1
418+
assert redactions[0] == "491👀-👀👀👀👀-👀👀👀👀-👀👀👀👀 is my credit card number, [REDACTED] ssn"
335419

336420
def test_scan_text_no_detection_rules():
337421
nightfall = Nightfall("NF-NOT_REAL")

0 commit comments

Comments
 (0)