~homeworkprod/byceps

4fad7af3c2826bc256b8a835787a83e387012199 — Jochen Kupperschmidt 10 months ago 315e7c9
Remove email config ID, promote brand ID to primary key

DDL:

    DROP INDEX ix_email_configs_brand_id;
    ALTER TABLE email_configs DROP CONSTRAINT email_configs_pkey;
    ALTER TABLE email_configs ADD CONSTRAINT email_configs_pkey PRIMARY KEY (brand_id);
    ALTER TABLE email_configs DROP COLUMN id;
M byceps/blueprints/admin/brand/views.py => byceps/blueprints/admin/brand/views.py +1 -1
@@ 181,7 181,7 @@ def email_config_update(brand_id):
    contact_address = form.contact_address.data.strip()

    config = email_service.update_config(
        config.id, sender_address, sender_name, contact_address
        config.brand_id, sender_address, sender_name, contact_address
    )

    flash_success(f'Die E-Mail-Konfiguration wurde aktualisiert.')

M byceps/services/email/models.py => byceps/services/email/models.py +2 -5
@@ 18,22 18,19 @@ class EmailConfig(db.Model):

    __tablename__ = 'email_configs'

    id = db.Column(db.UnicodeText, primary_key=True)
    brand_id = db.Column(db.UnicodeText, db.ForeignKey('brands.id'), index=True, unique=True, nullable=False)
    brand_id = db.Column(db.UnicodeText, db.ForeignKey('brands.id'), primary_key=True)
    sender_address = db.Column(db.UnicodeText, nullable=False)
    sender_name = db.Column(db.UnicodeText, nullable=True)
    contact_address = db.Column(db.UnicodeText, nullable=True)

    def __init__(
        self,
        config_id: str,
        brand_id: BrandID,
        sender_address: str,
        *,
        sender_name: Optional[str] = None,
        contact_address: Optional[str] = None,
    ) -> None:
        self.id = config_id
        self.brand_id = brand_id
        self.sender_address = sender_address
        self.sender_name = sender_name


@@ 41,5 38,5 @@ class EmailConfig(db.Model):

    def __repr__(self) -> str:
        return ReprBuilder(self) \
            .add_with_lookup('id') \
            .add_with_lookup('brand_id') \
            .build()

M byceps/services/email/service.py => byceps/services/email/service.py +13 -34
@@ 24,7 24,6 @@ class UnknownEmailConfigId(ValueError):


