Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Search for PrivacyRequest based on hashed identity [#765] #847

Merged
merged 28 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The types of changes are:
* Adds endpoint to get available connectors (database and saas) [#768](https://github.com/ethyca/fidesops/pull/768)
* Adds endpoint to get the secrets required for different connectors [#795](https://github.com/ethyca/fidesops/pull/795)
* Store provided identity data in the privacy request table [#743](https://github.com/ethyca/fidesops/pull/834)
* Adds exact match identity search to the privacy request status endpoint [#765](https://github.com/ethyca/fidesops/pull/847/)

### Developer Experience
* Replace user authentication routes with fideslib routes [#811](https://github.com/ethyca/fidesops/pull/811)
Expand Down
20 changes: 19 additions & 1 deletion src/fidesops/api/v1/endpoints/privacy_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import logging
from collections import defaultdict
from datetime import datetime
from typing import Any, Callable, DefaultDict, Dict, List, Optional, Union
from typing import Any, Callable, DefaultDict, Dict, List, Optional, Set, Union

from fastapi import APIRouter, Body, Depends, HTTPException, Security
from fastapi.params import Query as FastAPIQuery
Expand All @@ -15,6 +15,7 @@
from fideslib.models.audit_log import AuditLog, AuditLogAction
from fideslib.models.client import ClientDetail
from pydantic import conlist
from sqlalchemy import column
from sqlalchemy.orm import Query, Session
from starlette.responses import StreamingResponse
from starlette.status import (
Expand Down Expand Up @@ -59,6 +60,7 @@
ExecutionLog,
PrivacyRequest,
PrivacyRequestStatus,
ProvidedIdentity,
)
from fidesops.schemas.dataset import CollectionAddressResponse, DryRunDatasetResponse
from fidesops.schemas.external_https import PrivacyRequestResumeFormat
Expand Down Expand Up @@ -292,8 +294,10 @@ def execution_logs_by_dataset_name(


def _filter_privacy_request_queryset(
db: Session,
query: Query,
request_id: Optional[str] = None,
identity: Optional[str] = None,
status: Optional[List[PrivacyRequestStatus]] = None,
created_lt: Optional[datetime] = None,
created_gt: Optional[datetime] = None,
Expand Down Expand Up @@ -337,6 +341,17 @@ def _filter_privacy_request_queryset(
detail=f"Value specified for {field_name}_lt: {end} must be after {field_name}_gt: {start}.",
)

if identity:
hashed_identity = ProvidedIdentity.hash_value(value=identity)
identities: Set[str] = {
identity[0]
for identity in ProvidedIdentity.filter(
db=db,
conditions=(ProvidedIdentity.hashed_value == hashed_identity),
).values(column("privacy_request_id"))
}
query = query.filter(PrivacyRequest.id.in_(identities))

# Further restrict all PrivacyRequests by query params
if request_id:
query = query.filter(PrivacyRequest.id.ilike(f"{request_id}%"))
Expand Down Expand Up @@ -432,6 +447,7 @@ def get_request_status(
db: Session = Depends(deps.get_db),
params: Params = Depends(),
request_id: Optional[str] = None,
identity: Optional[str] = None,
status: Optional[List[PrivacyRequestStatus]] = FastAPIQuery(
default=None
), # type:ignore
Expand All @@ -457,8 +473,10 @@ def get_request_status(
logger.info(f"Finding all request statuses with pagination params {params}")
query = db.query(PrivacyRequest)
query = _filter_privacy_request_queryset(
db,
query,
request_id,
identity,
status,
created_lt,
created_gt,
Expand Down
26 changes: 26 additions & 0 deletions tests/api/v1/endpoints/test_privacy_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
from fidesops.schemas.dataset import DryRunDatasetResponse
from fidesops.schemas.masking.masking_secrets import SecretType
from fidesops.schemas.policy import PolicyResponse
from fidesops.schemas.redis_cache import PrivacyRequestIdentity
from fidesops.util.cache import (
get_encryption_cache_key,
get_identity_cache_key,
Expand Down Expand Up @@ -731,6 +732,31 @@ def test_filter_privacy_requests_by_internal_id(
assert len(resp["items"]) == 1
assert resp["items"][0]["id"] == privacy_request.id

def test_filter_privacy_requests_by_identity_exact(
self,
db,
api_client,
url,
generate_auth_header,
privacy_request,
):
TEST_EMAIL = "[email protected]"
privacy_request.persist_identity(
db=db,
identity=PrivacyRequestIdentity(
email=TEST_EMAIL,
),
)
auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ])
response = api_client.get(
url + f"?identity={TEST_EMAIL}",
headers=auth_header,
)
assert 200 == response.status_code
resp = response.json()
assert len(resp["items"]) == 1
assert resp["items"][0]["id"] == privacy_request.id

def test_filter_privacy_requests_by_external_id(
self,
db,
Expand Down