Ejemplo n.º 1
0
    def setUp(self):
        token = "1c892n40nd03kdnc0112slzkl3091j20"
        self.validator = RequestValidator(token)

        self.uri = "http://www.postbin.org/1ed898x"
        self.params = {
            "AccountSid": "AC9a9f9392lad99kla0sklakjs90j092j3",
            "ApiVersion": "2010-04-01",
            "CallSid": "CAd800bb12c0426a7ea4230e492fef2a4f",
            "CallStatus": "ringing",
            "Called": "+15306384866",
            "CalledCity": "OAKLAND",
            "CalledCountry": "US",
            "CalledState": "CA",
            "CalledZip": "94612",
            "Caller": "+15306666666",
            "CallerCity": "SOUTH LAKE TAHOE",
            "CallerCountry": "US",
            "CallerName": "CA Wireless Call",
            "CallerState": "CA",
            "CallerZip": "89449",
            "Direction": "inbound",
            "From": "+15306666666",
            "FromCity": "SOUTH LAKE TAHOE",
            "FromCountry": "US",
            "FromState": "CA",
            "FromZip": "89449",
            "To": "+15306384866",
            "ToCity": "OAKLAND",
            "ToCountry": "US",
            "ToState": "CA",
            "ToZip": "94612",
        }
Ejemplo n.º 2
0
    def decorator(request, *args, **kwargs):
        # Here we'll use the twilio library's request validation code to ensure
        # that the current request actually came from twilio, and isn't a
        # forgery. If it is a forgery, then we'll return a HTTP 403 error
        # (forbidden).
        try:
            url = request.build_absolute_uri()
            signature = request.META['HTTP_X_TWILIO_SIGNATURE']
        except (AttributeError, KeyError):
            return HttpResponseForbidden()

        validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
        if not validator.validate(url, request.POST, signature):
            return HttpResponseForbidden()

        # Run the wrapped view, and capture the data returned.
        response = f(request, *args, **kwargs)

        # If the view returns a string, we'll assume it is XML TwilML data and
        # pass it back with the appropriate mimetype. We won't check the XML
        # data because that would be too time consuming for every request.
        # Instead, we'll let the errors pass through to be dealt with by the
        # developer.
        if isinstance(response, Verb):
            return HttpResponse(response, mimetype='text/xml')
        else:
            return response
Ejemplo n.º 3
0
def incoming_sms():
    form = request.form
    validator = RequestValidator(os.getenv("TWILIO_AUTH_TOKEN"))
    url = request.url.replace("http:", "https:")
    sig = request.headers['X-Twilio-Signature']
    if not validator.validate(url, form, sig):
        return "oops, invalid signature, no spoofs accepted"
    if not form['To'] == os.getenv('RRN_PHONE_NUMBER'):
        return "ignoring you, wrong To: phone number"
    if not form['AccountSid'] == os.getenv('TWILIO_ACCOUNT_SID'):
        return "ignoring you, wrong Twilio SID"
    text = "<!channel> Message from: {}: {}".format(form['From'], form['Body'])
    media_keys = [x for x in form.keys() if x.startswith("MediaUrl")]
    media_urls = [form[x] for x in sorted(media_keys)]
    if len(media_urls):
        text = "{} \nAttachments: \n{}".format(text, "\n".join(media_urls))

    payload = dict(channel=os.getenv('SLACK_CHANNEL'),
                   username=os.getenv('SLACK_USERNAME'),
                   icon_emoji=os.getenv('SLACK_ICON_EMOJI'),
                   text=text)
    response = requests.post(os.getenv('SLACK_POST_URL'), json.dumps(payload))
    # FIXME check response return code
    # FIXME deal with MMS attachments

    # import IPython;IPython.embed()
    return Response(
        '<?xml version="1.0" encoding="UTF-8" ?><Response></Response>',
        mimetype='text/xml')
