Ejemplo n.º 1
0
 def test_from_kwargs(self):
     user = UserFactory()
     request_args = {'view_only': 'mykey'}
     kwargs = {'user': user}
     auth_obj = Auth.from_kwargs(request_args, kwargs)
     assert_equal(auth_obj.user, user)
     assert_equal(auth_obj.private_key, request_args['view_only'])
Ejemplo n.º 2
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user
            if user is not None:
                user.update_date_last_access()

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            if not include_view_only_anon:
                from osf.models import PrivateLink
                try:
                    link_anon = PrivateLink.objects.filter(key=key).values_list('anonymous', flat=True).get()
                except PrivateLink.DoesNotExist:
                    link_anon = None

            if not node.is_public or not include_public:
                if not include_view_only_anon and link_anon:
                    if not check_can_access(node=node, user=user):
                        raise HTTPError(http.UNAUTHORIZED)
                elif key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key, node=node, url=request.url)
                        if request.headers.get('Content-Type') == 'application/json':
                            raise HTTPError(http.UNAUTHORIZED)
                        else:
                            response = redirect(cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 3
0
        def wrapped(*args, **kwargs):
            response = None
            kwargs['project'], kwargs['node'] = _kwargs_to_nodes(kwargs)
            node = kwargs['node'] or kwargs['project']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            if 'api_node' in kwargs:
                api_node = kwargs['api_node']
            else:
                api_node = get_api_key()
                kwargs['api_node'] = api_node

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            if not node.is_public or not include_public:
                if key not in node.private_link_keys_active:
                    if not check_can_access(
                            node=node, user=user, api_node=api_node, key=key):
                        url = '/login/?next={0}'.format(request.path)
                        redirect_url = check_key_expired(key=key,
                                                         node=node,
                                                         url=url)
                        response = redirect(redirect_url)

            return response or func(*args, **kwargs)
Ejemplo n.º 4
0
        def wrapped(*args, **kwargs):
            response = None
            kwargs['project'], kwargs['node'] = _kwargs_to_nodes(kwargs)
            node = kwargs['node'] or kwargs['project']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            if 'api_node' in kwargs:
                api_node = kwargs['api_node']
            else:
                api_node = get_api_key()
                kwargs['api_node'] = api_node

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            if not node.is_public or not include_public:
                if key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user,
                            api_node=api_node, key=key):
                        url = '/login/?next={0}'.format(request.path)
                        redirect_url = check_key_expired(key=key, node=node, url=url)
                        response = redirect(redirect_url)

            return response or func(*args, **kwargs)
Ejemplo n.º 5
0
 def test_from_kwargs(self):
     user = UserFactory()
     request_args = {'view_only': 'mykey'}
     kwargs = {'user': user}
     auth_obj = Auth.from_kwargs(request_args, kwargs)
     assert_equal(auth_obj.user, user)
     assert_equal(auth_obj.private_key, request_args['view_only'])
