def update(self, request, *args, **kwargs): """ Update object """ try: self.require_data(request) org_key = get_org_key_from_request(request) user_key = get_user_key_from_request(request) with reversion.create_revision(): if request.user and request.user.is_authenticated: reversion.set_user(request.user) if org_key: reversion.set_comment(f"API-key: {org_key.prefix}") if user_key: reversion.set_comment(f"API-key: {user_key.prefix}") r = super().update(request, *args, **kwargs) if "_grainy" in r.data: del r.data["_grainy"] return r except PermissionDenied as inst: return Response(status=status.HTTP_403_FORBIDDEN) except TypeError as inst: return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(inst)}) except ValueError as inst: return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(inst)}) finally: self.get_serializer().finalize_update(request)
def allow_request(self, request, view): # If the parameter specified in cls.filter_name # is set in request parameters, set the scope # accordingly if self.filter_name in request.query_params: self.scope = f"filter_{self.filter_name}" else: return True # user either comes from request.user, or user api key # # it will be None if an organization key is set or request # is anonymous self.user = user = get_user_from_request(request) self.org_key = org_key = get_org_key_from_request(request) # Neither user nor organzation key could be identified # Get user directly from request, which will likely return # an anonymous user instance if not org_key and not user: self.user = user = request.user # require authenticated user to use this filter ? require_auth = (getattr( settings, f"API_{self.filter_name.upper()}_FILTER_REQUIRE_AUTH", False) and user) # require verified user to use this filter ? require_verified = (getattr( settings, f"API_{self.filter_name.upper()}_FILTER_REQUIRE_VERIFIED", False, ) and user) if (require_auth or require_verified) and not user.is_authenticated: raise PermissionDenied( f"Please authenticate to use the `{self.filter_name}` filter") if require_verified and not user.is_verified_user: raise PermissionDenied( f"Please verify your account to use the `{self.filter_name}` filter" ) self.rate = self.get_rate() self.num_requests, self.duration = self.parse_rate(self.rate) return super().allow_request(request, view)
def ticket_queue_asnauto_skipvq(request, org, net, rir_data): """ Queue deskro ticket creation for asn automation action: skip vq. """ if isinstance(net, dict): net_name = net.get("name") else: net_name = net.name if isinstance(org, dict): org_name = org.get("name") else: org_name = org.name user = get_user_from_request(request) if user: ticket_queue( f"[ASNAUTO] Network '{net_name}' approved for existing Org '{org_name}'", loader.get_template( "email/notify-pdb-admin-asnauto-skipvq.txt").render({ "user": user, "org": org, "net": net, "rir_data": rir_data }), user, ) return org_key = get_org_key_from_request(request) if org_key: ticket_queue_email_only( f"[ASNAUTO] Network '{net_name}' approved for existing Org '{org_name}'", loader.get_template( "email/notify-pdb-admin-asnauto-skipvq-org-key.txt").render({ "org_key": org_key, "org": org, "net": net, "rir_data": rir_data }), org_key.email, )
def ticket_queue_rdap_error(request, asn, error): if isinstance(error, RdapNotFoundError): return error_message = f"{error}" if re.match("(.+) returned 400", error_message): return user = get_user_from_request(request) if user: subject = f"[RDAP_ERR] {user.username} - AS{asn}" ticket_queue( subject, loader.get_template( "email/notify-pdb-admin-rdap-error.txt").render({ "user": user, "asn": asn, "error_details": error_message }), user, ) return org_key = get_org_key_from_request(request) if org_key: subject = f"[RDAP_ERR] {org_key.email} - AS{asn}" ticket_queue_email_only( subject, loader.get_template( "email/notify-pdb-admin-rdap-error-org-key.txt").render({ "org_key": org_key, "asn": asn, "error_details": error_message }), org_key.email, )
def destroy(self, request, pk, format=None): """ Delete object """ try: try: obj = self.model.objects.get(pk=pk) except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST, data={"extra": "Invalid id"}) except self.model.DoesNotExist: return Response(status=status.HTTP_204_NO_CONTENT) user_key = get_user_key_from_request(request) org_key = get_org_key_from_request(request) if check_permissions_from_request(request, obj, "d"): with reversion.create_revision(): if request.user and request.user.is_authenticated: reversion.set_user(request.user) if org_key: reversion.set_comment(f"API-key: {org_key.prefix}") if user_key: reversion.set_comment(f"API-key: {user_key.prefix}") obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) else: return Response(status=status.HTTP_403_FORBIDDEN) except ProtectedAction as exc: exc_message = f"{exc} - " + _( "Please contact {} to help with the deletion of this object" ).format(settings.DEFAULT_FROM_EMAIL) ticket_queue_deletion_prevented(request, exc.protected_object) return Response(status=status.HTTP_403_FORBIDDEN, data={"detail": exc_message}) finally: self.get_serializer().finalize_delete(request)
def ticket_queue_deletion_prevented(request, instance): """ Queue deskpro ticket to notify the prevented deletion of an object #696. """ subject = (f"[PROTECTED] Deletion prevented: " f"{instance.HandleRef.tag}-{instance.id} " f"{instance}") # we don't want to spam DeskPRO with tickets when a user # repeatedly clicks the delete button for an object # # so we check if a ticket has recently been sent for it # and opt out if it falls with in the spam protection # period defined in settings period = settings.PROTECTED_OBJECT_NOTIFICATION_PERIOD now = datetime.datetime.now(datetime.timezone.utc) max_age = now - datetime.timedelta(hours=period) ticket = DeskProTicket.objects.filter( subject=f"{settings.EMAIL_SUBJECT_PREFIX}{subject}") ticket = ticket.filter(created__gt=max_age) # recent ticket for object exists, bail if ticket.exists(): return model_name = instance.__class__.__name__.lower() # Create ticket if a request was made by user or UserAPIKey user = get_user_from_request(request) if user: ticket_queue( subject, loader.get_template( "email/notify-pdb-admin-deletion-prevented.txt").render({ "user": user, "instance": instance, "admin_url": settings.BASE_URL + django.urls.reverse( f"admin:peeringdb_server_{model_name}_change", args=(instance.id, ), ), }), user, ) return # Create ticket if request was made by OrgAPIKey org_key = get_org_key_from_request(request) if org_key: ticket_queue_email_only( subject, loader.get_template( "email/notify-pdb-admin-deletion-prevented-org-key.txt"). render({ "org_key": org_key, "instance": instance, "admin_url": settings.BASE_URL + django.urls.reverse( f"admin:peeringdb_server_{model_name}_change", args=(instance.id, ), ), }), org_key.email, )