ethyca-fides 2.58.2b2__py2.py3-none-any.whl → 2.58.2b5__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info}/METADATA +20 -11
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info}/RECORD +118 -115
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info}/WHEEL +1 -1
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info}/entry_points.txt +0 -1
- fides/_version.py +3 -3
- fides/api/alembic/migrations/versions/9288f729cac4_add_tcf_configuration_fk_to_experience_.py +62 -0
- fides/api/alembic/migrations/versions/99c603c1b8f9_add_password_login_enabled_and_totp_secret_to_fidesuser.py +45 -0
- fides/api/api/v1/endpoints/user_endpoints.py +8 -12
- fides/api/models/detection_discovery.py +31 -0
- fides/api/models/fides_user.py +26 -9
- fides/api/models/fides_user_invite.py +2 -0
- fides/api/models/privacy_experience.py +26 -0
- fides/api/models/tcf_publisher_restrictions.py +209 -48
- fides/api/schemas/user.py +5 -1
- fides/api/service/deps.py +9 -0
- fides/api/util/collection_util.py +48 -9
- fides/cli/commands/pull.py +77 -13
- fides/core/api.py +2 -1
- fides/core/pull.py +38 -7
- fides/service/user/__init__.py +0 -0
- fides/service/user/user_service.py +140 -0
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/{F-2Pz9ByzGwcvQtVLstwR → _o6WH0hDzNEhnUJyvLex7}/_buildManifest.js +1 -1
- fides/ui-build/static/admin/_next/static/chunks/1376-87058e04584cff20.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4121-4d5273d7a354994d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{4450-6a8aa0d7358ac26f.js → 4450-9c3086ccb55c66aa.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/6315-24a0483ee1cab6cc.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9046-8a5fdd335a76d224.js → 9046-a69fa8f99c414570.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-4a5be35cd8f832c0.js → _app-0c1548ca3b158123.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-17d1525551d8904f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-7d2cb947eee11262.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-9ef6b422ae7bc2a8.js → [id]-b75ab4ee677f118d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-26407674949bcbc4.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-28d4bdf060ec8cb2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-208e49ef43361d6f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-ff1985f72d50ef47.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-5a0b10ec955097d4.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-f8bca2e322ddf252.js → new-082c3156175f9267.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-af83245e9373a064.js +1 -0
- fides/ui-build/static/admin/add-systems/manual.html +1 -1
- fides/ui-build/static/admin/add-systems/multiple.html +1 -1
- fides/ui-build/static/admin/add-systems.html +1 -1
- fides/ui-build/static/admin/ant-poc.html +1 -1
- fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
- fides/ui-build/static/admin/consent/configure.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
- fides/ui-build/static/admin/consent/properties.html +1 -1
- fides/ui-build/static/admin/consent/reporting.html +1 -1
- fides/ui-build/static/admin/consent.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
- fides/ui-build/static/admin/data-catalog.html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
- fides/ui-build/static/admin/data-discovery/activity.html +1 -1
- fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/detection.html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
- fides/ui-build/static/admin/datamap.html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
- fides/ui-build/static/admin/dataset/new.html +1 -1
- fides/ui-build/static/admin/dataset.html +1 -1
- fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
- fides/ui-build/static/admin/datastore-connection/new.html +1 -1
- fides/ui-build/static/admin/datastore-connection.html +1 -1
- fides/ui-build/static/admin/index.html +1 -1
- fides/ui-build/static/admin/integrations/[id].html +1 -1
- fides/ui-build/static/admin/integrations.html +1 -1
- fides/ui-build/static/admin/lib/fides-tcf.js +1 -1
- fides/ui-build/static/admin/login/[provider].html +1 -1
- fides/ui-build/static/admin/login.html +1 -1
- fides/ui-build/static/admin/messaging/[id].html +1 -1
- fides/ui-build/static/admin/messaging/add-template.html +1 -1
- fides/ui-build/static/admin/messaging.html +1 -1
- fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
- fides/ui-build/static/admin/privacy-requests.html +1 -1
- fides/ui-build/static/admin/properties/[id].html +1 -1
- fides/ui-build/static/admin/properties/add-property.html +1 -1
- fides/ui-build/static/admin/properties.html +1 -1
- fides/ui-build/static/admin/reporting/datamap.html +1 -1
- fides/ui-build/static/admin/settings/about.html +1 -1
- fides/ui-build/static/admin/settings/consent.html +1 -1
- fides/ui-build/static/admin/settings/custom-fields.html +1 -1
- fides/ui-build/static/admin/settings/domain-records.html +1 -1
- fides/ui-build/static/admin/settings/domains.html +1 -1
- fides/ui-build/static/admin/settings/email-templates.html +1 -1
- fides/ui-build/static/admin/settings/locations.html +1 -1
- fides/ui-build/static/admin/settings/organization.html +1 -1
- fides/ui-build/static/admin/settings/regulations.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id].html +1 -1
- fides/ui-build/static/admin/systems.html +1 -1
- fides/ui-build/static/admin/taxonomy.html +1 -1
- fides/ui-build/static/admin/user-management/new.html +1 -1
- fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
- fides/ui-build/static/admin/user-management.html +1 -1
- fides/api/service/user/fides_user_service.py +0 -128
- fides/ui-build/static/admin/_next/static/chunks/1150-2642cd9cdc8a52f6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1376-03e7f50e708b7589.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6315-1adb10a8b98b4a13.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-719949074f10bd6e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-4892603e743cd6ab.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-1e60754abec1ee6b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-5e2687ab5ab10275.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-2914aade73dcaecc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-3ac1e5d3de5dd4a7.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-24cba38685dc872c.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-c0378fd1a26a71da.js +0 -1
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info/licenses}/LICENSE +0 -0
- {ethyca_fides-2.58.2b2.dist-info → ethyca_fides-2.58.2b5.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{F-2Pz9ByzGwcvQtVLstwR → _o6WH0hDzNEhnUJyvLex7}/_ssgManifest.js +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{1817-f82105a9608bba1a.js → 1817-48e1c9d3504e18f0.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6954-baa1d873abfe8b77.js → 6954-ec5276bb464d42b2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-b0f801d66e79a31a.js → privacy-requests-fd81714d811db7b3.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-3ca3c687e72d1364.js → user-management-a1db56f1cbfba373.js} +0 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
"""Add tcf_configuration FK to experience config
|
2
|
+
|
3
|
+
Revision ID: 9288f729cac4
|
4
|
+
Revises: 99c603c1b8f9
|
5
|
+
Create Date: 2025-04-07 18:49:31.843362
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sqlalchemy as sa
|
10
|
+
from alembic import op
|
11
|
+
|
12
|
+
# revision identifiers, used by Alembic.
|
13
|
+
revision = "9288f729cac4"
|
14
|
+
down_revision = "99c603c1b8f9"
|
15
|
+
branch_labels = None
|
16
|
+
depends_on = None
|
17
|
+
|
18
|
+
|
19
|
+
def upgrade():
|
20
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
21
|
+
op.add_column(
|
22
|
+
"privacyexperienceconfig",
|
23
|
+
sa.Column("tcf_configuration_id", sa.String(), nullable=True),
|
24
|
+
)
|
25
|
+
op.create_foreign_key(
|
26
|
+
"privacyexperienceconfig_tcf_configuration_fkey",
|
27
|
+
"privacyexperienceconfig",
|
28
|
+
"tcf_configuration",
|
29
|
+
["tcf_configuration_id"],
|
30
|
+
["id"],
|
31
|
+
ondelete="SET NULL",
|
32
|
+
)
|
33
|
+
op.add_column(
|
34
|
+
"privacyexperienceconfighistory",
|
35
|
+
sa.Column("tcf_configuration_id", sa.String(), nullable=True),
|
36
|
+
)
|
37
|
+
op.create_foreign_key(
|
38
|
+
"privacyexperienceconfighistory_tcf_configuration_fkey",
|
39
|
+
"privacyexperienceconfighistory",
|
40
|
+
"tcf_configuration",
|
41
|
+
["tcf_configuration_id"],
|
42
|
+
["id"],
|
43
|
+
ondelete="SET NULL",
|
44
|
+
)
|
45
|
+
# ### end Alembic commands ###
|
46
|
+
|
47
|
+
|
48
|
+
def downgrade():
|
49
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
50
|
+
op.drop_constraint(
|
51
|
+
"privacyexperienceconfighistory_tcf_configuration_fkey",
|
52
|
+
"privacyexperienceconfighistory",
|
53
|
+
type_="foreignkey",
|
54
|
+
)
|
55
|
+
op.drop_column("privacyexperienceconfighistory", "tcf_configuration_id")
|
56
|
+
op.drop_constraint(
|
57
|
+
"privacyexperienceconfig_tcf_configuration_fkey",
|
58
|
+
"privacyexperienceconfig",
|
59
|
+
type_="foreignkey",
|
60
|
+
)
|
61
|
+
op.drop_column("privacyexperienceconfig", "tcf_configuration_id")
|
62
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"""add password login enabled and totp secret to fidesuser
|
2
|
+
|
3
|
+
Revision ID: 99c603c1b8f9
|
4
|
+
Revises: 6e565c16dae1
|
5
|
+
Create Date: 2025-04-02 01:55:57.890545
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sqlalchemy as sa
|
10
|
+
import sqlalchemy_utils
|
11
|
+
from alembic import op
|
12
|
+
|
13
|
+
# revision identifiers, used by Alembic.
|
14
|
+
revision = "99c603c1b8f9"
|
15
|
+
down_revision = "6e565c16dae1"
|
16
|
+
branch_labels = None
|
17
|
+
depends_on = None
|
18
|
+
|
19
|
+
|
20
|
+
def upgrade():
|
21
|
+
op.add_column(
|
22
|
+
"fidesuser",
|
23
|
+
sa.Column(
|
24
|
+
"password_login_enabled",
|
25
|
+
sa.Boolean(),
|
26
|
+
nullable=True,
|
27
|
+
),
|
28
|
+
)
|
29
|
+
op.add_column(
|
30
|
+
"fidesuser",
|
31
|
+
sa.Column(
|
32
|
+
"totp_secret",
|
33
|
+
sqlalchemy_utils.types.encrypted.encrypted_type.StringEncryptedType(),
|
34
|
+
nullable=True,
|
35
|
+
),
|
36
|
+
)
|
37
|
+
op.alter_column("fidesuser", "hashed_password", nullable=True)
|
38
|
+
op.alter_column("fidesuser", "salt", nullable=True)
|
39
|
+
|
40
|
+
|
41
|
+
def downgrade():
|
42
|
+
op.alter_column("fidesuser", "hashed_password", nullable=False)
|
43
|
+
op.alter_column("fidesuser", "salt", nullable=False)
|
44
|
+
op.drop_column("fidesuser", "totp_secret")
|
45
|
+
op.drop_column("fidesuser", "password_login_enabled")
|
@@ -54,11 +54,7 @@ from fides.api.schemas.user import (
|
|
54
54
|
UserResponse,
|
55
55
|
UserUpdate,
|
56
56
|
)
|
57
|
-
from fides.api.service.
|
58
|
-
accept_invite,
|
59
|
-
invite_user,
|
60
|
-
perform_login,
|
61
|
-
)
|
57
|
+
from fides.api.service.deps import get_user_service
|
62
58
|
from fides.api.util.api_router import APIRouter
|
63
59
|
from fides.common.api.scope_registry import (
|
64
60
|
SCOPE_REGISTRY,
|
@@ -75,6 +71,7 @@ from fides.common.api.v1 import urn_registry as urls
|
|
75
71
|
from fides.common.api.v1.urn_registry import V1_URL_PREFIX
|
76
72
|
from fides.config import CONFIG, FidesConfig, get_config
|
77
73
|
from fides.config.config_proxy import ConfigProxy
|
74
|
+
from fides.service.user.user_service import UserService
|
78
75
|
|
79
76
|
router = APIRouter(tags=["Users"], prefix=V1_URL_PREFIX)
|
80
77
|
|
@@ -423,6 +420,7 @@ def create_user(
|
|
423
420
|
db: Session = Depends(get_db),
|
424
421
|
user_data: UserCreate,
|
425
422
|
config_proxy: ConfigProxy = Depends(get_config_proxy),
|
423
|
+
user_service: UserService = Depends(get_user_service),
|
426
424
|
) -> FidesUser:
|
427
425
|
"""
|
428
426
|
Create a user given a username and password.
|
@@ -461,7 +459,7 @@ def create_user(
|
|
461
459
|
user = FidesUser.create(db=db, data=user_data.model_dump(mode="json"))
|
462
460
|
|
463
461
|
# invite user via email
|
464
|
-
invite_user(
|
462
|
+
user_service.invite_user(user)
|
465
463
|
|
466
464
|
logger.info("Created user with id: '{}'.", user.id)
|
467
465
|
FidesUserPermissions.create(
|
@@ -544,6 +542,7 @@ def user_login(
|
|
544
542
|
db: Session = Depends(get_db),
|
545
543
|
config: FidesConfig = Depends(get_config),
|
546
544
|
user_data: UserLogin,
|
545
|
+
user_service: UserService = Depends(get_user_service),
|
547
546
|
) -> UserLoginResponse:
|
548
547
|
"""Login the user by creating a client if it doesn't exist, and have that client
|
549
548
|
generate a token."""
|
@@ -602,8 +601,7 @@ def user_login(
|
|
602
601
|
# from complaining.
|
603
602
|
user = user_check
|
604
603
|
|
605
|
-
client = perform_login(
|
606
|
-
db,
|
604
|
+
client = user_service.perform_login(
|
607
605
|
config.security.oauth_client_id_length_bytes,
|
608
606
|
config.security.oauth_client_secret_length_bytes,
|
609
607
|
user,
|
@@ -666,9 +664,9 @@ def verify_invite_code(
|
|
666
664
|
def accept_user_invite(
|
667
665
|
*,
|
668
666
|
db: Session = Depends(get_db),
|
669
|
-
config: FidesConfig = Depends(get_config),
|
670
667
|
user_data: UserForcePasswordReset,
|
671
668
|
verified_invite: FidesUserInvite = Depends(verify_invite_code),
|
669
|
+
user_service: UserService = Depends(get_user_service),
|
672
670
|
) -> UserLoginResponse:
|
673
671
|
"""Sets the password and enables the user if a valid username and invite code are provided."""
|
674
672
|
|
@@ -681,9 +679,7 @@ def accept_user_invite(
|
|
681
679
|
detail=f"User with username {verified_invite.username} does not exist.",
|
682
680
|
)
|
683
681
|
|
684
|
-
user, access_code = accept_invite(
|
685
|
-
db=db, config=config, user=user, new_password=user_data.new_password
|
686
|
-
)
|
682
|
+
user, access_code = user_service.accept_invite(user, user_data.new_password)
|
687
683
|
|
688
684
|
return UserLoginResponse(
|
689
685
|
user_data=user,
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from datetime import datetime
|
4
4
|
from enum import Enum
|
5
|
+
from re import match
|
5
6
|
from typing import Any, Dict, Iterable, List, Optional, Type
|
6
7
|
|
7
8
|
from loguru import logger
|
@@ -35,9 +36,17 @@ class MonitorFrequency(Enum):
|
|
35
36
|
DAILY = "Daily"
|
36
37
|
WEEKLY = "Weekly"
|
37
38
|
MONTHLY = "Monthly"
|
39
|
+
QUARTERLY = "Quarterly"
|
40
|
+
YEARLY = "Yearly"
|
38
41
|
NOT_SCHEDULED = "Not scheduled"
|
39
42
|
|
40
43
|
|
44
|
+
# pattern for a string of 4 comma-separated integers,
|
45
|
+
# used to represent the months of the year that the monitor will run
|
46
|
+
# on quarterly basis, in cron format
|
47
|
+
QUARTERLY_MONTH_PATTERN = r"^\d+,\d+,\d+,\d+$"
|
48
|
+
|
49
|
+
|
41
50
|
class MonitorConfig(Base):
|
42
51
|
"""
|
43
52
|
Monitor configuration used for data detection and discovery.
|
@@ -138,6 +147,13 @@ class MonitorConfig(Base):
|
|
138
147
|
or self.monitor_execution_trigger.get("hour", None) is None
|
139
148
|
):
|
140
149
|
return MonitorFrequency.NOT_SCHEDULED
|
150
|
+
month_trigger = self.monitor_execution_trigger.get("month", None)
|
151
|
+
if month_trigger is not None:
|
152
|
+
if isinstance(month_trigger, str) and match(
|
153
|
+
QUARTERLY_MONTH_PATTERN, month_trigger
|
154
|
+
):
|
155
|
+
return MonitorFrequency.QUARTERLY
|
156
|
+
return MonitorFrequency.YEARLY
|
141
157
|
if self.monitor_execution_trigger.get("day", None) is not None:
|
142
158
|
return MonitorFrequency.MONTHLY
|
143
159
|
if self.monitor_execution_trigger.get("day_of_week", None) is not None:
|
@@ -201,6 +217,10 @@ class MonitorConfig(Base):
|
|
201
217
|
a Tuesday.
|
202
218
|
- with an `execution_frequency` of "monthly", it will result in monthly
|
203
219
|
execution at 12:00:00+00:00 on the 14th day of every month.
|
220
|
+
- with an `execution_frequency` of "quarterly", it will result in quarterly
|
221
|
+
execution at 12:00:00+00:00 on the 14th day of the first month of each quarter.
|
222
|
+
- with an `execution_frequency` of "yearly", it will result in yearly
|
223
|
+
execution at 12:00:00+00:00 on May 14th of each year.
|
204
224
|
|
205
225
|
See https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html
|
206
226
|
for more information about the cron trigger parameters.
|
@@ -221,6 +241,17 @@ class MonitorConfig(Base):
|
|
221
241
|
cron_trigger_dict["day_of_week"] = execution_start_date.weekday()
|
222
242
|
if execution_frequency == MonitorFrequency.MONTHLY:
|
223
243
|
cron_trigger_dict["day"] = execution_start_date.day
|
244
|
+
if execution_frequency == MonitorFrequency.QUARTERLY:
|
245
|
+
cron_trigger_dict["day"] = execution_start_date.day
|
246
|
+
# Calculate which month of the quarter (0-2) this is
|
247
|
+
month_of_quarter = (execution_start_date.month - 1) % 3
|
248
|
+
# Set to run in the same month of each quarter (1, 4, 7, 10 for first month)
|
249
|
+
cron_trigger_dict["month"] = (
|
250
|
+
f"{1 + month_of_quarter},{4 + month_of_quarter},{7 + month_of_quarter},{10 + month_of_quarter}"
|
251
|
+
)
|
252
|
+
if execution_frequency == MonitorFrequency.YEARLY:
|
253
|
+
cron_trigger_dict["day"] = execution_start_date.day
|
254
|
+
cron_trigger_dict["month"] = execution_start_date.month
|
224
255
|
data["monitor_execution_trigger"] = cron_trigger_dict
|
225
256
|
|
226
257
|
|
fides/api/models/fides_user.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# pylint: disable=unused-import
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
|
-
import uuid
|
5
4
|
from datetime import datetime
|
6
5
|
from typing import TYPE_CHECKING, Any, List
|
7
6
|
|
@@ -10,6 +9,10 @@ from sqlalchemy import Boolean, Column, DateTime
|
|
10
9
|
from sqlalchemy import Enum as EnumColumn
|
11
10
|
from sqlalchemy import String
|
12
11
|
from sqlalchemy.orm import Session, relationship
|
12
|
+
from sqlalchemy_utils.types.encrypted.encrypted_type import (
|
13
|
+
AesGcmEngine,
|
14
|
+
StringEncryptedType,
|
15
|
+
)
|
13
16
|
|
14
17
|
from fides.api.common_exceptions import SystemManagerException
|
15
18
|
from fides.api.cryptography.cryptographic_util import (
|
@@ -20,8 +23,8 @@ from fides.api.db.base_class import Base
|
|
20
23
|
from fides.api.models.audit_log import AuditLog
|
21
24
|
|
22
25
|
# Intentionally importing SystemManager here to build the FidesUser.systems relationship
|
23
|
-
from fides.api.models.system_manager import SystemManager # type: ignore[unused-import]
|
24
26
|
from fides.api.schemas.user import DisabledReason
|
27
|
+
from fides.config import CONFIG
|
25
28
|
|
26
29
|
if TYPE_CHECKING:
|
27
30
|
from fides.api.models.sql_models import System # type: ignore[attr-defined]
|
@@ -34,12 +37,22 @@ class FidesUser(Base):
|
|
34
37
|
email_address = Column(CIText, unique=True, nullable=True)
|
35
38
|
first_name = Column(String, nullable=True)
|
36
39
|
last_name = Column(String, nullable=True)
|
37
|
-
hashed_password = Column(String, nullable=
|
38
|
-
salt = Column(String, nullable=
|
40
|
+
hashed_password = Column(String, nullable=True)
|
41
|
+
salt = Column(String, nullable=True)
|
39
42
|
disabled = Column(Boolean, nullable=False, server_default="f")
|
40
43
|
disabled_reason = Column(EnumColumn(DisabledReason), nullable=True)
|
41
44
|
last_login_at = Column(DateTime(timezone=True), nullable=True)
|
42
45
|
password_reset_at = Column(DateTime(timezone=True), nullable=True)
|
46
|
+
password_login_enabled = Column(Boolean, nullable=True)
|
47
|
+
totp_secret = Column(
|
48
|
+
StringEncryptedType(
|
49
|
+
type_in=String(),
|
50
|
+
key=CONFIG.security.app_encryption_key,
|
51
|
+
engine=AesGcmEngine,
|
52
|
+
padding="pkcs5",
|
53
|
+
),
|
54
|
+
nullable=True,
|
55
|
+
)
|
43
56
|
|
44
57
|
# passive_deletes="all" prevents audit logs from having their
|
45
58
|
# privacy_request_id set to null when a privacy_request is deleted.
|
@@ -79,11 +92,11 @@ class FidesUser(Base):
|
|
79
92
|
"""Create a FidesUser by hashing the password with a generated salt
|
80
93
|
and storing the hashed password and the salt"""
|
81
94
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
95
|
+
if password := data.get("password"):
|
96
|
+
hashed_password, salt = FidesUser.hash_password(password)
|
97
|
+
else:
|
98
|
+
hashed_password = None
|
99
|
+
salt = None
|
87
100
|
|
88
101
|
user = super().create(
|
89
102
|
db,
|
@@ -96,6 +109,7 @@ class FidesUser(Base):
|
|
96
109
|
"last_name": data.get("last_name"),
|
97
110
|
"disabled": data.get("disabled") or False,
|
98
111
|
"disabled_reason": data.get("disabled_reason"),
|
112
|
+
"password_login_enabled": data.get("password_login_enabled"),
|
99
113
|
},
|
100
114
|
check_name=check_name,
|
101
115
|
)
|
@@ -104,6 +118,9 @@ class FidesUser(Base):
|
|
104
118
|
|
105
119
|
def credentials_valid(self, password: str, encoding: str = "UTF-8") -> bool:
|
106
120
|
"""Verifies that the provided password is correct."""
|
121
|
+
if self.salt is None:
|
122
|
+
return False
|
123
|
+
|
107
124
|
provided_password_hash = hash_credential_with_salt(
|
108
125
|
password.encode(encoding),
|
109
126
|
self.salt.encode(encoding),
|
@@ -67,6 +67,8 @@ class FidesUserInvite(Base):
|
|
67
67
|
|
68
68
|
def invite_code_valid(self, invite_code: str, encoding: str = "UTF-8") -> bool:
|
69
69
|
"""Verifies that the provided invite code is correct."""
|
70
|
+
if self.salt is None:
|
71
|
+
return False
|
70
72
|
|
71
73
|
invite_code_hash = hash_credential_with_salt(
|
72
74
|
invite_code.encode(encoding),
|
@@ -20,6 +20,7 @@ from fides.api.models import (
|
|
20
20
|
from fides.api.models.location_regulation_selections import PrivacyNoticeRegion
|
21
21
|
from fides.api.models.privacy_notice import PrivacyNotice
|
22
22
|
from fides.api.models.property import Property
|
23
|
+
from fides.api.models.tcf_publisher_restrictions import TCFConfiguration
|
23
24
|
from fides.api.schemas.language import SupportedLanguage
|
24
25
|
|
25
26
|
|
@@ -228,6 +229,13 @@ class PrivacyExperienceConfig(PrivacyExperienceConfigBase, Base):
|
|
228
229
|
EnumColumn(RejectAllMechanism),
|
229
230
|
nullable=True,
|
230
231
|
)
|
232
|
+
# Optional FK to a TCF Configuration
|
233
|
+
|
234
|
+
tcf_configuration_id = Column(
|
235
|
+
String,
|
236
|
+
ForeignKey(TCFConfiguration.id_field_path, ondelete="SET NULL"),
|
237
|
+
nullable=True,
|
238
|
+
)
|
231
239
|
|
232
240
|
# Relationships
|
233
241
|
experiences = relationship(
|
@@ -258,6 +266,12 @@ class PrivacyExperienceConfig(PrivacyExperienceConfigBase, Base):
|
|
258
266
|
lazy="selectin",
|
259
267
|
)
|
260
268
|
|
269
|
+
tcf_configuration: RelationshipProperty[Optional[TCFConfiguration]] = relationship(
|
270
|
+
"TCFConfiguration",
|
271
|
+
back_populates="privacy_experience_configs",
|
272
|
+
lazy="selectin",
|
273
|
+
)
|
274
|
+
|
261
275
|
@property
|
262
276
|
def regions(self) -> List[PrivacyNoticeRegion]:
|
263
277
|
"""Return the regions using this experience config"""
|
@@ -548,6 +562,17 @@ class PrivacyExperienceConfigHistory(
|
|
548
562
|
EnumColumn(RejectAllMechanism),
|
549
563
|
nullable=True,
|
550
564
|
)
|
565
|
+
# Optional FK to a TCF Configuration
|
566
|
+
tcf_configuration_id = Column(
|
567
|
+
String,
|
568
|
+
ForeignKey(TCFConfiguration.id_field_path, ondelete="SET NULL"),
|
569
|
+
nullable=True,
|
570
|
+
)
|
571
|
+
|
572
|
+
tcf_configuration: RelationshipProperty[Optional[TCFConfiguration]] = relationship(
|
573
|
+
"TCFConfiguration",
|
574
|
+
lazy="selectin",
|
575
|
+
)
|
551
576
|
|
552
577
|
version = Column(Float, nullable=False, default=1.0)
|
553
578
|
|
@@ -611,6 +636,7 @@ class PrivacyExperience(Base):
|
|
611
636
|
tcf_special_features: List = []
|
612
637
|
tcf_system_consents: List = []
|
613
638
|
tcf_system_legitimate_interests: List = []
|
639
|
+
tcf_publisher_restrictions: List = []
|
614
640
|
gvl: Optional[Dict] = {}
|
615
641
|
# TCF Developer-Friendly Meta added at runtime as the result of build_tc_data_for_mobile
|
616
642
|
meta: Dict = {}
|