Ejemplo n.º 6
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            link_anon = None
            if not include_view_only_anon:
                from website.models import PrivateLink
                try:
                    link_anon = PrivateLink.find_one(Q('key', 'eq', key)).anonymous
                except ModularOdmException:
                    pass

            if not node.is_public or not include_public:
                if not include_view_only_anon and link_anon:
                    if not check_can_access(node=node, user=user):
                        raise HTTPError(http.UNAUTHORIZED)
                elif key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key, node=node, url=request.url)
                        if request.headers.get('Content-Type') == 'application/json':
                            raise HTTPError(http.UNAUTHORIZED)
                        else:
                            response = redirect(cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 7
0
def _view_registries_landing_page(campaign=None, **kwargs):
    """Landing page for the various registrations"""
    auth = kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
    is_logged_in = kwargs['auth'].logged_in
    if is_logged_in:
        # Using contributor_to instead of contributor_to_or_group_member.
        # You need to be an admin contributor to register a node
        registerable_nodes = [
            node for node
            in auth.user.contributor_to
            if node.has_permission(user=auth.user, permission=ADMIN)
        ]
        has_projects = bool(registerable_nodes)
    else:
        has_projects = False

    if campaign == 'registered_report':
        campaign_url_param = 'osf-registered-reports'
    elif campaign == 'prereg_challenge' or campaign == 'prereg':
        campaign_url_param = 'prereg'
    else:
        campaign_url_param = ''

    return {
        'is_logged_in': is_logged_in,
        'has_draft_registrations': bool(utils.drafts_for_user(auth.user, campaign)),
        'has_projects': has_projects,
        'campaign_long': utils.REG_CAMPAIGNS.get(campaign),
        'campaign_short': campaign,
        'sign_up_url': util.web_url_for('auth_register', _absolute=True, campaign=campaign_url_param, next=request.url),
    }
Ejemplo n.º 8
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            link_anon = None
            if not include_view_only_anon:
                from website.models import PrivateLink
                try:
                    link_anon = PrivateLink.find_one(Q('key', 'eq', key)).anonymous
                except ModularOdmException:
                    pass

            if not node.is_public or not include_public:
                if not include_view_only_anon and link_anon:
                    if not check_can_access(node=node, user=user):
                        raise HTTPError(http.UNAUTHORIZED)
                elif key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key, node=node, url=request.url)
                        if request.headers.get('Content-Type') == 'application/json':
                            raise HTTPError(http.UNAUTHORIZED)
                        else:
                            response = redirect(cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 9
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            if not node.is_public or not include_public:
                if key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key,
                                                         node=node,
                                                         url=request.url)
                        if request.headers.get(
                                'Content-Type') == 'application/json':
                            raise HTTPError(http.UNAUTHORIZED)
                        else:
                            response = redirect(
                                cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 10
0
        def wrapped(*args, **kwargs):
            _inject_nodes(kwargs)

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)

            response = check_contributor_auth(kwargs['node'], kwargs['auth'], include_public, include_view_only_anon)

            return response or func(*args, **kwargs)
Ejemplo n.º 11
0
        def wrapped(*args, **kwargs):
            _inject_nodes(kwargs)

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)

            response = check_contributor_auth(kwargs['node'], kwargs['auth'],
                                              include_public,
                                              include_view_only_anon)

            return response or func(*args, **kwargs)
Ejemplo n.º 12
0
        def wrapped(*args, **kwargs):
            response = None
            target = None
            guid = Guid.load(kwargs.get('guid'))
            if guid:
                target = getattr(guid, 'referent', None)
            else:
                _inject_nodes(kwargs)

            target = target or kwargs.get('node')

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)

            response = check_contributor_auth(target, kwargs['auth'], include_public, include_view_only_anon, include_groups)

            return response or func(*args, **kwargs)
Ejemplo n.º 13
0
        def wrapped(*args, **kwargs):
            response = None
            target = None
            guid = Guid.load(kwargs.get('guid'))
            if guid:
                target = getattr(guid, 'referent', None)
            else:
                _inject_nodes(kwargs)

            target = target or kwargs.get('node')

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)

            response = check_contributor_auth(target, kwargs['auth'], include_public, include_view_only_anon)

            return response or func(*args, **kwargs)
Ejemplo n.º 14
0
        def wrapped(*args, **kwargs):
            # Ensure `project` and `node` kwargs
            _inject_nodes(kwargs)
            node = kwargs["node"]

            kwargs["auth"] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs["auth"].user

            # User must be logged in
            if user is None:
                raise HTTPError(http.UNAUTHORIZED)

            # User must have permissions
            if not node.has_permission(user, permission):
                raise HTTPError(http.FORBIDDEN)

            # Call view function
            return func(*args, **kwargs)
Ejemplo n.º 15
0
        def wrapped(*args, **kwargs):
            # Ensure `project` and `node` kwargs
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            # User must be logged in
            if user is None:
                raise HTTPError(http.UNAUTHORIZED)

            # User must have permissions
            if not node.has_permission(user, permission):
                raise HTTPError(http.FORBIDDEN)

            # Call view function
            return func(*args, **kwargs)
Ejemplo n.º 16
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs['node']

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            key = request.args.get('view_only', '').strip('/')
            #if not login user check if the key is valid or the other privilege

            kwargs['auth'].private_key = key
            if not node.is_public or not include_public:
                if key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key, node=node, url=request.url)
                        response = redirect(cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 17
0
        def wrapped(*args, **kwargs):
            # Ensure `project` and `node` kwargs
            if kwargs.get('nid') or kwargs.get('pid'):
                _inject_nodes(kwargs)
            target = kwargs.get('node') or getattr(Guid.load(kwargs.get('guid')), 'referent', None)

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            # User must be logged in
            if user is None:
                raise HTTPError(http.UNAUTHORIZED)

            # User must have permissions
            if not target.has_permission(user, permission):
                raise HTTPError(http.FORBIDDEN)

            # Call view function
            return func(*args, **kwargs)
Ejemplo n.º 18
0
        def wrapped(*args, **kwargs):
            # Ensure `project` and `node` kwargs
            if kwargs.get('nid') or kwargs.get('pid'):
                _inject_nodes(kwargs)
            target = kwargs.get('node') or getattr(Guid.load(kwargs.get('guid')), 'referent', None)

            kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs['auth'].user

            # User must be logged in
            if user is None:
                raise HTTPError(http.UNAUTHORIZED)

            # User must have permissions
            if not target.has_permission(user, permission):
                raise HTTPError(http.FORBIDDEN)

            # Call view function
            return func(*args, **kwargs)
Ejemplo n.º 19
0
def _view_registries_landing_page(campaign=None, **kwargs):
    """Landing page for the various registrations"""
    auth = kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
    is_logged_in = kwargs['auth'].logged_in
    if is_logged_in:
        registerable_nodes = [
            node for node in auth.user.contributor_to
            if node.has_permission(user=auth.user, permission='admin')
        ]
        has_projects = bool(registerable_nodes)
    else:
        has_projects = False

    return {
        'is_logged_in': is_logged_in,
        'has_draft_registrations':
        bool(utils.drafts_for_user(auth.user, campaign)),
        'has_projects': has_projects,
        'campaign_long': utils.REG_CAMPAIGNS.get(campaign),
        'campaign_short': campaign
    }
Ejemplo n.º 20
0
        def wrapped(*args, **kwargs):
            response = None
            _inject_nodes(kwargs)
            node = kwargs["node"]

            kwargs["auth"] = Auth.from_kwargs(request.args.to_dict(), kwargs)
            user = kwargs["auth"].user

            key = request.args.get("view_only", "").strip("/")
            # if not login user check if the key is valid or the other privilege

            kwargs["auth"].private_key = key
            if not node.is_public or not include_public:
                if key not in node.private_link_keys_active:
                    if not check_can_access(node=node, user=user, key=key):
                        redirect_url = check_key_expired(key=key, node=node, url=request.url)
                        if request.headers.get("Content-Type") == "application/json":
                            raise HTTPError(http.UNAUTHORIZED)
                        else:
                            response = redirect(cas.get_login_url(redirect_url))

            return response or func(*args, **kwargs)
Ejemplo n.º 21
0
def _view_registries_landing_page(campaign=None, **kwargs):
    """Landing page for the various registrations"""
    auth = kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs)
    is_logged_in = kwargs['auth'].logged_in
    if is_logged_in:
        registerable_nodes = [
            node for node
            in auth.user.contributor_to
            if node.has_permission(user=auth.user, permission='admin')
        ]
        has_projects = bool(registerable_nodes)
    else:
        has_projects = False

    return {
        'is_logged_in': is_logged_in,
        'has_draft_registrations': bool(utils.drafts_for_user(auth.user, campaign)),
        'has_projects': has_projects,
        'campaign_long': utils.REG_CAMPAIGNS.get(campaign),
        'campaign_short': campaign

    }
Ejemplo n.º 22
0
def resolve_guid(guid, suffix=None):
    """Load GUID by primary key, look up the corresponding view function in the
    routing table, and return the return value of the view function without
    changing the URL.

    :param str guid: GUID primary key
    :param str suffix: Remainder of URL after the GUID
    :return: Return value of proxied view function
    """
    try:
        # Look up
        guid_object = Guid.load(guid)
    except KeyError as e:
        if e.message == 'osfstorageguidfile':  # Used when an old detached OsfStorageGuidFile object is accessed
            raise HTTPError(http.NOT_FOUND)
        else:
            raise e
    if guid_object:
        # verify that the object implements a GuidStoredObject-like interface. If a model
        #   was once GuidStoredObject-like but that relationship has changed, it's
        #   possible to have referents that are instances of classes that don't
        #   have a deep_url attribute or otherwise don't behave as
        #   expected.
        if not hasattr(guid_object.referent, 'deep_url'):
            sentry.log_message(
                'Guid resolved to an object with no deep_url', dict(guid=guid)
            )
            raise HTTPError(http.NOT_FOUND)
        referent = guid_object.referent
        if referent is None:
            logger.error('Referent of GUID {0} not found'.format(guid))
            raise HTTPError(http.NOT_FOUND)
        if not referent.deep_url:
            raise HTTPError(http.NOT_FOUND)

        # Handle file `/download` shortcut with supported types.
        if suffix and suffix.rstrip('/').lower() == 'download':
            file_referent = None
            if isinstance(referent, PreprintService) and referent.primary_file:
                if not referent.is_published:
                    # TODO: Ideally, permissions wouldn't be checked here.
                    # This is necessary to prevent a logical inconsistency with
                    # the routing scheme - if a preprint is not published, only
                    # admins and moderators should be able to know it exists.
                    auth = Auth.from_kwargs(request.args.to_dict(), {})
                    group_helper = GroupHelper(referent.provider)
                    admin_group = group_helper.get_group('admin')
                    mod_group = group_helper.get_group('moderator')
                    # Check if user isn't a nonetype or that the user has admin/moderator permissions
                    if auth.user is None or not (referent.node.has_permission(auth.user, permissions.ADMIN) or (mod_group.user_set.all() | admin_group.user_set.all()).filter(id=auth.user.id).exists()):
                        raise HTTPError(http.NOT_FOUND)
                file_referent = referent.primary_file
            elif isinstance(referent, BaseFileNode) and referent.is_file:
                file_referent = referent

            if file_referent:
                # Extend `request.args` adding `action=download`.
                request.args = request.args.copy()
                request.args.update({'action': 'download'})
                # Do not include the `download` suffix in the url rebuild.
                url = _build_guid_url(urllib.unquote(file_referent.deep_url))
                return proxy_url(url)

        # Handle Ember Applications
        if isinstance(referent, PreprintService):
            if referent.provider.domain_redirect_enabled:
                # This route should always be intercepted by nginx for the branded domain,
                # w/ the exception of `<guid>/download` handled above.
                return redirect(referent.absolute_url, http.MOVED_PERMANENTLY)

            if PROXY_EMBER_APPS:
                resp = requests.get(EXTERNAL_EMBER_APPS['preprints']['server'], stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT)
                return Response(stream_with_context(resp.iter_content()), resp.status_code)

            return send_from_directory(preprints_dir, 'index.html')

        if isinstance(referent, BaseFileNode) and referent.is_file and referent.node.is_quickfiles:
            if referent.is_deleted:
                raise HTTPError(http.GONE)
            if PROXY_EMBER_APPS:
                resp = requests.get(EXTERNAL_EMBER_APPS['ember_osf_web']['server'], stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT)
                return Response(stream_with_context(resp.iter_content()), resp.status_code)

            return send_from_directory(ember_osf_web_dir, 'index.html')

        if isinstance(referent, Node) and not referent.is_registration and suffix:
            page = suffix.strip('/').split('/')[0]
            flag_name = 'ember_project_{}_page'.format(page)
            request.user = _get_current_user() or MockUser()

            if waffle.flag_is_active(request, flag_name):
                use_ember_app()

        url = _build_guid_url(urllib.unquote(referent.deep_url), suffix)
        return proxy_url(url)

    # GUID not found; try lower-cased and redirect if exists
    guid_object_lower = Guid.load(guid.lower())
    if guid_object_lower:
        return redirect(
            _build_guid_url(guid.lower(), suffix)
        )

    # GUID not found
    raise HTTPError(http.NOT_FOUND)
Ejemplo n.º 23
0
def resolve_guid(guid, suffix=None):
    """Load GUID by primary key, look up the corresponding view function in the
    routing table, and return the return value of the view function without
    changing the URL.

    :param str guid: GUID primary key
    :param str suffix: Remainder of URL after the GUID
    :return: Return value of proxied view function
    """
    try:
        # Look up
        guid_object = Guid.load(guid)
    except KeyError as e:
        if e.message == 'osfstorageguidfile':  # Used when an old detached OsfStorageGuidFile object is accessed
            raise HTTPError(http.NOT_FOUND)
        else:
            raise e
    if guid_object:
        # verify that the object implements a GuidStoredObject-like interface. If a model
        #   was once GuidStoredObject-like but that relationship has changed, it's
        #   possible to have referents that are instances of classes that don't
        #   have a deep_url attribute or otherwise don't behave as
        #   expected.
        if not hasattr(guid_object.referent, 'deep_url'):
            sentry.log_message(
                'Guid resolved to an object with no deep_url', dict(guid=guid)
            )
            raise HTTPError(http.NOT_FOUND)
        referent = guid_object.referent
        if referent is None:
            logger.error('Referent of GUID {0} not found'.format(guid))
            raise HTTPError(http.NOT_FOUND)
        if not referent.deep_url:
            raise HTTPError(http.NOT_FOUND)

        # Handle file `/download` shortcut with supported types.
        if suffix and suffix.rstrip('/').lower() == 'download':
            file_referent = None
            if isinstance(referent, PreprintService) and referent.primary_file:
                if not referent.is_published:
                    # TODO: Ideally, permissions wouldn't be checked here.
                    # This is necessary to prevent a logical inconsistency with
                    # the routing scheme - if a preprint is not published, only
                    # admins should be able to know it exists.
                    auth = Auth.from_kwargs(request.args.to_dict(), {})
                    if not referent.node.has_permission(auth.user, permissions.ADMIN):
                        raise HTTPError(http.NOT_FOUND)
                file_referent = referent.primary_file
            elif isinstance(referent, BaseFileNode) and referent.is_file:
                file_referent = referent

            if file_referent:
                # Extend `request.args` adding `action=download`.
                request.args = request.args.copy()
                request.args.update({'action': 'download'})
                # Do not include the `download` suffix in the url rebuild.
                url = _build_guid_url(urllib.unquote(file_referent.deep_url))
                return proxy_url(url)

        # Handle Ember Applications
        if isinstance(referent, PreprintService):
            if referent.provider.domain_redirect_enabled:
                # This route should always be intercepted by nginx for the branded domain,
                # w/ the exception of `<guid>/download` handled above.
                return redirect(referent.absolute_url, http.MOVED_PERMANENTLY)

            return send_from_directory(preprints_dir, 'index.html')
        url = _build_guid_url(urllib.unquote(referent.deep_url), suffix)
        return proxy_url(url)

    # GUID not found; try lower-cased and redirect if exists
    guid_object_lower = Guid.load(guid.lower())
    if guid_object_lower:
        return redirect(
            _build_guid_url(guid.lower(), suffix)
        )

    # GUID not found
    raise HTTPError(http.NOT_FOUND)
