示例#1
0
文件: views.py 项目: stencila/hub
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()
示例#2
0
文件: views.py 项目: stencila/hub
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()
示例#3
0
文件: views.py 项目: stencila/hub
def test_user_agent(request):
    '''
    For testing what django-user-agents and our internal request handler
    is returning for different, ummm, user agents
    '''
    rh = API(request)
    ua = request.user_agent
    return rh.respond(OrderedDict([
        ('rh_accept', rh.accept),
        ('rh_browser', rh.browser),
        ('ua_is_mobile', ua.is_mobile),
        ('ua_is_tablet', ua.is_tablet),
        ('ua_is_touch_capable', ua.is_touch_capable),
        ('ua_is_pc', ua.is_pc),
        ('ua_is_bot', ua.is_bot),
        ('ua_browser', ua.browser),
        ('ua_browser_family', ua.browser.family),
        ('ua_browser_version', ua.browser.version),
        ('ua_browser_version_string', ua.browser.version_string),
        ('ua_os', ua.os),
        ('ua_os_family', ua.os.family),
        ('ua_os_version', ua.os.version),
        ('ua_os_version_string', ua.os.version_string),
        ('ua_device', ua.device),
        ('ua_device_family', ua.device.family),
    ]))
示例#4
0
文件: views.py 项目: stencila/hub
def key_list(request):
    '''
    For:
        GET /keys
        POST /keys
    '''
    api = API(request)
    api.authenticated_or_raise()
    if api.get:
        keys = Key.list_user(
            user=request.user
        )
        return api.respond(
            data=keys,
            paginate=True
        )
    elif api.post:
        key = Key.create_one(
            user=request.user,
            address=api.required('address'),
            type=api.required('type'),
            action=api.required('action'),
            users=api.required('users')
        )
        return api.respond(
            data=key
        )
    else:
        return api.raise_method_not_allowed()
示例#5
0
文件: views.py 项目: stencila/hub
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()
示例#6
0
文件: views.py 项目: stencila/hub
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()
示例#7
0
文件: views.py 项目: stencila/hub
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()
示例#8
0
文件: views.py 项目: stencila/hub
def snapshot(request, address=None):
    api = API(request)
    api.authenticated_or_raise()
    if address:
        if api.post:
            snapshot = Snapshot.create(
                address=address,
                user=request.user,
                file=request.FILES['file']
            )
            return api.respond(snapshot)
        elif api.get:
            snapshot_url = Snapshot.get(
                address=address,
                user=request.user
            )
            if snapshot_url:
                return redirect(snapshot_url)
            else:
                raise Http404
    else:
        if api.get:
            snapshots = Snapshot.list(
                user=request.user
            )
            return api.respond(snapshots)
示例#9
0
文件: views.py 项目: stencila/hub
def address_list(request):
    '''
    For:
        GET /addresses
        POST /addresses
    '''
    api = API(request)
    api.authenticated_or_raise()
    if api.get:
        addresses = Address.list(
            user=request.user
        )
        return api.respond(
            data=addresses,
            paginate=100
        )
    elif api.post:
        address = Address.create_one(
            user=request.user,
            address=api.required('address'),
            type=api.required('type'),
            action=api.required('action'),
            users=api.required('users')
        )
        return api.respond(
            data=address
        )
    else:
        return api.raise_method_not_allowed()
示例#10
0
文件: views.py 项目: stencila/hub
def users_read(request, username):
    '''
    Read a user
    '''
    api = API(request)
    try:
        return api.respond(User.objects.get(username=username))
    except User.DoesNotExist:
        raise Http404
示例#11
0
文件: views.py 项目: stencila/hub
def route(request, address=''):
    '''
    Route a request for component/s at an address

    If the address matches that of a single component then
    open in. Otherwise show a list of all components which have
    the address as a prefix
    '''
    # Remove any trailing slash for address matches
    if address.endswith('/'):
        address = address[:-1]
    # Check to see if there is a component matching this address
    # which the user is authorized to read
    component = Component.get(
        id=None,
        user=request.user,
        action=READ,
        address=address
    )
    if component:
        api = API(request)
        if api.accept == 'json':
            return api.respond(component)
        else:
            # Yes, return the components page or
            # redirect to the component's canonical URL if necessary
            if request.path == component.url():
                return page(request, address, component)
            else:
                return redirect(component.url(), permanent=True)
    else:
        # Is there an `all` stencil at the address?
        all = address+'/all'
        component = Component.get(request.user, READ, address=all)
        if component:
            # Yes, return that all stencil's page; ensure trailing slash
            if request.path.endswith('/'):
                return page(request, all, component)
            else:
                return redirect(request.path+'/')
        else:
            # Is there an `any` stencil at the parent address?
            parts = address.split('/')
            any = '/'.join(parts[:-1]) + '/any'
            component = Component.get(request.user, READ, address=any)
            if component:
                # Yes, return that any stencil's page; ensure trailing slash
                if request.path.endswith('/'):
                    return page(request, any, component)
                else:
                    return redirect(request.path+'/')
            else:
                # No, respond with stencil that provides a listing of
                # components at the address
                return page(request, '/core/stencils/index')
