Beispiel #1
0
class ConfigTest(base.RestTestCase):

    PATH = '/api/config'

    def testGetConfig(self):
        with self.queryLimit(0):
            resp = self.client.get(self.PATH)
        self.assert200(resp)
        expected_keys = set((
            'teams',
            'sbname',
            'news_mechanism',
            'news_poll_interval',
            'csrf_token',
            'rules',
            'game_start',
            'game_end',
            'login_url',
            'register_url',
            'login_method',
            'scoring',
            'validators',
        ))
        self.assertEqual(expected_keys, set(resp.json.keys()))

    testGetConfigAuthenticated = base.authenticated_test(testGetConfig)
    testGetConfigAdmin = base.authenticated_test(testGetConfig)
Beispiel #2
0
class ConfigzTest(base.RestTestCase):

    PATH = '/api/configz'

    def testGetFails(self):
        with self.queryLimit(0):
            response = self.client.get(self.PATH)
        self.assert403(response)

    testGetFailsNonAdmin = base.authenticated_test(testGetFails)

    @base.admin_test
    def testAdmin(self):
        with self.queryLimit(0):
            response = self.client.get(self.PATH)
        self.assert200(response)
Beispiel #3
0
class ConfigTest(base.RestTestCase):

    PATH = '/api/config'

    def makeTestGetConfig(extra_keys=None):
        extra_keys = set(extra_keys or [])

        def testGetConfig(self):
            with self.queryLimit(0):
                resp = self.client.get(self.PATH)
            self.assert200(resp)
            expected_keys = set((
                    'teams',
                    'sbname',
                    'news_mechanism',
                    'news_poll_interval',
                    'csrf_token',
                    'rules',
                    'game_start',
                    'game_end',
                    'login_url',
                    'register_url',
                    'login_method',
                    'scoring',
                    'validators',
                    'proof_of_work_bits',
                    'invite_only',
                    'tags_only',
            ))
            expected_keys |= extra_keys
            self.assertEqual(expected_keys, set(resp.json.keys()))
            self.assertIsInstance(resp.json['invite_only'], bool)
        return testGetConfig

    testGetConfig = makeTestGetConfig()
    testGetConfigAuthenticated = base.authenticated_test(
            makeTestGetConfig())
    testGetConfigAdmin = base.admin_test(
            makeTestGetConfig())
Beispiel #4
0
class ChallengeTest(base.RestTestCase):

    PATH_LIST = '/api/challenges'
    PATH_SINGLE = '/api/challenges/%d'

    def setUp(self):
        super(ChallengeTest, self).setUp()
        self.challs = makeTestChallenges()
        self.chall = self.challs[0]
        self.PATH_SINGLE %= self.chall.cid

    def testGetListAnonymous(self):
        with self.queryLimit(0):
            self.assert403(self.client.get(self.PATH_LIST))

    @base.authenticated_test
    def testGetListAuthenticated(self):
        # TODO: fix to not be O(n)
        with self.queryLimit(3):
            resp = self.client.get(self.PATH_LIST)
        self.assert200(resp)
        self.assertEqual(len(self.challs), len(resp.json['challenges']))

    @base.admin_test
    def testGetListAdmin(self):
        # TODO: fix to not be O(n)
        with self.queryLimit(3):
            resp = self.client.get(self.PATH_LIST)
        self.assert200(resp)
        self.assertEqual(len(self.challs), len(resp.json['challenges']))

    def newChallengeData(self):
        return {
            'name': 'Chall 1',
            'description': 'Challenge 1',
            'points': 200,
            'answer': 'abc',
            'unlocked': True,
            'validator': 'static_pbkdf2',
        }

    def testCreateChallengeAnonymous(self):
        data = self.newChallengeData()
        with self.queryLimit(0):
            self.assert403(self.postJSON(self.PATH_LIST, data))

    testCreateChallengeAuthenticated = base.authenticated_test(
        testCreateChallengeAnonymous)

    @base.admin_test
    def testCreateChallenge(self):
        # TODO: variants
        data = self.newChallengeData()
        # TODO: optimize count
        with self.queryLimit(8):
            resp = self.postJSON(self.PATH_LIST, data)
        self.assert200(resp)
        for field in ('name', 'description', 'points', 'unlocked'):
            self.assertEqual(data[field], resp.json[field])

    def getUpdateData(self):
        return {
            'name': 'Renamed',
            'points': 1,
            'weight': 12,
            'unlocked': False
        }

    @base.admin_test
    def testUpdateChallenge(self):
        data = self.getUpdateData()
        with self.queryLimit(6):
            resp = self.putJSON(self.PATH_SINGLE, data)
        self.assert200(resp)
        for k in data.keys():
            self.assertEqual(data[k], resp.json[k])

    def testUpdateChallengeAnonymous(self):
        data = self.getUpdateData()
        with self.queryLimit(0):
            self.assert403(self.putJSON(self.PATH_SINGLE, data))

    testUpdateChallengeAuthenticated = base.authenticated_test(
        testUpdateChallengeAnonymous)

    @base.admin_test
    def testGetSingleton(self):
        with self.queryLimit(6):
            resp = self.client.get(self.PATH_SINGLE)
        self.assert200(resp)
        for field in ('name', 'points', 'description', 'unlocked'):
            self.assertEqual(getattr(self.chall, field), resp.json[field])

    def testGetSingletonAnonymous(self):
        with self.queryLimit(0):
            self.assert403(self.client.get(self.PATH_SINGLE))

    testGetSingletonAuthenticated = base.authenticated_test(
        testGetSingletonAnonymous)

    @base.admin_test
    def testDeleteChallenge(self):
        with self.queryLimit(5):
            self.assert200(self.client.delete(self.PATH_SINGLE))

    def testDeleteChallengeAnonymous(self):
        with self.queryLimit(0):
            self.assert403(self.client.delete(self.PATH_SINGLE))

    testDeleteChallengeAuthenticated = base.authenticated_test(
        testDeleteChallengeAnonymous)