Ejemplo n.º 24
0
def resolve_guid(guid, suffix=None):
    """Load GUID by primary key, look up the corresponding view function in the
    routing table, and return the return value of the view function without
    changing the URL.

    :param str guid: GUID primary key
    :param str suffix: Remainder of URL after the GUID
    :return: Return value of proxied view function
    """
    try:
        # Look up
        guid_object = Guid.load(guid)
    except KeyError as e:
        if e.message == 'osfstorageguidfile':  # Used when an old detached OsfStorageGuidFile object is accessed
            raise HTTPError(http.NOT_FOUND)
        else:
            raise e
    if guid_object:
        # verify that the object implements a GuidStoredObject-like interface. If a model
        #   was once GuidStoredObject-like but that relationship has changed, it's
        #   possible to have referents that are instances of classes that don't
        #   have a deep_url attribute or otherwise don't behave as
        #   expected.
        if not hasattr(guid_object.referent, 'deep_url'):
            sentry.log_message(
                'Guid resolved to an object with no deep_url', dict(guid=guid)
            )
            raise HTTPError(http.NOT_FOUND)
        referent = guid_object.referent
        if referent is None:
            logger.error('Referent of GUID {0} not found'.format(guid))
            raise HTTPError(http.NOT_FOUND)
        if not referent.deep_url:
            raise HTTPError(http.NOT_FOUND)

        # Handle file `/download` shortcut with supported types.
        if suffix and suffix.rstrip('/').lower() == 'download':
            file_referent = None
            if isinstance(referent, Preprint) and referent.primary_file:
                file_referent = referent.primary_file
            elif isinstance(referent, BaseFileNode) and referent.is_file:
                file_referent = referent

            if file_referent:
                if isinstance(file_referent.target, Preprint) and not file_referent.target.is_published:
                    # TODO: Ideally, permissions wouldn't be checked here.
                    # This is necessary to prevent a logical inconsistency with
                    # the routing scheme - if a preprint is not published, only
                    # admins and moderators should be able to know it exists.
                    auth = Auth.from_kwargs(request.args.to_dict(), {})
                    # Check if user isn't a nonetype or that the user has admin/moderator/superuser permissions
                    if auth.user is None or not (auth.user.has_perm('view_submissions', file_referent.target.provider) or
                            file_referent.target.has_permission(auth.user, permissions.ADMIN)):
                        raise HTTPError(http.NOT_FOUND)

                # Extend `request.args` adding `action=download`.
                request.args = request.args.copy()
                request.args.update({'action': 'download'})
                # Do not include the `download` suffix in the url rebuild.
                url = _build_guid_url(urllib.unquote(file_referent.deep_url))
                return proxy_url(url)

        # Handle Ember Applications
        if isinstance(referent, Preprint):
            if referent.provider.domain_redirect_enabled:
                # This route should always be intercepted by nginx for the branded domain,
                # w/ the exception of `<guid>/download` handled above.
                return redirect(referent.absolute_url, http.MOVED_PERMANENTLY)

            if PROXY_EMBER_APPS:
                resp = requests.get(EXTERNAL_EMBER_APPS['preprints']['server'], stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT)
                return Response(stream_with_context(resp.iter_content()), resp.status_code)

            return send_from_directory(preprints_dir, 'index.html')

        if isinstance(referent, BaseFileNode) and referent.is_file and (getattr(referent.target, 'is_quickfiles', False)):
            if referent.is_deleted:
                raise HTTPError(http.GONE)
            if PROXY_EMBER_APPS:
                resp = requests.get(EXTERNAL_EMBER_APPS['ember_osf_web']['server'], stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT)
                return Response(stream_with_context(resp.iter_content()), resp.status_code)

            return send_from_directory(ember_osf_web_dir, 'index.html')

        if isinstance(referent, Registration) and (
                not suffix or suffix.rstrip('/').lower() in ('comments', 'links', 'components')
        ):
            if flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE):
                # Route only the base detail view to ember
                if PROXY_EMBER_APPS:
                    resp = requests.get(EXTERNAL_EMBER_APPS['ember_osf_web']['server'], stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT)
                    return Response(stream_with_context(resp.iter_content()), resp.status_code)

                return send_from_directory(registries_dir, 'index.html')

        url = _build_guid_url(urllib.unquote(referent.deep_url), suffix)
        return proxy_url(url)

    # GUID not found; try lower-cased and redirect if exists
    guid_object_lower = Guid.load(guid.lower())
    if guid_object_lower:
        return redirect(
            _build_guid_url(guid.lower(), suffix)
        )

    # GUID not found
    raise HTTPError(http.NOT_FOUND)