示例#12
0
文件: views.py 项目: stencila/hub
def component_one(request, id):
    # TODO integrate into the above
    api = API(request)
    if api.get:
        component = Component.read_one(
            id=id,
            user=request.user,
        )
        return api.respond(
            data=component
        )
    elif api.patch:
        # Currently, PATCH is not valid for components
        api.raise_method_not_allowed()
        # api.authenticated_or_raise()
        # component = Component.update_one(
        #    id=id,
        #    user=request.user,
        #    data=api.data
        # )
        # return api.respond(
        #    data=component
        # )
    elif api.delete:
        api.authenticated_or_raise()
        Component.delete_one(
            id=id,
            user=request.user
        )
        return api.respond()
    else:
        api.raise_method_not_allowed()
示例#13
0
文件: views.py 项目: stencila/hub
def builds(request, id=None):
    api = API(request)
    if id is None:
        if api.get:
            builds = Build.list()
            return api.respond(
                builds,
                template='builds/builds.html'
            )
        elif api.post:
            build = Build.create(
                user=request.user,
                package=api.required('package'),
                flavour=api.required('flavour'),
                version=api.required('version'),
                commit=api.required('commit'),
                platform=api.optional('platform'),
                url=api.optional('url')
            )
            return api.respond(build)
    else:
        if api.get:
            build = Build.objects.get(
                id=id
            )
            return api.respond(build)

    raise API.MethodNotAllowedError(
        method=request.method
    )
示例#14
0
文件: views.py 项目: stencila/hub
def stop(request, id):
    """
    Stop a session
    """
    api = API(request)
    if api.put:
        session = Session.get(id=id, user=request.user)
        session.stop(request.user)
        return api.respond(session)
    else:
        raise API.MethodNotAllowedError(method=request.method)
示例#15
0
文件: views.py 项目: stencila/hub
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()
示例#16
0
文件: views.py 项目: stencila/hub
def events(request):
    api = API(request)
    if api.post:
        UserEvent.create(
            user=request.user,
            name=api.required('name'),
            data=api.required('data')
        )
        return api.respond()
    else:
        return api.respond(status=405)
示例#17
0
文件: views.py 项目: stencila/hub
def commits(request, address):
    '''
    Get a list of commits for a component
    '''
    api = API(request)
    component = Component.get(
        id=None,
        user=request.user,
        action=READ,
        address=address
    )
    return api.respond(component.commits())
示例#18
0
文件: views.py 项目: stencila/hub
 def wrap(request, *args, **kwargs):
     if request.user.details.tester:
         return function(request, *args, **kwargs)
     else:
         api = API(request)
         return api.respond(
             data={
                 'error': 'user:not-tester',
                 'message': 'This page or API endpoint is only available to testers. See https://stenci.la/users/testers',
             },
             template='users/testers.html',
             status=403
         )
示例#19
0
文件: views.py 项目: stencila/hub
def address_one(request, id):
    '''
    For:
        GET /addresses/{id}
        PATCH /addresses/{id}
        DELETE /addresses/{id}
    '''
    api = API(request)
    api.authenticated_or_raise()
    if api.get:
        address = Address.read_one(
            id=id,
            user=request.user
        )
        return api.respond(
            data=address
        )
    elif api.patch:
        address = Address.update_one(
            id=id,
            user=request.user,
            data=api.data
        )
        return api.respond(
            data=address
        )
    elif api.delete:
        address = Address.delete_one(
            id=id,
            user=request.user
        )
        return api.respond()
    else:
        api.raise_method_not_allowed()
示例#20
0
文件: views.py 项目: stencila/hub
def key_one(request, id):
    '''
    For:
        GET /keys/{id}
        PATCH /keys/{id}
        DELETE /keys/{id}
    '''
    api = API(request)
    api.authenticated_or_raise()
    if api.get:
        key = Key.read_one(
            id=id,
            user=request.user
        )
        return api.respond(
            data=key
        )
    elif api.patch:
        key = Key.update_one(
            id=id,
            user=request.user,
            data=api.data
        )
        return api.respond(
            data=key
        )
    elif api.delete:
        key = Key.delete_one(
            id=id,
            user=request.user
        )
        return api.respond()
    else:
        api.raise_method_not_allowed()