Beispiel #5
0
class UserTest(base.RestTestCase):

    PATH = '/api/users/%d'
    USER_FIELDS = ('admin', 'nick', 'email', 'team_tid', 'uid')

    def testGetAnonymous(self):
        path = self.PATH % makeTestUser().uid
        with self.queryLimit(0):
            self.assert403(self.client.get(path))

    def testGetNonExistent(self):
        path = self.PATH % 999
        with self.queryLimit(0):
            resp = self.client.get(path)
        self.assert403(resp)

    testGetNonExistentAuth = base.authenticated_test(testGetNonExistent)

    @base.admin_test
    def testGetNonExistentAdmin(self):
        path = self.PATH % 999
        with self.queryLimit(1):
            resp = self.client.get(path)
        self.assert404(resp)

    @base.authenticated_test
    def testGetSelf(self):
        user = self.authenticated_client.user
        with self.queryLimit(1):
            resp = self.client.get(self.PATH % user.uid)
        self.assert200(resp)
        self.assertEqual(user.email, resp.json['email'])
        self.assertEqual(user.nick, resp.json['nick'])
        self.assertEqual(user.admin, resp.json['admin'])

    @base.authenticated_test
    def testUpdateUser(self):
        user = self.authenticated_client.user
        data = {'password': '******'}  # for security
        with self.queryLimit(2):
            self.assert200(self.putJSON(self.PATH % user.uid, data))

    @base.authenticated_test
    def testUpdateUserNoAccess(self):
        uid = self.admin_client.user.uid
        data = {'password': '******'}
        with self.queryLimit(0):
            resp = self.putJSON(self.PATH % uid, data)
            self.assert403(resp)

    @base.admin_test
    def testUpdateUserAdmin(self):
        uid = self.authenticated_client.user.uid
        data = {'nick': 'Lame'}
        with self.queryLimit(2):
            resp = self.putJSON(self.PATH % uid, data)
        self.assert200(resp)
        self.assertEqual('Lame', resp.json['nick'])
        self.assertNotEqual('Lame', self.authenticated_client.user.team.name)

    @base.admin_test
    def testUpdateUsersNoTeams(self):
        uid = self.authenticated_client.user.uid
        self.app.config['TEAMS'] = False
        data = {'nick': 'Lame'}
        with self.queryLimit(3):
            resp = self.putJSON(self.PATH % uid, data)
        self.assert200(resp)
        self.assertEqual('Lame', resp.json['nick'])
        self.assertEqual('Lame', self.authenticated_client.user.team.name)

    @base.admin_test
    def testUpdateUserPromote(self):
        user = self.authenticated_client.user
        data = {'nick': user.nick, 'admin': True}
        # yes, this is a lot, but promoting is infrequent
        with self.queryLimit(7):
            resp = self.putJSON(self.PATH % user.uid, data)
        self.assert200(resp)
        self.assertTrue(resp.json['admin'])

    @base.admin_test
    def testUpdateUserDemote(self):
        user = self.admin_client.user
        data = {'nick': user.nick, 'admin': False}
        with self.queryLimit(3):
            resp = self.putJSON(self.PATH % user.uid, data)
        self.assert200(resp)
        self.assertFalse(resp.json['admin'])

    @base.authenticated_test
    def testUpdateUserNoSelfPromotion(self):
        uid = self.authenticated_client.user.uid
        data = {'admin': True}
        with self.queryLimit(1):
            resp = self.putJSON(self.PATH % uid, data)
        self.assert200(resp)
        self.assertFalse(resp.json['admin'])

    @base.admin_test
    def testUpdateUserNoAnswers(self):
        user = self.authenticated_client.user
        team = self.authenticated_client.user.team
        chall = models.Challenge.create('Foo', 'Foo', 1, 'Foo')
        models.Answer.create(chall, team, 'Foo')
        models.db.session.commit()
        data = {'nick': user.nick, 'admin': True}
        with self.queryLimit(3):
            resp = self.putJSON(self.PATH % user.uid, data)
        self.assert400(resp)
        user = models.User.query.get(user.uid)
        self.assertFalse(user.admin)

    @base.authenticated_test
    def testGetUsersNoAccess(self):
        with self.queryLimit(0):
            resp = self.client.get('/api/users')
        self.assert403(resp)

    @base.admin_test
    def testGetUsers(self):
        self.admin_client.user
        with self.queryLimit(1):
            resp = self.client.get('/api/users')
        self.assert200(resp)
        self.assertIsInstance(resp.json, dict)
        self.assertIn('users', resp.json)
        self.assertIsInstance(resp.json['users'], list)
        users = resp.json['users']
        self.assertEqual(2, len(users))
        for u in users:
            self.assertItemsEqual(self.USER_FIELDS, u.keys())

    @staticmethod
    def default_data():
        return {
            'email': '*****@*****.**',
            'nick': 'test3',
            'password': '******',
            'team_id': 'new',
            'team_name': 'New Team',
            'team_code': None,
        }

    def testRegisterUserNewTeam(self):
        data = self.default_data()
        # TODO: maybe optimize?
        with self.client:
            with self.queryLimit(9):
                resp = self.postJSON('/api/users', data)
            self.assert200(resp)
            self.assertItemsEqual(self.USER_FIELDS, resp.json.keys())
            self.assertEqual(resp.json['uid'], flask.session['user'])
            self.assertEqual(resp.json['admin'], flask.session['admin'])
            self.assertEqual(resp.json['team_tid'], flask.session['team'])

    def testRegisterUserExistingTeam(self):
        team = self.authenticated_client.team
        data = self.default_data()
        data.update({
            'team_id': team.tid,
            'team_name': None,
            'team_code': team.code,
        })
        with self.client:
            with self.queryLimit(8):
                resp = self.postJSON('/api/users', data)
            self.assert200(resp)
            self.assertItemsEqual(self.USER_FIELDS, resp.json.keys())
            self.assertEqual(resp.json['uid'], flask.session['user'])
            self.assertEqual(resp.json['admin'], flask.session['admin'])
            self.assertEqual(resp.json['team_tid'], flask.session['team'])
            self.assertEqual(team.tid, resp.json['team_tid'])

    def testRegisterUserTeamWrongCode(self):
        team = self.authenticated_client.team
        data = self.default_data()
        data.update({
            'team_id': team.tid,
            'team_name': None,
            'team_code': 'xxx',
        })
        with self.client:
            with self.queryLimit(1):
                resp = self.postJSON('/api/users', data)
            self.assert400(resp)

    @base.authenticated_test
    def testRegisterUserLoggedInFails(self):
        data = self.default_data()
        with self.queryLimit(0):
            resp = self.postJSON('/api/users', data)
        self.assert400(resp)

    def testRegisterUserNoNick(self):
        data = self.default_data()
        del data['nick']
        with self.queryLimit(0):
            self.assert400(self.postJSON('/api/users', data))

    def testRegisterUserNoTeam(self):
        data = self.default_data()
        del data['team_name']
        del data['team_id']
        with self.queryLimit(0):
            self.assert400(self.postJSON('/api/users', data))

    def testRegisterUserInviteKey(self):
        self.app.config['INVITE_KEY'] = 'foobar'
        data = self.default_data()
        data['invite_key'] = self.app.config['INVITE_KEY']
        with self.client:
            resp = self.postJSON('/api/users', data)
        self.assert200(resp)

    def testRegisterUserNoInviteKey(self):
        self.app.config['INVITE_KEY'] = 'foobar'
        data = self.default_data()
        with self.client:
            with self.queryLimit(0):
                resp = self.postJSON('/api/users', data)
        self.assert400(resp)

    def testRegisterUserWrongInviteKey(self):
        self.app.config['INVITE_KEY'] = 'foobar'
        data = self.default_data()
        data['invite_key'] = 'notright'
        with self.client:
            with self.queryLimit(0):
                resp = self.postJSON('/api/users', data)
        self.assert400(resp)
