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

Add due_date to PrivacyRequest model #1259

Merged
merged 11 commits into from
Sep 7, 2022
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ The types of changes are:
* Foundations for a new email connector type [#1142](https://github.com/ethyca/fidesops/pull/1142)
* Have the new email connector cache action needed for each collection [#1168](https://github.com/ethyca/fidesops/pull/1168)
* Added `execution_timeframe` to Policy model and schema [#1244](https://github.com/ethyca/fidesops/pull/1244)
* Added `due_date` to Privacy request model [#1259](https://github.com/ethyca/fidesops/pull/1259)
* Wrap up the email connector - it sends an email with erasure instructions as part of request execution [#1246](https://github.com/ethyca/fidesops/pull/1246)

### Docs

* Fix analytics opt out environment variable name [#1170](https://github.com/ethyca/fidesops/pull/1170)
* Added how to view a subject request history and reprocess a subject request [#1164](https://github.com/ethyca/fidesops/pull/1164)
* Adds section on email communications, and exposes previously hidden guides in nav bar [1233](https://github.com/ethyca/fidesops/pull/1233)
* Adds section on email communications, and exposes previously hidden guides in nav bar [#1233](https://github.com/ethyca/fidesops/pull/1233)

### Fixed

Expand Down
30 changes: 30 additions & 0 deletions src/fidesops/ops/migrations/versions/d8df7ff7aab4_add_due_date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""add_due_date

Revision ID: d8df7ff7aab4
Revises: 912d801f06c0
Create Date: 2022-09-06 15:21:21.181463

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "d8df7ff7aab4"
down_revision = "912d801f06c0"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"privacyrequest",
sa.Column("due_date", sa.DateTime(timezone=True), nullable=True),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("privacyrequest", "due_date")
# ### end Alembic commands ###
16 changes: 15 additions & 1 deletion src/fidesops/ops/models/privacy_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import json
import logging
from datetime import datetime
from datetime import datetime, timedelta
from enum import Enum as EnumType
from typing import Any, Dict, List, Optional

Expand Down Expand Up @@ -209,6 +209,7 @@ class PrivacyRequest(Base): # pylint: disable=R0904
)
paused_at = Column(DateTime(timezone=True), nullable=True)
identity_verified_at = Column(DateTime(timezone=True), nullable=True)
due_date = Column(DateTime(timezone=True), nullable=True)

@classmethod
def create(cls, db: Session, *, data: Dict[str, Any]) -> FidesBase:
Expand All @@ -218,6 +219,19 @@ def create(cls, db: Session, *, data: Dict[str, Any]) -> FidesBase:
"""
if data.get("requested_at", None) is None:
data["requested_at"] = datetime.utcnow()

policy: Policy = Policy.get_by(
db=db,
field="id",
value=data["policy_id"],
)

if policy.execution_timeframe:
requested_at = data["requested_at"]
if isinstance(requested_at, str):
requested_at = datetime.strptime(requested_at, "%Y-%m-%dT%H:%M:%S.%fZ")
seanpreston marked this conversation as resolved.
Show resolved Hide resolved
data["due_date"] = requested_at + timedelta(days=policy.execution_timeframe)

return super().create(db=db, data=data)

def delete(self, db: Session) -> None:
Expand Down
8 changes: 4 additions & 4 deletions tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ def test_get_privacy_requests_by_id(
"reviewer": None,
"policy": {
"drp_action": None,
"execution_timeframe": None,
"execution_timeframe": 7,
"name": privacy_request.policy.name,
"key": privacy_request.policy.key,
"rules": [
Expand Down Expand Up @@ -640,7 +640,7 @@ def test_get_privacy_requests_by_partial_id(
"paused_at": None,
"reviewer": None,
"policy": {
"execution_timeframe": None,
"execution_timeframe": 7,
"drp_action": None,
"name": privacy_request.policy.name,
"key": privacy_request.policy.key,
Expand Down Expand Up @@ -996,7 +996,7 @@ def test_verbose_privacy_requests(
"paused_at": None,
"reviewer": None,
"policy": {
"execution_timeframe": None,
"execution_timeframe": 7,
"drp_action": None,
"name": privacy_request.policy.name,
"key": privacy_request.policy.key,
Expand Down Expand Up @@ -2044,7 +2044,7 @@ def test_resume_privacy_request(
"reviewer": None,
"paused_at": None,
"policy": {
"execution_timeframe": None,
"execution_timeframe": 7,
"drp_action": None,
"key": privacy_request.policy.key,
"name": privacy_request.policy.name,
Expand Down
1 change: 1 addition & 0 deletions tests/ops/fixtures/application_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ def policy(
"name": "example access request policy",
"key": "example_access_request_policy",
"client_id": oauth_client.id,
"execution_timeframe": 7,
},
)

Expand Down
44 changes: 44 additions & 0 deletions tests/ops/models/test_privacy_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,50 @@ def test_create_privacy_request_sets_requested_at(
pr.delete(db)


def test_create_privacy_request_sets_due_date(
db: Session,
policy: Policy,
) -> None:
pr = PrivacyRequest.create(
db=db,
data={
"policy_id": policy.id,
"status": "pending",
},
)
assert pr.due_date is not None
pr.delete(db)

requested_at = datetime.now(timezone.utc)
due_date = timedelta(days=policy.execution_timeframe) + requested_at
pr = PrivacyRequest.create(
db=db,
data={
"requested_at": requested_at,
"policy_id": policy.id,
"status": "pending",
},
)
assert pr.due_date == due_date
pr.delete(db)

requested_at_str = "2021-08-30T16:09:37.359Z"
requested_at = datetime.strptime(requested_at_str, "%Y-%m-%dT%H:%M:%S.%fZ").replace(
seanpreston marked this conversation as resolved.
Show resolved Hide resolved
tzinfo=timezone.utc
)
due_date = timedelta(days=policy.execution_timeframe) + requested_at
pr = PrivacyRequest.create(
db=db,
data={
"requested_at": requested_at_str,
"policy_id": policy.id,
"status": "pending",
},
)
assert pr.due_date == due_date
pr.delete(db)


def test_update_privacy_requests(db: Session, privacy_requests: PrivacyRequest) -> None:
privacy_request = privacy_requests[0]
EXTERNAL_ID_TO_UPDATE = privacy_request.external_id
Expand Down