mirror of
				https://github.com/peeringdb/peeringdb.git
				synced 2024-05-11 05:55:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			392 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from django.db.models.signals import post_save, pre_delete, pre_save
 | |
| from django.contrib.contenttypes.models import ContentType
 | |
| from django_namespace_perms.models import Group, GroupPermission
 | |
| from django_namespace_perms.constants import PERM_CRUD, PERM_READ
 | |
| from django.template import loader
 | |
| from django.conf import settings
 | |
| from django.dispatch import receiver
 | |
| from allauth.account.signals import user_signed_up
 | |
| from django.core import urlresolvers
 | |
| 
 | |
| from corsheaders.signals import check_request_enabled
 | |
| 
 | |
| from django_peeringdb.models.abstract import AddressModel
 | |
| 
 | |
| from peeringdb_server.inet import RdapLookup, RdapNotFoundError, RdapException
 | |
| 
 | |
| from peeringdb_server.deskpro import (ticket_queue, ticket_queue_asnauto_affil,
 | |
|                                       ticket_queue_asnauto_create)
 | |
| 
 | |
| from peeringdb_server.models import (
 | |
|     QUEUE_ENABLED, QUEUE_NOTIFY, UserOrgAffiliationRequest, is_suggested,
 | |
|     VerificationQueueItem, Organization, Facility, Network, NetworkContact)
 | |
| 
 | |
| import peeringdb_server.settings as pdb_settings
 | |
| 
 | |
| from django.utils.translation import ugettext_lazy as _
 | |
| from django.utils.translation import override
 | |
| 
 | |
| 
 | |
| def addressmodel_save(sender, instance=None, **kwargs):
 | |
|     """
 | |
|     Mark address model objects for geocode sync if one of the address
 | |
|     fields is updated
 | |
|     """
 | |
| 
 | |
|     if instance.id:
 | |
|         # instance is being updated
 | |
|         old = sender.objects.get(id=instance.id)
 | |
|         for field in AddressModel._meta.get_fields():
 | |
|             if field.name in ["latitude", "longitude"]:
 | |
|                 continue
 | |
|             a = getattr(instance, field.name)
 | |
|             b = getattr(old, field.name)
 | |
|             if a != b:
 | |
|                 #print("Change in field '%s' - '%s'(%s) to '%s'(%s) - marking %s for geocode sync" % (field.name, a, type(a), b, type(b), instance))
 | |
|                 # address model field has changed, mark for geocode sync
 | |
|                 instance.geocode_status = False
 | |
| 
 | |
| 
 | |
| pre_save.connect(addressmodel_save, sender=Facility)
 | |
| 
 | |
| 
 | |
| def org_save(sender, **kwargs):
 | |
|     """
 | |
|     we want to create a user group for an organization when that
 | |
|     organization is created
 | |
|     """
 | |
| 
 | |
|     inst = kwargs.get("instance")
 | |
| 
 | |
|     # make the general member group for the org
 | |
|     try:
 | |
|         group = Group.objects.get(name=inst.group_name)
 | |
|     except Group.DoesNotExist:
 | |
|         group = Group(name=inst.group_name)
 | |
|         group.save()
 | |
| 
 | |
|         perm = GroupPermission(group=group, namespace=inst.nsp_namespace,
 | |
|                                permissions=PERM_READ)
 | |
|         perm.save()
 | |
| 
 | |
|         GroupPermission(
 | |
|             group=group, namespace=NetworkContact.nsp_namespace_from_id(
 | |
|                 inst.id, "*", "private"), permissions=PERM_READ).save()
 | |
| 
 | |
|     # make the admin group for the org
 | |
|     try:
 | |
|         group = Group.objects.get(name=inst.admin_group_name)
 | |
|     except Group.DoesNotExist:
 | |
|         group = Group(name=inst.admin_group_name)
 | |
|         group.save()
 | |
| 
 | |
|         perm = GroupPermission(group=group, namespace=inst.nsp_namespace,
 | |
|                                permissions=PERM_CRUD)
 | |
|         perm.save()
 | |
| 
 | |
|         GroupPermission(group=group, namespace=inst.nsp_namespace_manage,
 | |
|                         permissions=PERM_CRUD).save()
 | |
| 
 | |
|         GroupPermission(
 | |
|             group=group, namespace=NetworkContact.nsp_namespace_from_id(
 | |
|                 inst.id, "*", "private"), permissions=PERM_CRUD).save()
 | |