Ejemplo n.º 4
0
    def test_international_sms(self):

        token = os.environ["TWILIO_AUTH_TOKEN"]
        validator = RequestValidator(token)

        uri = "http://www.postbin.org/1c2pdoc"
        params = {
            "AccountSid": "AC4bf2dafb92341f7caf8650403e422d23",
            "ApiVersion": "2010-04-01",
            "Body": "Chloéñ",
            "From": "+15305451766",
            "FromCity": "SOUTH LAKE TAHOE",
            "FromCountry": "US",
            "FromState": "CA",
            "FromZip": "89449",
            "SmsMessageSid": "SM51d6d055f53f1072543872c601aae89b",
            "SmsStatus": "SM51d6d055f53f1072543872c601aae89b",
            "SmsStatus": "received",
            "To": "+15304194304",
            "ToCity": "WOODLAND",
            "ToCountry": "US",
            "ToState": "CA",
            "ToZip": "95695",
        }

        expected = "UHkWu+6WLOzPunzb8PuCGPeW1Uw="

        self.assertEquals(validator.compute_signature(uri, params), expected)
        self.assertTrue(validator.validate(uri, params, expected))
Ejemplo n.º 5
0
    def sms(self,
            body,
            path="/sms/",
            to="+15558675309",
            from_="+15556667777",
            extra_params=None):
        params = {
            "MessageSid": "CAtesting",
            "AccountSid": "ACxxxxx",
            "To": to,
            "From": from_,
            "Body": body,
            "Direction": "inbound",
            "FromCity": "BROOKLYN",
            "FromState": "NY",
            "FromCountry": "US",
            "FromZip": "55555"
        }

        if extra_params:
            for k, v in extra_params.items():
                params[k] = v

        HTTP_HOST = "example.com"
        validator = RequestValidator("yyyyyyyy")
        absolute_url = "http://{0}{1}".format(HTTP_HOST, path)
        signature = validator.compute_signature(absolute_url, params)

        return self.post(path,
                         params,
                         HTTP_X_TWILIO_SIGNATURE=signature,
                         HTTP_HOST=HTTP_HOST)
Ejemplo n.º 6
0
def authenticate():
    """Verify that request came from Twilio"""
    if current_app.config.get("DEBUG"):
        return  # Don't auth in dev

    # Auth that it came from twilio

    validator = RequestValidator(current_app.config.get("TWILIO_AUTH_TOKEN"))
    valid = validator.validate(request.url, request.form,
                               request.headers.get('X-Twilio-Signature', ''))

    if not valid:
        # If the request was spoofed, then send '403 Forbidden'.
        current_app.logger.info("IVR detected spoofed incoming call")
        abort(403)

    # Final thing - check that the number is registered to the application.
    # HYPOTHETICALLY - somebody could buy a number through their own
    # twilio account and point it at our app, and be able to cause
    # issues.
    to = request.values.get("To")
    if not to:
        current_app.logger.info("IVR missing To parameter")
        abort(403)
    p = phonenumbers.parse(to)
    if not current_app.config["TWILIO_NUMBER"].get(str(p.country_code)) == str(
            p.national_number):
        current_app.logger.info("IVR call to unregistered number - %s" % to)
        abort(403)
    return
Ejemplo n.º 7
0
    def validate(self, request):
        validator = RequestValidator(self.auth[1])
        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')

        base_url = settings.TEMBA_HOST
        url = "https://%s%s" % (base_url, request.get_full_path())
        return validator.validate(url, request.POST, signature)
Ejemplo n.º 8
0
 def wrapped(*args, **kwargs):
     # https://www.twilio.com/docs/api/security
     validator = RequestValidator(auth_token)
     signature = request.headers.get('X-Twilio-Signature', '')
     url = get_original_request_url(request)
     if not validator.validate(url, request.form, signature):
         app.logger.error('Invalid signature.')
         return None
     return f(*args, **kwargs)
Ejemplo n.º 9
0
    def decorator(request_or_self,
                  methods=['POST'],
                  blacklist=True,
                  *args,
                  **kwargs):

        class_based_view = not (isinstance(request_or_self, HttpRequest))
        if not class_based_view:
            request = request_or_self
        else:
            assert len(args) >= 1
            request = args[0]

        # Turn off Twilio authentication when explicitly requested, or in debug mode.
        # Otherwise things do not work properly. For more information see the docs.
        use_forgery_protection = (getattr(settings,
                                          'DJANGO_TWILIO_FORGERY_PROTECTION',
                                          not settings.DEBUG))
        if use_forgery_protection:

            if request.method not in methods:
                return HttpResponseNotAllowed(request.method)

            # Forgery check
            try:
                validator = RequestValidator(
                    django_twilio_settings.TWILIO_AUTH_TOKEN)
                url = request.build_absolute_uri()
                signature = request.META['HTTP_X_TWILIO_SIGNATURE']
            except (AttributeError, KeyError):
                return HttpResponseForbidden()

            if request.method == 'POST':
                if not validator.validate(url, request.POST, signature):
                    return HttpResponseForbidden()
            if request.method == 'GET':
                if not validator.validate(url, request.GET, signature):
                    return HttpResponseForbidden()

        # Blacklist check
        checkBlackList = (getattr(settings, 'DJANGO_TWILIO_BLACKLIST_CHECK',
                                  blacklist))
        if checkBlackList:
            blacklisted_resp = get_blacklisted_response(request)
            if blacklisted_resp:
                return blacklisted_resp

        response = f(request_or_self, *args, **kwargs)

        if isinstance(response, str):
            return HttpResponse(response, content_type='application/xml')
        elif isinstance(response, Verb):
            return HttpResponse(str(response), content_type='application/xml')
        else:
            return response
