Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API for messaging-related app config settings #2551

Merged
merged 22 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 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
4 changes: 4 additions & 0 deletions .fides/db_dataset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ dataset:
data_categories:
- system.operations
data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified
- name: config_set
data_categories:
- system.operations
data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified
- name: updated_at
data_categories:
- system.operations
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ The types of changes are:

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

### Added
* Add API support for messaging config properties [#2551](https://github.com/ethyca/fides/pull/2551)

### Changed

* Add warning to 'fides deploy' when installed outside of a virtual environment [#2641](https://github.com/ethyca/fides/pull/2641)
Expand All @@ -25,6 +28,7 @@ The types of changes are:
* Fides API
* Access and erasure support for Braintree [#2223](https://github.com/ethyca/fides/pull/2223)
* Added route to send a test message [#2585](https://github.com/ethyca/fides/pull/2585)
* Add default storage configuration functionality and associated APIs [#2438](https://github.com/ethyca/fides/pull/2438)

* Admin UI
* Custom Metadata [#2536](https://github.com/ethyca/fides/pull/2536)
Expand Down Expand Up @@ -105,8 +109,6 @@ The types of changes are:

* Issue addressing missing field in dataset migration [#2510](https://github.com/ethyca/fides/pull/2510)

### Added
* Add default storage configuration functionality and associated APIs [#2438](https://github.com/ethyca/fides/pull/2438)

## [2.6.1](https://github.com/ethyca/fides/compare/2.6.0...2.6.1)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""add config_set column to application settings

Revision ID: c9ee230fa6da
Revises: 8e198eb13802
Create Date: 2023-02-01 15:13:52.133075

"""
import sqlalchemy as sa
import sqlalchemy_utils
from alembic import op

# revision identifiers, used by Alembic.
revision = "c9ee230fa6da"
down_revision = "8e198eb13802"
branch_labels = None
depends_on = None


def upgrade():
op.add_column(
"applicationconfig",
sa.Column(
"config_set",
sqlalchemy_utils.types.encrypted.encrypted_type.StringEncryptedType(),
nullable=False,
),
)
pattisdr marked this conversation as resolved.
Show resolved Hide resolved

# include this update here to make up for an earlier miss when creating the table
op.alter_column("applicationconfig", "api_set", nullable=False)


def downgrade():
op.drop_column("applicationconfig", "config_set")

# add a downgrade here for consistency
op.alter_column("applicationconfig", "api_set", nullable=True)
13 changes: 13 additions & 0 deletions src/fides/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
FunctionalityNotConfigured,
RedisConnectionError,
)
from fides.api.ops.models.application_config import ApplicationConfig
from fides.api.ops.schemas.analytics import Event, ExtraData
from fides.api.ops.service.connectors.saas.connector_registry_service import (
load_registry,
Expand Down Expand Up @@ -244,6 +245,18 @@ async def setup_server() -> None:
logger.error("Error creating parent user: {}", str(e))
raise FidesError(f"Error creating parent user: {str(e)}")

logger.info("Loading config settings into database...")
try:
db = get_api_session()
ApplicationConfig.update_config_set(db, CONFIG)
except Exception as e:
logger.error("Error occurred writing config settings to database: {}", str(e))
raise FidesError(
f"Error occurred writing config settings to database: {str(e)}"
)
finally:
db.close()

logger.info("Validating SaaS connector templates...")
try:
registry = load_registry(registry_file)
Expand Down
6 changes: 6 additions & 0 deletions src/fides/api/ops/api/deps.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from typing import Generator

from fastapi import Depends
from sqlalchemy.orm import Session

from fides.api.ops.common_exceptions import FunctionalityNotConfigured
from fides.api.ops.util.cache import get_cache as get_redis_connection
from fides.core.config import FidesConfig
from fides.core.config import get_config as get_app_config
from fides.core.config.config_proxy import ConfigProxy
from fides.lib.db.session import get_db_engine, get_db_session

_engine = None
Expand Down Expand Up @@ -40,6 +42,10 @@ def get_api_session() -> Session:
return db


def get_config_proxy(db: Session = Depends(get_db)) -> ConfigProxy:
return ConfigProxy(db)


def get_cache() -> Generator:
"""Return a connection to our redis cache"""
if not CONFIG.redis.enabled:
Expand Down
33 changes: 27 additions & 6 deletions src/fides/api/ops/api/v1/endpoints/config_endpoints.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict
from typing import Any, Dict, Optional

from fastapi import Depends
from fastapi.params import Security
Expand Down Expand Up @@ -33,7 +33,7 @@ def get_config(
logger.info("Getting the exposable Fides configuration")
if api_set:
logger.info("Retrieving api-set application settings")
return ApplicationConfig.get_api_set_config(db)
return censor_config(ApplicationConfig.get_api_set(db))
config = censor_config(get_app_config())
pattisdr marked this conversation as resolved.
Show resolved Hide resolved
return config

Expand All @@ -43,6 +43,7 @@ def get_config(
status_code=HTTP_200_OK,
dependencies=[Security(verify_oauth_client, scopes=[scopes.CONFIG_UPDATE])],
response_model=ApplicationConfigSchema,
response_model_exclude_unset=True,
)
def update_settings(
*,
Expand All @@ -56,8 +57,28 @@ def update_settings(
i.e. true PATCH behavior.
"""
logger.info("Updating application settings")

updated_settings: ApplicationConfig = ApplicationConfig.create_or_update(
db, data={"api_set": data.dict()}
update_config: ApplicationConfig = ApplicationConfig.update_api_set(
db, data.dict(exclude_none=True)
)
return updated_settings.api_set
return update_config.api_set


@router.delete(
urls.CONFIG,
status_code=HTTP_200_OK,
dependencies=[Security(verify_oauth_client, scopes=[scopes.CONFIG_UPDATE])],
response_model=Dict,
)
def reset_settings(
*,
db: Session = Depends(deps.get_db),
) -> dict:
"""
Resets the global application settings record.

Only the "api-set" values are cleared, "config-set" values are
not updated via any API calls
"""
logger.info("Resetting api-set application settings")
update_config: Optional[ApplicationConfig] = ApplicationConfig.clear_api_set(db)
return update_config.api_set if update_config else {}
21 changes: 14 additions & 7 deletions src/fides/api/ops/api/v1/endpoints/consent_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)

from fides.api.ctl.database.seed import DEFAULT_CONSENT_POLICY
from fides.api.ops.api.deps import get_db
from fides.api.ops.api.deps import get_config_proxy, get_db
from fides.api.ops.api.v1.endpoints.privacy_request_endpoints import (
create_privacy_request_func,
)
Expand Down Expand Up @@ -58,6 +58,7 @@
from fides.api.ops.util.logger import Pii
from fides.api.ops.util.oauth_util import verify_oauth_client
from fides.core.config import get_config
from fides.core.config.config_proxy import ConfigProxy

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

Expand All @@ -73,6 +74,7 @@
def create_consent_request(
*,
db: Session = Depends(get_db),
config_proxy: ConfigProxy = Depends(get_config_proxy),
data: Identity,
) -> ConsentRequestResponse:
"""Creates a verification code for the user to verify access to manage consent preferences."""
Expand All @@ -97,7 +99,7 @@ def create_consent_request(
}
consent_request = ConsentRequest.create(db, data=consent_request_data)

if CONFIG.execution.subject_identity_verification_required:
if config_proxy.execution.subject_identity_verification_required:
try:
send_verification_code_to_user(db, consent_request, data)
except MessageDispatchException as exc:
Expand Down Expand Up @@ -168,11 +170,14 @@ def consent_request_verify(
},
)
def get_consent_preferences_no_id(
*, db: Session = Depends(get_db), consent_request_id: str
*,
db: Session = Depends(get_db),
config_proxy: ConfigProxy = Depends(get_config_proxy),
consent_request_id: str,
) -> ConsentPreferences:
"""Returns the current consent preferences if successful."""

if CONFIG.execution.subject_identity_verification_required:
if config_proxy.execution.subject_identity_verification_required:
raise HTTPException(
status_code=HTTP_400_BAD_REQUEST,
detail="Retrieving consent preferences without identity verification is "
Expand Down Expand Up @@ -267,6 +272,7 @@ def queue_privacy_request_to_propagate_consent(
logger.info("Executable consent options: {}", executable_data_uses)
privacy_request_results: BulkPostPrivacyRequests = create_privacy_request_func(
db=db,
config_proxy=ConfigProxy(db),
data=[
PrivacyRequestCreate(
identity=identity,
Expand Down Expand Up @@ -358,7 +364,7 @@ def _get_or_create_provided_identity(
identity_data: Identity,
) -> ProvidedIdentity:
"""Based on target identity type, retrieves or creates associated ProvidedIdentity"""
target_identity_type: str = infer_target_identity_type(identity_data)
target_identity_type: str = infer_target_identity_type(db, identity_data)

if target_identity_type == ProvidedIdentityType.email.value and identity_data.email:
identity = ProvidedIdentity.filter(
Expand Down Expand Up @@ -418,6 +424,7 @@ def _get_or_create_provided_identity(


def infer_target_identity_type(
db: Session,
identity_data: Identity,
) -> str:
"""
Expand All @@ -428,7 +435,7 @@ def infer_target_identity_type(
"""
if identity_data.email and identity_data.phone_number:
messaging_method = get_messaging_method(
CONFIG.notifications.notification_service_type
ConfigProxy(db).notifications.notification_service_type
)
if messaging_method == MessagingMethod.EMAIL:
target_identity_type = ProvidedIdentityType.email.value
Expand Down Expand Up @@ -458,7 +465,7 @@ def _get_consent_request_and_provided_identity(
status_code=HTTP_404_NOT_FOUND, detail="Consent request not found"
)

if CONFIG.execution.subject_identity_verification_required:
if ConfigProxy(db).execution.subject_identity_verification_required:
try:
consent_request.verify_identity(verification_code)
except IdentityVerificationException as exc:
Expand Down
4 changes: 3 additions & 1 deletion src/fides/api/ops/api/v1/endpoints/drp_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from fides.api.ops.util.logger import Pii
from fides.api.ops.util.oauth_util import verify_oauth_client
from fides.core.config import get_config
from fides.core.config.config_proxy import ConfigProxy

router = APIRouter(tags=["DRP"], prefix=urls.V1_URL_PREFIX)
CONFIG = get_config()
Expand All @@ -63,6 +64,7 @@ async def create_drp_privacy_request(
*,
cache: FidesopsRedis = Depends(deps.get_cache),
db: Session = Depends(deps.get_db),
config_proxy: ConfigProxy = Depends(deps.get_config_proxy),
data: DrpPrivacyRequestCreate,
) -> PrivacyRequestDRPStatusResponse:
"""
Expand Down Expand Up @@ -91,7 +93,7 @@ async def create_drp_privacy_request(
)

privacy_request_kwargs: Dict[str, Any] = build_required_privacy_request_kwargs(
None, policy.id
None, policy.id, config_proxy.execution.subject_identity_verification_required
)

try:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
IdentityVerificationConfigResponse,
)
from fides.api.ops.util.api_router import APIRouter
from fides.core.config import get_config
from fides.core.config.config_proxy import ConfigProxy

router = APIRouter(tags=["Identity Verification"], prefix=urls.V1_URL_PREFIX)

Expand All @@ -22,11 +22,11 @@
def get_id_verification_config(
*,
db: Session = Depends(deps.get_db),
config_proxy: ConfigProxy = Depends(deps.get_config_proxy)
) -> IdentityVerificationConfigResponse:
"""Returns id verification config."""
config = get_config()
messaging_config: Optional[MessagingConfig] = db.query(MessagingConfig).first()
return IdentityVerificationConfigResponse(
identity_verification_required=config.execution.subject_identity_verification_required,
identity_verification_required=config_proxy.execution.subject_identity_verification_required,
valid_email_config_exists=bool(messaging_config and messaging_config.secrets),
)
Loading