| 
 | |
|     if inst.status == "deleted":
 | |
|         for ar in inst.affiliation_requests.all():
 | |
|             ar.delete()
 | |
| 
 | |
| 
 | |
| post_save.connect(org_save, sender=Organization)
 | |
| 
 | |
| 
 | |
| def org_delete(sender, instance, **kwargs):
 | |
|     """
 | |
|     When an organization is HARD deleted we want to also remove any
 | |
|     usergroups tied to the organization
 | |
|     """
 | |
| 
 | |
|     try:
 | |
|         instance.usergroup.delete()
 | |
|     except Group.DoesNotExist:
 | |
|         pass
 | |
| 
 | |
|     try:
 | |
|         instance.admin_usergroup.delete()
 | |
|     except Group.DoesNotExist:
 | |
|         pass
 | |
| 
 | |
|     for ar in instance.affiliation_requests.all():
 | |
|         ar.delete()
 | |
| 
 | |
| 
 | |
| pre_delete.connect(org_delete, sender=Organization)
 | |
| 
 | |
| 
 | |
| @receiver(user_signed_up, dispatch_uid="allauth.user_signed_up")
 | |
| def new_user_to_guests(request, user, sociallogin=None, **kwargs):
 | |
|     """
 | |
|     When a user is created via oauth login put them in the guest
 | |
|     group for now.
 | |
| 
 | |
|     Unless pdb_settings.AUTO_VERIFY_USERS is toggled on in settings, in which
 | |
|     case users get automatically verified (note that this does
 | |
|     not include email verification, they will still need to do that)
 | |
|     """
 | |
| 
 | |
|     if pdb_settings.AUTO_VERIFY_USERS:
 | |
|         user.set_verified()
 | |
|     else:
 | |
|         user.set_unverified()
 | |
| 
 | |
| 
 | |
| # USER TO ORGANIZATION AFFILIATION
 | |
| 
 | |
| 
 | |
| def uoar_creation(sender, instance, created=False, **kwargs):
 | |
|     """
 | |
|     When a user to organization affiliation request is created
 | |
|     we want to notify the approporiate management entity
 | |
| 
 | |
|     We also want to attempt to derive the targeted organization
 | |
|     from the ASN the user provided
 | |
|     """
 | |
| 
 | |
|     if created:
 | |
| 
 | |
|         if instance.asn and not instance.org_id:
 | |
|             network = Network.objects.filter(asn=instance.asn).first()
 | |
|             if network:
 | |
|                 # network with targeted asn found, set org
 | |
|                 instance.org = network.org
 | |
| 
 | |
|         instance.status = "pending"
 | |
|         instance.save()
 | |
| 
 | |
|         if instance.org_id and instance.org.admin_usergroup.user_set.count(
 | |
|         ) > 0:
 | |
| 
 | |
|             # check that user is not already a member of that org
 | |
|             if instance.user.groups.filter(
 | |
|                     name=instance.org.usergroup.name).exists():
 | |
|                 instance.approve()
 | |
|                 return
 | |
| 
 | |
|             # organization exists already and has admins, notify organization
 | |
|             # admins
 | |
|             for user in instance.org.admin_usergroup.user_set.all():
 | |
|                 with override(user.locale):
 | |
|                     user.email_user(
 | |
|                         _(u"User %(u_name)s wishes to be affiliated to your Organization"
 | |
|                           ) % {'u_name': instance.user.full_name},
 | |
|                         loader.get_template(
 | |
|                             'email/notify-org-admin-user-affil.txt').render({
 | |
|                                 "user": instance.user,
 | |
|                                 "org": instance.org,
 | |
|                                 "org_management_url": '%s/org/%d#users' %
 | |
|                                                       (settings.BASE_URL,
 | |
|                                                        instance.org.id)
 | |
|                             }))
 | |
|         else:
 | |
|             request_type = "be affiliated to"
 | |
|             rdap_data = {"emails": []}
 | |
|             org_created = False
 | |
|             net_created = False
 | |
|             rdap_lookup = None
 | |
|             if instance.asn and not instance.org_id:
 | |
|                 # ASN specified in request, but no network found
 | |
|                 # Lookup RDAP information
 | |
|                 try:
 | |
|                     rdap_lookup = rdap = RdapLookup().get_asn(instance.asn)
 | |
|                     ok = rdap_lookup.emails
 | |
|                 except RdapException, inst:
 | |
