diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml index e7e38856b..7c2a0fe6a 100644 --- a/.github/workflows/deploy-sandbox.yaml +++ b/.github/workflows/deploy-sandbox.yaml @@ -40,7 +40,7 @@ jobs: docker compose run node npx gulp compile - name: Collect static assets working-directory: ./src - run: docker compose run app python manage.py collectstatic + run: docker compose run app python manage.py collectstatic --no-input - name: Deploy to cloud.gov sandbox uses: 18f/cg-deploy-action@main env: @@ -69,4 +69,4 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, body: '🥳 Successfully deployed to developer sandbox **[${{ env.ENVIRONMENT }}](https://getgov-${{ env.ENVIRONMENT }}.app.cloud.gov/)**.' - }) \ No newline at end of file + }) diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index a3086db50..30caf3713 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -49,7 +49,7 @@ class ViewsTest(TestCase): # assert self.assertEqual(response.status_code, 500) self.assertTemplateUsed(response, "500.html") - self.assertIn("Server Error", response.content.decode("utf-8")) + self.assertIn("server error", response.content.decode("utf-8")) def test_login_callback_reads_next(self, mock_client): # setup diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 30c8e8b89..439dfd9f9 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -55,6 +55,7 @@ admin.site.register(models.UserDomainRole, AuditedAdmin) admin.site.register(models.Contact, AuditedAdmin) admin.site.register(models.DomainInvitation, AuditedAdmin) admin.site.register(models.DomainApplication, AuditedAdmin) +admin.site.register(models.DomainInformation, AuditedAdmin) admin.site.register(models.Domain, AuditedAdmin) admin.site.register(models.Host, MyHostAdmin) admin.site.register(models.Nameserver, MyHostAdmin) diff --git a/src/registrar/assets/sass/_theme/_uswds-theme-custom-styles.scss b/src/registrar/assets/sass/_theme/_uswds-theme-custom-styles.scss index d43e82c9b..dbb4f4ef7 100644 --- a/src/registrar/assets/sass/_theme/_uswds-theme-custom-styles.scss +++ b/src/registrar/assets/sass/_theme/_uswds-theme-custom-styles.scss @@ -417,6 +417,10 @@ footer { color: color('primary'); } +.usa-identifier__logo { + height: units(7); +} + abbr[title] { // workaround for underlining abbr element border-bottom: none; diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py index ee226b7cb..0161527e1 100644 --- a/src/registrar/fixtures.py +++ b/src/registrar/fixtures.py @@ -44,6 +44,21 @@ class UserFixture: "first_name": "Neil", "last_name": "Martinsen-Burrell", }, + { + "username": "7185e6cd-d3c8-4adc-90a3-ceddba71d24f", + "first_name": "Jon", + "last_name": "Roberts", + }, + { + "username": "5f283494-31bd-49b5-b024-a7e7cae00848", + "first_name": "Rachid", + "last_name": "Mrad", + }, + { + "username": "eb2214cd-fc0c-48c0-9dbd-bc4cd6820c74", + "first_name": "Alysia", + "last_name": "Broddrick", + }, ] @classmethod diff --git a/src/registrar/migrations/0018_domaininformation.py b/src/registrar/migrations/0018_domaininformation.py new file mode 100644 index 000000000..408fa048b --- /dev/null +++ b/src/registrar/migrations/0018_domaininformation.py @@ -0,0 +1,273 @@ +# Generated by Django 4.1.6 on 2023-05-08 15:30 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0017_alter_domainapplication_status_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="DomainInformation", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "organization_type", + models.CharField( + blank=True, + choices=[ + ( + "federal", + "Federal: an agency of the U.S. government's executive, legislative, or judicial branches", + ), + ( + "interstate", + "Interstate: an organization of two or more states", + ), + ( + "state_or_territory", + "State or territory: one of the 50 U.S. states, the District of Columbia, American Samoa, Guam, Northern Mariana Islands, Puerto Rico, or the U.S. Virgin Islands", + ), + ( + "tribal", + "Tribal: a tribal government recognized by the federal or a state government", + ), + ("county", "County: a county, parish, or borough"), + ("city", "City: a city, town, township, village, etc."), + ( + "special_district", + "Special district: an independent organization within a single state", + ), + ( + "school_district", + "School district: a school district that is not part of a local government", + ), + ], + help_text="Type of Organization", + max_length=255, + null=True, + ), + ), + ( + "federally_recognized_tribe", + models.BooleanField( + help_text="Is the tribe federally recognized", null=True + ), + ), + ( + "state_recognized_tribe", + models.BooleanField( + help_text="Is the tribe recognized by a state", null=True + ), + ), + ( + "tribe_name", + models.TextField(blank=True, help_text="Name of tribe", null=True), + ), + ( + "federal_agency", + models.TextField(blank=True, help_text="Federal agency", null=True), + ), + ( + "federal_type", + models.CharField( + blank=True, + choices=[ + ("executive", "Executive"), + ("judicial", "Judicial"), + ("legislative", "Legislative"), + ], + help_text="Federal government branch", + max_length=50, + null=True, + ), + ), + ( + "is_election_board", + models.BooleanField( + blank=True, + help_text="Is your organization an election office?", + null=True, + ), + ), + ( + "organization_name", + models.TextField( + blank=True, + db_index=True, + help_text="Organization name", + null=True, + ), + ), + ( + "address_line1", + models.TextField(blank=True, help_text="Street address", null=True), + ), + ( + "address_line2", + models.CharField( + blank=True, + help_text="Street address line 2", + max_length=15, + null=True, + ), + ), + ("city", models.TextField(blank=True, help_text="City", null=True)), + ( + "state_territory", + models.CharField( + blank=True, + help_text="State, territory, or military post", + max_length=2, + null=True, + ), + ), + ( + "zipcode", + models.CharField( + blank=True, + db_index=True, + help_text="Zip code", + max_length=10, + null=True, + ), + ), + ( + "urbanization", + models.TextField( + blank=True, + help_text="Urbanization (Puerto Rico only)", + null=True, + ), + ), + ( + "type_of_work", + models.TextField( + blank=True, + help_text="Type of work of the organization", + null=True, + ), + ), + ( + "more_organization_information", + models.TextField( + blank=True, + help_text="Further information about the government organization", + null=True, + ), + ), + ( + "purpose", + models.TextField( + blank=True, help_text="Purpose of your domain", null=True + ), + ), + ( + "no_other_contacts_rationale", + models.TextField( + blank=True, + help_text="Reason for listing no additional contacts", + null=True, + ), + ), + ( + "anything_else", + models.TextField( + blank=True, help_text="Anything else we should know?", null=True + ), + ), + ( + "is_policy_acknowledged", + models.BooleanField( + blank=True, + help_text="Acknowledged .gov acceptable use policy", + null=True, + ), + ), + ( + "security_email", + models.EmailField( + blank=True, + help_text="Security email for public use", + max_length=320, + null=True, + ), + ), + ( + "authorizing_official", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="information_authorizing_official", + to="registrar.contact", + ), + ), + ( + "creator", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="information_created", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "domain", + models.OneToOneField( + blank=True, + help_text="Domain to which this information belongs", + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="domain_info", + to="registrar.domain", + ), + ), + ( + "domain_application", + models.OneToOneField( + blank=True, + help_text="Associated domain application", + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="domainapplication_info", + to="registrar.domainapplication", + ), + ), + ( + "other_contacts", + models.ManyToManyField( + blank=True, + related_name="contact_applications_information", + to="registrar.contact", + ), + ), + ( + "submitter", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="submitted_applications_information", + to="registrar.contact", + ), + ), + ], + options={ + "verbose_name_plural": "Domain Information", + }, + ), + ] diff --git a/src/registrar/migrations/0019_alter_domainapplication_organization_type.py b/src/registrar/migrations/0019_alter_domainapplication_organization_type.py new file mode 100644 index 000000000..1a7397255 --- /dev/null +++ b/src/registrar/migrations/0019_alter_domainapplication_organization_type.py @@ -0,0 +1,47 @@ +# Generated by Django 4.1.6 on 2023-05-09 19:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0018_domaininformation"), + ] + + operations = [ + migrations.AlterField( + model_name="domainapplication", + name="organization_type", + field=models.CharField( + blank=True, + choices=[ + ( + "federal", + "Federal: an agency of the U.S. government's executive, legislative, or judicial branches", + ), + ("interstate", "Interstate: an organization of two or more states"), + ( + "state_or_territory", + "State or territory: one of the 50 U.S. states, the District of Columbia, American Samoa, Guam, Northern Mariana Islands, Puerto Rico, or the U.S. Virgin Islands", + ), + ( + "tribal", + "Tribal: a tribal government recognized by the federal or a state government", + ), + ("county", "County: a county, parish, or borough"), + ("city", "City: a city, town, township, village, etc."), + ( + "special_district", + "Special district: an independent organization within a single state", + ), + ( + "school_district", + "School district: a school district that is not part of a local government", + ), + ], + help_text="Type of organization", + max_length=255, + null=True, + ), + ), + ] diff --git a/src/registrar/models/__init__.py b/src/registrar/models/__init__.py index 0fcfeca40..9351e312d 100644 --- a/src/registrar/models/__init__.py +++ b/src/registrar/models/__init__.py @@ -2,6 +2,7 @@ from auditlog.registry import auditlog # type: ignore from .contact import Contact from .domain_application import DomainApplication +from .domain_information import DomainInformation from .domain import Domain from .host_ip import HostIP from .host import Host @@ -15,6 +16,7 @@ from .website import Website __all__ = [ "Contact", "DomainApplication", + "DomainInformation", "Domain", "DomainInvitation", "HostIP", diff --git a/src/registrar/models/domain_application.py b/src/registrar/models/domain_application.py index ca7f4d76f..44c93892c 100644 --- a/src/registrar/models/domain_application.py +++ b/src/registrar/models/domain_application.py @@ -9,7 +9,7 @@ from django_fsm import FSMField, transition # type: ignore from .utility.time_stamped_model import TimeStampedModel from ..utility.email import send_templated_email, EmailSendingError - +from itertools import chain logger = logging.getLogger(__name__) @@ -520,6 +520,10 @@ class DomainApplication(TimeStampedModel): Domain = apps.get_model("registrar.Domain") created_domain, _ = Domain.objects.get_or_create(name=self.requested_domain) + # copy the information from domainapplication into domaininformation + DomainInformation = apps.get_model("registrar.DomainInformation") + DomainInformation.create_from_da(self) + # create the permission for the user UserDomainRole = apps.get_model("registrar.UserDomainRole") UserDomainRole.objects.get_or_create( @@ -577,3 +581,26 @@ class DomainApplication(TimeStampedModel): if self.organization_type == DomainApplication.OrganizationChoices.FEDERAL: return True return False + + def to_dict(self): + """This is to process to_dict for Domain Information, making it friendly + to "copy" it + + More information can be found at this- (This used #5) + https://stackoverflow.com/questions/21925671/convert-django-model-object-to-dict-with-all-of-the-fields-intact/29088221#29088221 + """ # noqa 590 + opts = self._meta + data = {} + for field in chain(opts.concrete_fields, opts.private_fields): + if field.get_internal_type() in ("ForeignKey", "OneToOneField"): + # get the related instance of the FK value + fk_id = field.value_from_object(self) + if fk_id: + data[field.name] = field.related_model.objects.get(id=fk_id) + else: + data[field.name] = None + else: + data[field.name] = field.value_from_object(self) + for field in opts.many_to_many: + data[field.name] = field.value_from_object(self) + return data diff --git a/src/registrar/models/domain_information.py b/src/registrar/models/domain_information.py new file mode 100644 index 000000000..6561a82b4 --- /dev/null +++ b/src/registrar/models/domain_information.py @@ -0,0 +1,250 @@ +from __future__ import annotations +from .domain_application import DomainApplication +from .utility.time_stamped_model import TimeStampedModel + +import logging + +from django.db import models + + +logger = logging.getLogger(__name__) + + +class DomainInformation(TimeStampedModel): + + """A registrant's domain information for that domain, exported from + DomainApplication. We use these field from DomainApplication with few exceptation + which are 'removed' via pop at the bottom of this file. Most of design for domain + management's user information are based on application, but we cannot change + the application once approved, so copying them that way we can make changes + after its approved. Most fields here are copied from Application.""" + + StateTerritoryChoices = DomainApplication.StateTerritoryChoices + + OrganizationChoices = DomainApplication.OrganizationChoices + + BranchChoices = DomainApplication.BranchChoices + + AGENCY_CHOICES = DomainApplication.AGENCY_CHOICES + + # This is the application user who created this application. The contact + # information that they gave is in the `submitter` field + creator = models.ForeignKey( + "registrar.User", + on_delete=models.PROTECT, + related_name="information_created", + ) + + domain_application = models.OneToOneField( + "registrar.DomainApplication", + on_delete=models.PROTECT, + blank=True, + null=True, + related_name="domainapplication_info", + help_text="Associated domain application", + unique=True, + ) + + # ##### data fields from the initial form ##### + organization_type = models.CharField( + max_length=255, + choices=OrganizationChoices.choices, + null=True, + blank=True, + help_text="Type of Organization", + ) + + federally_recognized_tribe = models.BooleanField( + null=True, + help_text="Is the tribe federally recognized", + ) + + state_recognized_tribe = models.BooleanField( + null=True, + help_text="Is the tribe recognized by a state", + ) + + tribe_name = models.TextField( + null=True, + blank=True, + help_text="Name of tribe", + ) + + federal_agency = models.TextField( + null=True, + blank=True, + help_text="Federal agency", + ) + + federal_type = models.CharField( + max_length=50, + choices=BranchChoices.choices, + null=True, + blank=True, + help_text="Federal government branch", + ) + + is_election_board = models.BooleanField( + null=True, + blank=True, + help_text="Is your organization an election office?", + ) + + organization_name = models.TextField( + null=True, + blank=True, + help_text="Organization name", + db_index=True, + ) + address_line1 = models.TextField( + null=True, + blank=True, + help_text="Street address", + ) + address_line2 = models.CharField( + max_length=15, + null=True, + blank=True, + help_text="Street address line 2", + ) + city = models.TextField( + null=True, + blank=True, + help_text="City", + ) + state_territory = models.CharField( + max_length=2, + null=True, + blank=True, + help_text="State, territory, or military post", + ) + zipcode = models.CharField( + max_length=10, + null=True, + blank=True, + help_text="Zip code", + db_index=True, + ) + urbanization = models.TextField( + null=True, + blank=True, + help_text="Urbanization (Puerto Rico only)", + ) + + type_of_work = models.TextField( + null=True, + blank=True, + help_text="Type of work of the organization", + ) + + more_organization_information = models.TextField( + null=True, + blank=True, + help_text="Further information about the government organization", + ) + + authorizing_official = models.ForeignKey( + "registrar.Contact", + null=True, + blank=True, + related_name="information_authorizing_official", + on_delete=models.PROTECT, + ) + + domain = models.OneToOneField( + "registrar.Domain", + on_delete=models.PROTECT, + blank=True, + null=True, + # Access this information via Domain as "domain.domain_info" + related_name="domain_info", + help_text="Domain to which this information belongs", + ) + + # This is the contact information provided by the applicant. The + # application user who created it is in the `creator` field. + submitter = models.ForeignKey( + "registrar.Contact", + null=True, + blank=True, + related_name="submitted_applications_information", + on_delete=models.PROTECT, + ) + + purpose = models.TextField( + null=True, + blank=True, + help_text="Purpose of your domain", + ) + + other_contacts = models.ManyToManyField( + "registrar.Contact", + blank=True, + related_name="contact_applications_information", + ) + + no_other_contacts_rationale = models.TextField( + null=True, + blank=True, + help_text="Reason for listing no additional contacts", + ) + + anything_else = models.TextField( + null=True, + blank=True, + help_text="Anything else we should know?", + ) + + is_policy_acknowledged = models.BooleanField( + null=True, + blank=True, + help_text="Acknowledged .gov acceptable use policy", + ) + security_email = models.EmailField( + max_length=320, + null=True, + blank=True, + help_text="Security email for public use", + ) + + def __str__(self): + try: + if self.domain and self.domain.name: + return self.domain.name + else: + return f"domain info set up and created by {self.creator}" + except Exception: + return "" + + @classmethod + def create_from_da(cls, domain_application): + """Takes in a DomainApplication dict and converts it into DomainInformation""" + da_dict = domain_application.to_dict() + # remove the id so one can be assinged on creation + da_id = da_dict.pop("id") + # check if we have a record that corresponds with the domain + # application, if so short circuit the create + domain_info = cls.objects.filter(domain_application__id=da_id).first() + if domain_info: + return domain_info + # the following information below is not needed in the domain information: + da_dict.pop("status") + da_dict.pop("current_websites") + da_dict.pop("investigator") + da_dict.pop("alternative_domains") + # use the requested_domain to create information for this domain + da_dict["domain"] = da_dict.pop("requested_domain") + other_contacts = da_dict.pop("other_contacts") + domain_info = cls(**da_dict) + domain_info.domain_application = domain_application + # Save so the object now have PK + # (needed to process the manytomany below before, first) + domain_info.save() + + # Process the remaining "many to many" stuff + domain_info.other_contacts.add(*other_contacts) + domain_info.save() + return domain_info + + class Meta: + verbose_name_plural = "Domain Information" diff --git a/src/registrar/public/img/registrar/dotgov_401_illo.svg b/src/registrar/public/img/registrar/dotgov_401_illo.svg new file mode 100644 index 000000000..71de33eaa --- /dev/null +++ b/src/registrar/public/img/registrar/dotgov_401_illo.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/registrar/public/img/registrar/dotgov_404_illo.svg b/src/registrar/public/img/registrar/dotgov_404_illo.svg new file mode 100644 index 000000000..3c9adab7e --- /dev/null +++ b/src/registrar/public/img/registrar/dotgov_404_illo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/registrar/public/img/registrar/dotgov_500_illo.svg b/src/registrar/public/img/registrar/dotgov_500_illo.svg new file mode 100644 index 000000000..6dd538644 --- /dev/null +++ b/src/registrar/public/img/registrar/dotgov_500_illo.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/registrar/templates/401.html b/src/registrar/templates/401.html index 64bcec563..9fe0194ed 100644 --- a/src/registrar/templates/401.html +++ b/src/registrar/templates/401.html @@ -1,28 +1,45 @@ {% extends "base.html" %} -{% load i18n %} +{% load i18n static %} -{% block title %}{% translate "Unauthorized" %}{% endblock %} +{% block title %}{% translate "Unauthorized | " %}{% endblock %} {% block content %}
-

