def test_user_resource_counts_are_accurate_when_removing(self): with session.begin(): user = data_setup.create_user() job = data_setup.create_job(owner=user) data_setup.mark_job_running(job) owned_system = data_setup.create_system(owner=user) loaned_system = data_setup.create_system() loaned_system.loaned = user owned_pool = data_setup.create_system_pool(owning_user=user) group = data_setup.create_group(owner=user) s = requests.Session() requests_login(s) response = s.get(get_server_base() + 'users/%s' % user.user_name, headers={'Accept': 'application/json'}) response.raise_for_status() self.assertEquals(response.json()['job_count'], 1) self.assertEquals(response.json()['reservation_count'], 1) self.assertEquals(response.json()['loan_count'], 1) self.assertEquals(response.json()['owned_system_count'], 1) self.assertEquals(response.json()['owned_pool_count'], 1) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'removed': 'now'}, session=s) response.raise_for_status() # The bug was that the counts in the PATCH response would still show # their old values, because the queries for producing the counts were # being run before all the removals were flushed to the database. # Note that job_count stays as 1, because the job has been cancelled # but it will still be running until the next iteration of beakerd's # update_dirty_jobs. self.assertEquals(response.json()['job_count'], 1) self.assertEquals(response.json()['reservation_count'], 0) self.assertEquals(response.json()['loan_count'], 0) self.assertEquals(response.json()['owned_system_count'], 0) self.assertEquals(response.json()['owned_pool_count'], 0)
def test_empty_notes_are_rejected(self): s = requests.Session() requests_login(s, user=self.owner.user_name, password=u'owner') response = post_json(get_server_base() + 'systems/%s/notes/' % self.system.fqdn, session=s, data={'text': ''}) self.assertEquals(response.status_code, 400) self.assertEquals(response.content, 'Note text cannot be empty')
def test_whitespace_only_values_are_not_accepted(self): # Whitespace-only values also count as empty, because we strip s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': ' \t\v', 'display_name': 'Bilbo Baggins', 'email_address': '*****@*****.**' }) self.assertEqual(response.status_code, 400) self.assertEqual(response.text, 'Username must not be empty') response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': 'bbaggins', 'display_name': ' \t\v', 'email_address': '*****@*****.**' }) self.assertEqual(response.status_code, 400) self.assertEqual(response.text, 'Display name must not be empty') response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': 'bbaggins', 'display_name': 'Bilbo Baggins', 'email_address': ' \t\v' }) self.assertEqual(response.status_code, 400) self.assertEqual(response.text, 'Email address must not be empty')
def test_non_ascii_username_and_display_name(self): user_name = u'ломоносов' display_name = u'Михаил Ломоносов' email = '*****@*****.**' s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': user_name, 'display_name': display_name, 'email_address': email}) response.raise_for_status() # Test that search works as well response = s.get(get_server_base() + 'users/', params={'q': u'user_name:%s' % user_name}, headers={'Accept': 'application/json'}) response.raise_for_status() self.assertEqual(response.json()['count'], 1) self.assertEqual(response.json()['entries'][0]['user_name'], user_name) # Test that typeahead works as well response = s.get(get_server_base() + 'users/+typeahead', params={'q': user_name[:4]}, headers={'Accept': 'application/json'}) self.assertEqual(response.json()['data'][0]['user_name'], user_name)
def test_mark_note_as_deleted(self): # Notes never get actually deleted, they just get marked as "deleted" # which hides them by default in the UI. "Obsoleted" would be a better # word but "deleted" is what we have. with session.begin(): note_text = u'some obsolete info' self.system.notes.append(Note(text=note_text, user=self.owner)) session.flush() note_id = self.system.notes[0].id s = requests.Session() requests_login(s, user=self.owner.user_name, password=u'owner') response = patch_json(get_server_base() + 'systems/%s/notes/%s' % (self.system.fqdn, note_id), session=s, data={'deleted': 'now'}) response.raise_for_status() self.assertEquals(response.json()['id'], note_id) assert_datetime_within(datetime.datetime.strptime( response.json()['deleted'], '%Y-%m-%d %H:%M:%S'), reference=datetime.datetime.utcnow(), tolerance=datetime.timedelta(seconds=10)) with session.begin(): session.refresh(self.system.notes[0]) assert_datetime_within(self.system.notes[0].deleted, reference=datetime.datetime.utcnow(), tolerance=datetime.timedelta(seconds=10))
def test_non_ascii_username_and_display_name(self): user_name = u'ломоносов' display_name = u'Михаил Ломоносов' email = '*****@*****.**' s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': user_name, 'display_name': display_name, 'email_address': email }) response.raise_for_status() # Test that search works as well response = s.get(get_server_base() + 'users/', params={'q': u'user_name:%s' % user_name}, headers={'Accept': 'application/json'}) response.raise_for_status() self.assertEqual(response.json()['count'], 1) self.assertEqual(response.json()['entries'][0]['user_name'], user_name) # Test that typeahead works as well response = s.get(get_server_base() + 'users/+typeahead', params={'q': user_name[:4]}, headers={'Accept': 'application/json'}) self.assertEqual(response.json()['data'][0]['user_name'], user_name)
def test_404_response_to_string_rs_id(self): s = requests.Session() requests_login(s, user=self.owner, password=u'theowner') response = post_json(get_server_base() + '/recipes/thisisnotanint/tasks/%s/comments/' % self.recipe.tasks[0].id, session=s, data={'comment': 'testdata'}) self.assertEqual(response.status_code, 404)
def test_unprivileged_user_cannot_add_note(self): with session.begin(): unprivileged = data_setup.create_user(password=u'password') s = requests.Session() requests_login(s, user=unprivileged.user_name, password=u'password') response = post_json(get_server_base() + 'systems/%s/notes/' % self.system.fqdn, session=s, data={'text': 'asdf'}) self.assertEquals(response.status_code, 403)
def test_remove_account(self): with session.begin(): user = data_setup.create_user() job = data_setup.create_job(owner=user) data_setup.mark_job_running(job) owned_system = data_setup.create_system(owner=user) loaned_system = data_setup.create_system() loaned_system.loaned = user reserved_system = data_setup.create_system( status=SystemStatus.manual) reserved_system.reserve_manually(service=u'testdata', user=user) reserved_system.custom_access_policy.add_rule( SystemPermission.reserve, user=user) group = data_setup.create_group(owner=user) s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'removed': 'now'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertIsNotNone(user.removed) # running jobs should be cancelled job.update_status() self.assertEquals(job.status, TaskStatus.cancelled) self.assertIn('User %s removed' % user.user_name, job.recipesets[0].recipes[0].tasks[0].results[0].log) # reservations should be released self.assertIsNone(reserved_system.user) # loans should be returned self.assertIsNone(loaned_system.loaned) # access policy rules should be removed self.assertEqual([], [ rule for rule in reserved_system.custom_access_policy.rules if rule.user == user ]) self.assertEqual(reserved_system.activity[0].field_name, u'Access Policy Rule') self.assertEqual(reserved_system.activity[0].action, u'Removed') self.assertEqual(reserved_system.activity[0].old_value, u'<grant reserve to %s>' % user.user_name) # systems owned by the user should be transferred to the caller self.assertEqual(owned_system.owner.user_name, data_setup.ADMIN_USER) self.assertEqual(owned_system.activity[0].field_name, u'Owner') self.assertEqual(owned_system.activity[0].action, u'Changed') self.assertEqual(owned_system.activity[0].old_value, user.user_name) self.assertEqual(owned_system.activity[0].new_value, data_setup.ADMIN_USER) # group membership/ownership should be removed self.assertNotIn(group, user.groups) self.assertNotIn(user, group.users) self.assertFalse(group.has_owner(user)) self.assertEqual(group.activity[-1].field_name, u'User') self.assertEqual(group.activity[-1].action, u'Removed') self.assertEqual(group.activity[-1].old_value, user.user_name)
def test_remove_account(self): with session.begin(): user = data_setup.create_user() job = data_setup.create_job(owner=user) data_setup.mark_job_running(job) owned_system = data_setup.create_system(owner=user) loaned_system = data_setup.create_system() loaned_system.loaned = user reserved_system = data_setup.create_system(status=SystemStatus.manual) reserved_system.reserve_manually(service=u'testdata', user=user) reserved_system.custom_access_policy.add_rule( SystemPermission.reserve, user=user) owned_pool = data_setup.create_system_pool(owning_user=user) group = data_setup.create_group(owner=user) s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'removed': 'now'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertIsNotNone(user.removed) # running jobs should be cancelled job.update_status() self.assertEquals(job.status, TaskStatus.cancelled) self.assertIn('User %s removed' % user.user_name, job.recipesets[0].recipes[0].tasks[0].results[0].log) # reservations should be released self.assertIsNone(reserved_system.user) # loans should be returned self.assertIsNone(loaned_system.loaned) # access policy rules should be removed self.assertEqual([], [rule for rule in reserved_system.custom_access_policy.rules if rule.user == user]) self.assertEqual(reserved_system.activity[0].field_name, u'Access Policy Rule') self.assertEqual(reserved_system.activity[0].action, u'Removed') self.assertEqual(reserved_system.activity[0].old_value, u'User:%s:reserve' % user.user_name) # systems owned by the user should be transferred to the caller self.assertEqual(owned_system.owner.user_name, data_setup.ADMIN_USER) self.assertEqual(owned_system.activity[0].field_name, u'Owner') self.assertEqual(owned_system.activity[0].action, u'Changed') self.assertEqual(owned_system.activity[0].old_value, user.user_name) self.assertEqual(owned_system.activity[0].new_value, data_setup.ADMIN_USER) # pools owned by the user should be transferred to the caller self.assertEqual(owned_pool.owner.user_name, data_setup.ADMIN_USER) self.assertEqual(owned_pool.activity[0].field_name, u'Owner') self.assertEqual(owned_pool.activity[0].action, u'Changed') self.assertEqual(owned_pool.activity[0].old_value, user.user_name) self.assertEqual(owned_pool.activity[0].new_value, data_setup.ADMIN_USER) # group membership/ownership should be removed self.assertNotIn(group, user.groups) self.assertNotIn(user, group.users) self.assertFalse(group.has_owner(user)) self.assertEqual(group.activity[-1].field_name, u'User') self.assertEqual(group.activity[-1].action, u'Removed') self.assertEqual(group.activity[-1].old_value, user.user_name)
def test_regular_users_cannot_rename_themselves(self): with session.begin(): user = data_setup.create_user(password=u'password') s = requests.Session() requests_login(s, user=user.user_name, password=u'password') response = patch_json(get_server_base() + 'users/%s' % user.user_name, session=s, data={'user_name': 'gandalf'}) self.assertEqual(response.status_code, 403) self.assertIn('Cannot rename user', response.text)
def test_does_not_create_user_with_empty_email_address(self): s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': 'fbagginsone', 'display_name': 'Frodo Baggins pne', 'email_address': ''}) self.assertEqual(response.status_code, 400) self.assertIn('Email address must not be empty', response.text)
def test_get_user(self): with session.begin(): user = data_setup.create_user() s = requests.Session() requests_login(s) response = s.get(get_server_base() + 'users/%s' % user.user_name, headers={'Accept': 'application/json'}) response.raise_for_status() self.assertEqual(response.json()['user_name'], user.user_name)
def test_cannot_update_reservation_request_if_duration_too_long(self): with session.begin(): data_setup.mark_job_running(self.job) s = requests.Session() requests_login(s, user=self.owner, password=u'theowner') response = patch_json(get_server_base() + 'recipes/%s/reservation-request' % self.recipe_with_reservation_request.id, session=s, data={'reserve': True, 'duration': 605000}) self.assertEquals(response.status_code, 400)
def test_user_with_edit_permission_can_add_note(self): with session.begin(): user = data_setup.create_user(password='******') self.system.custom_access_policy.add_rule( permission=SystemPermission.edit_system, user=user) s = requests.Session() requests_login(s, user=user.user_name, password=u'password') response = post_json(get_server_base() + 'systems/%s/notes/' % self.system.fqdn, session=s, data={'text': 'asdf'}) response.raise_for_status()
def test_updating_power_returns_correct_id(self): # The bug was that Power.id was overwriting System.id with session.begin(): system = data_setup.create_system(with_power=False, owner=self.owner) s = requests.Session() requests_login(s, user=self.owner.user_name, password=u'theowner') response = patch_json(get_server_base() + 'systems/%s/' % system.fqdn, session=s, data={'power_type': 'ilo', 'power_address': 'nowhere'}) response.raise_for_status() self.assertEqual(response.json()['id'], system.id)
def test_task_update_task_not_available_404(self): req_sess = requests.Session() with session.begin(): result = session.query(func.max(Task.id)).first() fake_id = result[0] + 1 requests_login(req_sess, data_setup.ADMIN_USER, data_setup.ADMIN_PASSWORD) response = patch_json(get_server_base() + 'tasks/%s' % fake_id, session=req_sess, data={'disabled': True}) self.assertEqual(response.status_code, 404) self.assertEqual(response.text, 'Task %s does not exist' % fake_id)
def test_get_self(self): with session.begin(): user = data_setup.create_user(password=u'password') s = requests.Session() requests_login(s, user=user.user_name, password=u'password') response = s.get(get_server_base() + 'users/+self', headers={'Accept': 'application/json'}) response.raise_for_status() self.assertEqual(response.json()['user_name'], user.user_name) self.assertEqual(response.json()['email_address'], user.email_address)
def test_task_update_disable_normal_user_fail(self): req_sess = requests.Session() requests_login(req_sess, self.normal_user.user_name, 'secret') self.assertEqual(self.my_task.valid, True) response = patch_json(get_server_base() + 'tasks/%s' % self.my_task.id, session=req_sess, data={'disabled': True}) self.assertEqual(response.status_code, 403) with session.begin(): session.expire_all() self.assertEqual(self.my_task.valid, True)
def test_does_not_create_user_with_empty_display_name(self): s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': 'fbagginsone', 'display_name': '', 'email_address': '*****@*****.**'}) self.assertEqual(response.status_code, 400) self.assertEqual(response.text, 'Display name must not be empty')
def test_task_update_disable_successful(self): req_sess = requests.Session() requests_login(req_sess, data_setup.ADMIN_USER, data_setup.ADMIN_PASSWORD) self.assertEqual(self.my_task.valid, True) response = patch_json(get_server_base() + 'tasks/%s' % self.my_task.id, session=req_sess, data={'disabled': True}) response.raise_for_status() self.assertEqual(response.json()['valid'], False) with session.begin(): session.expire_all() self.assertEqual(self.my_task.valid, False)
def test_set_root_password(self): with session.begin(): user = data_setup.create_user() s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'root_password': u'D6BeK7Cq9a4M'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertIsNotNone(user._root_password)
def test_disable_user(self): with session.begin(): user = data_setup.create_user() s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'disabled': True}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertTrue(user.disabled)
def test_renaming_user_to_existing_username_gives_409(self): with session.begin(): user = data_setup.create_user() other_user = data_setup.create_user() s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, session=s, data={'user_name': other_user.user_name}) self.assertEqual(response.status_code, 409) self.assertEqual(response.text, 'User %s already exists' % other_user.user_name)
def test_cannot_create_keystone_trust_if_openstack_is_disabled(self): if config.get('openstack.identity_api_url'): raise SkipTest('OpenStack integration is enabled') with session.begin(): user = data_setup.create_user() s = requests.Session() requests_login(s) response = put_json(get_server_base() + 'users/%s/keystone-trust' % user.user_name, session=s, data={'openstack_username': u'dummyuser'}) self.assertEqual(response.status_code, 400) self.assertIn('OpenStack Integration is not enabled', response.text)
def test_update_display_name(self): with session.begin(): user = data_setup.create_user(display_name=u'Frodo Baggins') s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'display_name': u'Frodo Gamgee'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertEqual(user.display_name, u'Frodo Gamgee')
def test_update_email_address(self): with session.begin(): user = data_setup.create_user(email_address=u'*****@*****.**') s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'email_address': u'*****@*****.**'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertEqual(user.email_address, u'*****@*****.**')
def test_can_clear_reviewed_state(self): with session.begin(): self.recipe.set_reviewed_state(self.owner, True) s = requests.Session() requests_login(s, user=self.owner, password=u'theowner') response = patch_json(get_server_base() + 'recipes/%s' % self.recipe.id, session=s, data={'reviewed': False}) response.raise_for_status() with session.begin(): session.expire_all() self.assertEqual(self.recipe.get_reviewed_state(self.owner), False)
def test_unprivileged_user_cannot_delete_note(self): with session.begin(): self.system.notes.append(Note(text=u'asdf', user=self.owner)) session.flush() note_id = self.system.notes[0].id unprivileged = data_setup.create_user(password=u'password') s = requests.Session() requests_login(s, user=unprivileged.user_name, password=u'password') response = patch_json(get_server_base() + 'systems/%s/notes/%s' % (self.system.fqdn, note_id), session=s, data={'deleted': 'now'}) self.assertEquals(response.status_code, 403)
def test_empty_comment_is_rejected(self): s = requests.Session() requests_login(s, user=self.owner, password=u'theowner') response = post_json(get_server_base() + 'recipes/%s/tasks/%s/comments/' % (self.recipe.id, self.recipetask.id), session=s, data={'comment': None}) self.assertEqual(response.status_code, 400) # whitespace-only comment also counts as empty response = post_json(get_server_base() + 'recipes/%s/tasks/%s/comments/' % (self.recipe.id, self.recipetask.id), session=s, data={'comment': ' '}) self.assertEqual(response.status_code, 400)
def test_set_use_old_job_page(self): with session.begin(): user = data_setup.create_user(password=u'password') user.use_old_job_page = True s = requests.Session() requests_login(s, user=user.user_name, password='******') response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'use_old_job_page': False}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertEqual(user.use_old_job_page, False)
def test_add_submission_delegate(self): with session.begin(): user = data_setup.create_user() other_user = data_setup.create_user() s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/%s/submission-delegates/' % user.user_name, session=s, data={'user_name': other_user.user_name}) response.raise_for_status() with session.begin(): session.expire_all() self.assertItemsEqual(user.submission_delegates, [other_user])
def test_cannot_lend_to_deleted_user(self): with session.begin(): system = data_setup.create_system() deleted_user = data_setup.create_user() deleted_user.removed = datetime.datetime.utcnow() s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'systems/%s/loans/' % system.fqdn, session=s, data={'recipient': {'user_name': deleted_user.user_name}}) self.assertEquals(response.status_code, 400) self.assertEquals(response.text, 'Cannot lend to deleted user %s' % deleted_user.user_name)
def test_set_password(self): with session.begin(): user = data_setup.create_user() user.password = u'frodo' s = requests.Session() requests_login(s) response = patch_json(get_server_base() + 'users/%s' % user.user_name, data={'password': u'bilbo'}, session=s) response.raise_for_status() with session.begin(): session.expire_all() self.assertTrue(user.check_password(u'bilbo'))
def test_can_update_recipe_whiteboard(self): s = requests.Session() requests_login(s, user=self.owner, password=u'theowner') response = patch_json(get_server_base() + 'recipes/%s' % self.recipe.id, session=s, data={'whiteboard': u'newwhiteboard'}) response.raise_for_status() with session.begin(): session.expire_all() self.assertEquals(self.recipe.whiteboard, 'newwhiteboard') self.assertEquals(self.recipe.activity[0].field_name, u'Whiteboard') self.assertEquals(self.recipe.activity[0].action, u'Changed') self.assertEquals(self.recipe.activity[0].new_value, u'newwhiteboard')