<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
from nose.tools import *  # PEP8 asserts
from webtest_plus import TestApp
import mock
import datetime
import httplib as http

from flask import Flask
from werkzeug.wrappers import BaseResponse
from modularodm import Q

from framework import auth
from framework.exceptions import HTTPError
from tests.base import OsfTestCase, assert_is_redirect
from tests.factories import (
    UserFactory, UnregUserFactory, AuthFactory,
    ProjectFactory, AuthUserFactory, PrivateLinkFactory
)

from framework.auth import User, Auth, utils
from framework.auth.decorators import must_be_logged_in

from website.util import web_url_for
from website.project.decorators import (
    must_have_permission, must_be_contributor,
    must_have_addon, must_be_addon_authorizer,
)


class TestAuthUtils(OsfTestCase):

    def test_register(self):
        super(TestAuthUtils, self).setUp()
        auth.register('<EMAIL>', 'gattaca', fullname="<NAME>")
        user = User.find_one(Q('username', 'eq', '<EMAIL>'))
        # The password should be set
        assert_true(user.check_password('<PASSWORD>'))
        assert_equal(user.fullname, "<NAME>")
        assert_equal(user.username, '<EMAIL>')
        assert_in("<EMAIL>", user.emails)

    def test_unreg_user_can_register(self):
        user = UnregUserFactory()

        auth.register_unconfirmed(
            username=user.username,
            password='<PASSWORD>',
            fullname='Rosie',
        )

        assert_true(user.get_confirmation_token(user.username))

    def test_get_user_by_id(self):
        user = UserFactory()
        assert_equal(User.load(user._id), user)

    def test_get_user_by_username(self):
        user = UserFactory()
        assert_equal(auth.get_user(username=user.username), user)

    def test_get_user_with_wrong_password_returns_false(self):
        user = UserFactory.build()
        user.set_password('<PASSWORD>')
        assert_false(
            auth.get_user(
                username=user.username,
                password='<PASSWORD>'
            )
        )

    def test_login_success_authenticates_user(self):
        user = UserFactory.build(date_last_login=datetime.datetime.utcnow())
        user.set_password('<PASSWORD>')
        user.save()
        # need request context because login returns a rsponse
        res = auth.login(user.username, 'killerqueen')
        assert_true(isinstance(res, BaseResponse))
        assert_equal(res.status_code, 302)

    def test_login_unregistered_user(self):
        user = UnregUserFactory()
        user.set_password('<PASSWORD>')
        user.save()
        with assert_raises(auth.LoginNotAllowedError):
            # password is correct, but user is unregistered
            auth.login(user.username, 'killerqueen')

    def test_login_with_incorrect_password_returns_false(self):
        user = UserFactory.build()
        user.set_password('<PASSWORD>')
        user.save()
        with assert_raises(auth.PasswordIncorrectError):
            auth.login(user.username, '<PASSWORD>')

    @mock.patch('framework.auth.utils.mailchimp.Lists.list')
    def test_get_list_id_from_name(self, mock_list):
        list_name = 'foo'
        mock_list.return_value = {'data': [{'id': 1, 'list_name': list_name}]}
        list_id = auth.utils.get_list_id_from_name(list_name)
        mock_list.assert_called_with(filters={'list_name': list_name})
        assert_equal(list_id, 1)

    @mock.patch('framework.auth.utils.mailchimp.Lists.list')
    @mock.patch('framework.auth.utils.mailchimp.Lists.subscribe')
    def test_subscribe_called_with_correct_arguments(self, mock_subscribe, mock_list):
        list_name = 'foo'
        username = '<EMAIL>'
        mock_list.return_value = {'data': [{'id': 1, 'list_name': list_name}]}
        list_id = auth.utils.get_list_id_from_name(list_name)
        auth.utils.subscribe(list_id, username)
        mock_subscribe.assert_called_with(id=list_id, email={'email': username}, double_optin=False)


class TestAuthObject(OsfTestCase):

    def test_repr(self):
        auth = AuthFactory()
        rep = repr(auth)
        assert_in(str(auth.user), rep)

    def test_factory(self):
        super(TestAuthObject, self).setUp()
        auth_obj = AuthFactory()
        assert_true(isinstance(auth_obj.user, auth.User))
        assert_true(auth_obj.api_key)

    def test_from_kwargs(self):
        user = UserFactory()
        request_args = {'view_only': 'mykey'}
        kwargs = {'user': user, 'api_key': 'myapikey', 'api_node': '123v'}
        auth_obj = Auth.from_kwargs(request_args, kwargs)
        assert_equal(auth_obj.user, user)
        assert_equal(auth_obj.api_key, kwargs['api_key'])
        assert_equal(auth_obj.private_key, request_args['view_only'])

    def test_logged_in(self):
        user = UserFactory()
        auth_obj = Auth(user=user)
        assert_true(auth_obj.logged_in)
        auth2 = Auth(user=None)
        assert_false(auth2.logged_in)


class TestPrivateLink(OsfTestCase):

    def setUp(self):
        super(TestPrivateLink, self).setUp()
        self.flaskapp = Flask('testing_private_links')

        @self.flaskapp.route('/project/<pid>/')
        @must_be_contributor
        def project_get(**kwargs):
            return 'success', 200

        self.app = TestApp(self.flaskapp)

        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False)
        self.link = PrivateLinkFactory()
        self.link.nodes.append(self.project)
        self.link.save()

    @mock.patch('website.project.decorators.get_api_key')
    @mock.patch('website.project.decorators.Auth.from_kwargs')
    def test_has_private_link_key(self, mock_from_kwargs, mock_get_api_key):
        mock_get_api_key.return_value = 'foobar123'
        mock_from_kwargs.return_value = Auth(user=None)
        res = self.app.get('/project/{0}'.format(self.project._primary_key),
            {'view_only': self.link.key})
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_equal(res.body, 'success')

    @mock.patch('website.project.decorators.get_api_key')
    @mock.patch('website.project.decorators.Auth.from_kwargs')
    def test_does_not_have_key(self, mock_from_kwargs, mock_get_api_key):
        mock_get_api_key.return_value = 'foobar123'
        mock_from_kwargs.return_value = Auth(user=None)
        res = self.app.get('/project/{0}'.format(self.project._primary_key),
            {'key': None})
        assert_is_redirect(res)


# Flask app for testing view decorators
decoratorapp = Flask('decorators')


@must_be_contributor
def view_that_needs_contributor(**kwargs):
    return kwargs['project'] or kwargs['node']


class AuthAppTestCase(OsfTestCase):

    def setUp(self):
        self.ctx = decoratorapp.test_request_context()
        self.ctx.push()

    def tearDown(self):
        self.ctx.pop()


class TestMustBeContributorDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustBeContributorDecorator, self).setUp()
        self.contrib = AuthUserFactory()
        self.project = ProjectFactory()
        self.project.add_contributor(self.contrib, auth=Auth(self.project.creator))
        self.project.save()

    def test_must_be_contributor_when_user_is_contributor(self):
        result = view_that_needs_contributor(
            pid=self.project._primary_key,
            api_key=self.contrib.auth[1],
            api_node=self.project,
            user=self.contrib)
        assert_equal(result, self.project)

    def test_must_be_contributor_when_user_is_not_contributor_raises_error(self):
        non_contributor = AuthUserFactory()
        with assert_raises(HTTPError):
            view_that_needs_contributor(
                pid=self.project._primary_key,
                api_key=non_contributor.auth[1],
                api_node=non_contributor.auth[1],
                user=non_contributor
            )

    def test_must_be_contributor_no_user(self):
        res = view_that_needs_contributor(
            pid=self.project._primary_key,
            user=None,
            api_key='123',
            api_node='abc',
        )
        assert_is_redirect(res)
        redirect_url = res.headers['Location']
        assert_equal(redirect_url, '/login/?next=/')


@must_be_logged_in
def protected(**kwargs):
    return 'open sesame'


@must_have_permission('dance')
def thriller(**kwargs):
    return 'chiller'


class TestPermissionDecorators(AuthAppTestCase):

    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_be_logged_in_decorator_with_user(self, mock_from_kwargs):
        user = UserFactory()
        mock_from_kwargs.return_value = Auth(user=user)
        protected()

    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_be_logged_in_decorator_with_no_user(self, mock_from_kwargs):
        mock_from_kwargs.return_value = Auth()
        resp = protected()
        assert_true(isinstance(resp, BaseResponse))
        assert_in('/login/', resp.headers.get('location'))

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_true(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        project.add_permission(project.creator, 'dance')
        mock_from_kwargs.return_value = Auth(user=project.creator)
        mock_to_nodes.return_value = (project, None)
        thriller(node=project)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_false(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        mock_from_kwargs.return_value = Auth(user=project.creator)
        mock_to_nodes.return_value = (project, None)
        with assert_raises(HTTPError) as ctx:
            thriller(node=project)
        assert_equal(ctx.exception.code, http.FORBIDDEN)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_not_logged_in(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        mock_from_kwargs.return_value = Auth()
        mock_to_nodes.return_value = (project, None)
        with assert_raises(HTTPError) as ctx:
            thriller(node=project)
        assert_equal(ctx.exception.code, http.UNAUTHORIZED)


def needs_addon_view(**kwargs):
    return 'openaddon'


class TestMustHaveAddonDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustHaveAddonDecorator, self).setUp()
        self.project = ProjectFactory()

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    def test_must_have_addon_node_true(self, mock_kwargs_to_nodes):
        mock_kwargs_to_nodes.return_value = (self.project, None)
        self.project.add_addon('github', auth=None)
        decorated = must_have_addon('github', 'node')(needs_addon_view)
        res = decorated()
        assert_equal(res, 'openaddon')

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    def test_must_have_addon_node_false(self, mock_kwargs_to_nodes):
        mock_kwargs_to_nodes.return_value = (self.project, None)
        decorated = must_have_addon('github', 'node')(needs_addon_view)
        with assert_raises(HTTPError):
            decorated()

    @mock.patch('website.project.decorators.get_current_user')
    def test_must_have_addon_user_true(self, mock_current_user):
        mock_current_user.return_value = self.project.creator
        self.project.creator.add_addon('github')
        decorated = must_have_addon('github', 'user')(needs_addon_view)
        res = decorated()
        assert_equal(res, 'openaddon')

    @mock.patch('website.project.decorators.get_current_user')
    def test_must_have_addon_user_false(self, mock_current_user):
        mock_current_user.return_value = self.project.creator
        decorated = must_have_addon('github', 'user')(needs_addon_view)
        with assert_raises(HTTPError):
            decorated()


class TestMustBeAddonAuthorizerDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustBeAddonAuthorizerDecorator, self).setUp()
        self.project = ProjectFactory()
        self.decorated = must_be_addon_authorizer('github')(needs_addon_view)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('website.project.decorators.get_current_user')
    def test_must_be_authorizer_true(self, mock_get_current_user, mock_kwargs_to_nodes):

        # Mock
        mock_get_current_user.return_value = self.project.creator
        mock_kwargs_to_nodes.return_value = (self.project, None)

        # Setup
        self.project.add_addon('github', auth=None)
        node_settings = self.project.get_addon('github')
        self.project.creator.add_addon('github')
        user_settings = self.project.creator.get_addon('github')
        node_settings.user_settings = user_settings

        # Test
        res = self.decorated()
        assert_equal(res, 'openaddon')

    def test_must_be_authorizer_false(self):

        # Setup
        self.project.add_addon('github', auth=None)
        node_settings = self.project.get_addon('github')
        user2 = UserFactory()
        user2.add_addon('github')
        user_settings = user2.get_addon('github')
        node_settings.user_settings = user_settings

        # Test
        with assert_raises(HTTPError):
            self.decorated()

    def test_must_be_authorizer_no_user_settings(self):
        self.project.add_addon('github', auth=None)
        with assert_raises(HTTPError):
            self.decorated()

    def test_must_be_authorizer_no_node_settings(self):
        with assert_raises(HTTPError):
            self.decorated()

class TestBasicAuth(OsfTestCase):

    def test_basic_auth_returns_403(self):
        url = web_url_for('dashboard')
        ret = self.app.get(url, auth=('test', 'test'), expect_errors=True)
        assert_equal(ret.status_code, 403)


if __name__ == '__main__':
    unittest.main()
<commit_msg>Fix failing tests<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
from nose.tools import *  # PEP8 asserts
from webtest_plus import TestApp
import mock
import datetime
import httplib as http

from flask import Flask
from werkzeug.wrappers import BaseResponse
from modularodm import Q

from framework import auth
from framework.exceptions import HTTPError
from tests.base import OsfTestCase, assert_is_redirect
from tests.factories import (
    UserFactory, UnregUserFactory, AuthFactory,
    ProjectFactory, AuthUserFactory, PrivateLinkFactory
)

from framework.auth import User, Auth, utils
from framework.auth.decorators import must_be_logged_in

from website.util import web_url_for
from website.project.decorators import (
    must_have_permission, must_be_contributor,
    must_have_addon, must_be_addon_authorizer,
)


class TestAuthUtils(OsfTestCase):

    def test_register(self):
        super(TestAuthUtils, self).setUp()
        auth.register('<EMAIL>', 'gattaca', fullname="<NAME>")
        user = User.find_one(Q('username', 'eq', '<EMAIL>'))
        # The password should be set
        assert_true(user.check_password('<PASSWORD>'))
        assert_equal(user.fullname, "<NAME>")
        assert_equal(user.username, '<EMAIL>')
        assert_in("<EMAIL>", user.emails)

    def test_unreg_user_can_register(self):
        user = UnregUserFactory()

        auth.register_unconfirmed(
            username=user.username,
            password='<PASSWORD>',
            fullname='Rosie',
        )

        assert_true(user.get_confirmation_token(user.username))

    def test_get_user_by_id(self):
        user = UserFactory()
        assert_equal(User.load(user._id), user)

    def test_get_user_by_username(self):
        user = UserFactory()
        assert_equal(auth.get_user(username=user.username), user)

    def test_get_user_with_wrong_password_returns_false(self):
        user = UserFactory.build()
        user.set_password('<PASSWORD>')
        assert_false(
            auth.get_user(
                username=user.username,
                password='<PASSWORD>'
            )
        )

    def test_login_success_authenticates_user(self):
        user = UserFactory.build(date_last_login=datetime.datetime.utcnow())
        user.set_password('<PASSWORD>')
        user.save()
        # need request context because login returns a rsponse
        res = auth.login(user.username, 'killerqueen')
        assert_true(isinstance(res, BaseResponse))
        assert_equal(res.status_code, 302)

    def test_login_unregistered_user(self):
        user = UnregUserFactory()
        user.set_password('<PASSWORD>')
        user.save()
        with assert_raises(auth.LoginNotAllowedError):
            # password is correct, but user is unregistered
            auth.login(user.username, 'killerqueen')

    def test_login_with_incorrect_password_returns_false(self):
        user = UserFactory.build()
        user.set_password('<PASSWORD>')
        user.save()
        with assert_raises(auth.PasswordIncorrectError):
            auth.login(user.username, '<PASSWORD>')

    @mock.patch('framework.auth.utils.get_mailchimp_api')
    def test_get_list_id_from_name(self, mock_get_mailchimp_api):
        list_name = 'foo'
        mock_client = mock.MagicMock()
        mock_get_mailchimp_api.return_value = mock_client
        mock_client.lists.list.return_value = {'data': [{'id': 1, 'list_name': list_name}]}
        list_id = auth.utils.get_list_id_from_name(list_name)
        mock_client.lists.list.assert_called_with(filters={'list_name': list_name})
        assert_equal(list_id, 1)

    @mock.patch('framework.auth.utils.get_mailchimp_api')
    def test_subscribe_called_with_correct_arguments(self, mock_get_mailchimp_api):
        list_name = 'foo'
        username = '<EMAIL>'
        mock_client = mock.MagicMock()
        mock_get_mailchimp_api.return_value = mock_client
        mock_client.lists.list.return_value = {'data': [{'id': 1, 'list_name': list_name}]}
        list_id = auth.utils.get_list_id_from_name(list_name)
        auth.utils.subscribe(list_id, username)
        mock_client.lists.subscribe.assert_called_with(id=list_id, email={'email': username}, double_optin=False)


class TestAuthObject(OsfTestCase):

    def test_repr(self):
        auth = AuthFactory()
        rep = repr(auth)
        assert_in(str(auth.user), rep)

    def test_factory(self):
        super(TestAuthObject, self).setUp()
        auth_obj = AuthFactory()
        assert_true(isinstance(auth_obj.user, auth.User))
        assert_true(auth_obj.api_key)

    def test_from_kwargs(self):
        user = UserFactory()
        request_args = {'view_only': 'mykey'}
        kwargs = {'user': user, 'api_key': 'myapikey', 'api_node': '123v'}
        auth_obj = Auth.from_kwargs(request_args, kwargs)
        assert_equal(auth_obj.user, user)
        assert_equal(auth_obj.api_key, kwargs['api_key'])
        assert_equal(auth_obj.private_key, request_args['view_only'])

    def test_logged_in(self):
        user = UserFactory()
        auth_obj = Auth(user=user)
        assert_true(auth_obj.logged_in)
        auth2 = Auth(user=None)
        assert_false(auth2.logged_in)


class TestPrivateLink(OsfTestCase):

    def setUp(self):
        super(TestPrivateLink, self).setUp()
        self.flaskapp = Flask('testing_private_links')

        @self.flaskapp.route('/project/<pid>/')
        @must_be_contributor
        def project_get(**kwargs):
            return 'success', 200

        self.app = TestApp(self.flaskapp)

        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False)
        self.link = PrivateLinkFactory()
        self.link.nodes.append(self.project)
        self.link.save()

    @mock.patch('website.project.decorators.get_api_key')
    @mock.patch('website.project.decorators.Auth.from_kwargs')
    def test_has_private_link_key(self, mock_from_kwargs, mock_get_api_key):
        mock_get_api_key.return_value = 'foobar123'
        mock_from_kwargs.return_value = Auth(user=None)
        res = self.app.get('/project/{0}'.format(self.project._primary_key),
            {'view_only': self.link.key})
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_equal(res.body, 'success')

    @mock.patch('website.project.decorators.get_api_key')
    @mock.patch('website.project.decorators.Auth.from_kwargs')
    def test_does_not_have_key(self, mock_from_kwargs, mock_get_api_key):
        mock_get_api_key.return_value = 'foobar123'
        mock_from_kwargs.return_value = Auth(user=None)
        res = self.app.get('/project/{0}'.format(self.project._primary_key),
            {'key': None})
        assert_is_redirect(res)


# Flask app for testing view decorators
decoratorapp = Flask('decorators')


@must_be_contributor
def view_that_needs_contributor(**kwargs):
    return kwargs['project'] or kwargs['node']


class AuthAppTestCase(OsfTestCase):

    def setUp(self):
        self.ctx = decoratorapp.test_request_context()
        self.ctx.push()

    def tearDown(self):
        self.ctx.pop()


class TestMustBeContributorDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustBeContributorDecorator, self).setUp()
        self.contrib = AuthUserFactory()
        self.project = ProjectFactory()
        self.project.add_contributor(self.contrib, auth=Auth(self.project.creator))
        self.project.save()

    def test_must_be_contributor_when_user_is_contributor(self):
        result = view_that_needs_contributor(
            pid=self.project._primary_key,
            api_key=self.contrib.auth[1],
            api_node=self.project,
            user=self.contrib)
        assert_equal(result, self.project)

    def test_must_be_contributor_when_user_is_not_contributor_raises_error(self):
        non_contributor = AuthUserFactory()
        with assert_raises(HTTPError):
            view_that_needs_contributor(
                pid=self.project._primary_key,
                api_key=non_contributor.auth[1],
                api_node=non_contributor.auth[1],
                user=non_contributor
            )

    def test_must_be_contributor_no_user(self):
        res = view_that_needs_contributor(
            pid=self.project._primary_key,
            user=None,
            api_key='123',
            api_node='abc',
        )
        assert_is_redirect(res)
        redirect_url = res.headers['Location']
        assert_equal(redirect_url, '/login/?next=/')


@must_be_logged_in
def protected(**kwargs):
    return 'open sesame'


@must_have_permission('dance')
def thriller(**kwargs):
    return 'chiller'


class TestPermissionDecorators(AuthAppTestCase):

    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_be_logged_in_decorator_with_user(self, mock_from_kwargs):
        user = UserFactory()
        mock_from_kwargs.return_value = Auth(user=user)
        protected()

    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_be_logged_in_decorator_with_no_user(self, mock_from_kwargs):
        mock_from_kwargs.return_value = Auth()
        resp = protected()
        assert_true(isinstance(resp, BaseResponse))
        assert_in('/login/', resp.headers.get('location'))

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_true(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        project.add_permission(project.creator, 'dance')
        mock_from_kwargs.return_value = Auth(user=project.creator)
        mock_to_nodes.return_value = (project, None)
        thriller(node=project)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_false(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        mock_from_kwargs.return_value = Auth(user=project.creator)
        mock_to_nodes.return_value = (project, None)
        with assert_raises(HTTPError) as ctx:
            thriller(node=project)
        assert_equal(ctx.exception.code, http.FORBIDDEN)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('framework.auth.decorators.Auth.from_kwargs')
    def test_must_have_permission_not_logged_in(self, mock_from_kwargs, mock_to_nodes):
        project = ProjectFactory()
        mock_from_kwargs.return_value = Auth()
        mock_to_nodes.return_value = (project, None)
        with assert_raises(HTTPError) as ctx:
            thriller(node=project)
        assert_equal(ctx.exception.code, http.UNAUTHORIZED)


def needs_addon_view(**kwargs):
    return 'openaddon'


class TestMustHaveAddonDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustHaveAddonDecorator, self).setUp()
        self.project = ProjectFactory()

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    def test_must_have_addon_node_true(self, mock_kwargs_to_nodes):
        mock_kwargs_to_nodes.return_value = (self.project, None)
        self.project.add_addon('github', auth=None)
        decorated = must_have_addon('github', 'node')(needs_addon_view)
        res = decorated()
        assert_equal(res, 'openaddon')

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    def test_must_have_addon_node_false(self, mock_kwargs_to_nodes):
        mock_kwargs_to_nodes.return_value = (self.project, None)
        decorated = must_have_addon('github', 'node')(needs_addon_view)
        with assert_raises(HTTPError):
            decorated()

    @mock.patch('website.project.decorators.get_current_user')
    def test_must_have_addon_user_true(self, mock_current_user):
        mock_current_user.return_value = self.project.creator
        self.project.creator.add_addon('github')
        decorated = must_have_addon('github', 'user')(needs_addon_view)
        res = decorated()
        assert_equal(res, 'openaddon')

    @mock.patch('website.project.decorators.get_current_user')
    def test_must_have_addon_user_false(self, mock_current_user):
        mock_current_user.return_value = self.project.creator
        decorated = must_have_addon('github', 'user')(needs_addon_view)
        with assert_raises(HTTPError):
            decorated()


class TestMustBeAddonAuthorizerDecorator(AuthAppTestCase):

    def setUp(self):
        super(TestMustBeAddonAuthorizerDecorator, self).setUp()
        self.project = ProjectFactory()
        self.decorated = must_be_addon_authorizer('github')(needs_addon_view)

    @mock.patch('website.project.decorators._kwargs_to_nodes')
    @mock.patch('website.project.decorators.get_current_user')
    def test_must_be_authorizer_true(self, mock_get_current_user, mock_kwargs_to_nodes):

        # Mock
        mock_get_current_user.return_value = self.project.creator
        mock_kwargs_to_nodes.return_value = (self.project, None)

        # Setup
        self.project.add_addon('github', auth=None)
        node_settings = self.project.get_addon('github')
        self.project.creator.add_addon('github')
        user_settings = self.project.creator.get_addon('github')
        node_settings.user_settings = user_settings

        # Test
        res = self.decorated()
        assert_equal(res, 'openaddon')

    def test_must_be_authorizer_false(self):

        # Setup
        self.project.add_addon('github', auth=None)
        node_settings = self.project.get_addon('github')
        user2 = UserFactory()
        user2.add_addon('github')
        user_settings = user2.get_addon('github')
        node_settings.user_settings = user_settings

        # Test
        with assert_raises(HTTPError):
            self.decorated()

    def test_must_be_authorizer_no_user_settings(self):
        self.project.add_addon('github', auth=None)
        with assert_raises(HTTPError):
            self.decorated()

    def test_must_be_authorizer_no_node_settings(self):
        with assert_raises(HTTPError):
            self.decorated()

class TestBasicAuth(OsfTestCase):

    def test_basic_auth_returns_403(self):
        url = web_url_for('dashboard')
        ret = self.app.get(url, auth=('test', 'test'), expect_errors=True)
        assert_equal(ret.status_code, 403)


if __name__ == '__main__':
    unittest.main()

{'fraction_non_alphanumeric': 0.10691076794074487, 'fraction_numerical': 0.00293480539445182, 'mean_word_length': 3.3679230886616818, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1311999', 'n_tokens_mistral': 9171, 'n_tokens_neox': 8941, 'n_words': 1304}