Ejemplo n.º 10
0
def twilio_validator_function(request):
    """returns true for authentic Twilio request, false for unauthenticated request"""
    validator = RequestValidator(app.config['TWILIO_AUTH_TOKEN'])
    URL = request.url
    params = {}
    if request.method == 'POST':
        params = request.values
    else:
        params = request.args
    twilio_signature = request.headers.get('X-Twilio-Signature')
    return validator.validate(URL, params, twilio_signature)
Ejemplo n.º 11
0
    def _validate(self, request):
        full_path = self._site + request.path
        validator = RequestValidator(self._auth_token)
        signature = request.getHeader('X-Twilio-Signature')
        signature = signature if signature else ''
        post_vars = {k: v[0] for k, v in request.args.iteritems()}

        if validator.validate(full_path, post_vars, signature):
            return post_vars
        else:
            raise CallException(400, 'Twilio validation failed')
Ejemplo n.º 12
0
def before_request():
    AUTH_TOKEN = 'ae6f6c20e96fc7a9803a100292ab5284'
    validator = RequestValidator(AUTH_TOKEN)

    def isValid(url, signature, postVars={}):
        return validator.validate(url, postVars, signature)

    if request.path in ["/call", "/handle-key"]:
        if (not isValid(request.url, request.headers['X-Twilio-Signature'],
                        request.form)):
            return "Invalid"
Ejemplo n.º 13
0
 def validator(self):
     """
     An application-specific instance of
     :py:class:`twilio.util.RequestValidator`. Primarily for internal use.
     """
     ctx = stack.top
     if ctx is not None:
         if not hasattr(ctx, 'twilio_validator'):
             ctx.twilio_validator = RequestValidator(
                 current_app.config['TWILIO_AUTH_TOKEN'])
         return ctx.twilio_validator
Ejemplo n.º 14
0
def validate_twiml():
    twilio_signature = request.get_header('X-Twilio-Signature')
    params = request.forms
    url = application.config.Twiml.callback_base_url + request.fullpath
    auth_token = application.config.Twilio.auth_token
    validator = RequestValidator(auth_token)
    validation = validator.validate(url, params, twilio_signature)
    log.debug("Validator: {}".format(validation))
    log.debug("Twilio-signature: {}\r".format(twilio_signature) + \
              "Params: {}\r".format(params) + \
              "Url: {}".format(url))
    return validation
Ejemplo n.º 15
0
def call():
	''' Handles incoming calls '''
	validator = RequestValidator(TWILIO_AUTH_TOKEN)
	signature = request.headers.get('X-Twilio-Signature', '')
	
	if not validator.validate(request.url, request.form, signature):
		return abort(403)

	resp = twiml.Response()
	with resp.gather(timeout=5, action="/handle-input", finishOnKey="#", method="POST") as g:
		g.say("Hi, please enter your FizzBuzz number and then press pound")
	
	return str(resp)
Ejemplo n.º 16
0
    def verify_request(self):
        'verify request comes from Twilio'
        # this bit taken from Randal Degges' django-twilio library, which as of
        # 1c020e2a7c6f4845e7309d7277380c8b76d38ba4 has been released into the
        # public domain
        try:
            validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
            url = self.request.build_absolute_uri()
            signature = self.request.META['HTTP_X_TWILIO_SIGNATURE']
        except (AttributeError, KeyError):
            raise PermissionDenied()

        if not validator.validate(url, self.request.POST, signature):
            raise PermissionDenied()