Ejemplo n.º 25
0
def resolve_guid(guid, suffix=None):
    """Load GUID by primary key, look up the corresponding view function in the
    routing table, and return the return value of the view function without
    changing the URL.

    :param str guid: GUID primary key
    :param str suffix: Remainder of URL after the GUID
    :return: Return value of proxied view function
    """
    try:
        # Look up
        guid_object = Guid.load(guid)
    except KeyError as e:
        if e.message == 'osfstorageguidfile':  # Used when an old detached OsfStorageGuidFile object is accessed
            raise HTTPError(http.NOT_FOUND)
        else:
            raise e
    if guid_object:
        # verify that the object implements a GuidStoredObject-like interface. If a model
        #   was once GuidStoredObject-like but that relationship has changed, it's
        #   possible to have referents that are instances of classes that don't
        #   have a deep_url attribute or otherwise don't behave as
        #   expected.
        if not hasattr(guid_object.referent, 'deep_url'):
            sentry.log_message(
                'Guid `{}` resolved to an object with no deep_url'.format(
                    guid))
            raise HTTPError(http.NOT_FOUND)
        referent = guid_object.referent
        if referent is None:
            logger.error('Referent of GUID {0} not found'.format(guid))
            raise HTTPError(http.NOT_FOUND)
        if not referent.deep_url:
            raise HTTPError(http.NOT_FOUND)

        # Handle file `/download` shortcut with supported types.
        if suffix and suffix.rstrip('/').lower() == 'download':
            file_referent = None
            if isinstance(referent, PreprintService) and referent.primary_file:
                if not referent.is_published:
                    # TODO: Ideally, permissions wouldn't be checked here.
                    # This is necessary to prevent a logical inconsistency with
                    # the routing scheme - if a preprint is not published, only
                    # admins should be able to know it exists.
                    auth = Auth.from_kwargs(request.args.to_dict(), {})
                    if not referent.node.has_permission(
                            auth.user, permissions.ADMIN):
                        raise HTTPError(http.NOT_FOUND)
                file_referent = referent.primary_file
            elif isinstance(referent, BaseFileNode) and referent.is_file:
                file_referent = referent

            if file_referent:
                # Extend `request.args` adding `action=download`.
                request.args = request.args.copy()
                request.args.update({'action': 'download'})
                # Do not include the `download` suffix in the url rebuild.
                url = _build_guid_url(urllib.unquote(file_referent.deep_url))
                return proxy_url(url)

        # Handle Ember Applications
        if isinstance(referent, PreprintService):
            if referent.provider.domain_redirect_enabled:
                # This route should always be intercepted by nginx for the branded domain,
                # w/ the exception of `<guid>/download` handled above.
                return redirect(referent.absolute_url, http.MOVED_PERMANENTLY)

            return send_from_directory(preprints_dir, 'index.html')
        url = _build_guid_url(urllib.unquote(referent.deep_url), suffix)
        return proxy_url(url)

    # GUID not found; try lower-cased and redirect if exists
    guid_object_lower = Guid.load(guid.lower())
    if guid_object_lower:
        return redirect(_build_guid_url(guid.lower(), suffix))

    # GUID not found
    raise HTTPError(http.NOT_FOUND)