Esempio n. 1
0
def content_route(request, route_slug=None):

    if request.is_ajax():
        return get_page(request)

    session = get_object_or_404(Session, route_slug=route_slug)

    if (not session.is_open and session.program
            and session.program.programuseraccess_set.filter(
                user=request.user).exists()):
        return HttpResponseRedirect(settings.HOME_URL)

    context = {'session': session.id, 'node': 0}

    engine = Engine(user=request.user,
                    context=context,
                    push=True,
                    is_interactive=True)
    engine.run()

    context = {
        'program': session.program,
        'title': session.display_title,
        'api': reverse('content_api'),
    }

    return render(request, 'session.html', context)
Esempio n. 2
0
def init_session(session_id, user_id, push=False):
    '''Initialize a given session from start and traverse on behalf of user'''

    context = {
        'session': session_id,
        'node': 0,
    }

    if not push:
        context['stack'] = []

    engine = Engine(user_id=user_id, context=context, push=push)

    if not engine.user.is_active:
        return _('Inactive user, no action taken')

    engine.run()

    if engine.session.trigger_login:
        engine.user.send_login_link()
        message = _('Session initialized and login e-mail sent')
    else:
        message = _('Session initialized')

    return message
Esempio n. 3
0
    def test_flow(self):
        # test init with session and node context, a common pattern
        context = {
            'session': self.session_activate.id,
            'node': 0,
        }
        engine = Engine(user=self.user, context=context)
        self.assertEqual(engine.session, self.session_activate)
        page = engine.run()

        token = token_generator.make_token(self.user.id)
        default_data = {
            'From': '+4799999999',
            'Body': 'no',
        }

        primafon_data = {
            'from': '4799999999',
            'body': 'no',
        }

        Request = namedtuple('Request', 'method body POST')
        request = Request(method='POST',
                          body=json.dumps(primafon_data),
                          POST=default_data)
        receive_sms(request)
Esempio n. 4
0
    def test_complex_session(self):
        context = {
            'session': self.session_complex.id,
            'node': 0,
        }
        engine = Engine(user=self.user, context=context)

        # retroactively monkey patch StatefulAnonymousUser
        def send_email(self, subject=None, message=None, html_message=None):

            self.data['mail'] = message
            self.save()

        def send_sms(self, message=None):

            self.data['sms'] = message
            self.save()

        StatefulAnonymousUser.send_email = send_email
        StatefulAnonymousUser.send_sms = send_sms

        # we expect this to cascade through a number of nodes
        page = engine.run()

        # having tried to send an email and sms (normally pass for StatefulAnonymousUser),
        # which we have monkey patched, saves to user data, which saves to session
        self.assertEqual(self.session['user_data']['mail'], 'Email content')
        self.assertEqual(self.session['user_data']['sms'], 'SMS content')

        # then registering the user,
        registered_user = engine.user
        self.assertIsNotNone(registered_user)
        self.assertFalse(registered_user.is_anonymous())

        # having set password for the user,
        self.assertTrue(registered_user.check_password('hunter2'))

        # then enrolled the user if registered,
        program_user = self.program.users.first()
        self.assertEqual(program_user, registered_user)

        # then not get stuck in an infinite loop on enroll,
        # then followed the normal edge from second expression to first page (asserted above)
        self.assertEqual(page, self.page_first_complex)

        # the next edge is a session node, should return the first page of that node
        page = engine.run(next=True)
        self.assertEqual(page, self.page_first)
Esempio n. 5
0
def transition(session_id, node_id, user_id, stack=None):
    '''A task to schedule an Engine transition'''

    context = {'session': session_id, 'node': node_id, 'stack': stack or []}

    engine = Engine(user_id=user_id, context=context)

    if not engine.user.is_active:
        return _('Inactive user, no action taken')

    node = engine.transition(node_id)

    message = _('%(session)s transitioned to node %(node)s') % {
        'session': engine.session.title,
        'node': getattr(node, 'name', node_id)
    }

    return message
Esempio n. 6
0
    def test_snippet(self):
        # re-init user
        self.session = {}
        self.user = StatefulAnonymousUser(session=self.session)
        self.user.data = {}

        context = {
            'session': self.session_hub.id,
            'node': 0,
        }
        engine = Engine(user=self.user, context=context)
        page = engine.run()

        # we've visited processing session and set value
        self.assertEqual(self.user.data['somevar'], 'some value')

        # stack is now empty
        self.assertEqual(self.user.data['stack'], [])

        # we're on page_first
        self.assertEqual(page, self.page_first)