{% translate "Unauthorized" %}

+
+
+

+ {% translate "You are not authorized to view this page" %} +

+

+ {% translate "Status 401" %} +

- {% if friendly_message %} -

{{ friendly_message }}

- {% else %} -

{% translate "Authorization failed." %}

- {% endif %} -

- {% translate "Would you like to try logging in again?" %} -

+ {% if friendly_message %} +

{{ friendly_message }}

+ {% else %} +

{% translate "Authorization failed." %}

+ {% endif %} +

+ You must be an authorized user and need to be signed in to view this page. + Would you like to try logging in again? +

+

+ If you would like help with this error contact us +

- {% if log_identifier %} -

Here's a unique identifier for this error.

-
{{ log_identifier }}
-

{% translate "Please include it if you contact us." %}

- {% endif %} - - TODO: Content team to create a "how to contact us" footer for the error pages + {% if log_identifier %} +

Here's a unique identifier for this error.

+

{{ log_identifier }}

+

{% translate "Please include it if you contact us." %}

+ {% endif %} +
+
+ +
+
{% endblock %} diff --git a/src/registrar/templates/403.html b/src/registrar/templates/403.html new file mode 100644 index 000000000..cc8c98656 --- /dev/null +++ b/src/registrar/templates/403.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} +{% load i18n static %} + +{% block title %}{% translate "Forbidden | " %}{% endblock %} + +{% block content %} +
+
+
+