|                     if not pdb_settings.AUTO_APPROVE_AFFILIATION:
 | |
|                         instance.deny()
 | |
|                         raise
 | |
| 
 | |
|                 # create organization
 | |
|                 instance.org, org_created = Organization.create_from_rdap(
 | |
|                     rdap, instance.asn, instance.org_name)
 | |
|                 instance.save()
 | |
| 
 | |
|                 # create network
 | |
|                 net, net_created = Network.create_from_rdap(
 | |
|                     rdap, instance.asn, instance.org)
 | |
| 
 | |
|                 # if affiliate auto appove is on, auto approve at this point
 | |
|                 if pdb_settings.AUTO_APPROVE_AFFILIATION:
 | |
|                     instance.approve()
 | |
|                     return
 | |
| 
 | |
|                 ticket_queue_asnauto_create(
 | |
|                     instance.user, instance.org, net, rdap, net.asn,
 | |
|                     org_created=org_created, net_created=net_created)
 | |
| 
 | |
|                 # if user's relationship to network can be validated now
 | |
|                 # we can approve the ownership request right away
 | |
|                 if instance.user.validate_rdap_relationship(rdap):
 | |
|                     instance.approve()
 | |
|                     ticket_queue_asnauto_affil(instance.user, instance.org,
 | |
|                                                net, rdap)
 | |
|                     return
 | |
| 
 | |
|             if instance.org:
 | |
|                 # organization has been set on affiliation request
 | |
|                 entity_name = instance.org.name
 | |
|                 if not instance.org.owned:
 | |
|                     # organization is currently not owned
 | |
|                     request_type = "request ownership of"
 | |
| 
 | |
|                     # if affiliate auto appove is on, auto approve at this point
 | |
|                     if pdb_settings.AUTO_APPROVE_AFFILIATION:
 | |
|                         instance.approve()
 | |
|                         return
 | |
| 
 | |
|                     # if user's relationship to the org can be validated by
 | |
|                     # checking the rdap information of the org's networks
 | |
|                     # we can approve the affiliation (ownership) request right away
 | |
|                     for asn, rdap in instance.org.rdap_collect.items():
 | |
|                         rdap_data["emails"].extend(rdap.emails)
 | |
|                         if instance.user.validate_rdap_relationship(rdap):
 | |
|                             ticket_queue_asnauto_affil(
 | |
|                                 instance.user, instance.org,
 | |
|                                 Network.objects.get(asn=asn), rdap)
 | |
|                             instance.approve()
 | |
|                             return
 | |
|             else:
 | |
|                 entity_name = instance.org_name
 | |
| 
 | |
|                 if pdb_settings.AUTO_APPROVE_AFFILIATION:
 | |
|                     org = Organization.objects.create(name=instance.org_name, status="ok")
 | |
|                     instance.org = org
 | |
|                     instance.approve()
 | |
|                     return
 | |
| 
 | |
| 
 | |
| 
 | |
|             # organization has no owners and RDAP information could not verify the user's relationship to the organization, notify pdb staff for review
 | |
|             ticket_queue(
 | |
|                 u'User %s wishes to %s %s' % (instance.user.username,
 | |
|                                               request_type, entity_name),
 | |
|                 loader.get_template('email/notify-pdb-admin-user-affil.txt')
 | |
|                 .render({
 | |
|                     "user": instance.user,
 | |
|                     "instance": instance,
 | |
|                     "base_url": settings.BASE_URL,
 | |
|                     "org_add_url": "%s%s" % (
 | |
|                         settings.BASE_URL,
 | |
|                         urlresolvers.reverse(
 | |
|                             "admin:peeringdb_server_organization_add")),
 | |
|                     "net_add_url": "%s%s" %
 | |
|                                    (settings.BASE_URL,
 | |
|                                     urlresolvers.reverse(
 | |
|                                         "admin:peeringdb_server_network_add")),
 | |
|                     "review_url": "%s%s" %
 | |
|                                   (settings.BASE_URL,
 | |
|                                    urlresolvers.reverse(
 | |
|                                        "admin:peeringdb_server_user_change",
 | |
|                                        args=(instance.user.id, ))),
 | |
|                     "approve_url": "%s%s" % (
 | |
|                         settings.BASE_URL,
 | |
|                         urlresolvers.reverse(
 | |
|                             "admin:peeringdb_server_userorgaffiliationrequest_actions",
 | |
|                             args=(instance.id, "approve_and_notify"))),
 | |
|                     "emails": list(set(rdap_data["emails"])),
 | |
|                     "rdap_lookup": rdap_lookup
 | |
|                 }), instance.user)
 | |
