diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml index d7ca9d71a..fe94a1351 100644 --- a/.github/workflows/deploy-sandbox.yaml +++ b/.github/workflows/deploy-sandbox.yaml @@ -16,6 +16,7 @@ jobs: || startsWith(github.head_ref, 'ko/') || startsWith(github.head_ref, 'gd/') || startsWith(github.head_ref, 'rh/') + || startsWith(github.head_ref, 'za/') outputs: environment: ${{ steps.var.outputs.environment}} runs-on: "ubuntu-latest" diff --git a/.github/workflows/migrate.yaml b/.github/workflows/migrate.yaml index dcd7eee66..66ca23992 100644 --- a/.github/workflows/migrate.yaml +++ b/.github/workflows/migrate.yaml @@ -16,6 +16,7 @@ on: - stable - staging - rh + - za - gd - rb - ko diff --git a/.github/workflows/reset-db.yaml b/.github/workflows/reset-db.yaml index e5af08808..2b1fbf08b 100644 --- a/.github/workflows/reset-db.yaml +++ b/.github/workflows/reset-db.yaml @@ -17,6 +17,7 @@ on: - stable - staging - rh + - za - gd - rb - ko diff --git a/docs/developer/README.md b/docs/developer/README.md index d824ea820..73000f35a 100644 --- a/docs/developer/README.md +++ b/docs/developer/README.md @@ -66,7 +66,7 @@ The endpoint /admin can be used to view and manage site content, including but n 1. Login via login.gov 2. Go to the home page and make sure you can see the part where you can submit an application 3. Go to /admin and it will tell you that UUID is not authorized, copy that UUID for use in 4 -4. in src/registrar/fixtures.py add to the ADMINS list in that file by adding your UUID as your username along with your first and last name. See below: +4. in src/registrar/fixtures.py add to the `ADMINS` list in that file by adding your UUID as your username along with your first and last name. See below: ``` ADMINS = [ @@ -79,8 +79,30 @@ The endpoint /admin can be used to view and manage site content, including but n ] ``` -5. In the browser, navigate to /admins. To verify that all is working correctly, under "domain applications" you should see fake domains with various fake statuses. +5. In the browser, navigate to /admin. To verify that all is working correctly, under "domain applications" you should see fake domains with various fake statuses. +### Adding an Analyst to /admin +Analysts are a variant of the admin role with limited permissions. The process for adding an Analyst is much the same as adding an admin: + +1. Login via login.gov (if you already exist as an admin, you will need to create a separate login.gov account for this: i.e. first.last+1@email.com) +2. Go to the home page and make sure you can see the part where you can submit an application +3. Go to /admin and it will tell you that UUID is not authorized, copy that UUID for use in 4 (this will be a different UUID than the one obtained from creating an admin) +4. in src/registrar/fixtures.py add to the `STAFF` list in that file by adding your UUID as your username along with your first and last name. See below: + +``` + STAFF = [ + { + "username": "", + "first_name": "", + "last_name": "", + }, + ... + ] +``` + +5. In the browser, navigate to /admin. To verify that all is working correctly, verify that you can only see a sub-section of the modules and some are set to view-only. + +Do note that if you wish to have both an analyst and admin account, append `-Analyst` to your first and last name, or use a completely different first/last name to avoid confusion. Example: `Bob-Analyst` ## Adding to CODEOWNERS (optional) The CODEOWNERS file sets the tagged individuals as default reviewers on any Pull Request that changes files that they are marked as owners of. diff --git a/ops/manifests/manifest-za.yaml b/ops/manifests/manifest-za.yaml new file mode 100644 index 000000000..fbacb6912 --- /dev/null +++ b/ops/manifests/manifest-za.yaml @@ -0,0 +1,29 @@ +--- +applications: +- name: getgov-za + buildpacks: + - python_buildpack + path: ../../src + instances: 1 + memory: 512M + stack: cflinuxfs4 + timeout: 180 + command: ./run.sh + health-check-type: http + health-check-http-endpoint: /health + env: + # Send stdout and stderr straight to the terminal without buffering + PYTHONUNBUFFERED: yup + # Tell Django where to find its configuration + DJANGO_SETTINGS_MODULE: registrar.config.settings + # Tell Django where it is being hosted + DJANGO_BASE_URL: https://getgov-za.app.cloud.gov + # Tell Django how much stuff to log + DJANGO_LOG_LEVEL: INFO + # default public site location + GETGOV_PUBLIC_SITE_URL: https://beta.get.gov + routes: + - route: getgov-za.app.cloud.gov + services: + - getgov-credentials + - getgov-za-database diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 183245e55..c67697487 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -572,6 +572,7 @@ ALLOWED_HOSTS = [ "getgov-stable.app.cloud.gov", "getgov-staging.app.cloud.gov", "getgov-rh.app.cloud.gov", + "getgov-za.app.cloud.gov", "getgov-gd.app.cloud.gov", "getgov-rb.app.cloud.gov", "getgov-ko.app.cloud.gov", diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py index 9ca20b2a0..01de666a4 100644 --- a/src/registrar/fixtures.py +++ b/src/registrar/fixtures.py @@ -62,6 +62,11 @@ class UserFixture: "first_name": "Zander", "last_name": "Adkinson", }, + { + "username": "bb21f687-c773-4df3-9243-111cfd4c0be4", + "first_name": "Paul", + "last_name": "Kuykendall", + }, ] STAFF = [ @@ -80,6 +85,11 @@ class UserFixture: "first_name": "Zander-Analyst", "last_name": "Adkinson-Analyst", }, + { + "username": "57ab5847-7789-49fe-a2f9-21d38076d699", + "first_name": "Paul-Analyst", + "last_name": "Kuykendall-Analyst", + }, ] STAFF_PERMISSIONS = [ diff --git a/src/registrar/templates/application_tribal_government.html b/src/registrar/templates/application_tribal_government.html index 83fbc98ff..3c2a8999f 100644 --- a/src/registrar/templates/application_tribal_government.html +++ b/src/registrar/templates/application_tribal_government.html @@ -3,7 +3,17 @@ {% block form_fields %} - {% input_with_errors forms.0.tribe_name %} + + {% with sublabel_text="Please include the entire name of your tribe as recognized by the Bureau of Indian Affairs." %} + {% with link_text="Bureau of Indian Affairs" %} + {% with link_href="https://www.federalregister.gov/documents/2023/01/12/2023-00504/indian-entities-recognized-by-and-eligible-to-receive-services-from-the-united-states-bureau-of" %} + {% with target_blank="true" %} + {% input_with_errors forms.0.tribe_name %} + {% endwith %} + {% endwith %} + {% endwith %} + {% endwith %} +

Is your organization a federally-recognized tribe or a state-recognized tribe? Check all that apply. diff --git a/src/registrar/templates/home.html b/src/registrar/templates/home.html index 6163a1ce0..792beec43 100644 --- a/src/registrar/templates/home.html +++ b/src/registrar/templates/home.html @@ -33,6 +33,8 @@ {% for domain in domains %} + {% comment %} ticket 796 + {% if domain.application_status == "approved" or (domain.application does not exist) %} {% endcomment %} {{ domain.name }} diff --git a/src/registrar/templates/includes/input_with_errors.html b/src/registrar/templates/includes/input_with_errors.html index 4e9de8195..b35ab1b7a 100644 --- a/src/registrar/templates/includes/input_with_errors.html +++ b/src/registrar/templates/includes/input_with_errors.html @@ -3,6 +3,8 @@ Template include for form fields with classes and their corresponding error messages, if necessary. {% endcomment %} +{% load custom_filters %} + {% load widget_tweaks %} {% if widget.attrs.maxlength %} @@ -29,8 +31,19 @@ error messages, if necessary. {% endif %} {% if sublabel_text %} -

{{ sublabel_text }}

- {% endif %} +

+ {% comment %} If the link_text appears more than once, the first instance will be a link and the other instances will be ignored {% endcomment %} + {% if link_text and link_text in sublabel_text %} + {% with link_index=sublabel_text|find_index:link_text %} + {{ sublabel_text|slice:link_index }} + {% comment %} HTML will convert a new line into a space, resulting with a space before the fullstop in case link_text is at the end of sublabel_text, hence the unfortunate line below {% endcomment %} + {{ link_text }}{% with sublabel_part_after=sublabel_text|slice_after:link_text %}{{ sublabel_part_after }}{% endwith %} + {% endwith %} + {% else %} + {{ sublabel_text }} + {% endif %} +

