mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-17 18:09:25 +02:00
Merge branch 'za/bugfix-failing-migrations' into gd/1900-add-action-needed-reason
This commit is contained in:
commit
2a9d33defe
12 changed files with 154 additions and 38 deletions
|
@ -320,16 +320,6 @@ it may help to resync your laptop with time.nist.gov:
|
||||||
sudo sntp -sS 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
|
## 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.
|
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
|
#### Step 1: Running the script
|
||||||
```docker-compose exec app ./manage.py populate_verification_type```
|
```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. |
|
||||||
|
|
|
@ -609,7 +609,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
||||||
None,
|
None,
|
||||||
{"fields": ("username", "password", "status", "verification_type")},
|
{"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",
|
"Permissions",
|
||||||
{
|
{
|
||||||
|
@ -640,7 +640,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",
|
"Permissions",
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@ from registrar.management.commands.utility.terminal_helper import (
|
||||||
)
|
)
|
||||||
from registrar.models.contact import Contact
|
from registrar.models.contact import Contact
|
||||||
from registrar.models.user import User
|
from registrar.models.user import User
|
||||||
|
from registrar.models.utility.domain_helper import DomainHelper
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -110,13 +111,19 @@ class Command(BaseCommand):
|
||||||
{TerminalColors.ENDC}""", # noqa
|
{TerminalColors.ENDC}""", # noqa
|
||||||
)
|
)
|
||||||
|
|
||||||
# ---- UPDATE THE USER IF IT DOES NOT HAVE A FIRST AND LAST NAMES
|
# Get the fields that exist on both User and Contact. Excludes id.
|
||||||
# ---- LET'S KEEP A LIGHT TOUCH
|
common_fields = DomainHelper.get_common_fields(User, Contact)
|
||||||
if not eligible_user.first_name and not eligible_user.last_name:
|
if "email" in common_fields:
|
||||||
# (expression has type "str | None", variable has type "str | int | Combinable")
|
# Don't change the email field.
|
||||||
# so we'll ignore type
|
common_fields.remove("email")
|
||||||
eligible_user.first_name = contact.first_name # type: ignore
|
|
||||||
eligible_user.last_name = contact.last_name # type: ignore
|
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()
|
eligible_user.save()
|
||||||
processed_user = eligible_user
|
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
|
self.user.last_name = self.last_name
|
||||||
updated = True
|
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
|
# Update phone if necessary
|
||||||
if not self.user.phone:
|
if not self.user.phone:
|
||||||
self.user.phone = self.phone
|
self.user.phone = self.phone
|
||||||
updated = True
|
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
|
# Save user if any updates were made
|
||||||
if updated:
|
if updated:
|
||||||
self.user.save()
|
self.user.save()
|
||||||
|
|
|
@ -42,14 +42,14 @@ class DomainRequest(TimeStampedModel):
|
||||||
|
|
||||||
# Constants for choice fields
|
# Constants for choice fields
|
||||||
class DomainRequestStatus(models.TextChoices):
|
class DomainRequestStatus(models.TextChoices):
|
||||||
STARTED = "started", "Started"
|
|
||||||
SUBMITTED = "submitted", "Submitted"
|
|
||||||
IN_REVIEW = "in review", "In review"
|
IN_REVIEW = "in review", "In review"
|
||||||
ACTION_NEEDED = "action needed", "Action needed"
|
ACTION_NEEDED = "action needed", "Action needed"
|
||||||
APPROVED = "approved", "Approved"
|
APPROVED = "approved", "Approved"
|
||||||
WITHDRAWN = "withdrawn", "Withdrawn"
|
|
||||||
REJECTED = "rejected", "Rejected"
|
REJECTED = "rejected", "Rejected"
|
||||||
INELIGIBLE = "ineligible", "Ineligible"
|
INELIGIBLE = "ineligible", "Ineligible"
|
||||||
|
SUBMITTED = "submitted", "Submitted"
|
||||||
|
WITHDRAWN = "withdrawn", "Withdrawn"
|
||||||
|
STARTED = "started", "Started"
|
||||||
|
|
||||||
class StateTerritoryChoices(models.TextChoices):
|
class StateTerritoryChoices(models.TextChoices):
|
||||||
ALABAMA = "AL", "Alabama (AL)"
|
ALABAMA = "AL", "Alabama (AL)"
|
||||||
|
|
|
@ -87,7 +87,6 @@ class User(AbstractUser):
|
||||||
phone = PhoneNumberField(
|
phone = PhoneNumberField(
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Phone",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
middle_name = models.CharField(
|
middle_name = models.CharField(
|
||||||
|
|
|
@ -24,9 +24,11 @@ def handle_profile(sender, instance, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
first_name = getattr(instance, "first_name", "")
|
first_name = getattr(instance, "first_name", "")
|
||||||
|
middle_name = getattr(instance, "middle_name", "")
|
||||||
last_name = getattr(instance, "last_name", "")
|
last_name = getattr(instance, "last_name", "")
|
||||||
email = getattr(instance, "email", "")
|
email = getattr(instance, "email", "")
|
||||||
phone = getattr(instance, "phone", "")
|
phone = getattr(instance, "phone", "")
|
||||||
|
title = getattr(instance, "title", "")
|
||||||
|
|
||||||
is_new_user = kwargs.get("created", False)
|
is_new_user = kwargs.get("created", False)
|
||||||
|
|
||||||
|
@ -39,9 +41,11 @@ def handle_profile(sender, instance, **kwargs):
|
||||||
Contact.objects.create(
|
Contact.objects.create(
|
||||||
user=instance,
|
user=instance,
|
||||||
first_name=first_name,
|
first_name=first_name,
|
||||||
|
middle_name=middle_name,
|
||||||
last_name=last_name,
|
last_name=last_name,
|
||||||
email=email,
|
email=email,
|
||||||
phone=phone,
|
phone=phone,
|
||||||
|
title=title,
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(contacts) >= 1 and is_new_user: # a matching contact
|
if len(contacts) >= 1 and is_new_user: # a matching contact
|
||||||
|
|
|
@ -3590,7 +3590,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")}),
|
("Permissions", {"fields": ("is_active", "groups")}),
|
||||||
("Important dates", {"fields": ("last_login", "date_joined")}),
|
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,15 +23,32 @@ class TestDataUpdates(TestCase):
|
||||||
self.bs_user = User.objects.create()
|
self.bs_user = User.objects.create()
|
||||||
|
|
||||||
self.contact1 = Contact.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(
|
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(
|
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()
|
self.command = Command()
|
||||||
|
|
||||||
|
@ -42,14 +59,15 @@ class TestDataUpdates(TestCase):
|
||||||
Contact.objects.all().delete()
|
Contact.objects.all().delete()
|
||||||
|
|
||||||
def test_script_updates_linked_users(self):
|
def test_script_updates_linked_users(self):
|
||||||
"""Test the script that copies contacts' first and last names into associated users that
|
"""Test the script that copies contact information to the user object"""
|
||||||
are eligible (first or last are blank or undefined)"""
|
|
||||||
|
|
||||||
# Set up the users' first and last names here so
|
# Set up the users' first and last names here so
|
||||||
# they that they don't get overwritten by Contact's save()
|
# they that they don't get overwritten by Contact's save()
|
||||||
# User with no first or last names
|
# User with no first or last names
|
||||||
self.user1.first_name = ""
|
self.user1.first_name = ""
|
||||||
self.user1.last_name = ""
|
self.user1.last_name = ""
|
||||||
|
self.user1.title = "dummytitle"
|
||||||
|
self.user1.middle_name = "dummymiddle"
|
||||||
self.user1.save()
|
self.user1.save()
|
||||||
|
|
||||||
# User with a first name but no last name
|
# 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
|
# 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.first_name, "first1")
|
||||||
self.assertEqual(self.user1.last_name, "last1")
|
self.assertEqual(self.user1.last_name, "last1")
|
||||||
# The user that has a first but no last will be left alone
|
self.assertEqual(self.user1.middle_name, "middle1")
|
||||||
self.assertEqual(self.user2.first_name, "First name but no last name")
|
self.assertEqual(self.user1.title, "title1")
|
||||||
self.assertEqual(self.user2.last_name, "")
|
# The user that has a first but no last will be updated
|
||||||
# The user that has a first and a last will be left alone
|
self.assertEqual(self.user2.first_name, "first2")
|
||||||
self.assertEqual(self.user3.first_name, "An existing first name")
|
self.assertEqual(self.user2.last_name, "last2")
|
||||||
self.assertEqual(self.user3.last_name, "An existing last name")
|
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
|
# The unlinked user will be left alone
|
||||||
self.assertEqual(self.user4.first_name, "")
|
self.assertEqual(self.user4.first_name, "")
|
||||||
self.assertEqual(self.user4.last_name, "")
|
self.assertEqual(self.user4.last_name, "")
|
||||||
|
self.assertEqual(self.user4.middle_name, None)
|
||||||
|
self.assertEqual(self.user4.title, None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue