mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-19 19:09:22 +02:00
Merge remote-tracking branch 'origin/main' into nl/2136-CISA-rep-additional-details
This commit is contained in:
commit
09f872061f
24 changed files with 369 additions and 44 deletions
2
.github/workflows/deploy-sandbox.yaml
vendored
2
.github/workflows/deploy-sandbox.yaml
vendored
|
@ -25,6 +25,8 @@ jobs:
|
|||
|| startsWith(github.head_ref, 'meoward/')
|
||||
|| startsWith(github.head_ref, 'bob/')
|
||||
|| startsWith(github.head_ref, 'cb/')
|
||||
|| startsWith(github.head_ref, 'hotgov/')
|
||||
|| startsWith(github.head_ref, 'litterbox/')
|
||||
outputs:
|
||||
environment: ${{ steps.var.outputs.environment}}
|
||||
runs-on: "ubuntu-latest"
|
||||
|
|
2
.github/workflows/migrate.yaml
vendored
2
.github/workflows/migrate.yaml
vendored
|
@ -16,6 +16,8 @@ on:
|
|||
- stable
|
||||
- staging
|
||||
- development
|
||||
- litterbox
|
||||
- hotgov
|
||||
- cb
|
||||
- bob
|
||||
- meoward
|
||||
|
|
2
.github/workflows/reset-db.yaml
vendored
2
.github/workflows/reset-db.yaml
vendored
|
@ -16,6 +16,8 @@ on:
|
|||
options:
|
||||
- staging
|
||||
- development
|
||||
- litterbox
|
||||
- hotgov
|
||||
- cb
|
||||
- bob
|
||||
- meoward
|
||||
|
|
|
@ -320,16 +320,6 @@ it may help to resync your laptop with time.nist.gov:
|
|||
sudo sntp -sS time.nist.gov
|
||||
```
|
||||
|
||||
### Settings
|
||||
The config for the connection pool exists inside the `settings.py` file.
|
||||
| Name | Purpose |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------- |
|
||||
| EPP_CONNECTION_POOL_SIZE | Determines the number of concurrent sockets that should exist in the pool. |
|
||||
| POOL_KEEP_ALIVE | Determines the interval in which we ping open connections in seconds. Calculated as POOL_KEEP_ALIVE / EPP_CONNECTION_POOL_SIZE |
|
||||
| POOL_TIMEOUT | Determines how long we try to keep a pool alive for, before restarting it. |
|
||||
|
||||
Consider updating the `POOL_TIMEOUT` or `POOL_KEEP_ALIVE` periods if the pool often restarts. If the pool only restarts after a period of inactivity, update `POOL_KEEP_ALIVE`. If it restarts during the EPP call itself, then `POOL_TIMEOUT` needs to be updated.
|
||||
|
||||
## Adding a S3 instance to your sandbox
|
||||
This can either be done through the CLI, or through the cloud.gov dashboard. Generally, it is better to do it through the dashboard as it handles app binding for you.
|
||||
|
||||
|
|
|
@ -668,3 +668,32 @@ Example: `cf ssh getgov-za`
|
|||
|
||||
#### Step 1: Running the script
|
||||
```docker-compose exec app ./manage.py populate_verification_type```
|
||||
|
||||
|
||||
## Copy names from contacts to users
|
||||
|
||||
### Running on sandboxes
|
||||
|
||||
#### Step 1: Login to CloudFoundry
|
||||
```cf login -a api.fr.cloud.gov --sso```
|
||||
|
||||
#### Step 2: SSH into your environment
|
||||
```cf ssh getgov-{space}```
|
||||
|
||||
Example: `cf ssh getgov-za`
|
||||
|
||||
#### Step 3: Create a shell instance
|
||||
```/tmp/lifecycle/shell```
|
||||
|
||||
#### Step 4: Running the script
|
||||
```./manage.py copy_names_from_contacts_to_users --debug```
|
||||
|
||||
### Running locally
|
||||
|
||||
#### Step 1: Running the script
|
||||
```docker-compose exec app ./manage.py copy_names_from_contacts_to_users --debug```
|
||||
|
||||
##### Optional parameters
|
||||
| | Parameter | Description |
|
||||
|:-:|:-------------------------- |:----------------------------------------------------------------------------|
|
||||
| 1 | **debug** | Increases logging detail. Defaults to False. |
|
||||
|
|
32
ops/manifests/manifest-hotgov.yaml
Normal file
32
ops/manifests/manifest-hotgov.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
applications:
|
||||
- name: getgov-hotgov
|
||||
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
|
||||
health-check-invocation-timeout: 40
|
||||
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-hotgov.app.cloud.gov
|
||||
# Tell Django how much stuff to log
|
||||
DJANGO_LOG_LEVEL: INFO
|
||||
# default public site location
|
||||
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||
# Flag to disable/enable features in prod environments
|
||||
IS_PRODUCTION: False
|
||||
routes:
|
||||
- route: getgov-hotgov.app.cloud.gov
|
||||
services:
|
||||
- getgov-credentials
|
||||
- getgov-hotgov-database
|
32
ops/manifests/manifest-litterbox.yaml
Normal file
32
ops/manifests/manifest-litterbox.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
applications:
|
||||
- name: getgov-litterbox
|
||||
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
|
||||
health-check-invocation-timeout: 40
|
||||
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-litterbox.app.cloud.gov
|
||||
# Tell Django how much stuff to log
|
||||
DJANGO_LOG_LEVEL: INFO
|
||||
# default public site location
|
||||
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||
# Flag to disable/enable features in prod environments
|
||||
IS_PRODUCTION: False
|
||||
routes:
|
||||
- route: getgov-litterbox.app.cloud.gov
|
||||
services:
|
||||
- getgov-credentials
|
||||
- getgov-litterbox-database
|
|
@ -383,6 +383,39 @@ class CustomLogEntryAdmin(LogEntryAdmin):
|
|||
change_form_template = "admin/change_form_no_submit.html"
|
||||
add_form_template = "admin/change_form_no_submit.html"
|
||||
|
||||
# Select log entry to change -> Log entries
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Log entries"
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
# #786: Skipping on updating audit log tab titles for now
|
||||
# def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
# if extra_context is None:
|
||||
# extra_context = {}
|
||||
|
||||
# log_entry = self.get_object(request, object_id)
|
||||
|
||||
# if log_entry:
|
||||
# # Reset title to empty string
|
||||
# extra_context["subtitle"] = ""
|
||||
# extra_context["tabtitle"] = ""
|
||||
|
||||
# object_repr = log_entry.object_repr # Hold name of the object
|
||||
# changes = log_entry.changes
|
||||
|
||||
# # Check if this is a log entry for an addition and related to the contact model
|
||||
# # Created [name] -> Created [name] contact | Change log entry
|
||||
# if (
|
||||
# all(new_value != "None" for field, (old_value, new_value) in changes.items())
|
||||
# and log_entry.content_type.model == "contact"
|
||||
# ):
|
||||
# extra_context["subtitle"] = f"Created {object_repr} contact"
|
||||
# extra_context["tabtitle"] = "Change log entry"
|
||||
|
||||
# return super().change_view(request, object_id, form_url, extra_context=extra_context)
|
||||
|
||||
|
||||
class AdminSortFields:
|
||||
_name_sort = ["first_name", "last_name", "email"]
|
||||
|
@ -594,7 +627,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
None,
|
||||
{"fields": ("username", "password", "status", "verification_type")},
|
||||
),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "title", "email", "phone")}),
|
||||
(
|
||||
"Permissions",
|
||||
{
|
||||
|
@ -625,7 +658,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
)
|
||||
},
|
||||
),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "title", "email", "phone")}),
|
||||
(
|
||||
"Permissions",
|
||||
{
|
||||
|
@ -778,6 +811,14 @@ class MyHostAdmin(AuditedAdmin, ImportExportModelAdmin):
|
|||
search_help_text = "Search by domain or host name."
|
||||
inlines = [HostIPInline]
|
||||
|
||||
# Select host to change -> Host
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Host"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class HostIpResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -793,6 +834,14 @@ class HostIpAdmin(AuditedAdmin, ImportExportModelAdmin):
|
|||
resource_classes = [HostIpResource]
|
||||
model = models.HostIP
|
||||
|
||||
# Select host ip to change -> Host ip
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Host IP"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class ContactResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -926,6 +975,14 @@ class ContactAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
|
||||
return super().change_view(request, object_id, form_url, extra_context=extra_context)
|
||||
|
||||
# Select contact to change -> Contacts
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Contacts"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class WebsiteResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -1043,6 +1100,21 @@ class UserDomainRoleAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
else:
|
||||
return response
|
||||
|
||||
# User Domain manager [email] is manager on domain [domain name] ->
|
||||
# Domain manager [email] on [domain name]
|
||||
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
|
||||
if object_id:
|
||||
obj = self.get_object(request, object_id)
|
||||
if obj:
|
||||
email = obj.user.email
|
||||
domain_name = obj.domain.name
|
||||
extra_context["subtitle"] = f"Domain manager {email} on {domain_name}"
|
||||
|
||||
return super().changeform_view(request, object_id, form_url, extra_context=extra_context)
|
||||
|
||||
|
||||
class DomainInvitationAdmin(ListHeaderAdmin):
|
||||
"""Custom domain invitation admin class."""
|
||||
|
@ -1079,6 +1151,14 @@ class DomainInvitationAdmin(ListHeaderAdmin):
|
|||
|
||||
change_form_template = "django/admin/email_clipboard_change_form.html"
|
||||
|
||||
# Select domain invitations to change -> Domain invitations
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Domain invitations"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class DomainInformationResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -1219,6 +1299,14 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
readonly_fields.extend([field for field in self.analyst_readonly_fields])
|
||||
return readonly_fields # Read-only fields for analysts
|
||||
|
||||
# Select domain information to change -> Domain information
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Domain information"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class DomainRequestResource(FsmModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -1678,11 +1766,17 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
if next_char.isdigit():
|
||||
should_apply_default_filter = True
|
||||
|
||||
# Select domain request to change -> Domain requests
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Domain requests"
|
||||
|
||||
if should_apply_default_filter:
|
||||
# modify the GET of the request to set the selected filter
|
||||
modified_get = copy.deepcopy(request.GET)
|
||||
modified_get["status__in"] = "submitted,in review,action needed"
|
||||
request.GET = modified_get
|
||||
|
||||
response = super().changelist_view(request, extra_context=extra_context)
|
||||
return response
|
||||
|
||||
|
@ -2248,6 +2342,14 @@ class DraftDomainAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
# If no redirection is needed, return the original response
|
||||
return response
|
||||
|
||||
# Select draft domain to change -> Draft domains
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "Draft domains"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class PublicContactResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -2292,6 +2394,20 @@ class PublicContactAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
change_form_template = "django/admin/email_clipboard_change_form.html"
|
||||
autocomplete_fields = ["domain"]
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
|
||||
if object_id:
|
||||
obj = self.get_object(request, object_id)
|
||||
if obj:
|
||||
name = obj.name
|
||||
email = obj.email
|
||||
registry_id = obj.registry_id
|
||||
extra_context["subtitle"] = f"{name} <{email}> id: {registry_id}"
|
||||
|
||||
return super().changeform_view(request, object_id, form_url, extra_context=extra_context)
|
||||
|
||||
|
||||
class VerifiedByStaffAdmin(ListHeaderAdmin):
|
||||
list_display = ("email", "requestor", "truncated_notes", "created_at")
|
||||
|
@ -2344,6 +2460,14 @@ class UserGroupAdmin(AuditedAdmin):
|
|||
def user_group(self, obj):
|
||||
return obj.name
|
||||
|
||||
# Select user groups to change -> User groups
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
if extra_context is None:
|
||||
extra_context = {}
|
||||
extra_context["tabtitle"] = "User groups"
|
||||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
|
||||
class WaffleFlagAdmin(FlagAdmin):
|
||||
"""Custom admin implementation of django-waffle's Flag class"""
|
||||
|
|
|
@ -659,6 +659,8 @@ ALLOWED_HOSTS = [
|
|||
"getgov-stable.app.cloud.gov",
|
||||
"getgov-staging.app.cloud.gov",
|
||||
"getgov-development.app.cloud.gov",
|
||||
"getgov-litterbox.app.cloud.gov",
|
||||
"getgov-hotgov.app.cloud.gov",
|
||||
"getgov-cb.app.cloud.gov",
|
||||
"getgov-bob.app.cloud.gov",
|
||||
"getgov-meoward.app.cloud.gov",
|
||||
|
|
|
@ -10,6 +10,7 @@ from registrar.management.commands.utility.terminal_helper import (
|
|||
)
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.models.user import User
|
||||
from registrar.models.utility.domain_helper import DomainHelper
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -110,13 +111,19 @@ class Command(BaseCommand):
|
|||
{TerminalColors.ENDC}""", # noqa
|
||||
)
|
||||
|
||||
# ---- UPDATE THE USER IF IT DOES NOT HAVE A FIRST AND LAST NAMES
|
||||
# ---- LET'S KEEP A LIGHT TOUCH
|
||||
if not eligible_user.first_name and not eligible_user.last_name:
|
||||
# (expression has type "str | None", variable has type "str | int | Combinable")
|
||||
# so we'll ignore type
|
||||
eligible_user.first_name = contact.first_name # type: ignore
|
||||
eligible_user.last_name = contact.last_name # type: ignore
|
||||
# Get the fields that exist on both User and Contact. Excludes id.
|
||||
common_fields = DomainHelper.get_common_fields(User, Contact)
|
||||
if "email" in common_fields:
|
||||
# Don't change the email field.
|
||||
common_fields.remove("email")
|
||||
|
||||
for field in common_fields:
|
||||
# Grab the value that contact has stored for this field
|
||||
new_value = getattr(contact, field)
|
||||
|
||||
# Set it on the user field
|
||||
setattr(eligible_user, field, new_value)
|
||||
|
||||
eligible_user.save()
|
||||
processed_user = eligible_user
|
||||
|
||||
|
|
19
src/registrar/migrations/0097_alter_user_phone.py
Normal file
19
src/registrar/migrations/0097_alter_user_phone.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.10 on 2024-06-06 18:38
|
||||
|
||||
from django.db import migrations
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0096_alter_contact_email_alter_contact_first_name_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="phone",
|
||||
field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True, region=None),
|
||||
),
|
||||
]
|
32
src/registrar/migrations/0098_alter_domainrequest_status.py
Normal file
32
src/registrar/migrations/0098_alter_domainrequest_status.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 4.2.10 on 2024-06-07 15:27
|
||||
|
||||
from django.db import migrations
|
||||
import django_fsm
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0097_alter_user_phone"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="domainrequest",
|
||||
name="status",
|
||||
field=django_fsm.FSMField(
|
||||
choices=[
|
||||
("in review", "In review"),
|
||||
("action needed", "Action needed"),
|
||||
("approved", "Approved"),
|
||||
("rejected", "Rejected"),
|
||||
("ineligible", "Ineligible"),
|
||||
("submitted", "Submitted"),
|
||||
("withdrawn", "Withdrawn"),
|
||||
("started", "Started"),
|
||||
],
|
||||
default="started",
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
]
|
|
@ -123,11 +123,21 @@ class Contact(TimeStampedModel):
|
|||
self.user.last_name = self.last_name
|
||||
updated = True
|
||||
|
||||
# Update middle_name if necessary
|
||||
if not self.user.middle_name:
|
||||
self.user.middle_name = self.middle_name
|
||||
updated = True
|
||||
|
||||
# Update phone if necessary
|
||||
if not self.user.phone:
|
||||
self.user.phone = self.phone
|
||||
updated = True
|
||||
|
||||
# Update title if necessary
|
||||
if not self.user.title:
|
||||
self.user.title = self.title
|
||||
updated = True
|
||||
|
||||
# Save user if any updates were made
|
||||
if updated:
|
||||
self.user.save()
|
||||
|
|
|
@ -43,14 +43,14 @@ class DomainRequest(TimeStampedModel):
|
|||
|
||||
# Constants for choice fields
|
||||
class DomainRequestStatus(models.TextChoices):
|
||||
STARTED = "started", "Started"
|
||||
SUBMITTED = "submitted", "Submitted"
|
||||
IN_REVIEW = "in review", "In review"
|
||||
ACTION_NEEDED = "action needed", "Action needed"
|
||||
APPROVED = "approved", "Approved"
|
||||
WITHDRAWN = "withdrawn", "Withdrawn"
|
||||
REJECTED = "rejected", "Rejected"
|
||||
INELIGIBLE = "ineligible", "Ineligible"
|
||||
SUBMITTED = "submitted", "Submitted"
|
||||
WITHDRAWN = "withdrawn", "Withdrawn"
|
||||
STARTED = "started", "Started"
|
||||
|
||||
class StateTerritoryChoices(models.TextChoices):
|
||||
ALABAMA = "AL", "Alabama (AL)"
|
||||
|
|
|
@ -87,7 +87,6 @@ class User(AbstractUser):
|
|||
phone = PhoneNumberField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Phone",
|
||||
)
|
||||
|
||||
middle_name = models.CharField(
|
||||
|
|
|
@ -24,9 +24,11 @@ def handle_profile(sender, instance, **kwargs):
|
|||
"""
|
||||
|
||||
first_name = getattr(instance, "first_name", "")
|
||||
middle_name = getattr(instance, "middle_name", "")
|
||||
last_name = getattr(instance, "last_name", "")
|
||||
email = getattr(instance, "email", "")
|
||||
phone = getattr(instance, "phone", "")
|
||||
title = getattr(instance, "title", "")
|
||||
|
||||
is_new_user = kwargs.get("created", False)
|
||||
|
||||
|
@ -39,9 +41,11 @@ def handle_profile(sender, instance, **kwargs):
|
|||
Contact.objects.create(
|
||||
user=instance,
|
||||
first_name=first_name,
|
||||
middle_name=middle_name,
|
||||
last_name=last_name,
|
||||
email=email,
|
||||
phone=phone,
|
||||
title=title,
|
||||
)
|
||||
|
||||
if len(contacts) >= 1 and is_new_user: # a matching contact
|
||||
|
|
|
@ -26,7 +26,18 @@
|
|||
<script type="application/javascript" src="{% static 'js/dja-collapse.js' %}" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
|
||||
{% block title %}
|
||||
{% if subtitle %}
|
||||
{{ subtitle }} |
|
||||
{% endif %}
|
||||
{% if tabtitle %}
|
||||
{{ tabtitle }} |
|
||||
{% else %}
|
||||
{{ title }} |
|
||||
{% endif %}
|
||||
{{ site_title|default:_('Django site admin') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/styles.css' %}" />
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "domain_base.html" %}
|
||||
{% load static field_helpers url_helpers %}
|
||||
|
||||
{% block title %}Domain authorizing official | {{ domain.name }} | {% endblock %}
|
||||
{% block title %}Authorizing official | {{ domain.name }} | {% endblock %}
|
||||
|
||||
{% block domain_content %}
|
||||
{# this is right after the messages block in the parent template #}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Domain: {{ domain.name }} | {% endblock %}
|
||||
{% block title %}{{ domain.name }} | {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid-container">
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static form_helpers url_helpers %}
|
||||
|
||||
{% block title %} Start a request | {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" class="grid-container">
|
||||
<div class="grid-col desktop:grid-offset-2 desktop:grid-col-8">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="usa-logo display-inline-block" id="extended-logo">
|
||||
<strong class="usa-logo__text" >
|
||||
{% if logo_clickable %}
|
||||
<a href="{% url 'home' %}">.gov Registrar </a>
|
||||
<a href="{% url 'home' %}">.gov Registrar</a>
|
||||
{% else %}
|
||||
<button
|
||||
class="usa-button--unstyled disabled-button usa-tooltip"
|
||||
|
|
|
@ -3538,7 +3538,7 @@ class TestMyUserAdmin(TestCase):
|
|||
)
|
||||
},
|
||||
),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}),
|
||||
("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "title", "email", "phone")}),
|
||||
("Permissions", {"fields": ("is_active", "groups")}),
|
||||
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||
)
|
||||
|
|
|
@ -23,15 +23,32 @@ class TestDataUpdates(TestCase):
|
|||
self.bs_user = User.objects.create()
|
||||
|
||||
self.contact1 = Contact.objects.create(
|
||||
user=self.user1, email="email1@igorville.gov", first_name="first1", last_name="last1"
|
||||
user=self.user1,
|
||||
email="email1@igorville.gov",
|
||||
first_name="first1",
|
||||
last_name="last1",
|
||||
middle_name="middle1",
|
||||
title="title1",
|
||||
)
|
||||
self.contact2 = Contact.objects.create(
|
||||
user=self.user2, email="email2@igorville.gov", first_name="first2", last_name="last2"
|
||||
user=self.user2,
|
||||
email="email2@igorville.gov",
|
||||
first_name="first2",
|
||||
last_name="last2",
|
||||
middle_name="middle2",
|
||||
title="title2",
|
||||
)
|
||||
self.contact3 = Contact.objects.create(
|
||||
user=self.user3, email="email3@igorville.gov", first_name="first3", last_name="last3"
|
||||
user=self.user3,
|
||||
email="email3@igorville.gov",
|
||||
first_name="first3",
|
||||
last_name="last3",
|
||||
middle_name="middle3",
|
||||
title="title3",
|
||||
)
|
||||
self.contact4 = Contact.objects.create(
|
||||
email="email4@igorville.gov", first_name="first4", last_name="last4", middle_name="middle4", title="title4"
|
||||
)
|
||||
self.contact4 = Contact.objects.create(email="email4@igorville.gov", first_name="first4", last_name="last4")
|
||||
|
||||
self.command = Command()
|
||||
|
||||
|
@ -42,14 +59,15 @@ class TestDataUpdates(TestCase):
|
|||
Contact.objects.all().delete()
|
||||
|
||||
def test_script_updates_linked_users(self):
|
||||
"""Test the script that copies contacts' first and last names into associated users that
|
||||
are eligible (first or last are blank or undefined)"""
|
||||
"""Test the script that copies contact information to the user object"""
|
||||
|
||||
# Set up the users' first and last names here so
|
||||
# they that they don't get overwritten by Contact's save()
|
||||
# User with no first or last names
|
||||
self.user1.first_name = ""
|
||||
self.user1.last_name = ""
|
||||
self.user1.title = "dummytitle"
|
||||
self.user1.middle_name = "dummymiddle"
|
||||
self.user1.save()
|
||||
|
||||
# User with a first name but no last name
|
||||
|
@ -87,12 +105,20 @@ class TestDataUpdates(TestCase):
|
|||
# The user that has no first and last names will get them from the contact
|
||||
self.assertEqual(self.user1.first_name, "first1")
|
||||
self.assertEqual(self.user1.last_name, "last1")
|
||||
# The user that has a first but no last will be left alone
|
||||
self.assertEqual(self.user2.first_name, "First name but no last name")
|
||||
self.assertEqual(self.user2.last_name, "")
|
||||
# The user that has a first and a last will be left alone
|
||||
self.assertEqual(self.user3.first_name, "An existing first name")
|
||||
self.assertEqual(self.user3.last_name, "An existing last name")
|
||||
self.assertEqual(self.user1.middle_name, "middle1")
|
||||
self.assertEqual(self.user1.title, "title1")
|
||||
# The user that has a first but no last will be updated
|
||||
self.assertEqual(self.user2.first_name, "first2")
|
||||
self.assertEqual(self.user2.last_name, "last2")
|
||||
self.assertEqual(self.user2.middle_name, "middle2")
|
||||
self.assertEqual(self.user2.title, "title2")
|
||||
# The user that has a first and a last will be updated
|
||||
self.assertEqual(self.user3.first_name, "first3")
|
||||
self.assertEqual(self.user3.last_name, "last3")
|
||||
self.assertEqual(self.user3.middle_name, "middle3")
|
||||
self.assertEqual(self.user3.title, "title3")
|
||||
# The unlinked user will be left alone
|
||||
self.assertEqual(self.user4.first_name, "")
|
||||
self.assertEqual(self.user4.last_name, "")
|
||||
self.assertEqual(self.user4.middle_name, None)
|
||||
self.assertEqual(self.user4.title, None)
|
||||
|
|
|
@ -1087,7 +1087,7 @@ class TestDomainAuthorizingOfficial(TestDomainOverview):
|
|||
"""Can load domain's authorizing official page."""
|
||||
page = self.client.get(reverse("domain-authorizing-official", kwargs={"pk": self.domain.id}))
|
||||
# once on the sidebar, once in the title
|
||||
self.assertContains(page, "Authorizing official", count=2)
|
||||
self.assertContains(page, "Authorizing official", count=3)
|
||||
|
||||
def test_domain_authorizing_official_content(self):
|
||||
"""Authorizing official information appears on the page."""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue