diff --git a/.github/workflows/loaddata.yaml b/.github/workflows/loaddata.yaml index 96385a7cb..e104a9f49 100644 --- a/.github/workflows/loaddata.yaml +++ b/.github/workflows/loaddata.yaml @@ -6,7 +6,7 @@ name: Reset database # cf run-task getgov-staging --wait \ # --command 'python manage.py flush' --name flush # cf run-task getgov-staging --wait \ -# --command 'python manage.py loaddata registrar/fixtures/*' --name loaddata +# --command 'python manage.py load' --name loaddata on: workflow_dispatch: inputs: @@ -24,8 +24,8 @@ jobs: - name: Delete existing data for staging uses: 18f/cg-deploy-action@main with: - cf_username: ${{ secrets.CF_USERNAME }} - cf_password: ${{ secrets.CF_PASSWORD }} + cf_username: ${{ secrets.CF_STAGING_USERNAME }} + cf_password: ${{ secrets.CF_STAGING_PASSWORD }} cf_org: cisa-getgov-prototyping cf_space: staging full_command: "cf run-task getgov-staging --wait --command 'python manage.py flush' --name flush" @@ -37,4 +37,4 @@ jobs: cf_password: ${{ secrets.CF_STAGING_PASSWORD }} cf_org: cisa-getgov-prototyping cf_space: staging - full_command: "cf run-task getgov-staging --wait --command 'python manage.py loaddata registrar/fixtures/*' --name loaddata" + full_command: "cf run-task getgov-staging --wait --command 'python manage.py load' --name loaddata" diff --git a/docs/developer/README.md b/docs/developer/README.md index 0d814250c..3e282caac 100644 --- a/docs/developer/README.md +++ b/docs/developer/README.md @@ -38,6 +38,12 @@ If you run via `docker-compose up -d`, you can get logs with `docker-compose log You can change the logging verbosity, if needed. Do a web search for "django log level". +## Mock data + +There is a `post_migrate` signal in [signals.py](../../src/registrar/signals.py) that will load the fixtures from [fixtures.py](../../src/registrar/fixtures.py), giving you some test data to play with while developing. + +See the [database-access README](./database-access.md) for information on how to pull data to update these fixtures. + ## Running tests Crash course on Docker's `run` vs `exec`: in order to run the tests inside of a container, a container must be running. If you already have a container running, you can use `exec`. If you do not, you can use `run`, which will attempt to start one. diff --git a/docs/developer/database-access.md b/docs/developer/database-access.md index 913f58590..33bc65b0e 100644 --- a/docs/developer/database-access.md +++ b/docs/developer/database-access.md @@ -24,7 +24,7 @@ cf run-task getgov-unstable --command 'python manage.py migrate' --name migrate Optionally, load data from fixtures as well ```shell -cf run-task getgov-unstable --wait --command 'python manage.py loaddata registrar/fixtures/*' --name loaddata +cf run-task getgov-unstable --wait --command 'python manage.py load' --name loaddata ``` For the `staging` environment, developers don't have credentials so we need to diff --git a/src/Pipfile b/src/Pipfile index 6aa54ed72..5e036feb9 100644 --- a/src/Pipfile +++ b/src/Pipfile @@ -11,6 +11,7 @@ django-allow-cidr = "*" django-auditlog = "*" django-csp = "*" environs = {extras=["django"]} +Faker = "*" gunicorn = "*" oic = "*" pyjwkest = "*" diff --git a/src/Pipfile.lock b/src/Pipfile.lock index 26fe319cb..4c2f8befc 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4e755e3f5778ff572fba5755b966cde05d30a84c4eddb1d63ca5fe1034565283" + "sha256": "c1f5d0bb53a9268568ecaad6de6bbc8106cc2bf3a62537611ada4c69222fb9de" }, "pipfile-spec": 6, "requires": {}, @@ -16,17 +16,11 @@ "default": { "asgiref": { "hashes": [ - "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4", - "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424" + "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac", + "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506" ], "markers": "python_version >= '3.7'", - "version": "==3.5.2" - }, - "beaker": { - "hashes": [ - "sha256:2d5f427e3b13259c98c934cab0e428fc1c18a4c4b94acbdae930df7e7f51d1ec" - ], - "version": "==1.12.0" + "version": "==3.6.0" }, "cachetools": { "hashes": [ @@ -41,7 +35,7 @@ "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" ], - "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2022.12.7" }, "cfenv": { @@ -126,7 +120,7 @@ "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" ], - "markers": "python_version >= '3.6'", + "markers": "python_full_version >= '3.6.0'", "version": "==2.1.1" }, "cryptography": { @@ -171,10 +165,10 @@ }, "dj-database-url": { "hashes": [ - "sha256:ccf3e8718f75ddd147a1e212fca88eecdaa721759ee48e38b485481c77bca3dc", - "sha256:cd354a3b7a9136d78d64c17b2aec369e2ae5616fbca6bfbe435ef15bb372ce39" + "sha256:5c2993b91801c0f78a8b19e642b497b90831124cbade0c265900d4c1037b4730", + "sha256:b23b15046cb38180e0c95207bcc90fe5e9dbde8eef16065907dd85cf4ca7036c" ], - "version": "==1.0.0" + "version": "==1.2.0" }, "dj-email-url": { "hashes": [ @@ -185,11 +179,11 @@ }, "django": { "hashes": [ - "sha256:678bbfc8604eb246ed54e2063f0765f13b321a50526bdc8cb1f943eda7fa31f1", - "sha256:6b1de6886cae14c7c44d188f580f8ba8da05750f544c80ae5ad43375ab293cd5" + "sha256:0b223bfa55511f950ff741983d408d78d772351284c75e9f77d2b830b6b4d148", + "sha256:d38a4e108d2386cb9637da66a82dc8d0733caede4c83c4afdbda78af4214211b" ], "index": "pypi", - "version": "==4.1.3" + "version": "==4.1.4" }, "django-allow-cidr": { "hashes": [ @@ -201,18 +195,18 @@ }, "django-auditlog": { "hashes": [ - "sha256:0ab57a536e02341e27c3d0431ad0e124e674507bd965a0756e29b01cb67c38ce", - "sha256:2f83389f98db4b1a9c2961f17cd9ac4a3ea94304655071f30da45d8debf59688" + "sha256:51c724f878fb3bc275c498e2e44583f28565135b1c60e6e8f7faf54e030c804f", + "sha256:9ad9a0a04d37aa6dc8956126ceb499d64edf71f8fddb0bc908f1217b0c31ec21" ], "index": "pypi", - "version": "==2.2.0" + "version": "==2.2.1" }, "django-cache-url": { "hashes": [ - "sha256:6cc9901a99a99751f5458aa7de08ce06e48c1441b1a94c9457d78af74fab9a26", - "sha256:c4a62634cffc9d636073cef597a44576d67b07660ab2ef1f02b160ee7ecf0e98" + "sha256:5ca4760b4580b80e41279bc60d1e5c16a822e4e462265faab0a330701bb0ef9a", + "sha256:ef2cfacea361ee22e9b67d6ca941db22e0a9eaf892b67ca71cad52c62a17fd36" ], - "version": "==3.4.2" + "version": "==3.4.4" }, "django-csp": { "hashes": [ @@ -257,6 +251,14 @@ "index": "pypi", "version": "==9.5.0" }, + "faker": { + "hashes": [ + "sha256:2d5443724f640ce07658ca8ca8bbd40d26b58914e63eec6549727869aa67e2cc", + "sha256:c2a2ff9dd8dfd991109b517ab98d5cb465e857acb45f6b643a0e284a9eb2cc76" + ], + "index": "pypi", + "version": "==15.3.4" + }, "furl": { "hashes": [ "sha256:5a6188fe2666c484a12159c18be97a1977a71d632ef5bb867ef15f54af39cc4e", @@ -351,11 +353,11 @@ }, "oic": { "hashes": [ - "sha256:b82316c4b9633781b8fcb091a7d082ffc863f850a87d8725ead454746aeae677", - "sha256:c1a46dd5f803349f1eea7393d70a3f2bdbc97e73b96f3ebb54843e1dc190f5e4" + "sha256:1bb80d7717faed750f1d8d482c06616a45f1fa5b2295d0620049040b4b48b97e", + "sha256:6cd66c5203baa8cd90dd2b73d0cc83785e96c91fab67fa7b587549fcadb3c092" ], "index": "pypi", - "version": "==1.4.0" + "version": "==1.5.0" }, "orderedmultidict": { "hashes": [ @@ -458,42 +460,35 @@ }, "pycryptodomex": { "hashes": [ - "sha256:04a5d6a17560e987272fc1763e9772a87689a08427b8cbdebe3ca7cba95d6156", - "sha256:04cc393045a8f19dd110c975e30f38ed7ab3faf21ede415ea67afebd95a22380", - "sha256:0776bfaf2c48154ab54ea45392847c1283d2fcf64e232e85565f858baedfc1fa", - "sha256:0fadb9f7fa3150577800eef35f62a8a24b9ddf1563ff060d9bd3af22d3952c8c", - "sha256:18e2ab4813883ae63396c0ffe50b13554b32bb69ec56f0afaf052e7a7ae0d55b", - "sha256:191e73bc84a8064ad1874dba0ebadedd7cce4dedee998549518f2c74a003b2e1", - "sha256:35a8f7afe1867118330e2e0e0bf759c409e28557fb1fc2fbb1c6c937297dbe9a", - "sha256:3709f13ca3852b0b07fc04a2c03b379189232b24007c466be0f605dd4723e9d4", - "sha256:4540904c09704b6f831059c0dfb38584acb82cb97b0125cd52688c1f1e3fffa6", - "sha256:463119d7d22d0fc04a0f9122e9d3e6121c6648bcb12a052b51bd1eed1b996aa2", - "sha256:46b3f05f2f7ac7841053da4e0f69616929ca3c42f238c405f6c3df7759ad2780", - "sha256:48697790203909fab02a33226fda546604f4e2653f9d47bc5d3eb40879fa7c64", - "sha256:5676a132169a1c1a3712edf25250722ebc8c9102aa9abd814df063ca8362454f", - "sha256:65204412d0c6a8e3c41e21e93a5e6054a74fea501afa03046a388cf042e3377a", - "sha256:67e1e6a92151023ccdfcfbc0afb3314ad30080793b4c27956ea06ab1fb9bcd8a", - "sha256:6f5b6ba8aefd624834bc177a2ac292734996bb030f9d1b388e7504103b6fcddf", - "sha256:7341f1bb2dadb0d1a0047f34c3a58208a92423cdbd3244d998e4b28df5eac0ed", - "sha256:781efd04ea6762bb2ef7d4fa632c9c89895433744b6c345bd0c239d5ab058dfc", - "sha256:78d9621cf0ea35abf2d38fa2ca6d0634eab6c991a78373498ab149953787e5e5", - "sha256:7db44039cc8b449bd08ab338a074e87093bd170f1a1b76d2fcef8a3e2ee11199", - "sha256:8eecdf9cdc7343001d047f951b9cc805cd68cb6cd77b20ea46af5bffc5bd3dfb", - "sha256:94c7b60e1f52e1a87715571327baea0733708ab4723346598beca4a3b6879794", - "sha256:996e1ba717077ce1e6d4849af7a1426f38b07b3d173b879e27d5e26d2e958beb", - "sha256:a07a64709e366c2041cd5cfbca592b43998bf4df88f7b0ca73dca37071ccf1bd", - "sha256:b6306403228edde6e289f626a3908a2f7f67c344e712cf7c0a508bab3ad9e381", - "sha256:b9279adc16e4b0f590ceff581f53a80179b02cba9056010d733eb4196134a870", - "sha256:c4cb9cb492ea7dcdf222a8d19a1d09002798ea516aeae8877245206d27326d86", - "sha256:dd452a5af7014e866206d41751886c9b4bf379a339fdf2dbfc7dd16c0fb4f8e0", - "sha256:e2b12968522a0358b8917fc7b28865acac002f02f4c4c6020fcb264d76bfd06d", - "sha256:e3164a18348bd53c69b4435ebfb4ac8a4076291ffa2a70b54f0c4b80c7834b1d", - "sha256:e47bf8776a7e15576887f04314f5228c6527b99946e6638cf2f16da56d260cab", - "sha256:f8be976cec59b11f011f790b88aca67b4ea2bd286578d0bd3e31bcd19afcd3e4", - "sha256:fc9bc7a9b79fe5c750fc81a307052f8daabb709bdaabb0fb18fb136b66b653b5" + "sha256:04610536921c1ec7adba158ef570348550c9f3a40bc24be9f8da2ef7ab387981", + "sha256:0ba28aa97cdd3ff5ed1a4f2b7f5cd04e721166bd75bd2b929e2734433882b583", + "sha256:0da835af786fdd1c9930994c78b23e88d816dc3f99aa977284a21bbc26d19735", + "sha256:1619087fb5b31510b0b0b058a54f001a5ffd91e6ffee220d9913064519c6a69d", + "sha256:1cda60207be8c1cf0b84b9138f9e3ca29335013d2b690774a5e94678ff29659a", + "sha256:22aed0868622d95179217c298e37ed7410025c7b29dac236d3230617d1e4ed56", + "sha256:231dc8008cbdd1ae0e34645d4523da2dbc7a88c325f0d4a59635a86ee25b41dd", + "sha256:2ad9bb86b355b6104796567dd44c215b3dc953ef2fae5e0bdfb8516731df92cf", + "sha256:4dbbe18cc232b5980c7633972ae5417d0df76fe89e7db246eefd17ef4d8e6d7a", + "sha256:6a465e4f856d2a4f2a311807030c89166529ccf7ccc65bef398de045d49144b6", + "sha256:70288d9bfe16b2fd0d20b6c365db614428f1bcde7b20d56e74cf88ade905d9eb", + "sha256:7993d26dae4d83b8f4ce605bb0aecb8bee330bb3c95475ef06f3694403621e71", + "sha256:8851585ff19871e5d69e1790f4ca5f6fd1699d6b8b14413b472a4c0dbc7ea780", + "sha256:893f8a97d533c66cc3a56e60dd3ed40a3494ddb4aafa7e026429a08772f8a849", + "sha256:8dd2d9e3c617d0712ed781a77efd84ea579e76c5f9b2a4bc0b684ebeddf868b2", + "sha256:a1c0ae7123448ecb034c75c713189cb00ebe2d415b11682865b6c54d200d9c93", + "sha256:b0789a8490114a2936ed77c87792cfe77582c829cb43a6d86ede0f9624ba8aa3", + "sha256:b3d04c00d777c36972b539fb79958790126847d84ec0129fce1efef250bfe3ce", + "sha256:ba57ac7861fd2c837cdb33daf822f2a052ff57dd769a2107807f52a36d0e8d38", + "sha256:ce338a9703f54b2305a408fc9890eb966b727ce72b69f225898bb4e9d9ed3f1f", + "sha256:daa67f5ebb6fbf1ee9c90decaa06ca7fc88a548864e5e484d52b0920a57fe8a5", + "sha256:e2453162f473c1eae4826eb10cd7bce19b5facac86d17fb5f29a570fde145abd", + "sha256:e25a2f5667d91795f9417cb856f6df724ccdb0cdd5cbadb212ee9bf43946e9f8", + "sha256:e5a670919076b71522c7d567a9043f66f14b202414a63c3a078b5831ae342c03", + "sha256:e9ba9d8ed638733c9e95664470b71d624a6def149e2db6cc52c1aca5a6a2df1d", + "sha256:f2b971a7b877348a27dcfd0e772a0343fb818df00b74078e91c008632284137d" ], "index": "pypi", - "version": "==3.15.0" + "version": "==3.16.0" }, "pyjwkest": { "hashes": [ @@ -578,11 +573,11 @@ "develop": { "asgiref": { "hashes": [ - "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4", - "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424" + "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac", + "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506" ], "markers": "python_version >= '3.7'", - "version": "==3.5.2" + "version": "==3.6.0" }, "bandit": { "hashes": [ @@ -597,35 +592,26 @@ "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30", "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693" ], - "markers": "python_version >= '3.6'", + "markers": "python_full_version >= '3.6.0'", "version": "==4.11.1" }, "black": { "hashes": [ - "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7", - "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6", - "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650", - "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb", - "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d", - "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d", - "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de", - "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395", - "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae", - "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa", - "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef", - "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383", - "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66", - "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87", - "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d", - "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0", - "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b", - "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458", - "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4", - "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1", - "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff" + "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320", + "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351", + "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350", + "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f", + "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf", + "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148", + "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4", + "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d", + "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc", + "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d", + "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2", + "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f" ], "index": "pypi", - "version": "==22.10.0" + "version": "==22.12.0" }, "blinker": { "hashes": [ @@ -645,27 +631,27 @@ }, "django": { "hashes": [ - "sha256:678bbfc8604eb246ed54e2063f0765f13b321a50526bdc8cb1f943eda7fa31f1", - "sha256:6b1de6886cae14c7c44d188f580f8ba8da05750f544c80ae5ad43375ab293cd5" + "sha256:0b223bfa55511f950ff741983d408d78d772351284c75e9f77d2b830b6b4d148", + "sha256:d38a4e108d2386cb9637da66a82dc8d0733caede4c83c4afdbda78af4214211b" ], "index": "pypi", - "version": "==4.1.3" + "version": "==4.1.4" }, "django-debug-toolbar": { "hashes": [ - "sha256:1e3acad24e3d351ba45c6fa2072e4164820307332a776b16c9f06d1f89503465", - "sha256:80de23066b624d3970fd296cf02d61988e5d56c31aa0dc4a428970b46e2883a8" + "sha256:24ef1a7d44d25e60d7951e378454c6509bf536dce7e7d9d36e7c387db499bc27", + "sha256:879f8a4672d41621c06a4d322dcffa630fc4df056cada6e417ed01db0e5e0478" ], "index": "pypi", - "version": "==3.7.0" + "version": "==3.8.1" }, "django-stubs": { "hashes": [ - "sha256:424fdd1935f859a802365056f9ccf4db12d1d93a5ab3de6d5633dddba0c5fc76", - "sha256:eaecc1fc71532c1148f0c9687556651d880165476d7629bf318ff86a903a150c" + "sha256:bcc618ba353dabc540d982b9dac1d5a1921652f8fc2a13653d545a57d5e3cc0f", + "sha256:fbf2ee6a4bce76c3eb5f6707ccadb4cf1c2f1ec485e8c44701ca8de2d0a5df18" ], "index": "pypi", - "version": "==1.13.0" + "version": "==1.13.1" }, "django-stubs-ext": { "hashes": [ @@ -685,11 +671,11 @@ }, "flake8": { "hashes": [ - "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", - "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248" + "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7", + "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181" ], "index": "pypi", - "version": "==5.0.4" + "version": "==6.0.0" }, "gitdb": { "hashes": [ @@ -717,39 +703,39 @@ }, "mypy": { "hashes": [ - "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013", - "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec", - "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466", - "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c", - "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd", - "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8", - "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff", - "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5", - "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea", - "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af", - "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd", - "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706", - "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2", - "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852", - "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d", - "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0", - "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47", - "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6", - "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9", - "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb", - "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37", - "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa", - "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef", - "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5", - "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db", - "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74", - "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695", - "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46", - "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4", - "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e" + "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d", + "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6", + "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf", + "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f", + "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813", + "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33", + "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad", + "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05", + "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297", + "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06", + "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd", + "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243", + "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305", + "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476", + "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711", + "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70", + "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5", + "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461", + "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab", + "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c", + "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d", + "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135", + "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93", + "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648", + "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a", + "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb", + "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3", + "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372", + "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb", + "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef" ], "index": "pypi", - "version": "==0.990" + "version": "==0.991" }, "mypy-extensions": { "hashes": [ @@ -768,11 +754,11 @@ }, "pathspec": { "hashes": [ - "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5", - "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0" + "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6", + "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6" ], "markers": "python_version >= '3.7'", - "version": "==0.10.2" + "version": "==0.10.3" }, "pbr": { "hashes": [ @@ -792,19 +778,19 @@ }, "pycodestyle": { "hashes": [ - "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", - "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b" + "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053", + "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610" ], "markers": "python_version >= '3.6'", - "version": "==2.9.1" + "version": "==2.10.0" }, "pyflakes": { "hashes": [ - "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", - "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3" + "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf", + "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd" ], "markers": "python_version >= '3.6'", - "version": "==2.5.0" + "version": "==3.0.1" }, "pyyaml": { "hashes": [ @@ -897,7 +883,7 @@ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version < '3.11.0a7'", "version": "==2.0.1" }, "types-cachetools": { @@ -910,10 +896,10 @@ }, "types-pytz": { "hashes": [ - "sha256:bea605ce5d5a5d52a8e1afd7656c9b42476e18a0f888de6be91587355313ddf4", - "sha256:d078196374d1277e9f9984d49373ea043cf2c64d5d5c491fbc86c258557bd46f" + "sha256:1509f182f686ab76e9a8234f22b00b8f50d239974db0cf924b7ae8674bb31a6f", + "sha256:4f20c2953b3a3a0587e94489ec4c9e02c3d3aedb9ba5cd7e796e12f4cfa7027e" ], - "version": "==2022.6.0.1" + "version": "==2022.7.0.0" }, "types-pyyaml": { "hashes": [ @@ -924,11 +910,11 @@ }, "types-requests": { "hashes": [ - "sha256:bdb1f9811e53d0642c8347b09137363eb25e1a516819e190da187c29595a1df3", - "sha256:d4f342b0df432262e9e326d17638eeae96a5881e78e7a6aae46d33870d73952e" + "sha256:48b7c06e3dffc1b6359e1888084a2b97f41b6b63f208c571ddb02ddbc6a892e4", + "sha256:8c1b1e6a0b19522b4738063e772dcee82cee1c3646536ccc4eb96f655af2b6c6" ], "index": "pypi", - "version": "==2.28.11.4" + "version": "==2.28.11.6" }, "types-urllib3": { "hashes": [ @@ -950,7 +936,7 @@ "sha256:7500c9625927c8ec60f54377d590f67b30c8e70ef4b8894214ac6e4cad233d2a", "sha256:780a4082c5fbc0fde6a2fcfe5e26e6efc1e8f425730863c04085769781f51eba" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==2.1.2" }, "webob": { diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py new file mode 100644 index 000000000..3f30790ff --- /dev/null +++ b/src/registrar/fixtures.py @@ -0,0 +1,245 @@ +import logging, string, random +from faker import Faker + +from registrar.models import ( + User, + UserProfile, + DomainApplication, + Domain, + Contact, + Website, +) + +fake = Faker() +logger = logging.getLogger(__name__) + + +class UserFixture: + """ + Load users into the database. + + Make sure this class' `load` method is called from `handle` + in management/commands/load.py, then use `./manage.py load` + to run this code. + """ + ADMINS = [ + { + "username": "c4a0e101-73b4-4d7d-9e5e-7f19a726a0fa", + "first_name": "Seamus", + "last_name": "Johnston", + }, + { + "username": "d4c3bd84-dc3a-48bc-a3c3-f53111df2ec6", + "first_name": "Igor", + "last_name": "", + }, + { + "username": "ee80bfe0-49ad-456d-8d82-e2b608a66517", + "first_name": "Logan", + "last_name": "", + }, + ] + + @classmethod + def load(cls): + logger.info("Going to load %s users" % str(len(cls.ADMINS))) + for admin in cls.ADMINS: + try: + user, _ = User.objects.get_or_create( + username=admin["username"], + ) + user.is_superuser = True + user.first_name = admin["first_name"] + user.last_name = admin["last_name"] + user.is_staff = True + user.is_active = True + user.save() + logger.debug("User object created for %s" % admin["first_name"]) + UserProfile.objects.get_or_create(user=user) + logger.debug("Profile object created for %s" % admin["first_name"]) + except Exception as e: + logger.warning(e) + logger.debug("All users loaded.") + + +class DomainApplicationFixture: + """ + Load domain applications into the database. + + Make sure this class' `load` method is called from `handle` + in management/commands/load.py, then use `./manage.py load` + to run this code. + """ + + # any fields not specified here will be filled in with fake data or defaults + # NOTE BENE: each fixture must have `organization_name` for uniqueness! + DA = [ + { + "status": "started", + "organization_name": "Example - Finished but not Submitted", + }, + { + "status": "started", + "organization_name": "Example - Just started", + "organization_type": "federal", + "federal_agency": None, + "federal_type": None, + "address_line1": None, + "address_line2": None, + "city": None, + "state_territory": None, + "zipcode": None, + "urbanization": None, + "purpose": None, + "security_email": None, + "anything_else": None, + "is_policy_acknowledged": None, + "authorizing_official": None, + "submitter": None, + "other_contacts": [], + "current_websites": [], + "alternative_domains": [], + }, + { + "status": "submitted", + "organization_name": "Example - Submitted but pending Investigation", + }, + { + "status": "investigating", + "organization_name": "Example - In Investigation", + }, + ] + + @classmethod + def fake_contact(cls): + return { + "first_name": fake.first_name(), + "middle_name": None, + "last_name": fake.last_name(), + "title": fake.job(), + "email": fake.ascii_safe_email(), + "phone": fake.phone_number(), + } + + @classmethod + def fake_dot_gov(cls): + return "".join(random.choices(string.ascii_lowercase, k=16)) + ".gov" + + @classmethod + def _set_non_foreign_key_fields(cls, da: DomainApplication, app: dict): + """Helper method used by `load`.""" + da.status = app["status"] if "status" in app else "started" + da.organization_type = ( + app["organization_type"] if "organization_type" in app else "federal" + ) + da.federal_agency = app["federal_agency"] if "federal_agency" in app else "" + da.federal_type = ( + app["federal_type"] + if "federal_type" in app + else random.choice(["executive", "judicial", "legislative"]) + ) + da.address_line1 = ( + app["address_line1"] if "address_line1" in app else fake.street_address() + ) + da.address_line2 = app["address_line2"] if "address_line2" in app else None + da.city = app["city"] if "city" in app else fake.city() + da.state_territory = ( + app["state_territory"] if "state_territory" in app else fake.state_abbr() + ) + da.zipcode = app["zipcode"] if "zipcode" in app else fake.postalcode() + da.urbanization = app["urbanization"] if "urbanization" in app else None + da.purpose = app["purpose"] if "purpose" in app else fake.paragraph() + da.security_email = app["security_email"] if "security_email" in app else None + da.anything_else = app["anything_else"] if "anything_else" in app else None + da.is_policy_acknowledged = ( + app["is_policy_acknowledged"] if "is_policy_acknowledged" in app else True + ) + + @classmethod + def _set_foreign_key_fields(cls, da: DomainApplication, app: dict, user: User): + """Helper method used by `load`.""" + if not da.investigator: + da.investigator = ( + User.objects.get(username=user.username) + if "investigator" in app + else None + ) + + if not da.authorizing_official: + if "authorizing_official" in app and app["authorizing_official"] is not None: + da.authorizing_official, _ = Contact.objects.get_or_create(**app["authorizing_official"]) + else: + da.authorizing_official = Contact.objects.create(**cls.fake_contact()) + + if not da.submitter: + if "submitter" in app and app["submitter"] is not None: + da.submitter, _ = Contact.objects.get_or_create(**app["submitter"]) + else: + da.submitter = Contact.objects.create(**cls.fake_contact()) + + if not da.requested_domain: + if "requested_domain" in app and app["requested_domain"] is not None: + da.requested_domain, _ = Domain.objects.get_or_create(name=app["requested_domain"]) + else: + da.requested_domain = Domain.objects.create(name=cls.fake_dot_gov()) + + @classmethod + def _set_many_to_many_relations(cls, da: DomainApplication, app: dict): + """Helper method used by `load`.""" + if "other_contacts" in app: + for contact in app["other_contacts"]: + rel, _ = Contact.objects.get_or_create(**contact) + da.other_contacts.add(rel) + else: + others = [ + Contact.objects.create(**cls.fake_contact()) + for _ in range(random.randint(0, 3)) + ] + da.other_contacts.add(*others) + + if "current_websites" in app: + for website in app["current_websites"]: + rel, _ = Website.objects.get_or_create(website=website) + da.current_websites.add(rel) + else: + others = [ + Website.objects.create(website=fake.uri()) + for _ in range(random.randint(0, 3)) + ] + da.current_websites.add(*others) + + if "alternative_domains" in app: + for domain in app["alternative_domains"]: + rel, _ = Website.objects.get_or_create(website=domain) + da.alternative_domains.add(rel) + else: + others = [ + Website.objects.create(website=cls.fake_dot_gov()) + for _ in range(random.randint(0, 3)) + ] + da.alternative_domains.add(*others) + + @classmethod + def load(cls): + """Creates domain applications for each user in the database.""" + logger.info("Going to load %s domain applications" % len(cls.DA)) + try: + users = list(User.objects.all()) # force evaluation to catch db errors + except Exception as e: + logger.warning(e) + return + + for user in users: + logger.debug("Loading domain applications for %s" % user) + for app in cls.DA: + try: + da, _ = DomainApplication.objects.get_or_create( + creator=user, + organization_name=app["organization_name"], + ) + cls._set_non_foreign_key_fields(da, app) + cls._set_foreign_key_fields(da, app, user) + da.save() + cls._set_many_to_many_relations(da, app) + except Exception as e: + logger.warning(e) diff --git a/src/registrar/fixtures/users.json b/src/registrar/fixtures/users.json deleted file mode 100644 index 712fde168..000000000 --- a/src/registrar/fixtures/users.json +++ /dev/null @@ -1,107 +0,0 @@ -[ - { - "model": "registrar.user", - "pk": 1, - "fields": { - "password": "", - "last_login": "2022-10-04T15:07:34.590Z", - "is_superuser": true, - "username": "c4a0e101-73b4-4d7d-9e5e-7f19a726a0fa", - "first_name": "Seamus", - "last_name": "Johnston", - "email": "", - "is_staff": true, - "is_active": true, - "date_joined": "2022-09-30T14:14:02.280Z", - "groups": [], - "user_permissions": [] - } - }, - { - "model": "registrar.userprofile", - "pk": 1, - "fields": { - "created_at": "2022-09-30T14:14:02.284Z", - "updated_at": "2022-10-04T15:07:34.593Z", - "street1": "", - "street2": "", - "street3": "", - "city": "", - "sp": "", - "pc": "", - "cc": "", - "user": 1, - "display_name": "" - } - }, - { - "model": "registrar.user", - "pk": 2, - "fields": { - "password": "", - "last_login": "2022-10-04T16:43:07.738Z", - "is_superuser": true, - "username": "d4c3bd84-dc3a-48bc-a3c3-f53111df2ec6", - "first_name": "Igor", - "last_name": "", - "email": "", - "is_staff": true, - "is_active": true, - "date_joined": "2022-10-04T16:39:30.529Z", - "groups": [], - "user_permissions": [] - } - }, - { - "model": "registrar.userprofile", - "pk": 2, - "fields": { - "created_at": "2022-10-04T16:39:30.531Z", - "updated_at": "2022-10-04T16:43:07.740Z", - "street1": "", - "street2": "", - "street3": "", - "city": "", - "sp": "", - "pc": "", - "cc": "", - "user": 2, - "display_name": "" - } - }, - { - "model": "registrar.user", - "pk": 3, - "fields": { - "password": "", - "last_login": "2022-10-13T13:57:52.133Z", - "is_superuser": true, - "username": "ee80bfe0-49ad-456d-8d82-e2b608a66517", - "first_name": "Logan", - "last_name": "", - "email": "", - "is_staff": true, - "is_active": true, - "date_joined": "2022-10-13T13:57:52.124Z", - "groups": [], - "user_permissions": [] - } - }, - { - "model": "registrar.userprofile", - "pk": 3, - "fields": { - "created_at": "2022-10-04T16:39:30.531Z", - "updated_at": "2022-10-04T16:43:07.740Z", - "street1": "", - "street2": "", - "street3": "", - "city": "", - "sp": "", - "pc": "", - "cc": "", - "user": 3, - "display_name": "" - } - } -] diff --git a/src/registrar/management/commands/load.py b/src/registrar/management/commands/load.py new file mode 100644 index 000000000..0203a2e75 --- /dev/null +++ b/src/registrar/management/commands/load.py @@ -0,0 +1,18 @@ +import logging + +from django.core.management.base import BaseCommand +from auditlog.context import disable_auditlog # type: ignore + +from registrar.fixtures import UserFixture, DomainApplicationFixture + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + def handle(self, *args, **options): + # django-auditlog has some bugs with fixtures + # https://github.com/jazzband/django-auditlog/issues/17 + with disable_auditlog(): + UserFixture.load() + DomainApplicationFixture.load() + logger.info("All fixtures loaded.") diff --git a/src/registrar/management/commands/loaddata.py b/src/registrar/management/commands/loaddata.py deleted file mode 100644 index 7bc340bd3..000000000 --- a/src/registrar/management/commands/loaddata.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.core.management.commands import loaddata -from auditlog.context import disable_auditlog # type: ignore - - -class Command(loaddata.Command): - def handle(self, *args, **options): - # django-auditlog has some bugs with fixtures - # https://github.com/jazzband/django-auditlog/issues/17 - with disable_auditlog(): - super(Command, self).handle(*args, **options) diff --git a/src/registrar/signals.py b/src/registrar/signals.py index a39a90397..ee9d08612 100644 --- a/src/registrar/signals.py +++ b/src/registrar/signals.py @@ -1,9 +1,16 @@ -from django.db.models.signals import post_save +import logging + +from django.conf import settings +from django.core.management import call_command +from django.db.models.signals import post_save, post_migrate from django.dispatch import receiver from .models import User, UserProfile +logger = logging.getLogger(__name__) + + @receiver(post_save, sender=User) def handle_profile(sender, instance, **kwargs): @@ -21,3 +28,13 @@ def handle_profile(sender, instance, **kwargs): instance.userprofile.save() else: UserProfile.objects.create(user=instance) + + +@receiver(post_migrate) +def handle_loaddata(**kwargs): + """Attempt to load test fixtures when in DEBUG mode.""" + if settings.DEBUG: + try: + call_command("load") + except Exception as e: + logger.warning(e)