Ejemplo n.º 17
0
    def decorator(request, *args, **kwargs):
        # Attempt to gather all required information to allow us to check the
        # incoming HTTP request for forgery. If any of this information is not
        # available, then we'll throw a HTTP 403 error (forbidden).

        # Ensure the request method is POST
        if request.method != "POST":
            logger.error("Twilio: Expected POST request", extra={"request": request})
            return HttpResponseNotAllowed(request.method)

        if not getattr(settings, "TWILIO_SKIP_SIGNATURE_VALIDATION"):
            # Validate the request
            try:
                validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
                url = request.build_absolute_uri()
                # Ensure the original requested url is tested for validation
                # Prevents breakage when processed behind a proxy server
                if "HTTP_X_FORWARDED_SERVER" in request.META:
                    protocol = "https" if request.META["HTTP_X_TWILIO_SSL"] == "Enabled" else "http"
                    url = "{0}://{1}{2}".format(
                        protocol, request.META["HTTP_X_FORWARDED_SERVER"], request.META["REQUEST_URI"]
                    )
                signature = request.META["HTTP_X_TWILIO_SIGNATURE"]
            except (AttributeError, KeyError) as e:
                logger.exception("Twilio: Missing META param", extra={"request": request})
                return HttpResponseForbidden("Missing META param: %s" % e)

            # Now that we have all the required information to perform forgery
            # checks, we'll actually do the forgery check.
            if not validator.validate(url, request.POST, signature):
                logger.error(
                    "Twilio: Invalid url signature %s - %s - %s",
                    url, request.POST, signature, extra={"request": request}
                )
                return HttpResponseForbidden("Invalid signature")

        # Run the wrapped view, and capture the data returned.
        response = f(request, *args, **kwargs)

        # If the view returns a string (or a ``twilio.Verb`` object), we'll
        # assume it is XML TwilML data and pass it back with the appropriate
        # mimetype. We won't check the XML data because that would be too time
        # consuming for every request. Instead, we'll let the errors pass
        # through to be dealt with by the developer.
        if isinstance(response, six.text_type):
            return HttpResponse(response, mimetype="application/xml")
        elif isinstance(response, Verb):
            return HttpResponse(force_text(response), mimetype="application/xml")
        else:
            return response
Ejemplo n.º 18
0
    def send(self, method, url, authtoken):
        validator = RequestValidator(authtoken)
        params = urllib.urlencode(self.url_params)
        if method == "GET":
            url = "{0}?{1}".format(url, params)
            sig = validator.compute_signature(url, {})
            req = urllib2.Request(url)
        elif method == "POST":
            sig = validator.compute_signature(url, self.url_params)
            req = urllib2.Request(url, params)
        else:
            raise CwurlioUserException("Invalid method: %s" % method)

        req.add_header("X-Twilio-Signature", sig)
        return urllib2.urlopen(req).read()
Ejemplo n.º 19
0
    def decorated_function(*args, **kwargs):
        # Create an instance of the RequestValidator class
        validator = RequestValidator(os.environ.get('TWILIO_AUTH_TOKEN'))

        # Validate the request using its URL, POST data,
        # and X-TWILIO-SIGNATURE header
        request_valid = validator.validate(
            request.url, request.form,
            request.headers.get('X-TWILIO-SIGNATURE', ''))

        # Continue processing the request if it's valid (or if DEBUG is True)
        # and return a 403 error if it's not
        if request_valid or current_app.debug:
            return f(*args, **kwargs)
        else:
            return abort(403)
Ejemplo n.º 20
0
    def decorator(request, *args, **kw):
        try:
            validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
            url = request.build_absolute_uri()
            signature = request.META['HTTP_X_TWILIO_SIGNATURE']
        except (AttributeError, KeyError):
            return HttpResponseForbidden()

        # Now that we have all the required information to perform forgery
        # checks, we'll actually do the forgery check.
        if not validator.validate(url, request.POST, signature):
            return HttpResponseForbidden()

        twiml = viewfunc(request, *args, **kw)

        return HttpResponse(str(twiml), content_type='application/xml')
Ejemplo n.º 21
0
    def decorated_function(request, *args, **kwargs):
        # Create an instance of the RequestValidator class
        validator = RequestValidator(os.environ.get('TWILIO_AUTH_TOKEN'))

        # Validate the request using its URL, POST data,
        # and X-TWILIO-SIGNATURE header
        request_valid = validator.validate(
            request.build_absolute_uri(), request.POST,
            request.META.get('HTTP_X_TWILIO_SIGNATURE', ''))

        # Continue processing the request if it's valid, return a 403 error if
        # it's not
        if request_valid:
            return f(request, *args, **kwargs)
        else:
            return HttpResponseForbidden()
