Exemple #1
0
def live_html(request, address):
    '''
    Get the HTML of a live copy of a document

    This should be generalised and/or merge wiith the `content` view (which also gets (and sets) HTML).
    '''
    api = API(request)
    if api.get:
        # First, check access rights
        component = Component.get(
            id=None,
            address=address,
            user=request.user,
            action=READ
        )
        # Get HTML from broker
        response = requests.get('http://10.0.1.75:7315/' + address + '@live?format=html')
        if response.status_code != 200:
            raise Exception(response.text)
        else:
            if api.browser:
                response = HttpResponse(response.json()['data'], content_type='text/html')
                response['Content-Disposition'] = 'attachment; filename="document.html"'
                return response
            else:
                return api.respond(data=response.json())

    return api.respond_bad()
Exemple #2
0
def collaborate(request, address):
    '''
    Connect to a live collaboration clone via a Websocket connection
    '''
    api = API(request)
    if api.get:
        if not request.user.is_authenticated():
            return api.respond_signin()
        else:
            # Check that the permit is correct for this address and user
            # TODO add a salt
            if compare_digest(
                str(request.GET.get('permit', '')),
                hmac.new(settings.SECRET_KEY, address + ':' + request.user.username).hexdigest()
            ):
                url = '/internal-collaboration-websocket/%s:%s' % (
                    # TODO when we have multiple collaboration servers, find the IP one for the one hostong
                    # this address
                    '10.0.1.75',
                    7315
                )
                response = HttpResponse('X-Accel-Redirect : %s' % url)
                response['X-Accel-Redirect'] = url
                return response
            else:
                raise Http404()
    return api.respond_bad()
Exemple #3
0
def ping(request, address):
    '''
    Ping the component's session.

    Returns the session id since that could change
    '''
    api = API(request)
    if api.put:
        if not request.user.is_authenticated():
            return api.respond_signin()
        else:
            component = Component.get(
                id=None,
                user=request.user,
                action=READ,
                address=address
            )
            session = component.activate(
                user=request.user
            )
            session.ping()
            return api.respond({
                'session': session.id
            })
    return api.respond_bad()
Exemple #4
0
def boot(request, address):
    '''
    Boot up a component
    '''
    api = API(request)
    if api.put:
        component = Component.get(
            id=None,
            user=request.user,
            action=READ,
            address=address
        )

        action, grantor = component.rights(request.user)
        if action >= EXECUTE:
            api.user_ensure()
            session = component.activate(
                user=request.user
            )
        else:
            session = None

        return api.respond({
            'rights': {
                'action': action_string(action),
                'grantor': grantor.serialize(user=request.user) if grantor else None
            },
            'session': session.serialize(user=request.user) if session else None
        })
    return api.respond_bad()
Exemple #5
0
def method(request, address, method):
    '''
    A general view for calling methods on components that are hosted
    in a session. Will launch a new session for a component if necessary.
    Not all component methods need an active session so views
    should be explicitly provided for those below.
    '''
    api = API(request)
    if api.put:
        if not request.user.is_authenticated():
            return api.respond_signin()
        else:
            component = Component.get(
                id=None,
                user=request.user,
                action=READ, # TODO : allow for alternative rights
                address=address
            )
            session = component.activate(
                user=request.user
            )
            status, body = session.request(
                resource=address,
                verb=request.method,
                method=method,
                data=request.body
            )
            return api.respond(
                data=body,
                raw=True,
                status=status
            )
    return api.respond_bad()
Exemple #6
0
def live(request, address):
    '''
    Open the live collaboration clone for the component.
    '''
    api = API(request)
    if api.get:
        # First, check access rights
        component = Component.get(
            id=None,
            address=address,
            user=request.user,
            action=ANNOTATE
        )
        payload = {}
        # Then, see if a live collaboration clone already exists
        # Get the snapshot data
        # TODO: In the future there may be several collaboration servers
        response = requests.get('http://10.0.1.75:7315/' + address + '@live')
        if response.status_code == 404:
            response = requests.post('http://10.0.1.75:7315/', json = {
                'schemaName': 'stencila-document',
                'documentId': address + '@live',
                'format': 'html',
                'content': component.content_get('html')['content']
            })
            if response.status_code != 200:
                raise Exception(response.text)
        payload['snapshot'] = response.json()
        # Insert the collaboration websocket URL
        if settings.MODE == 'local':
            # It's not possible to do a Websocket redirect (without Nginx's 'X-Accel-Redirect') so
            # in development just give direct WS URL of collaboration server
            ws = 'ws://10.0.1.75:7315'
        else:
            ws = 'wss://stenci.la'
        ws += '/%s@collaborate?permit=%s' % (
            address,
            hmac.new(settings.SECRET_KEY, address + ':' + request.user.username).hexdigest()
        )
        payload['collabUrl'] = ws
        # Insert the user and access rights
        action, grantor = component.rights(request.user)
        payload['user'] = request.user.username
        payload['rights'] = action_string(action)
        # Render template with snapshot data embedded in it
        return api.respond(
            template = 'components/live.html',
            context = {
                'type': 'document',
                'payload': json.dumps(payload)
            }
        )

    return api.respond_bad()
