diff --git a/README.md b/README.md index d2dbc9892..8d31a6be3 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Create a local environment.sh file containing the following: ``` echo " -export NOTIFY_API_ENVIRONMENT='config.Development' +export NOTIFY_ENVIRONMENT='development' export ADMIN_BASE_URL='http://localhost:6012' export ADMIN_CLIENT_SECRET='dev-notify-secret-key' export ADMIN_CLIENT_USER_NAME='dev-notify-admin' diff --git a/app/models.py b/app/models.py index f236841ac..e3aeb3d13 100644 --- a/app/models.py +++ b/app/models.py @@ -5,7 +5,7 @@ from sqlalchemy.dialects.postgresql import ( UUID, JSON ) -from sqlalchemy import UniqueConstraint +from sqlalchemy import UniqueConstraint, text from app.encryption import ( hashpw, @@ -74,6 +74,24 @@ user_to_service = db.Table( ) +BRANDING_GOVUK = 'govuk' +BRANDING_ORG = 'org' +BRANDING_BOTH = 'both' + + +class BrandingTypes(db.Model): + __tablename__ = 'branding_type' + name = db.Column(db.String(255), primary_key=True) + + +class Organisation(db.Model): + __tablename__ = 'organisation' + id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + colour = db.Column(db.String(7), nullable=True) + logo = db.Column(db.String(255), nullable=True) + name = db.Column(db.String(255), nullable=True) + + class Service(db.Model, Versioned): __tablename__ = 'services' @@ -104,6 +122,15 @@ class Service(db.Model, Versioned): created_by_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), index=True, nullable=False) reply_to_email_address = db.Column(db.Text, index=False, unique=False, nullable=True) sms_sender = db.Column(db.String(11), nullable=True) + organisation_id = db.Column(UUID(as_uuid=True), db.ForeignKey('organisation.id'), index=True, nullable=True) + organisation = db.relationship('Organisation') + branding = db.Column( + db.String(255), + db.ForeignKey('branding_type.name'), + index=True, + nullable=False, + default=BRANDING_GOVUK + ) class ApiKey(db.Model, Versioned): diff --git a/app/schemas.py b/app/schemas.py index 659ea996f..ea71ac341 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -114,12 +114,13 @@ class ServiceSchema(BaseSchema): 'old_id', 'template_statistics', 'service_provider_stats', - 'service_notification_stats') + 'service_notification_stats', + 'organisation') strict = True @validates('sms_sender') def validate_sms_sender(self, value): - if value and not re.match('^[a-zA-Z0-9\s]+$', value): + if value and not re.match(r'^[a-zA-Z0-9\s]+$', value): raise ValidationError('Only alphanumeric characters allowed') @@ -136,7 +137,8 @@ class DetailedServiceSchema(BaseSchema): 'jobs', 'template_statistics', 'service_provider_stats', - 'service_notification_stats' + 'service_notification_stats', + 'organisation' ) diff --git a/migrations/versions/0046_organisations_and_branding.py b/migrations/versions/0046_organisations_and_branding.py new file mode 100644 index 000000000..e36d2ded6 --- /dev/null +++ b/migrations/versions/0046_organisations_and_branding.py @@ -0,0 +1,57 @@ +"""empty message + +Revision ID: 0046_organisations_and_branding +Revises: 0045_billable_units +Create Date: 2016-08-04 12:00:43.682610 + +""" + +# revision identifiers, used by Alembic. +revision = '0046_organisations_and_branding' +down_revision = '0045_billable_units' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +def upgrade(): + op.create_table('branding_type', + sa.Column('name', sa.String(length=255), nullable=False), + sa.PrimaryKeyConstraint('name') + ) + op.create_table('organisation', + sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('colour', sa.String(length=7), nullable=True), + sa.Column('logo', sa.String(length=255), nullable=True), + sa.Column('name', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + + op.add_column('services', sa.Column('branding', sa.String(length=255))) + op.add_column('services', sa.Column('organisation_id', postgresql.UUID(as_uuid=True))) + op.add_column('services_history', sa.Column('branding', sa.String(length=255))) + op.add_column('services_history', sa.Column('organisation_id', postgresql.UUID(as_uuid=True))) + + op.execute("INSERT INTO branding_type VALUES ('govuk'), ('org'), ('both')") + op.execute("UPDATE services SET branding='govuk'") + op.execute("UPDATE services_history SET branding='govuk'") + + op.alter_column('services', 'branding', nullable=False) + op.alter_column('services_history', 'branding', nullable=False) + + op.create_index(op.f('ix_services_branding'), 'services', ['branding'], unique=False) + op.create_index(op.f('ix_services_organisation_id'), 'services', ['organisation_id'], unique=False) + op.create_index(op.f('ix_services_history_branding'), 'services_history', ['branding'], unique=False) + op.create_index(op.f('ix_services_history_organisation_id'), 'services_history', ['organisation_id'], unique=False) + + op.create_foreign_key(None, 'services', 'branding_type', ['branding'], ['name']) + op.create_foreign_key(None, 'services', 'organisation', ['organisation_id'], ['id']) + + +def downgrade(): + op.drop_column('services_history', 'organisation_id') + op.drop_column('services_history', 'branding') + op.drop_column('services', 'organisation_id') + op.drop_column('services', 'branding') + op.drop_table('organisation') + op.drop_table('branding_type') diff --git a/tests/conftest.py b/tests/conftest.py index 0f88fe667..cf1789d6e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -49,7 +49,7 @@ def notify_db_session(request, notify_db): def teardown(): notify_db.session.remove() for tbl in reversed(notify_db.metadata.sorted_tables): - if tbl.name not in ["provider_details", "key_types"]: + if tbl.name not in ["provider_details", "key_types", "branding_type"]: notify_db.engine.execute(tbl.delete()) notify_db.session.commit()