Beispiel #6
0
class NewsTest(base.RestTestCase):

    PATH = '/api/news'

    def setUp(self):
        super(NewsTest, self).setUp()
        models.News.broadcast('test', 'Test message.')
        models.News.unicast(self.authenticated_client.team.tid, 'test',
                            'Test team message.')
        models.commit()

    def testGetNews(self):
        with self.queryLimit(2):
            resp = self.client.get(self.PATH)
        self.assert200(resp)
        self.assertEqual(1, len(resp.json))

    testGetNewsAdmin = base.admin_test(testGetNews)

    @base.authenticated_test
    def testGetNewsAuthenticated(self):
        with self.queryLimit(2):
            resp = self.client.get(self.PATH)
        self.assert200(resp)
        self.assertEqual(2, len(resp.json))

    def testCreateNews(self):
        with self.queryLimit(0):
            resp = self.postJSON(self.PATH, {
                'message': 'some message',
            })
        self.assert403(resp)

    testCreateNewsAuthenticated = base.authenticated_test(testCreateNews)

    @base.admin_test
    def testCreateNewsAdmin(self):
        msg = 'some message'
        with self.queryLimit(3):
            resp = self.postJSON(self.PATH, {
                'message': msg,
            })
        self.assert200(resp)
        self.assertEqual(self.client.user.nick, resp.json['author'])
        self.assertEqual(msg, resp.json['message'])

    @base.admin_test
    def testCreateTeamNewsAdmin(self):
        msg = 'some message'
        tid = self.authenticated_client.team.tid
        with self.queryLimit(3):
            resp = self.postJSON(self.PATH, {
                'message': msg,
                'tid': tid,
            })
        self.assert200(resp)
        self.assertEqual(self.client.user.nick, resp.json['author'])
        self.assertEqual(msg, resp.json['message'])
        self.assertEqual('Unicast', resp.json['news_type'])
        news = models.News.query.get(resp.json['nid'])
        self.assertEqual(tid, news.audience_team_tid)
