1
0
mirror of https://github.com/peeringdb/peeringdb.git synced 2024-05-11 05:55:09 +00:00

Support 202009 (#841)

* Add EmailMultiAlternatives import

* Add strip_tags import

* Add settings imports and new email test

* Add email increment to ixf and tests

* IX-F Importer: suggested update when it should be add + remove #832

* Take email increment out of if-else

* Add max and min speed settings

* Change validation check for models

* new speed validation

* Add basic user command

* Add pdb cleanup users tool

* Add pretty printing for speed

* Add users as a subparser

* add translation override to signals

* Add parser as parent of subparser

* refactor and change test

* Move override to cover single variable

* Add tooltip option for individual checkboxes

* address 'fix me' issue with field_help helper func

* Add zipcode validator and black format

* Make website required input but zipcode dependent on country

* Add net POC requirement to Netixlan serializer

* Website is now blank=False ie required in all forms

* refine error message

* Require email is not blank and add test

* Change error message

* add website and zipcode test, edit zipcode error message

* change placement of tooltip

* add question mark

* Add comment

* Add runtime error logging for ixp member import

* add uncaught error test

* delete two unused methods

* Rename test file and add different tests

* Add missing email imports (reproduces changes in hot_fix_gh_831)

* add resend methods

* Add missing email imports (reproduces changes in hot_fix_gh_831)

* Add pytest-mock to pipfile

* Add resend email mechanism

* Add email resending

* remove failing assertion

* fix for ticket_aged_proposals

* Wrap resending emails in conditional for commit

* Add resend email tests

* fix mail_Debug bug

* Figure out production mailing and resending settings

* Add stale info field

* default IXF_RESEND_FAILED_EMAILS to False
fix issue with sent being set even if email was not sent
fix issue with output stating resending of emails even if it wasnt

* IX-F Preview - shows the consolidated delete operation when it shouldn't (#824)

* black format (v 19.10)

* black formatting

* black formatting

* pipfile relock

* make changes from #825 play nice with changes from #833

* black to pipenv dev packages

Co-authored-by: Elliot Frank <elliot@20c.com>
Co-authored-by: Stefan Pratter <stefan@20c.com>
This commit is contained in:
Matt Griswold
2020-09-29 18:07:56 +00:00
committed by GitHub
parent 0178b93a2b
commit 1fa46e2acb
26 changed files with 1645 additions and 445 deletions

View File

@@ -571,6 +571,7 @@ class TestJSON(unittest.TestCase):
with pytest.raises(InvalidRequestException) as excinfo:
r = db.create(typ, data_invalid, return_response=True)
assert "400 Bad Request" in str(excinfo.value)
# we test fail because of parent entity status
@@ -1161,7 +1162,10 @@ class TestJSON(unittest.TestCase):
"fac",
data,
test_failures={
"invalid": {"name": "",},
"invalid": [
{"name": ""},
{"name": self.make_name("Test"), "website": ""},
],
"perms": {
# need to set name again so it doesnt fail unique validation
"name": self.make_name("Test"),
@@ -1222,6 +1226,30 @@ class TestJSON(unittest.TestCase):
##########################################################################
def test_org_admin_002_POST_PUT_DELETE_fac_zipcode(self):
data = self.make_data_fac()
# Requires a zipcode if country is a country
# with postal codes (ie US)
r_data = self.assert_create(
self.db_org_admin,
"fac",
data,
test_failures={
"invalid": [{"name": self.make_name("Test"), "zipcode": ""},],
},
test_success=False,
)
# Change to country w/o postal codes
data["country"] = "ZW"
data["zipcode"] = ""
r_data = self.assert_create(self.db_org_admin, "fac", data,)
assert r_data["zipcode"] == ""
##########################################################################
def test_org_admin_002_POST_PUT_DELETE_net(self):
data = self.make_data_net(asn=9000900)
@@ -1647,6 +1675,49 @@ class TestJSON(unittest.TestCase):
##########################################################################
def test_org_admin_002_POST_netixlan_no_net_contact(self):
network = SHARED["net_rw_ok"]
for poc in network.poc_set_active.all():
poc.delete()
data = self.make_data_netixlan(
net_id=SHARED["net_rw_ok"].id,
ixlan_id=SHARED["ixlan_rw_ok"].id,
asn=SHARED["net_rw_ok"].asn,
)
# When we create this netixlan it should fail with a
# non-field-error.
r_data = self.assert_create(
self.db_org_admin,
"netixlan",
data,
test_failures={"invalid": {"n/a": "n/a"}},
test_success=False,
)
# Undelete poc but blank email
poc = network.poc_set.first()
poc.status = "ok"
poc.email = ""
poc.visible = "Public"
poc.save()
network.refresh_from_db()
# Also fails with network contact that is
# missing an email
r_data = self.assert_create(
self.db_org_admin,
"netixlan",
data,
test_failures={"invalid": {"n/a": "n/a"}},
test_success=False,
)
##########################################################################
def test_org_admin_002_POST_PUT_netixlan_validation(self):
data = self.make_data_netixlan(
net_id=SHARED["net_rw_ok"].id, ixlan_id=SHARED["ixlan_rw_ok"].id
@@ -1657,6 +1728,12 @@ class TestJSON(unittest.TestCase):
{"invalid": {"ipaddr4": self.get_ip4(SHARED["ixlan_r_ok"])}},
# test failure if ip6 not in prefix
{"invalid": {"ipaddr6": self.get_ip6(SHARED["ixlan_r_ok"])}},
# test failure if speed is below limit
{"invalid": {"speed": 1}},
# test failure if speed is above limit
{"invalid": {"speed": 1250000}},
# test failure if speed is None
{"invalid": {"speed": None}},
]
for test_failure in test_failures:
@@ -1893,7 +1970,9 @@ class TestJSON(unittest.TestCase):
with fields parameter set would raise a 500 error for
unauthenticated users
"""
data = self.db_guest.get("ixlan", SHARED["ixlan_rw_ok"].id, fields="ixpfx_set", depth=2)
data = self.db_guest.get(
"ixlan", SHARED["ixlan_rw_ok"].id, fields="ixpfx_set", depth=2
)
assert len(data) == 1
row = data[0]
assert list(row.keys()) == ["ixpfx_set"]

View File

@@ -0,0 +1,17 @@
from django.core.management.base import BaseCommand
class PeeringDBBaseCommand(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
"--commit", action="store_true", help="Commit the changes."
)
def log(self, msg):
if self.commit:
self.stdout.write(msg)
else:
self.stdout.write("[pretend] {}".format(msg))
def handle(self, *args, **options):
self.commit = options.get("commit")

View File

@@ -0,0 +1,53 @@
from datetime import datetime, timedelta, timezone
from django.core.management.base import BaseCommand
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from peeringdb_server.models import VerificationQueueItem, User
from peeringdb_server.management.commands.pdb_base_command import PeeringDBBaseCommand
class Command(PeeringDBBaseCommand):
help = "Use this tool to clean up the Verification Queue"
def add_arguments(self, parser):
super().add_arguments(parser)
subparsers = parser.add_subparsers()
parser_users = subparsers.add_parser(
'users',
parents=[parser],
add_help=False,
help='Tool to remove outdated user verification requests')
parser_users.set_defaults(func=self._clean_users)
def handle(self, *args, **options):
super().handle(*args, **options)
if options.get("func"):
options["func"]()
def _clean_users(self):
model = User
content_type = ContentType.objects.get_for_model(model)
date = datetime.now(timezone.utc) - timedelta(days=settings.VQUEUE_USER_MAX_AGE)
qset = VerificationQueueItem.objects.filter(
content_type=content_type,
created__lte=date
)
count = qset.count()
self.log(f"Deleting VerificationQueueItems for Users created before {date:%x}")
self.log(f"Items flagged for deletion: {count}")
counter = 0
for vqi in qset:
counter += 1
self.log(f"Deleting VerificationQueueItem for {vqi.content_type} "
f"id #{vqi.object_id}... {counter} / {count}")
if self.commit:
vqi.delete()

View File

@@ -1,5 +1,6 @@
import traceback
import json
import sys
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
@@ -75,11 +76,14 @@ class Command(BaseCommand):
else:
self.stdout.write("[Pretend] {}".format(msg))
def release_env_check(self, flag):
if settings.RELEASE_ENV != "prod":
return True
else:
raise PermissionError("Flag {} is not permitted to be used in production.")
def store_runtime_error(self, error):
error_str = "ERROR: {}".format(error) + "\n"
error_str += traceback.format_exc()
self.runtime_errors.append(error_str)
def write_runtime_errors(self):
for error in self.runtime_errors:
self.stderr.write(error)
def initiate_reset_flags(self, **options):
flags = [
@@ -161,6 +165,12 @@ class Command(BaseCommand):
),
)
def resend_emails(self, importer):
num_emails_to_resend = len(importer.emails_to_resend)
self.log(f"Attemping to resend {num_emails_to_resend} emails.")
resent_emails = importer.resend_emails()
self.log(f"RE-SENT EMAILS: {len(resent_emails)}.")
def handle(self, *args, **options):
self.commit = options.get("commit", False)
self.debug = options.get("debug", False)
@@ -170,6 +180,8 @@ class Command(BaseCommand):
self.active_reset_flags = self.initiate_reset_flags(**options)
self.runtime_errors = []
if self.reset or self.reset_hints:
self.reset_all_hints()
if self.reset or self.reset_dismisses:
@@ -237,8 +249,7 @@ class Command(BaseCommand):
total_notifications += importer.notifications
except Exception as inst:
self.log("ERROR: {}".format(inst))
self.log(traceback.format_exc())
self.store_runtime_error(inst)
if self.preview:
self.stdout.write(json.dumps(total_log, indent=2))
@@ -249,6 +260,13 @@ class Command(BaseCommand):
importer = ixf.Importer()
importer.reset(save=self.commit)
importer.notifications = total_notifications
importer.notify_proposals()
importer.notify_proposals(error_handler=self.store_runtime_error)
self.stdout.write(f"Emails: {importer.emails}")
self.stdout.write(f"New Emails: {importer.emails}")
if len(self.runtime_errors) > 0:
self.write_runtime_errors()
sys.exit(1)
if self.commit:
self.resend_emails(importer)