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)
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)
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())
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)
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)
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)
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)