| 
 | |
|     elif instance.status == "approved" and instance.org_id:
 | |
| 
 | |
|         # uoar was not created, and status is now approved, call approve
 | |
|         # to finalize
 | |
| 
 | |
|         instance.approve()
 | |
| 
 | |
| 
 | |
| post_save.connect(uoar_creation, sender=UserOrgAffiliationRequest)
 | |
| 
 | |
| # VERIFICATION QUEUE
 | |
| 
 | |
| if getattr(settings, "DISABLE_VERIFICATION_QUEUE", False) is False:
 | |
| 
 | |
|     def verification_queue_update(sender, instance, **kwargs):
 | |
|         if instance.status == "pending":
 | |
|             try:
 | |
|                 VerificationQueueItem.objects.get(
 | |
|                     content_type=ContentType.objects.get_for_model(sender),
 | |
|                     object_id=instance.id)
 | |
|             except VerificationQueueItem.DoesNotExist:
 | |
|                 q = VerificationQueueItem(item=instance)
 | |
|                 q.save()
 | |
|         else:
 | |
|             try:
 | |
|                 q = VerificationQueueItem.objects.get(
 | |
|                     content_type=ContentType.objects.get_for_model(sender),
 | |
|                     object_id=instance.id)
 | |
|                 q.delete()
 | |
|             except VerificationQueueItem.DoesNotExist:
 | |
|                 pass
 | |
| 
 | |
|     def verification_queue_delete(sender, instance, **kwargs):
 | |
|         try:
 | |
|             q = VerificationQueueItem.objects.get(
 | |
|                 content_type=ContentType.objects.get_for_model(sender),
 | |
|                 object_id=instance.id)
 | |
|             q.delete()
 | |
|         except VerificationQueueItem.DoesNotExist:
 | |
|             pass
 | |
| 
 | |
|     def verification_queue_notify(sender, instance, **kwargs):
 | |
|         # notification was already sent
 | |
|         if instance.notified:
 | |
|             return
 | |
| 
 | |
|         # we dont sent notifications unless requesting user has been identified
 | |
|         if not instance.user_id:
 | |
|             return
 | |
| 
 | |
|         item = instance.item
 | |
|         user = instance.user
 | |
| 
 | |
|         if type(item) in QUEUE_NOTIFY and not getattr(
 | |
|                 settings, "DISABLE_VERIFICATION_QUEUE_EMAILS", False):
 | |
| 
 | |
|             if type(item) == Network:
 | |
|                 rdap = RdapLookup().get_asn(item.asn)
 | |
|             else:
 | |
|                 rdap = None
 | |
| 
 | |
|             title = u"{} - {}".format(instance.content_type, item)
 | |
| 
 | |
|             if is_suggested(item):
 | |
|                 title = u"[SUGGEST] {}".format(title)
 | |
| 
 | |
|             ticket_queue(
 | |
|                 title,
 | |
|                 loader.get_template('email/notify-pdb-admin-vq.txt').render({
 | |
|                     "entity_type_name": str(instance.content_type),
 | |
|                     "suggested": is_suggested(item),
 | |
|                     "item": item,
 | |
|                     "user": user,
 | |
|                     "rdap": rdap,
 | |
|                     "edit_url": "%s%s" % (settings.BASE_URL,
 | |
|                                           instance.item_admin_url)
 | |
|                 }), instance.user)
 | |
| 
 | |
|             instance.notified = True
 | |
|             instance.save()
 | |
| 
 | |
|     post_save.connect(verification_queue_notify, sender=VerificationQueueItem)
 | |
| 
 | |
|     for model in QUEUE_ENABLED:
 | |
|         post_save.connect(verification_queue_update, sender=model)
 | |
|         pre_delete.connect(verification_queue_delete, sender=model)
 | |
| 
 | |
| 
 | |
| def cors_allow_api_get_to_everyone(sender, request, **kwargs):
 | |
|     #FIXME: path name to look for should come from config
 | |
|     return ((request.path == "/api" or request.path.startswith('/api/'))
 | |
|             and request.method in ["GET", "OPTIONS"])
 | |
| 
 | |
| 
 | |
| check_request_enabled.connect(cors_allow_api_get_to_everyone)
 |