class CategoryTest(base.RestTestCase):

    PATH_LIST = '/api/categories'
    PATH_SINGLE = '/api/categories/%s'

    def setUp(self):
        super(CategoryTest, self).setUp()
        self.challs, self.cats = makeTestChallenges()
        self.cat = self.cats[0]
        self.PATH_SINGLE %= self.cat.slug

    def _testGetList(self):
        with self.queryLimit(3):
            resp = self.client.get(self.PATH_LIST)
        self.assert200(resp)
        self.assertEqual(len(self.cats), len(resp.json['categories']))
        # TODO: check that the expected fields are visible and that others are
        # not.

    testGetListAuthenticated = base.authenticated_test(_testGetList)
    testGetListAdmin = base.admin_test(_testGetList)

    def testGetListAnonymous(self):
        with self.queryLimit(0):
            resp = self.client.get(self.PATH_LIST)
        self.assert403(resp)

    def testCreateCategoryFails(self):
        data = {
            'name': 'New',
            'description': 'New Category',
        }
        with self.queryLimit(0):
            resp = self.postJSON(self.PATH_LIST, data)
        self.assert403(resp)
        self.assertEqual(len(self.cats), models.Category.query.count())

    testCreateCategoryFailsAuthenticated = base.authenticated_test(
        testCreateCategoryFails)

    @base.admin_test
    def testCreateCategory(self):
        data = {
            'name': 'New',
            'description': 'New Category',
        }
        with self.queryLimit(6):
            resp = self.postJSON(self.PATH_LIST, data)
        self.assert200(resp)
        for f in ('name', 'description'):
            self.assertEqual(data[f], resp.json[f])
        cat = models.Category.query.get(resp.json['slug'])
        for f in ('name', 'description'):
            self.assertEqual(data[f], getattr(cat, f))

    def testDeleteCategoryFails(self):
        with self.queryLimit(0):
            resp = self.client.delete(self.PATH_SINGLE)
        self.assert403(resp)
        self.assertIsNotNone(models.Category.query.get(self.cat.slug))

    testDeleteCategoryFailsAuthenticated = base.authenticated_test(
        testDeleteCategoryFails)

    @base.admin_test
    def testDeleteNonEmptyCategory(self):
        with self.queryLimit(3):
            resp = self.client.delete(self.PATH_SINGLE)
        self.assert400(resp)
        self.assertIsNotNone(models.Category.query.get(self.cat.slug))

    @base.admin_test
    def testDeleteEmptyCategory(self):
        for i in self.cat.challenges:
            models.db.session.delete(i)
        models.db.session.commit()
        with self.queryLimit(3):
            resp = self.client.delete(self.PATH_SINGLE)
        self.assert200(resp)
        self.assertIsNone(models.Category.query.get(self.cat.slug))

    def testGetCategoryAnonymous(self):
        with self.queryLimit(0):
            self.assert403(self.client.get(self.PATH_SINGLE))

    def _testGetCategory(self):
        with self.queryLimit(None):
            resp = self.client.get(self.PATH_SINGLE)
        self.assert200(resp)

    testGetCategoryAuthenticated = base.authenticated_test(_testGetCategory)
    testGetCategoryAdmin = base.admin_test(_testGetCategory)

    def testUpdateCategoryAnonymous(self):
        with self.queryLimit(0):
            resp = self.putJSON(self.PATH_SINGLE, {'name': 'new name'})
        self.assert403(resp)

    testUpdateCategoryAuthenticated = base.authenticated_test(
        testUpdateCategoryAnonymous)

    @base.admin_test
    def testUpdateCategoryAdmin(self):
        data = {'name': 'new name'}
        with self.queryLimit(None):
            resp = self.putJSON(self.PATH_SINGLE, data)
        self.assert200(resp)
        self.assertEqual(data['name'], resp.json['name'])
        cat = models.Category.query.get(self.cat.slug)
        self.assertEqual(data['name'], cat.name)