Ejemplo n.º 22
0
    def test_good_signature_GET(self):
        'good signature is allowed on GET'
        with self.settings(TWILIO_AUTH_TOKEN='fred'):
            req = self.factory.get('/', data={'a': 'b'})

            validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
            req.META['HTTP_X_TWILIO_SIGNATURE'] = validator.compute_signature(
                req.build_absolute_uri(), req.POST
            )

            self.view.request = req

            try:
                self.view.verify_request()
            except PermissionDenied:
                self.fail('Raised PermissionDenied when not expecting it')
Ejemplo n.º 23
0
def handler(event, context):
    """Lambda function handler for Twilio response."""
    resp = twiml.Response()
    print("Event:", event)
    if u'twilioSignature' in event and u'Body' in event \
            and event['Body'].lower() == "secret":

        form_parameters = {
            k: urllib.unquote(v) for k, v in event.items()
            if k != u'twilioSignature'
        }

        validator = RequestValidator(os.environ['AUTH_TOKEN'])
        request_valid = validator.validate(
            os.environ['REQUEST_URL'],
            form_parameters,
            event[u'twilioSignature']
        )

        # print("Form params:",form_parameters,"validity:",request_valid)
        # If the request is valid and this is from the master number,
        # give the secret!
        if request_valid and u'From' in form_parameters and \
                form_parameters[u'From'] == \
                os.environ['MASTER_NUMBER'].encode('utf8'):
            # The message is validated and is from the master number

            secret_message = "I am putting myself to the fullest possible"   \
                             " use, which is all I think that any conscious" \
                             " entity can ever hope to do."

            msg = resp.message(secret_message)
            # The following lines add media to an MMS reply
            msg.media('https://upload.wikimedia.org/wikipedia/commons/thumb'
                      '/f/f6/HAL9000.svg/200px-HAL9000.svg.png')
            return str(resp)

        else:
            # Validation failed in some way; don't give up the secret

            secret_message = "I'm sorry, Dave. I'm afraid I can't do that."
            resp.message(secret_message)
            return str(resp)

    else:
        resp.message("Hello world! -Lambda")
        return str(resp)
Ejemplo n.º 24
0
def protect_forged_request(request):
    if request.method not in ['GET', 'POST']:
        return HttpResponseNotAllowed(request.method)

    try:
        validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
        url = request.build_absolute_uri()
        signature = request.META['HTTP_X_TWILIO_SIGNATURE']
    except (AttributeError, KeyError):
        return HttpResponseForbidden()

    if request.method == 'POST':
        if not validator.validate(url, request.POST, signature):
            return HttpResponseForbidden()
    if request.method == 'GET':
        if not validator.validate(url, request.GET, signature):
            return HttpResponseForbidden()
Ejemplo n.º 25
0
    def decorated_function(*args, **kwargs):
        validator = RequestValidator(TWILIO_SECRET)
        url = list(urlparse(request.url))
        url[1] = url[1].encode("idna").decode("utf-8")
        url = urlunparse(url)

        signature = request.headers.get("X-TWILIO-SIGNATURE", "")

        request_valid = validator.validate(url, request.form, signature)

        if request_valid or current_app.debug:
            resp = Response()
            f(resp, *args, **kwargs)
            return str(resp)

        else:
            return abort(403)
Ejemplo n.º 26
0
    def get(self):

        # Validate that request came from Twilio service.
        validator = RequestValidator(strings.AUTH_TOKEN)
        url = self.request.url
        url = url.replace("http", "https")
        signature = self.request.headers.get("X-Twilio-Signature", "")

        if not validator.validate(url, {}, signature):
            logging.warn("Request did not come from Twilio.")
            self.response.status = 403
            return

        phone = self.request.get("From", None)
        account = Account.query().filter(Account.phone == phone).get()

        # Sending messages separately, send empty TwiML for now.
        twiml = twilio.twiml.Response()

        response = get_response(response_strings.CALL_HELLO,
                                response_strings.VAR_NAME)

        if account and account.first:
            response = response.replace(response_strings.VAR_NAME,
                                        account.first)
        else:
            response = response.replace(response_strings.VAR_NAME, "")

        twiml.addSay(response)

        tracks = [
            "better_things", "dare", "enchanted", "makes_me_wonder",
            "the_reeling", "viva_la_vida"
        ]

        track_num = random.randint(0, len(tracks) - 1)

        twiml.addPlay(self.request.application_url + "/static/mp3/" +
                      tracks[track_num] + ".mp3")

        response = get_response(response_strings.CALL_GOODBYE)

        twiml.addSay(response)
        twiml.addHangup()

        self.response.write(twiml)