+ {% translate "You do not have the right permissions to view this page." %} +

+

+ {% translate "Status 403" %} +

+ + + {% if friendly_message %} +

{{ friendly_message }}

+ {% else %} +

{% translate "Forbidden." %}

+ {% endif %} +

+ You must be an authorized user and need to be signed in to view this page. + Would you like to try logging in again? +

+

+ If you would like help with this error contact us +

+ + {% if log_identifier %} +

Here's a unique identifier for this error.

+

{{ log_identifier }}

+

{% translate "Please include it if you contact us." %}

+ {% endif %} +
+
+ +
+
+
+{% endblock %} diff --git a/src/registrar/templates/404.html b/src/registrar/templates/404.html index f715e0fa9..76a301187 100644 --- a/src/registrar/templates/404.html +++ b/src/registrar/templates/404.html @@ -1,15 +1,31 @@ - {% extends "base.html" %} -{% load i18n %} +{% load i18n static %} -{% block title %}{% translate "Page not found" %}{% endblock %} +{% block title %}{% translate "Page not found | " %}{% endblock %} {% block content %}
+
+
+

+ {% translate "We couldn’t find that page" %} +

+

+ {% translate "Status 404" %} +

-

{% translate "Page not found" %}

+

Try going to the homepage. If you can’t find what you’re looking for, contact us. +

