Skip to content

Commit 3d49406

Browse files
authored
Adding ability to resubmit DSRs (#5658)
1 parent 8e151f5 commit 3d49406

40 files changed

+1673
-964
lines changed

CHANGELOG.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o
2121

2222
## [Unreleased](https://github.com/ethyca/fides/compare/2.53.0...main)
2323

24+
### Added
25+
- Migration to add the `data_uses` column to `stagedresource` table, prereqs for Data Catalog work in Fidesplus [#5600](https://github.com/ethyca/fides/pull/5600/) https://github.com/ethyca/fides/labels/db-migration
26+
- Added a new endpoint to fully resubmit any errored privacy requests [#5658](https://github.com/ethyca/fides/pull/5658) https://github.com/ethyca/fides/labels/db-migration
27+
2428
### Changed
2529
- Updated UI colors to new brand. Update logo, homepage cards. [#5668](https://github.com/ethyca/fides/pull/5668)
2630
- Privacy request status tags colors have been updated [#5699](https://github.com/ethyca/fides/pull/5699)
@@ -32,9 +36,6 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o
3236
### Developer Experience
3337
- Migrated radio buttons and groups to Ant Design [#5681](https://github.com/ethyca/fides/pull/5681)
3438

35-
### Added
36-
- Migration to add the `data_uses` column to `stagedresource` table, prereqs for Data Catalog work in Fidesplus [#5600](https://github.com/ethyca/fides/pull/5600/) https://github.com/ethyca/fides/labels/db-migration
37-
3839
### Fixed
3940
- Updating mongodb connectors so it can support usernames and password with URL encoded characters [#5682](https://github.com/ethyca/fides/pull/5682)
4041
- After creating a new system, the url is now updated correctly to the new system edit page [#5701](https://github.com/ethyca/fides/pull/5701)

clients/admin-ui/src/features/privacy-requests/RequestDetails.tsx

+1-7
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,7 @@ const RequestDetails = ({ subjectRequest }: RequestDetailsProps) => {
3333

3434
return (
3535
<Flex direction="column" gap={4}>
36-
<Heading
37-
color="gray.900"
38-
fontSize="lg"
39-
fontWeight="semibold"
40-
mt={4}
41-
mb={4}
42-
>
36+
<Heading color="gray.900" fontSize="lg" fontWeight="semibold">
4337
Request details
4438
</Heading>
4539
<Divider />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""update privacy request relationships
2+
3+
Revision ID: 1088e8353890
4+
Revises: d9237a0c0d5a
5+
Create Date: 2024-12-26 22:38:37.905571
6+
7+
"""
8+
9+
from alembic import op
10+
11+
# revision identifiers, used by Alembic.
12+
revision = "1088e8353890"
13+
down_revision = "d9237a0c0d5a"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade():
19+
op.drop_constraint(
20+
"custom_privacy_request_field_privacy_request_id_fkey",
21+
"custom_privacy_request_field",
22+
type_="foreignkey",
23+
)
24+
op.create_foreign_key(
25+
"custom_privacy_request_field_privacy_request_id_fkey",
26+
"custom_privacy_request_field",
27+
"privacyrequest",
28+
["privacy_request_id"],
29+
["id"],
30+
onupdate="CASCADE",
31+
ondelete="CASCADE",
32+
)
33+
op.drop_constraint(
34+
"providedidentity_privacy_request_id_fkey",
35+
"providedidentity",
36+
type_="foreignkey",
37+
)
38+
op.create_foreign_key(
39+
"providedidentity_privacy_request_id_fkey",
40+
"providedidentity",
41+
"privacyrequest",
42+
["privacy_request_id"],
43+
["id"],
44+
onupdate="CASCADE",
45+
ondelete="CASCADE",
46+
)
47+
op.drop_constraint(
48+
"privacyrequesterror_privacy_request_id_fkey",
49+
"privacyrequesterror",
50+
type_="foreignkey",
51+
)
52+
op.create_foreign_key(
53+
"privacyrequesterror_privacy_request_id_fkey",
54+
"privacyrequesterror",
55+
"privacyrequest",
56+
["privacy_request_id"],
57+
["id"],
58+
onupdate="CASCADE",
59+
ondelete="CASCADE",
60+
)
61+
62+
63+
def downgrade():
64+
op.drop_constraint(
65+
"providedidentity_privacy_request_id_fkey",
66+
"providedidentity",
67+
type_="foreignkey",
68+
)
69+
op.create_foreign_key(
70+
"providedidentity_privacy_request_id_fkey",
71+
"providedidentity",
72+
"privacyrequest",
73+
["privacy_request_id"],
74+
["id"],
75+
)
76+
op.drop_constraint(
77+
"custom_privacy_request_field_privacy_request_id_fkey",
78+
"custom_privacy_request_field",
79+
type_="foreignkey",
80+
)
81+
op.create_foreign_key(
82+
"custom_privacy_request_field_privacy_request_id_fkey",
83+
"custom_privacy_request_field",
84+
"privacyrequest",
85+
["privacy_request_id"],
86+
["id"],
87+
)
88+
op.drop_constraint(
89+
"privacyrequesterror_privacy_request_id_fkey",
90+
"privacyrequesterror",
91+
type_="foreignkey",
92+
)
93+
op.create_foreign_key(
94+
"privacyrequesterror_privacy_request_id_fkey",
95+
"privacyrequesterror",
96+
"privacyrequest",
97+
["privacy_request_id"],
98+
["id"],
99+
)

src/fides/api/api/deps.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
from fastapi import Depends
55
from sqlalchemy.orm import Session
66

7-
from fides.api.common_exceptions import FunctionalityNotConfigured
7+
from fides.api.common_exceptions import RedisNotConfigured
88
from fides.api.db.session import get_db_engine, get_db_session
99
from fides.api.util.cache import get_cache as get_redis_connection
1010
from fides.config import CONFIG, FidesConfig
1111
from fides.config import get_config as get_app_config
1212
from fides.config.config_proxy import ConfigProxy
13+
from fides.service.messaging.messaging_service import MessagingService
14+
from fides.service.privacy_request.privacy_request_service import PrivacyRequestService
1315

1416
_engine = None
1517

@@ -60,9 +62,25 @@ def get_config_proxy(db: Session = Depends(get_db)) -> ConfigProxy:
6062

6163

6264
def get_cache() -> Generator:
63-
"""Return a connection to our redis cache"""
65+
"""Return a connection to our Redis cache"""
6466
if not CONFIG.redis.enabled:
65-
raise FunctionalityNotConfigured(
66-
"Application redis cache required, but it is currently disabled! Please update your application configuration to enable integration with a redis cache."
67+
raise RedisNotConfigured(
68+
"Application redis cache required, but it is currently disabled! Please update your application configuration to enable integration with a Redis cache."
6769
)
6870
yield get_redis_connection()
71+
72+
73+
def get_messaging_service(
74+
db: Session = Depends(get_db),
75+
config: FidesConfig = Depends(get_config),
76+
config_proxy: ConfigProxy = Depends(get_config_proxy),
77+
) -> MessagingService:
78+
return MessagingService(db, config, config_proxy)
79+
80+
81+
def get_privacy_request_service(
82+
db: Session = Depends(get_db),
83+
config_proxy: ConfigProxy = Depends(get_config_proxy),
84+
messaging_service: MessagingService = Depends(get_messaging_service),
85+
) -> PrivacyRequestService:
86+
return PrivacyRequestService(db, config_proxy, messaging_service)

src/fides/api/api/v1/endpoints/consent_request_endpoints.py

+36-46
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from datetime import datetime
4-
from typing import Dict, List, Optional, Set, Tuple, Union
4+
from typing import List, Optional, Set, Tuple, Union
55

66
from fastapi import Depends, HTTPException, Security
77
from fastapi_pagination import Page, Params
@@ -19,17 +19,12 @@
1919
HTTP_403_FORBIDDEN,
2020
HTTP_404_NOT_FOUND,
2121
HTTP_422_UNPROCESSABLE_ENTITY,
22-
HTTP_500_INTERNAL_SERVER_ERROR,
2322
)
2423

25-
from fides.api.api.deps import get_config_proxy, get_db
26-
from fides.api.api.v1.endpoints.privacy_request_endpoints import (
27-
create_privacy_request_func,
28-
)
24+
from fides.api.api.deps import get_config_proxy, get_db, get_messaging_service
2925
from fides.api.common_exceptions import (
30-
FunctionalityNotConfigured,
3126
IdentityVerificationException,
32-
MessageDispatchException,
27+
RedisNotConfigured,
3328
)
3429
from fides.api.db.seed import DEFAULT_CONSENT_POLICY
3530
from fides.api.models.messaging import get_messaging_method
@@ -41,7 +36,7 @@
4136
)
4237
from fides.api.models.property import Property
4338
from fides.api.oauth.utils import verify_oauth_client
44-
from fides.api.schemas.messaging.messaging import MessagingActionType, MessagingMethod
39+
from fides.api.schemas.messaging.messaging import MessagingMethod
4540
from fides.api.schemas.privacy_request import BulkPostPrivacyRequests
4641
from fides.api.schemas.privacy_request import Consent as ConsentSchema
4742
from fides.api.schemas.privacy_request import (
@@ -55,8 +50,6 @@
5550
VerificationCode,
5651
)
5752
from fides.api.schemas.redis_cache import Identity
58-
from fides.api.service._verification import send_verification_code_to_user
59-
from fides.api.service.messaging.message_dispatch_service import message_send_enabled
6053
from fides.api.util.api_router import APIRouter
6154
from fides.api.util.consent_util import (
6255
get_or_create_fides_user_device_id_provided_identity,
@@ -73,6 +66,8 @@
7366
)
7467
from fides.config import CONFIG
7568
from fides.config.config_proxy import ConfigProxy
69+
from fides.service.messaging.messaging_service import MessagingService
70+
from fides.service.privacy_request.privacy_request_service import PrivacyRequestService
7671

7772
router = APIRouter(tags=["Consent"], prefix=V1_URL_PREFIX)
7873

@@ -183,12 +178,13 @@ def create_consent_request(
183178
*,
184179
db: Session = Depends(get_db),
185180
config_proxy: ConfigProxy = Depends(get_config_proxy),
181+
messaging_service: MessagingService = Depends(get_messaging_service),
186182
data: ConsentRequestCreate,
187183
) -> ConsentRequestResponse:
188184
"""Creates a verification code for the user to verify access to manage consent preferences."""
189185
if not CONFIG.redis.enabled:
190-
raise FunctionalityNotConfigured(
191-
"Application redis cache required, but it is currently disabled! Please update your application configuration to enable integration with a redis cache."
186+
raise RedisNotConfigured(
187+
"Application Redis cache required, but it is currently disabled! Please update your application configuration to enable integration with a Redis cache."
192188
)
193189
# TODO: (PROD-2142)- pass in property id here
194190
if data.property_id:
@@ -228,25 +224,12 @@ def create_consent_request(
228224
consent_request.persist_custom_privacy_request_fields(
229225
db=db, custom_privacy_request_fields=data.custom_privacy_request_fields
230226
)
231-
if message_send_enabled(
232-
db,
233-
data.property_id,
234-
MessagingActionType.SUBJECT_IDENTITY_VERIFICATION,
235-
not config_proxy.execution.disable_consent_identity_verification,
236-
):
237-
try:
238-
send_verification_code_to_user(
239-
db, consent_request, data.identity, data.property_id
240-
)
241-
except MessageDispatchException as exc:
242-
logger.error("Error sending the verification code message: {}", str(exc))
243-
raise HTTPException(
244-
status_code=HTTP_500_INTERNAL_SERVER_ERROR,
245-
detail=f"Error sending the verification code message: {str(exc)}",
246-
)
227+
228+
messaging_service.send_verification_code(
229+
consent_request, data.identity, data.property_id
230+
)
247231

248232
return ConsentRequestResponse(
249-
identity=identity,
250233
consent_request_id=consent_request.id,
251234
)
252235

@@ -407,8 +390,8 @@ def queue_privacy_request_to_propagate_consent_old_workflow(
407390
]
408391

409392
# Restrict consent preferences to just those that are executable
410-
executable_consent_preferences: List[Dict] = [
411-
pref.model_dump(mode="json")
393+
executable_consent_preferences: List[ConsentSchema] = [
394+
pref
412395
for pref in consent_preferences.consent or []
413396
if pref.data_use in executable_data_uses
414397
]
@@ -422,20 +405,27 @@ def queue_privacy_request_to_propagate_consent_old_workflow(
422405
return None
423406

424407
logger.info("Executable consent options: {}", executable_data_uses)
425-
privacy_request_results: BulkPostPrivacyRequests = create_privacy_request_func(
426-
db=db,
427-
config_proxy=ConfigProxy(db),
428-
data=[
429-
PrivacyRequestCreate(
430-
identity=identity,
431-
policy_key=policy,
432-
consent_preferences=executable_consent_preferences,
433-
consent_request_id=consent_request.id,
434-
custom_privacy_request_fields=consent_request.get_persisted_custom_privacy_request_fields(),
435-
source=consent_request.source,
436-
)
437-
],
438-
authenticated=True,
408+
409+
# It's a bit weird to initialize the privacy request service here,
410+
# but this logic is slated for deprecation so it's not worth doing a larger refactor
411+
privacy_request_service = PrivacyRequestService(
412+
db, ConfigProxy(db), MessagingService(db, CONFIG, ConfigProxy(db))
413+
)
414+
415+
privacy_request_results: BulkPostPrivacyRequests = (
416+
privacy_request_service.create_bulk_privacy_requests(
417+
[
418+
PrivacyRequestCreate(
419+
identity=identity,
420+
policy_key=policy,
421+
consent_preferences=executable_consent_preferences,
422+
consent_request_id=consent_request.id,
423+
custom_privacy_request_fields=consent_request.get_persisted_custom_privacy_request_fields(),
424+
source=consent_request.source,
425+
)
426+
],
427+
authenticated=True,
428+
)
439429
)
440430

441431
if privacy_request_results.failed or not privacy_request_results.succeeded:

src/fides/api/api/v1/endpoints/drp_endpoints.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@
3232
from fides.api.schemas.privacy_request import PrivacyRequestDRPStatusResponse
3333
from fides.api.schemas.redis_cache import Identity
3434
from fides.api.service.drp.drp_fidesops_mapper import DrpFidesopsMapper
35-
from fides.api.service.messaging.message_dispatch_service import (
36-
check_and_dispatch_error_notifications,
37-
)
38-
from fides.api.service.privacy_request.request_runner_service import (
39-
queue_privacy_request,
40-
)
4135
from fides.api.service.privacy_request.request_service import (
4236
build_required_privacy_request_kwargs,
4337
cache_data,
@@ -49,6 +43,10 @@
4943
from fides.common.api.v1 import urn_registry as urls
5044
from fides.config import CONFIG
5145
from fides.config.config_proxy import ConfigProxy
46+
from fides.service.messaging.messaging_service import (
47+
check_and_dispatch_error_notifications,
48+
)
49+
from fides.service.privacy_request.privacy_request_service import queue_privacy_request
5250

5351
router = APIRouter(tags=["DRP"], prefix=urls.V1_URL_PREFIX)
5452

0 commit comments

Comments
 (0)