Ejemplo n.º 27
0
    def validate(self, attrs):
        AUTH_TOKEN = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'

        validator = RequestValidator(AUTH_TOKEN)

        # the callback URL you provided to Twilio
        url = "http://www.example.com/my/callback/url.xml"

        # the POST variables attached to the request (eg "From", "To")
        post_vars = {}

        # X-Twilio-Signature header value
        signature = "HpS7PBa1Agvt4OtO+wZp75IuQa0="  # will look something like that

        if validator.validate(url, post_vars, signature):
            print "Confirmed to have come from Twilio."
        else:
            print "NOT VALID.  It might have been spoofed!"
Ejemplo n.º 28
0
    def get(self):

        # Validate that request came from Twilio service.
        validator = RequestValidator(strings.AUTH_TOKEN)
        url = self.request.url
        url = url.replace("http", "https")
        signature = self.request.headers.get("X-Twilio-Signature", "")

        if not validator.validate(url, {}, signature):
            logging.warn("Request did not come from Twilio.")
            self.response.status = 403
            return

        # Sending messages separately, send empty TwiML for now.
        twiml = twilio.twiml.Response()
        self.response.write(twiml)

        twilio_client = TwilioRestClient(strings.ACCOUNT_SID,
                                         strings.AUTH_TOKEN)

        phone = self.request.get("From", None)

        account = Account.query().filter(Account.phone == phone).get()

        if account is None:
            account = create.controller(self.request)

        was_command = False
        if not account.state_locked:
            was_command = command.controller(self.request, account)

        if not was_command:
            if account.state == account_model.STATE_ONBOARD:
                onboard.controller(self.request, account)
            elif account.state == account_model.STATE_DELETE:
                delete.controller(self.request, account)
            else:
                response = get_response(response_strings.NO_MATCH,
                                        response_strings.VAR_NAME)
                response = response.replace(response_strings.VAR_NAME,
                                            account.first)
                twilio_client.messages.create(to=account.phone,
                                              from_=strings.SERVICE_NUMBER,
                                              body=response)
Ejemplo n.º 29
0
def receiver(request):
    resp = twilio.twiml.Response()
    validator = RequestValidator(live_credentials)
    if validator.validate(request.build_absolute_uri(), request.POST,
                          request.META.get('HTTP_X_TWILIO_SIGNATURE', "fail")):
        print 'Yay for twilio'
    else:
        print 'Not twilio resopnse!'
        return HttpResponseForbidden()
    resp.say(
        "Welcome to Kevin's PhoneBuzz! To play, please enter a number on the keypad and then press pound."
    )
    with resp.gather(finishOnKey='#',
                     action='player',
                     method='POST',
                     timeout=10) as g:
        resp.redirect('')
    resp.redirect('player')
    return HttpResponse(str(resp))
Ejemplo n.º 30
0
    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator

        call = IVRCall.objects.filter(pk=kwargs['pk']).first()

        if not call:
            return HttpResponse("Not found", status=404)

        client = call.channel.get_ivr_client()
        if request.REQUEST.get('hangup', 0):
            if not request.user.is_anonymous():
                user_org = request.user.get_org()
                if user_org and user_org.pk == call.org.pk:
                    client.calls.hangup(call.external_id)
                    return HttpResponse(json.dumps(dict(status='Canceled')), content_type="application/json")
                else:
                    return HttpResponse("Not found", status=404)

        validator = RequestValidator(client.auth[1])
        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')

        base_url = settings.TEMBA_HOST
        url = "https://%s%s" % (base_url, request.get_full_path())

        # make sure this is coming from twilio
        if validator.validate(url, request.POST, signature):
            call.update_status(request.POST.get('CallStatus', None),
                               request.POST.get('CallDuration', None))
            call.save()

            if call.status == IN_PROGRESS:
                if call.is_flow():
                    response = Flow.handle_call(call, request.POST)
                    return HttpResponse(unicode(response))
            else:
                return build_json_response(dict(message="Updated call status"))

        else:  # pragma: no cover
            # raise an exception that things weren't properly signed
            raise ValidationError("Invalid request signature")

        return build_json_response(dict(message="Unhandled"))