+
+ +
+ +
+
-

{% translate "The requested page could not be found." %}

{% endblock %} diff --git a/src/registrar/templates/500.html b/src/registrar/templates/500.html index 5fbd30d2d..7b7e1dfed 100644 --- a/src/registrar/templates/500.html +++ b/src/registrar/templates/500.html @@ -1,24 +1,39 @@ {% extends "base.html" %} -{% load i18n %} +{% load i18n static %} -{% block title %}{% translate "Server error" %}{% endblock %} +{% block title %}{% translate "Server error | " %}{% endblock %} {% block content %}
-

{% translate "Server Error" %}

+
+
+

+ {% translate "We're having some trouble" %} +

+

+ {% translate "Status 500 – server error" %} +

+ {% if friendly_message %} +

{{ friendly_message }}

+ {% else %} +

+ Sorry! Try waiting a few minutes and then reloading the page. + Contact us if you need help. +

+ {% endif %} - {% if friendly_message %} -

{{ friendly_message }}

- {% else %} -

{% translate "An internal server error occurred." %}

- {% endif %} - - {% if log_identifier %} -

Here's a unique identifier for this error.

-
{{ log_identifier }}
-

{% translate "Please include it if you contact us." %}

- {% endif %} - - TODO: Content team to create a "how to contact us" footer for the error pages + {% if log_identifier %} +

Here's a unique identifier for this error.

+

{{ log_identifier }}

+

{% translate "Please include it if you contact us." %}

+ {% endif %} +
+
+ +
+
{% endblock %} diff --git a/src/registrar/templates/includes/footer.html b/src/registrar/templates/includes/footer.html index 929a49cce..ea7bd8420 100644 --- a/src/registrar/templates/includes/footer.html +++ b/src/registrar/templates/includes/footer.html @@ -52,7 +52,7 @@ src="{% static 'img/CISA_logo.png' %}" alt="CISA logo" role="img" - width="48px" + width="56px" />