def create_config(
    config_id: str,
    brand_id: BrandID,
    sender_address: str,
    *,


@@ 33,7 32,6 @@ def create_config(
) -> EmailConfig:
    """Create a configuration."""
    config = DbEmailConfig(
        config_id,
        brand_id,
        sender_address,
        sender_name=sender_name,


@@ 47,16 45,18 @@ def create_config(


def update_config(
    config_id: str,
    brand_id: BrandID,
    sender_address: str,
    sender_name: Optional[str],
    contact_address: Optional[str],
) -> EmailConfig:
    """Update a configuration."""
    config = DbEmailConfig.query.get(config_id)
    config = _find_db_config_for_brand(brand_id)

    if config is None:
        raise UnknownEmailConfigId(config_id)
        raise UnknownEmailConfigId(
            f'No e-mail config found for brand ID "{brand_id}"'
        )

    config.sender_address = sender_address
    config.sender_name = sender_name


@@ 67,7 67,7 @@ def update_config(
    return _db_entity_to_config(config)


def delete_config(config_id: str) -> bool:
def delete_config(brand_id: BrandID) -> bool:
    """Delete a configuration.

    It is expected that no database records (sites) refer to the


@@ 75,11 75,11 @@ def delete_config(config_id: str) -> bool:

    Return `True` on success, or `False` if an error occurred.
    """
    get_config(config_id)  # Verify ID exists.
    get_config_for_brand(brand_id)  # Verify ID exists.

    try:
        db.session.query(DbEmailConfig) \
            .filter_by(id=config_id) \
            .filter_by(brand_id=brand_id) \
            .delete()

        db.session.commit()


@@ 90,33 90,15 @@ def delete_config(config_id: str) -> bool:
    return True


def find_config(config_id: str) -> Optional[EmailConfig]:
    """Return the configuration, or `None` if not found."""
    config = DbEmailConfig.query.get(config_id)

    if config is None:
        return None

    return _db_entity_to_config(config)


def get_config(config_id: str) -> EmailConfig:
    """Return the configuration, or raise an error if none is
    configured for that ID.
    """
    config = find_config(config_id)

    if not config:
        raise UnknownEmailConfigId(f'Unknown e-mail config ID "{config_id}"')

    return config
def _find_db_config_for_brand(brand_id: BrandID) -> Optional[DbEmailConfig]:
    return DbEmailConfig.query \
        .filter_by(brand_id=brand_id) \
        .one_or_none()


def find_config_for_brand(brand_id: BrandID) -> Optional[EmailConfig]:
    """Return the configuration for that brand, or `None` if not found."""
    config = DbEmailConfig.query \
        .filter_by(brand_id=brand_id) \
        .one_or_none()
    config = _find_db_config_for_brand(brand_id)

    if config is None:
        return None


@@ 139,7 121,6 @@ def get_config_for_brand(brand_id: BrandID) -> EmailConfig:


def set_config(
    config_id: str,
    brand_id: BrandID,
    sender_address: str,
    *,


@@ 149,7 130,6 @@ def set_config(
    """Add or update configuration for that ID."""
    table = DbEmailConfig.__table__
    identifier = {
        'id': config_id,
        'brand_id': brand_id,
        'sender_address': sender_address,
    }


@@ 198,7 178,6 @@ def _db_entity_to_config(config: DbEmailConfig) -> EmailConfig:
    )

    return EmailConfig(
        config.id,
        config.brand_id,
        sender,
        config.contact_address,

M byceps/services/email/transfer/models.py => byceps/services/email/transfer/models.py +0 -1
@@ 26,7 26,6 @@ class Sender:

@dataclass(frozen=True)
class EmailConfig:
    id: str
    brand_id: BrandID
    sender: Sender
    contact_address: str

M tests/conftest.py => tests/conftest.py +4 -8
@@ 188,12 188,12 @@ def deleted_user(make_user):
    return make_user('DeletedUser', deleted=True)


# Dependency on `brand` avoids error on clean up.
@pytest.fixture(scope='session')
def make_email_config(admin_app, brand):
    configs = []

    def _wrapper(
        config_id: str,
        brand_id: BrandID,
        sender_address: str,
        *,


@@ 201,14 201,13 @@ def make_email_config(admin_app, brand):
        contact_address: Optional[str] = None,
    ):
        email_service.set_config(
            config_id,
            brand_id,
            sender_address,
            sender_name=sender_name,
            contact_address=contact_address,
        )

        config = email_service.get_config(config_id)
        config = email_service.get_config_for_brand(brand_id)
        configs.append(config)

        return config


@@ 216,15 215,12 @@ def make_email_config(admin_app, brand):
    yield _wrapper

    for config in configs:
        email_service.delete_config(config.id)
        email_service.delete_config(config.brand_id)


# Dependency on `brand` avoids error on clean up.
@pytest.fixture(scope='session')
def email_config(make_email_config, brand):
    return make_email_config(
        'email-config-1', brand.id, sender_address='noreply@acmecon.test'
    )
    return make_email_config(brand.id, sender_address='noreply@acmecon.test')


@pytest.fixture(scope='session')

M tests/integration/blueprints/site/user_message/test_send.py => tests/integration/blueprints/site/user_message/test_send.py +0 -2
@@ 17,7 17,6 @@ def site1(make_brand, make_email_config):
    brand = make_brand('acme-brand-1', 'ACME Brand 1')

    email_config = make_email_config(
        'acme-noreply',
        brand.id,
        sender_address='noreply@acmecon.test',
        sender_name='ACME Entertainment Convention',


@@ 40,7 39,6 @@ def site2(make_brand, make_email_config):
    brand = make_brand('acme-brand-2', 'ACME Brand 2')

    email_config = make_email_config(
        'acme-noreply-with-contact-address',
        brand.id,
        sender_address='noreply@acmecon.test',
        sender_name='ACME Entertainment Convention',