Esempio n. 7
0
    def test_run(self):
        # test init with session and node context, a common pattern
        context = {
            'session': self.session_simple.id,
            'node': 0,
        }
        engine = Engine(user=self.user, context=context)

        self.assertEqual(engine.session, self.session_simple)
        self.assertEqual(self.user.data['session'], self.session_simple.id)
        self.assertEqual(self.user.data['node'], 0)

        # test run, will transition from start and return the first page
        page = engine.run()
        self.assertEqual(page, self.page_first)

        # repeated run will return the same page
        page = engine.run()
        self.assertEqual(page, self.page_first)

        # repeated run with next will return the second page
        page = engine.run(next=True)
        self.assertEqual(page, self.page_second)
        self.assertEqual(self.user.data['session'], self.session_simple.id)
        self.assertEqual(self.user.data['node'], 2)

        # test init with push, will push current session and node to stack
        context = {
            'session': self.session_empty.id,
            'node': 0,
        }
        engine = Engine(user=self.user, context=context, push=True)
        self.assertEqual(engine.session, self.session_empty)
        self.assertEqual(self.user.data['session'], self.session_empty.id)
        self.assertEqual(self.user.data['node'], 0)
        self.assertEqual(self.user.data['stack'],
                         [(self.session_simple.id, 2)])

        # run with pop will return to previous session and node
        engine.run(pop=True)
        self.assertEqual(engine.session, self.session_simple)
        self.assertEqual(self.user.data['session'], self.session_simple.id)
        self.assertEqual(self.user.data['node'], 2)
Esempio n. 8
0
def get_page(request):

    context = {}

    if request.method == 'POST':
        post_data = json.loads(request.body) if request.body else {}
        context.update(post_data)

    # admin page preview support
    page_id = request.GET.get('page_id')
    if request.user.is_staff and page_id:
        page = get_object_or_404(Page, id=page_id)
        page.update_html(request.user)
        page.dead_end = True
        page.stacked = False

    # engine selection
    else:
        next = request.GET.get('next')
        pop = request.GET.get('pop')
        engine = Engine(user=request.user,
                        context=context,
                        is_interactive=True)
        page = engine.run(next=next, pop=pop)

    if not page:
        raise Http404

    response = {
        'title': page.display_title,
        'data': page.data,
        'dead_end': page.dead_end,
        'stacked': page.stacked
    }

    return JsonResponse(response)
Esempio n. 9
0
    def test_init(self):
        context = {
            'session': self.session_empty.id,
            'node': 0,
            'expression_somevar': '1 + 1',
            'other_var': 'value',
            'undefined': None,
        }
        engine = Engine(user=self.user, context=context)

        # test that user data is set (or not set) from context
        self.assertEqual(self.user.data['somevar'], 2)
        self.assertEqual(self.user.data['other_var'], 'value')
        self.assertEqual(self.user.data.get('undefined', 'no value'),
                         'no value')

        # test that session is loaded and initialized
        self.assertEqual(engine.session, self.session_empty)
        self.assertEqual(engine.nodes, {})
        self.assertEqual(engine.edges, [])
Esempio n. 10
0
def receive_sms(request):
    '''Receive sms message from user, process through Engine and respond'''

    reply = ''
    response = ''
    sender = ''
    body = ''
    dst = ''
    src = ''

    debug_logger = logging.getLogger('debug')
    now = timezone.now()

    if request.method == 'POST':

        debug_logger.debug('received post %s', request.POST)

        if settings.SMS_SERVICE == 'Twilio' or settings.SMS_SERVICE == 'Console':
            sender = request.POST.get('From')
            body = request.POST.get('Body')

        if settings.SMS_SERVICE == 'Plivo':
            sender = '+' + request.POST.get('From')
            dst = request.POST.get('From')
            src = request.POST.get('To')
            body = request.POST.get('Text')

        if settings.SMS_SERVICE == 'Primafon':
            data = json.loads(request.body)
            sender = '+' + data['from']
            dst = data['from']
            src = '12345678'
            body = data['body']

        try:
            user = User.objects.get(phone=sender)
            debug_logger.debug('got user %r', user)
        except:
            user = None
            reply = _('Sorry, I\'m not sure who this is.')

        if user:
            reply_session = user.data.get('reply_session')
            reply_node = user.data.get('reply_node')
            reply_var = user.data.get('reply_variable')

            if reply_session and reply_node and reply_var:

                log_event.send(user,
                               domain='user',
                               actor=user,
                               variable=reply_var,
                               pre_value=user.data.get(reply_var, ''),
                               post_value=body)

                try:
                    context = {
                        'session': reply_session,
                        'node': reply_node,
                        reply_var: body,
                    }
                    engine = Engine(user=user, context=context)
                    debug_logger.debug('prepared engine')

                    del engine.user.data['reply_session']
                    del engine.user.data['reply_node']
                    del engine.user.data['reply_variable']
                    debug_logger.debug('deleted reply vars')

                    engine.transition(reply_node)
                    debug_logger.debug('finished engine transitions')

                    engine.user.save()
                    debug_logger.debug('saved user %s', engine.user)

                except Exception as e:
                    reply = _(
                        'Sorry, there was an error processing your SMS. '
                        'Our technicians have been notified and will try to fix it.'
                    )
    else:
        debug_logger.debug('no data received')
        reply = _('No data received.')

    if settings.SMS_SERVICE == 'Twilio':
        response = twiml.Response()
        if reply:
            response.message(reply)

    if settings.SMS_SERVICE == 'Plivo':
        response = plivoxml.Response()
        if reply and src and dst:
            response.addMessage(reply, src=src, dst=dst)

    debug_logger.debug('finished request')
    return HttpResponse(response, content_type='text/xml')