Exemple #7
0
def deactivate(request, address):
    '''
    Dectivate a component by stopping the currently active session for it
    '''
    api = API(request)
    if api.put:
        if not request.user.is_authenticated():
            return api.respond_signin()
        else:
            component = Component.get(
                id=None,
                user=request.user,
                action=READ,
                address=address
            )
            session = component.deactivate(
                user=request.user
            )
            return api.respond(session)
    return api.respond_bad()
Exemple #8
0
def new(request):
    """
    List session types, create a new session, launch it and redirect the
    user to it's page
    """
    api = API(request)
    if api.get:
        return api.respond(
            template="sessions/new.html",
            context={
                "sessions": Session.list(user=request.user, filter={"active": True}).count(),
                "types": SessionType.objects.order_by("rank").all(),
                "images": SessionImage.objects.all(),
            },
        )
    elif api.post:
        session = Session.launch(user=request.user, type_id=api.required("type"), image_name=api.required("image"))
        return api.respond_created(url=session.url())

    return api.respond_bad()
Exemple #9
0
def session(request, address):
    '''
    Get the session, if any, for a component
    '''
    api = API(request)
    if api.put:
        if not request.user.is_authenticated():
            return api.respond_signin()
        else:
            component = Component.get(
                id=None,
                user=request.user,
                action=READ,
                address=address
            )
            session = component.session(
                user=request.user,
                required=False
            )
            if session and session.active:
                session.update()
            return api.respond(session)
    return api.respond_bad()
Exemple #10
0
def accept(request, string):
    """
    @brief      View for accepting an invitation
    
    @param      request  The request
    @param      string   The string
    """
    api = API(request)

    # Get the invitation
    try:
        invitation = Invitation.objects.get(string=string)
    except Invitation.DoesNotExist:
        return api.raise_not_found()

    # If the invitatation has already expired, let the user know
    if invitation.sent + datetime.timedelta(days=invitation.expiry) < timezone.now():
        return render(request, 'invitations/expired.html', dict(
            invitation=invitation
        ))

    # Check whether the user need to be authenticated first
    if not request.user.is_authenticated():
        authed = False
    elif request.user.details.guest:
        # Logout the guest
        # TODO it would be better to "join up" the guest
        authed = False
    else:
        authed = True

    if authed:
        # Add the user to the key and redirect them to the path
        invitation.key.users.add(request.user)
        invitation.accepted = timezone.now()
        invitation.accepter = request.user
        invitation.save()
        return redirect(invitation.path)
    else:
        # Authenticate the user...
        if invitation.accepted:
            # Don't Offer the "express" login where we create
            # a new user if this invitation has already been accepted
            express_username = None
        else:
            # Create a username for "express" signin
            base = invitation.invitee.split('@')[0]
            express_username = base
            trials = 0
            while True:
                if User.objects.filter(username=express_username).count() == 0:
                    break
                trials += 1
                if trials > 1000000:
                    raise Exception("Maximum number of ")
                express_username = '******' %(base, trials)

        # URL for redirect when using third party account
        # to login (come back to this view and get redirected)
        next = '/invitations/%s/accept' % string

        if api.get:
            # Render athentication forms
            return render(request, 'invitations/accept.html', dict(
                invitation=invitation,
                next=next,
                userpass_form=AuthenticationForm(),
                express_username=express_username
            ))
        elif api.post:
            if request.POST.get('userpass_signin'):
                # Attempt to signin with username/password
                form = AuthenticationForm(data=request.POST)
                if not form.is_valid():
                    # Display errors
                    return render(request, 'invitations/accept.html', dict(
                        invitation=invitation,
                        next=next,
                        userpass_form=form,
                        express_username=express_username
                    ))
                else:
                    # Login the user and then proceed with accept view
                    login(request, form.get_user())
                    # Continue recursively
                    return accept(request, string)
            elif express_username and request.POST.get('express_signin'):
                # Create a new user and log them in 
                user = User.objects.create_user(
                    username=express_username,
                    email=invitation.invitee
                )
                user.backend = 'django.contrib.auth.backends.ModelBackend'
                login(request, user)
                # Continue recursively
                return accept(request, string)
            else:
                # Some thing else, just go back the page
                return redirect(next)
        else:
            return api.respond_bad()