Skip to content

Commit

Permalink
consent/access/erasure query param filters on connection type endpoint (
Browse files Browse the repository at this point in the history
  • Loading branch information
adamsachs authored Apr 7, 2023
2 parents 1c88fd9 + ce72b98 commit 487cae3
Show file tree
Hide file tree
Showing 7 changed files with 623 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The types of changes are:
* Added the datamap UI to make it open source [#2988](https://github.com/ethyca/fides/pull/2988)
* Introduced a `FixedLayout` component (from the datamap UI) for pages that need to be a fixed height and scroll within [#2992](https://github.com/ethyca/fides/pull/2992)
* Added preliminary privacy notice page [#2995](https://github.com/ethyca/fides/pull/2995)
* Query params on connection type endpoint to filter by supported action type [#2996](https://github.com/ethyca/fides/pull/2996)

### Changed
* Set `privacyDeclarationDeprecatedFields` flags to false and set `userCannotModify` to true [2987](https://github.com/ethyca/fides/pull/2987)
Expand Down
33 changes: 33 additions & 0 deletions docs/fides/docs/development/postman/Fides.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -4239,6 +4239,39 @@
},
"response": []
},
{
"name": "Get available connectors - consent",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{client_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{host}}/connection_type?consent=true",
"host": [
"{{host}}"
],
"path": [
"connection_type"
],
"query": [
{
"key": "consent",
"value": "true"
}
]
}
},
"response": []
},
{
"name": "Get connection secrets schema",
"request": {
Expand Down
26 changes: 24 additions & 2 deletions src/fides/api/ops/api/v1/endpoints/connection_type_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
V1_URL_PREFIX,
)
from fides.api.ops.common_exceptions import NoSuchConnectionTypeSecretSchemaError
from fides.api.ops.models.policy import ActionType
from fides.api.ops.schemas.connection_configuration.connection_config import (
ConnectionSystemTypeMap,
SystemType,
Expand All @@ -36,11 +37,32 @@ def get_all_connection_types(
params: Params = Depends(),
search: Optional[str] = None,
system_type: Optional[SystemType] = None,
consent: Optional[bool] = None,
access: Optional[bool] = None,
erasure: Optional[bool] = None,
) -> AbstractPage[ConnectionSystemTypeMap]:
"""Returns a list of connection options in Fidesops - includes only database and saas options here."""
"""
Returns a list of connection options in Fides - includes only database and saas options here.
Query params for types of requests supported - `consent`, `access` and `erasure` - act as filters.
If set to `true`, only connections that support the specified type of request will be returned.
If no filters are specified, then no filtering is performed.
When applied together, the filters act as a union: result sets are additive.
"""
action_types = set()
# special-case when no action type filters are provided
if consent is None and access is None and erasure is None:
action_types = {ActionType.access, ActionType.erasure, ActionType.consent}
else:
if access:
action_types.add(ActionType.access)
if erasure:
action_types.add(ActionType.erasure)
if consent:
action_types.add(ActionType.consent)

return paginate(
get_connection_types(search, system_type),
get_connection_types(search, system_type, action_types),
params,
)

Expand Down
4 changes: 4 additions & 0 deletions src/fides/api/ops/models/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class ActionType(str, EnumType):
update = "update"


# action types we actively support in policies/requests
SUPPORTED_ACTION_TYPES = {ActionType.access, ActionType.consent, ActionType.erasure}


class DrpAction(EnumType):
"""
Enum to hold valid DRP actions. For more details, see:
Expand Down
76 changes: 71 additions & 5 deletions src/fides/api/ops/util/connection_type.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from __future__ import annotations

from typing import Any
from typing import Any, Set

import yaml

from fides.api.ops.common_exceptions import NoSuchConnectionTypeSecretSchemaError
from fides.api.ops.models.connectionconfig import ConnectionType
from fides.api.ops.models.policy import SUPPORTED_ACTION_TYPES, ActionType
from fides.api.ops.schemas.connection_configuration import (
SaaSSchemaFactory,
secrets_schemas,
Expand Down Expand Up @@ -70,14 +73,65 @@ def connection_type_secret_schema(*, connection_type: str) -> dict[str, Any]:


def get_connection_types(
search: str | None = None, system_type: SystemType | None = None
search: str | None = None,
system_type: SystemType | None = None,
action_types: Set[ActionType] = SUPPORTED_ACTION_TYPES,
) -> list[ConnectionSystemTypeMap]:
def is_match(elem: str) -> bool:
"""If a search query param was included, is it a substring of an available connector type?"""
return search.lower() in elem.lower() if search else True

def saas_request_type_filter(connection_type: str) -> bool:
"""
If any of the request type filters are set to true,
ensure the given saas connector supports requests of at least one of those types.
"""
if SUPPORTED_ACTION_TYPES == action_types:
# if none of our filters are enabled, pass quickly to avoid unnecessary overhead
return True

template = ConnectorRegistry.get_connector_template(connection_type)
if template is None: # shouldn't happen, but we can be safe
return False

saas_config = SaaSConfig(**yaml.safe_load(template.config).get("saas_config"))
has_access = bool(
next(
(
request.read
for request in [
endpoint.requests for endpoint in saas_config.endpoints
]
),
None,
)
)
has_erasure = (
bool(
next(
(
request.update or request.delete
for request in [
endpoint.requests for endpoint in saas_config.endpoints
]
),
None,
)
)
or saas_config.data_protection_request
)
has_consent = saas_config.consent_requests

return bool(
(ActionType.consent in action_types and has_consent)
or (ActionType.access in action_types and has_access)
or (ActionType.erasure in action_types and has_erasure)
)

connection_system_types: list[ConnectionSystemTypeMap] = []
if system_type == SystemType.database or system_type is None:
if (system_type == SystemType.database or system_type is None) and (
ActionType.access in action_types or ActionType.erasure in action_types
):
database_types: list[str] = sorted(
[
conn_type.value
Expand Down Expand Up @@ -110,7 +164,7 @@ def is_match(elem: str) -> bool:
[
saas_type
for saas_type in ConnectorRegistry.connector_types()
if is_match(saas_type)
if is_match(saas_type) and saas_request_type_filter(saas_type)
]
)

Expand All @@ -131,7 +185,9 @@ def is_match(elem: str) -> bool:
)
)

if system_type == SystemType.manual or system_type is None:
if (
system_type == SystemType.manual or system_type is None
) and ActionType.access in action_types:
manual_types: list[str] = sorted(
[
manual_type.value
Expand Down Expand Up @@ -159,6 +215,16 @@ def is_match(elem: str) -> bool:
if email_type
in ERASURE_EMAIL_CONNECTOR_TYPES + CONSENT_EMAIL_CONNECTOR_TYPES
and is_match(email_type.value)
and ( # include consent or erasure connectors if requested, respectively
(
ActionType.consent in action_types
and email_type in CONSENT_EMAIL_CONNECTOR_TYPES
)
or (
ActionType.erasure in action_types
and email_type in ERASURE_EMAIL_CONNECTOR_TYPES
)
)
]
)
connection_system_types.extend(
Expand Down
Loading

0 comments on commit 487cae3

Please sign in to comment.