+ {% endif %} {% if field.errors %}
diff --git a/src/registrar/templatetags/custom_filters.py b/src/registrar/templatetags/custom_filters.py index a22b15a28..f16408bf8 100644 --- a/src/registrar/templatetags/custom_filters.py +++ b/src/registrar/templatetags/custom_filters.py @@ -23,3 +23,20 @@ def extract_a_text(value): extracted_text = "" return extracted_text + + +@register.filter +def find_index(haystack, needle): + try: + return haystack.index(needle) + except ValueError: + return -1 + + +@register.filter +def slice_after(value, substring): + index = value.find(substring) + if index != -1: + result = value[index + len(substring) :] + return result + return value diff --git a/src/registrar/tests/test_templatetags.py b/src/registrar/tests/test_templatetags.py index 0d1eed4fc..36325ab5d 100644 --- a/src/registrar/tests/test_templatetags.py +++ b/src/registrar/tests/test_templatetags.py @@ -3,6 +3,12 @@ from django.conf import settings from django.test import TestCase from django.template import Context, Template +from registrar.templatetags.custom_filters import ( + extract_value, + extract_a_text, + find_index, + slice_after, +) class TestTemplateTags(TestCase): @@ -33,8 +39,6 @@ class TestTemplateTags(TestCase): class CustomFiltersTestCase(TestCase): def test_extract_value_filter(self): - from registrar.templatetags.custom_filters import extract_value - html_input = ( '' @@ -50,8 +54,6 @@ class CustomFiltersTestCase(TestCase): self.assertEqual(result, "abc") def test_extract_a_text_filter(self): - from registrar.templatetags.custom_filters import extract_a_text - input_text = 'Link Text' result = extract_a_text(input_text) self.assertEqual(result, "Link Text") @@ -59,3 +61,25 @@ class CustomFiltersTestCase(TestCase): input_text = 'Another Link' result = extract_a_text(input_text) self.assertEqual(result, "Another Link") + + def test_find_index(self): + haystack = "Hello, World!" + needle = "lo" + result = find_index(haystack, needle) + self.assertEqual(result, 3) + + needle = "XYZ" + result = find_index(haystack, needle) + self.assertEqual(result, -1) + + def test_slice_after(self): + value = "Hello, World!" + substring = "lo" + result = slice_after(value, substring) + self.assertEqual(result, ", World!") + + substring = "XYZ" + result = slice_after(value, substring) + self.assertEqual( + result, value + ) # Should return the original value if substring not found diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index 890b10a02..05da75d35 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -24,6 +24,12 @@ class DomainPermission(PermissionsLoginMixin): The user is in self.request.user and the domain needs to be looked up from the domain's primary key in self.kwargs["pk"] """ + + # ticket 806 + # if self.request.user is staff or admin and + # domain.application__status = 'approved' or 'rejected' or 'action needed' + # return True + if not self.request.user.is_authenticated: return False @@ -33,6 +39,10 @@ class DomainPermission(PermissionsLoginMixin): ).exists(): return False + # ticket 796 + # if domain.application__status != 'approved' + # return false + # if we need to check more about the nature of role, do it here. return True