Beispiel #8
0
class APIKeyTest(base.RestTestCase):

    PATH = '/api/apikey'

    def setUp(self):
        super(APIKeyTest, self).setUp()
        self.admin_client.user.api_key = None
        models.commit()

    @base.admin_test
    def testGetApiKey(self):
        key = '44' * 16
        self.admin_client.user.api_key = key
        models.commit()
        with self.queryLimit(1):
            resp = self.client.get(self.PATH)
        self.assert200(resp)
        self.assertEqual(key, resp.json['api_key'])

    @base.admin_test
    def testUpdateApiKey(self):
        key = '55' * 16
        with mock.patch.object(self.admin_client.user,
                               'reset_api_key') as mock_reset:

            def mock_side_effect():
                self.admin_client.user.api_key = key

            mock_reset.side_effect = mock_side_effect
            with self.queryLimit(3):
                resp = self.postJSON(self.PATH, {})
            mock_reset.assert_called_once()
        self.assert200(resp)
        self.assertEqual(key, resp.json['api_key'])

    @base.admin_test
    def testDelete_Own(self):
        key = '55' * 16
        self.admin_client.user.api_key = key
        models.commit()
        with self.queryLimit(2):
            resp = self.client.delete(self.PATH + '/' + key)
        self.assert200(resp)
        self.assertIsNone(self.admin_client.user.api_key)

    @base.admin_test
    def testDelete_All(self):
        self.admin_client.user.api_key = '55' * 16
        other_admin = models.User.create('*****@*****.**', 'foo', 'foo')
        other_admin.promote()
        other_admin.api_key = '44' * 16
        models.commit()
        with self.queryLimit(4):
            resp = self.client.delete(self.PATH)
        self.assert200(resp)
        self.assertIsNone(self.admin_client.user.api_key)
        self.assertIsNone(other_admin.api_key)

    def testGetApiKey_Denied(self):
        with self.queryLimit(0):
            resp = self.client.get(self.PATH)
        self.assert403(resp)

    testGetApiKey_Denied_Authenticated = base.authenticated_test(
        testGetApiKey_Denied)

    def testUpdateApiKey_Denied(self):
        with self.queryLimit(0):
            resp = self.postJSON(self.PATH, {})
        self.assert403(resp)

    testUpdateApiKey_Denied_Authenticated = base.authenticated_test(
        testUpdateApiKey_Denied)

    def testDeleteApiKey_All_Denied(self):
        with self.queryLimit(0):
            resp = self.client.delete(self.PATH)
        self.assert403(resp)

    testDeleteApiKey_All_Denied_Auth = base.authenticated_test(
        testDeleteApiKey_All_Denied)