示例#21
0
文件: views.py 项目: stencila/hub
def component_forks(request, id):
    '''
    Get a list of a component's forks
    For:
        GET /components/{id}/forks
    '''
    api = API(request)
    component = Component.one_if_authorized_or_raise(
        user=request.user,
        action=READ,
        id=id
    )
    if api.get:
        forks = component.forks(user)
        return api.respond(forks)
    else:
        api.raise_method_not_allowed()
示例#22
0
文件: views.py 项目: stencila/hub
def commit(request, address):
    '''
    Commit the component

    This is a temporary stub implementation.
    It should robably be implemented as a "method"
    call above.
    '''
    api = API(request)
    component = Component.get(
        id=None,
        user=request.user,
        action=READ,
        address=address
    )
    return api.respond(dict(
        revision='xxxxxxxxx'
    ))
示例#23
0
文件: views.py 项目: stencila/hub
def ping(request, id):
    """
    Ping a session to keep it open

    Return `ready` value.
    Sessions that have not been pinged for sometime will be automatically
    stopped.
    """
    api = API(request)
    if api.put:
        session = Session.get(id=id, user=request.user)
        if session.active:
            session.ping()
            return api.respond({"ready": session.ready})
        else:
            return api.respond({"error": "session:inactive", "message": "Session is no longer active"})
    else:
        raise API.MethodNotAllowedError(method=request.method)
示例#24
0
文件: views.py 项目: stencila/hub
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()
示例#25
0
文件: views.py 项目: stencila/hub
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()
示例#26
0
文件: views.py 项目: stencila/hub
def received(request, address):
    '''
    Endpoint for the `curator` to ping when a component has
    received an update e.g. from `git push`. A token is used to protect access.
    But this endpoint only accepts the address of the component and then fetches an
    update from the `curator`, so a malicious user can not read or write data anyway.
    '''
    api = API(request)
    # Check access token
    token = api.required('token')
    if token != settings.COMMS_TOKEN:
        return JsonResponse(
            {'error': 'invalid token'},
            status=403
        )
    # Update the component
    component = Component.objects.get(
        address=address
    )
    component.update()
    return api.respond()
示例#27
0
文件: views.py 项目: stencila/hub
def content(request, address):
    '''
    Get or set the content of a stencil
    '''
    api = API(request)
    if api.get:
        component = Component.get(
            id=None,
            user=request.user,
            action=READ,
            address=address
        )
        result = component.content_get(
            format=api.optional('format', 'html'),
        )
    elif api.put:
        component = Component.get(
            id=None,
            user=request.user,
            action=UPDATE,
            address=address
        )
        result = component.content_set(
            user=request.user,
            format=api.required('format'),
            content=api.required('content'),
            revision=api.required('revision')
        )
    return api.respond(result)
示例#28
0
文件: views.py 项目: stencila/hub
def sessions(request, id=None):
    api = API(request)
    if id is None:
        if api.get:
            # Get a list of sessions
            sessions = Session.list(user=request.user, filter={"active": True})
            return api.respond(
                sessions,
                template="sessions/list.html",
                context={
                    "sessions": sessions,
                    "types": SessionType.objects.order_by("rank").all(),
                    "images": SessionImage.objects.all(),
                },
            )
        elif api.post:
            # Launch a session for the user
            session = Session.launch(user=request.user, type_id=api.required("type"), image_name=api.require("image"))
            return api.respond(session)
    else:
        if api.get:
            # Get a session, updating it first
            session = Session.get(id=id, user=request.user)
            if session.active:
                session.update()
            return api.respond(session)

    return api.respond(status=405)
示例#29
0
文件: views.py 项目: stencila/hub
def tokens(request, id=None):
    '''
    List, create, read, update, delete user tokens
    '''
    api = API(request)
    if id is None:
        if api.get:
            # List all tokens for the user
            tokens = UserToken.objects.filter(
                user=request.user
            )
            return api.respond(tokens)
        elif api.post:
            # Create a token for the user
            token = UserToken.objects.create(
                user=request.user,
                name=api.optional('name'),
                notes=api.optional('notes')
            )
            return api.respond(token)
    else:
        # Get token, ensuring it is associated with the
        # request user
        token = UserToken.get_or_raise(
            id=id,
            user=request.user
        )
        if api.get:
            # Read it
            return api.respond(token)
        elif api.patch:
            # Update it
            token.name = api.optional('name')
            token.notes = api.optional('notes')
            token.save()
            return api.respond(token)
        elif api.delete:
            # Delete it
            token.delete()
            return api.respond()
示例#30
0
文件: views.py 项目: stencila/hub
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()