def test_gestore_comunicati_can_delete_data(self): api_session = RelativeSession(self.portal_url) api_session.headers.update({"Accept": "application/json"}) api_session.auth = ("memberuser", "secret") url = "{}/123".format(self.url) self.assertEqual(api_session.delete(url, json={}).status_code, 401) setRoles(self.portal, "memberuser", ["Gestore Comunicati"]) transaction.commit() # 400 because it's a fake id self.assertEqual( api_session.delete(self.url, json={}).status_code, 400) api_session.close()
class TestUsersEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ['Manager']) self.mailhost = getUtility(IMailHost) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.anon_api_session = RelativeSession(self.portal_url) self.anon_api_session.headers.update({'Accept': 'application/json'}) properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create(email='*****@*****.**', username='******', properties=properties, password=u'password') properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Other user', } api.user.create(email='*****@*****.**', username='******', properties=properties, password=u'otherpassword') transaction.commit() def tearDown(self): self.api_session.close() self.anon_api_session.close() def test_list_users(self): response = self.api_session.get('/@users') self.assertEqual(200, response.status_code) self.assertEqual(4, len(response.json())) user_ids = [user['id'] for user in response.json()] self.assertIn('admin', user_ids) self.assertIn('test_user_1_', user_ids) self.assertIn('noam', user_ids) noam = [x for x in response.json() if x.get('username') == 'noam'][0] self.assertEqual('noam', noam.get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', noam.get('@id')) self.assertEqual('*****@*****.**', noam.get('email')) self.assertEqual('Noam Avram Chomsky', noam.get('fullname')) self.assertEqual('web.mit.edu/chomsky', noam.get('home_page')) # noqa self.assertEqual('Professor of Linguistics', noam.get('description')) # noqa self.assertEqual('Cambridge, MA', noam.get('location')) def test_list_users_without_being_manager(self): noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({'Accept': 'application/json'}) noam_api_session.auth = ('noam', 'password') response = noam_api_session.get('/@users') self.assertEqual(response.status_code, 401) noam_api_session.close() def test_list_users_as_anonymous(self): response = self.anon_api_session.get('/@users') self.assertEqual(response.status_code, 401) def test_add_user(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******", "roles": [ "Contributor", ], }, ) transaction.commit() self.assertEqual(201, response.status_code) howard = api.user.get(userid='howard') self.assertEqual("*****@*****.**", howard.getProperty('email')) self.assertIn('Contributor', api.user.get_roles(username="******")) def test_add_user_username_is_required(self): response = self.api_session.post( '/@users', json={"password": "******"}, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('Property \'username\' is required' in response.text) def test_add_user_password_is_required(self): response = self.api_session.post( '/@users', json={"username": "******"}, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue(('You have to either send a ' 'password or sendPasswordReset') in response.text) def test_add_user_email_is_required_if_email_login_is_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "password": "******" }, ) self.assertEqual(400, response.status_code) self.assertTrue( 'Property \'username\' is not allowed' in response.text) def test_add_user_email_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue(api.user.get(userid='*****@*****.**')) def test_username_is_not_allowed_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue( 'Property \'username\' is not allowed' in response.text) def test_add_user_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user = api.user.get(userid='*****@*****.**') self.assertTrue(user) self.assertEqual('*****@*****.**', user.getUserName()) self.assertEqual('*****@*****.**', user.getProperty('email')) def test_add_user_with_sendPasswordRest_sends_email(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "sendPasswordReset": True }, ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue( 'To: [email protected]' in self.mailhost.messages[0]) def test_add_user_send_properties(self): response = self.api_session.post( '/@users', json={ "username": "******", "password": "******", "email": "*****@*****.**", "fullname": "Howard Zinn", }, ) transaction.commit() self.assertEqual(201, response.status_code) member = api.user.get(username='******') self.assertEqual(member.getProperty('fullname'), 'Howard Zinn') def test_add_anon_user_sends_properties_are_saved(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "fullname": "Howard Zinn", }, ) transaction.commit() self.assertEqual(201, response.status_code) member = api.user.get(username='******') self.assertEqual(member.getProperty('fullname'), 'Howard Zinn') def test_add_anon_no_roles(self): """Make sure anonymous users cannot set their own roles. Allowing so would make them Manager. """ security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "roles": ['Manager'], }, ) transaction.commit() self.assertEqual(400, response.status_code) errors = response.json()['error']['errors'] fields = [x['field'] for x in errors] self.assertEqual(['roles'], fields) def test_add_user_with_uuid_as_userid_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()['id'] user = api.user.get(userid=user_id) self.assertTrue(user) self.assertEqual('*****@*****.**', user.getUserName()) self.assertEqual('*****@*****.**', user.getProperty('email')) def test_get_user(self): response = self.api_session.get('/@users/noam') self.assertEqual(response.status_code, 200) self.assertEqual('noam', response.json().get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', response.json().get('@id')) self.assertEqual('*****@*****.**', response.json().get('email')) self.assertEqual('Noam Avram Chomsky', response.json().get('fullname')) self.assertEqual('web.mit.edu/chomsky', response.json().get('home_page')) # noqa self.assertEqual('Professor of Linguistics', response.json().get('description')) # noqa self.assertEqual('Cambridge, MA', response.json().get('location')) def test_get_user_as_anonymous(self): response = self.anon_api_session.get('/@users/noam') self.assertEqual(response.status_code, 401) def test_get_other_user_info_when_logged_in(self): noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({'Accept': 'application/json'}) noam_api_session.auth = ('noam', 'password') response = noam_api_session.get('/@users/otheruser') self.assertEqual(response.status_code, 401) noam_api_session.close() def test_get_search_user_with_filter(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() response = self.api_session.get('/@users', params={'query': 'noa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('noam', response.json()[0].get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', response.json()[0].get('@id')) self.assertEqual('*****@*****.**', response.json()[0].get('email')) self.assertEqual('Noam Avram Chomsky', response.json()[0].get('fullname')) # noqa response = self.api_session.get('/@users', params={'query': 'howa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('howard', response.json()[0].get('id')) def test_get_search_user_with_filter_as_anonymous(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() response = self.anon_api_session.get('/@users', params={'query': 'howa'}) self.assertEqual(response.status_code, 401) def test_get_search_user_with_filter_as_unauthorized_user(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({'Accept': 'application/json'}) noam_api_session.auth = ('noam', 'password') response = noam_api_session.get('/@users', params={'query': 'howa'}) self.assertEqual(response.status_code, 401) noam_api_session.close() def test_get_non_existing_user(self): response = self.api_session.get('/@users/non-existing-user') self.assertEqual(response.status_code, 404) def test_update_user(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } response = self.api_session.patch('/@users/noam', json=payload) transaction.commit() self.assertEqual(response.status_code, 204) noam = api.user.get(userid='noam') self.assertEqual('noam', noam.getUserId()) # user id never changes self.assertEqual('avram', noam.getUserName()) self.assertEqual('Noam A. Chomsky', noam.getProperty('fullname')) self.assertEqual('*****@*****.**', noam.getProperty('email')) def test_user_can_update_himself(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } self.api_session.auth = ('noam', 'password') response = self.api_session.patch('/@users/noam', json=payload) self.assertEqual(response.status_code, 204) transaction.commit() noam = api.user.get(userid='noam') self.assertEqual('noam', noam.getUserId()) # user id never changes self.assertEqual('Noam A. Chomsky', noam.getProperty('fullname')) self.assertEqual('*****@*****.**', noam.getProperty('email')) def test_update_roles(self): self.assertNotIn('Contributor', api.user.get_roles(username='******')) self.api_session.patch('/@users/noam', json={'roles': { 'Contributor': True }}) transaction.commit() self.assertIn('Contributor', api.user.get_roles(username='******')) self.api_session.patch('/@users/noam', json={'roles': { 'Contributor': False }}) transaction.commit() self.assertNotIn('Contributor', api.user.get_roles(username='******')) def test_update_user_password(self): old_password_hashes = dict( self.portal.acl_users.source_users._user_passwords) payload = {'password': '******'} response = self.api_session.patch('/@users/noam', json=payload) transaction.commit() self.assertEqual(response.status_code, 204) new_password_hashes = dict( self.portal.acl_users.source_users._user_passwords) self.assertNotEqual(old_password_hashes['noam'], new_password_hashes['noam']) def test_anonymous_user_can_not_update_existing_user(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } self.api_session.auth = ('noam', 'password') response = self.anon_api_session.patch('/@users/noam', json=payload) self.assertEqual(response.status_code, 401) def test_user_can_not_update_another_user(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } self.api_session.auth = ('otheruser', 'otherpassword') response = self.api_session.patch('/@users/noam', json=payload) self.assertEqual(response.status_code, 403) def test_user_requests_password_sends_password_via_mail(self): self.api_session.auth = ('noam', 'password') payload = {} response = self.api_session.post('/@users/noam/reset-password', json=payload) transaction.commit() self.assertEqual(response.status_code, 200) # FIXME: Test that mail is sent def test_user_can_set_her_own_password(self): self.api_session.auth = ('noam', 'password') self.portal.manage_permission(SetOwnPassword, roles=['Authenticated', 'Manager'], acquire=False) transaction.commit() payload = {'old_password': '******', 'new_password': '******'} response = self.api_session.post('/@users/noam/reset-password', json=payload) transaction.commit() self.assertEqual(response.status_code, 200) authed = self.portal.acl_users.authenticate('noam', 'new_password', {}) self.assertTrue(authed) def test_normal_authenticated_user_cannot_set_other_users_password(self): self.api_session.auth = ('noam', 'password') self.portal.manage_permission(SetOwnPassword, roles=['Authenticated', 'Manager'], acquire=False) transaction.commit() payload = {'old_password': '******', 'new_password': '******'} response = self.api_session.post('/@users/otheruser/reset-password', json=payload) transaction.commit() self.assertEqual(response.status_code, 403) self.assertEqual(response.json()['error']['type'], 'Wrong user') def test_user_set_own_password_requires_set_own_password_permission(self): self.api_session.auth = ('noam', 'password') self.portal.manage_permission(SetOwnPassword, roles=['Manager'], acquire=False) transaction.commit() payload = {'old_password': '******', 'new_password': '******'} response = self.api_session.post('/@users/noam/reset-password', json=payload) transaction.commit() self.assertEqual(response.status_code, 403) def test_user_set_own_password_requires_old_and_new_password(self): self.api_session.auth = ('noam', 'password') payload = {'old_password': '******'} response = self.api_session.post('/@users/noam/reset-password', json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()['error']['type'], 'Invalid parameters') payload = {'new_password': '******'} response = self.api_session.post('/@users/noam/reset-password', json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()['error']['type'], 'Invalid parameters') def test_user_set_own_password_checks_old_password(self): self.api_session.auth = ('noam', 'password') payload = { 'new_password': '******', 'old_password': '******' } response = self.api_session.post('/@users/noam/reset-password', json=payload) self.assertEqual(response.status_code, 403) self.assertEqual(response.json()['error']['type'], 'Wrong password') def test_user_set_reset_token_requires_new_password(self): self.api_session.auth = ('noam', 'password') payload = {'reset_token': 'abc'} response = self.api_session.post('/@users/noam/reset-password', json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()['error']['type'], 'Invalid parameters') def test_reset_with_token(self): reset_tool = getToolByName(self.portal, 'portal_password_reset') reset_info = reset_tool.requestReset('noam') token = reset_info['randomstring'] transaction.commit() payload = {'reset_token': token, 'new_password': '******'} response = self.api_session.post('/@users/noam/reset-password', json=payload) transaction.commit() self.assertEqual(response.status_code, 200) authed = self.portal.acl_users.authenticate('noam', 'new_password', {}) self.assertTrue(authed) def test_reset_with_uuid_as_userid_and_login_email_using_id(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()['id'] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, 'portal_password_reset') reset_info = reset_tool.requestReset(user.id) token = reset_info['randomstring'] transaction.commit() payload = {'reset_token': token, 'new_password': '******'} response = self.api_session.post('/@users/{}/reset-password'.format( user.id), json=payload) self.assertEqual(response.status_code, 200) def test_reset_with_uuid_as_userid_and_login_email_using_mail(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()['id'] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, 'portal_password_reset') reset_info = reset_tool.requestReset(user.id) token = reset_info['randomstring'] transaction.commit() payload = {'reset_token': token, 'new_password': '******'} response = self.api_session.post('/@users/{}/reset-password'.format( user.getUserName()), json=payload) self.assertEqual(response.status_code, 200) def test_reset_and_login_email_using_mail(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()['id'] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, 'portal_password_reset') reset_info = reset_tool.requestReset(user.id) token = reset_info['randomstring'] transaction.commit() payload = {'reset_token': token, 'new_password': '******'} response = self.api_session.post('/@users/{}/reset-password'.format( user.getUserName()), json=payload) self.assertEqual(response.status_code, 200) def test_delete_user(self): response = self.api_session.delete('/@users/noam') transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, api.user.get(userid='noam')) def test_delete_non_existing_user(self): response = self.api_session.delete('/@users/non-existing-user') transaction.commit() self.assertEqual(response.status_code, 404) def test_anonymous_requires_enable_self_reg(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = False transaction.commit() response = self.anon_api_session.post( '/@users', json={"password": "******"}, ) transaction.commit() self.assertEqual(403, response.status_code) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**' }, ) transaction.commit() self.assertEqual(201, response.status_code) def test_anonymous_without_enable_user_pwd_choice_sends_mail(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**' }, ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue( 'To: [email protected]' in self.mailhost.messages[0]) def test_anonymous_can_set_password_with_enable_user_pwd_choice(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**', 'password': '******' }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue( 'Property \'password\' is not allowed' in response.text) security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**', 'password': '******' }, ) transaction.commit() self.assertEqual(201, response.status_code) def test_anonymous_with_enable_user_pwd_choice_doent_send_email(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**', 'password': '******' }, ) transaction.commit() self.assertEqual(self.mailhost.messages, []) self.assertEqual(201, response.status_code) def test_anonymous_with_enable_user_sets_only_member_role(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( '/@users', json={ "username": "******", 'email': '*****@*****.**', 'password': '******' }, ) response = response.json() self.assertIn('Member', response['roles']) self.assertEqual(1, len(response['roles'])) def test_add_user_no_roles_sets_member_as_sensible_default(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) response = response.json() self.assertIn('Member', response['roles']) self.assertEqual(1, len(response['roles']))
class TestLocking(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.portal = self.layer["portal"] self.request = self.layer["request"] login(self.portal, SITE_OWNER_NAME) self.doc = self.portal[self.portal.invokeFactory("Document", id="doc1", title="My Document")] alsoProvides(self.doc, ITTWLockable) self.api_session = RelativeSession(self.doc.absolute_url(), test=self) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) transaction.commit() def tearDown(self): self.api_session.close() def test_lock_object(self): response = self.api_session.post("/@lock") transaction.commit() self.assertEqual(response.status_code, 200) self.assertTrue(ILockable(self.doc).locked()) def test_lock_object_non_stealable(self): response = self.api_session.post("/@lock", json={"stealable": False}) transaction.commit() self.assertEqual(response.status_code, 200) self.assertTrue(INonStealableLock.providedBy(self.doc)) def test_lock_object_with_custom_timeout(self): response = self.api_session.post("/@lock", json={"timeout": 86400}) transaction.commit() self.assertEqual(response.status_code, 200) self.assertEqual(self.doc.wl_lockValues()[0].getTimeout(), 86400) def test_unlock_object(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.delete("/@lock") transaction.commit() self.assertEqual(response.status_code, 200) self.assertFalse(lockable.locked()) def test_refresh_lock(self): lockable = ILockable(self.doc) lockable.lock() modified = self.doc.wl_lockValues()[0].getModifiedTime() transaction.commit() response = self.api_session.patch("/@lock") transaction.commit() self.assertEqual(response.status_code, 200) self.assertTrue( self.doc.wl_lockValues()[0].getModifiedTime() > modified) def test_lock_info_for_locked_object(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.get("/@lock") self.assertEqual(response.status_code, 200) self.assertTrue(response.json()["locked"]) def test_lock_info_for_unlocked_object(self): response = self.api_session.get("/@lock") self.assertEqual(response.status_code, 200) self.assertFalse(response.json()["locked"]) def test_update_locked_object_without_token_fails(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.patch("/", json={"title": "New Title"}) transaction.commit() self.assertEqual(response.status_code, 403) self.assertEqual(self.doc.Title(), "My Document") def test_update_locked_object_with_token_succeeds(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.patch( "/", headers={"Lock-Token": lockable.lock_info()[0]["token"]}, json={"title": "New Title"}, ) transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(self.doc.Title(), "New Title")
class TestTraversal(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.request = self.layer['request'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() self.time_freezer = freeze_time("2016-10-21 19:00:00") self.frozen_time = self.time_freezer.start() self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory('Document', id='front-page') self.document = self.portal['front-page'] self.document.title = u"Welcome to Plone" self.document.description = \ u"Congratulations! You have successfully installed Plone." self.document.text = RichTextValue( u"If you're seeing this instead of the web site you were " + u"expecting, the owner of this web site has just installed " + u"Plone. Do not contact the Plone Team or the Plone mailing " + u"lists about this.", 'text/plain', 'text/html') self.document.creation_date = DateTime('2016-01-21T01:14:48+00:00') IMutableUUID(self.document).set('1f699ffa110e45afb1ba502f75f7ec33') self.document.reindexObject() self.document.modification_date = DateTime('2016-01-21T01:24:11+00:00') import transaction transaction.commit() self.browser = Browser(self.app) self.browser.handleErrors = False self.browser.addHeader( 'Authorization', 'Basic %s:%s' % ( SITE_OWNER_NAME, SITE_OWNER_PASSWORD, )) def tearDown(self): self.time_freezer.stop() def test_documentation_document(self): response = self.api_session.get(self.document.absolute_url()) save_response_for_documentation('document.json', response) def test_documentation_news_item(self): self.portal.invokeFactory('News Item', id='newsitem') self.portal.newsitem.title = 'My News Item' self.portal.newsitem.description = u'This is a news item' self.portal.newsitem.text = RichTextValue(u"Lorem ipsum", 'text/plain', 'text/html') image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.newsitem.image = NamedBlobImage(data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png') self.portal.newsitem.image_caption = u'This is an image caption.' self.portal.newsitem.creation_date = DateTime( '2016-01-21T02:14:48+00:00') self.portal.newsitem.modification_date = DateTime( '2016-01-21T02:24:11+00:00') IMutableUUID( self.portal.newsitem).set('80c2a074cb4240d08c9a129e3a834c74') import transaction transaction.commit() response = self.api_session.get(self.portal.newsitem.absolute_url()) save_response_for_documentation('newsitem.json', response) def test_documentation_event(self): self.portal.invokeFactory('Event', id='event') self.portal.event.title = 'Event' self.portal.event.description = u'This is an event' self.portal.event.start = datetime(2013, 1, 1, 10, 0) self.portal.event.end = datetime(2013, 1, 1, 12, 0) self.portal.event.creation_date = DateTime('2016-01-21T03:14:48+00:00') self.portal.event.modification_date = DateTime( '2016-01-21T03:24:11+00:00') IMutableUUID(self.portal.event).set('846d632bc0854c5aa6d3dcae171ed2db') import transaction transaction.commit() response = self.api_session.get(self.portal.event.absolute_url()) save_response_for_documentation('event.json', response) def test_documentation_link(self): self.portal.invokeFactory('Link', id='link') self.portal.link.title = 'My Link' self.portal.link.description = u'This is a link' self.portal.remoteUrl = 'http://plone.org' self.portal.link.creation_date = DateTime('2016-01-21T04:14:48+00:00') self.portal.link.modification_date = DateTime( '2016-01-21T04:24:11+00:00') IMutableUUID(self.portal.link).set('6ff48d27762143a0ae8d63cee73d9fc2') import transaction transaction.commit() response = self.api_session.get(self.portal.link.absolute_url()) save_response_for_documentation('link.json', response) def test_documentation_file(self): self.portal.invokeFactory('File', id='file') self.portal.file.title = 'My File' self.portal.file.description = u'This is a file' pdf_file = os.path.join(os.path.dirname(__file__), u'file.pdf') self.portal.file.file = NamedBlobFile(data=open(pdf_file, 'r').read(), contentType='application/pdf', filename=u'file.pdf') self.portal.file.creation_date = DateTime('2016-01-21T05:14:48+00:00') self.portal.file.modification_date = DateTime( '2016-01-21T05:24:11+00:00') IMutableUUID(self.portal.file).set('9b6a4eadb9074dde97d86171bb332ae9') import transaction transaction.commit() response = self.api_session.get(self.portal.file.absolute_url()) save_response_for_documentation('file.json', response) def test_documentation_image(self): self.portal.invokeFactory('Image', id='image') self.portal.image.title = 'My Image' self.portal.image.description = u'This is an image' image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.image.image = NamedBlobImage(data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png') self.portal.image.creation_date = DateTime('2016-01-21T06:14:48+00:00') self.portal.image.modification_date = DateTime( '2016-01-21T06:24:11+00:00') IMutableUUID(self.portal.image).set('2166e81a0c224fe3b62e197c7fdc9c3e') import transaction transaction.commit() response = self.api_session.get(self.portal.image.absolute_url()) save_response_for_documentation('image.json', response) def test_documentation_folder(self): self.portal.invokeFactory('Folder', id='folder') self.portal.folder.title = 'My Folder' self.portal.folder.description = u'This is a folder with two documents' self.portal.folder.invokeFactory('Document', id='doc1', title='A document within a folder') self.portal.folder.invokeFactory('Document', id='doc2', title='A document within a folder') self.portal.folder.creation_date = DateTime( '2016-01-21T07:14:48+00:00') self.portal.folder.modification_date = DateTime( '2016-01-21T07:24:11+00:00') IMutableUUID( self.portal.folder).set('fc7881c46d61452db4177bc059d9dcb5') import transaction transaction.commit() response = self.api_session.get(self.portal.folder.absolute_url()) save_response_for_documentation('folder.json', response) def test_documentation_collection(self): self.portal.invokeFactory('Collection', id='collection') self.portal.collection.title = 'My Collection' self.portal.collection.description = \ u'This is a collection with two documents' self.portal.collection.query = [{ 'i': 'portal_type', 'o': 'plone.app.querystring.operation.string.is', 'v': 'Document', }] self.portal.invokeFactory('Document', id='doc1', title='Document 1') self.portal.invokeFactory('Document', id='doc2', title='Document 2') self.portal.collection.creation_date = DateTime( '2016-01-21T08:14:48+00:00') self.portal.collection.modification_date = DateTime( '2016-01-21T08:24:11+00:00') IMutableUUID( self.portal.collection).set('d0c89bc77f874ce1aad5720921d875c0') import transaction transaction.commit() response = self.api_session.get(self.portal.collection.absolute_url()) save_response_for_documentation('collection.json', response) def test_documentation_siteroot(self): response = self.api_session.get(self.portal.absolute_url()) save_response_for_documentation('siteroot.json', response) def test_documentation_404_not_found(self): response = self.api_session.get('non-existing-resource') save_response_for_documentation('404_not_found.json', response) def test_documentation_search(self): query = {'sort_on': 'path'} response = self.api_session.get('/@search', params=query) save_response_for_documentation('search.json', response) def test_documentation_workflow(self): response = self.api_session.get('{}/@workflow'.format( self.document.absolute_url())) save_response_for_documentation('workflow_get.json', response) def test_documentation_workflow_transition(self): self.frozen_time.tick(timedelta(minutes=5)) response = self.api_session.post('{}/@workflow/publish'.format( self.document.absolute_url())) save_response_for_documentation('workflow_post.json', response) def test_documentation_registry_get(self): response = self.api_session.get( '/@registry/plone.app.querystring.field.path.title') save_response_for_documentation('registry_get.json', response) def test_documentation_registry_update(self): response = self.api_session.patch( '/@registry/', json={'plone.app.querystring.field.path.title': 'Value'}) save_response_for_documentation('registry_update.json', response) def test_documentation_types(self): response = self.api_session.get('/@types') save_response_for_documentation('types.json', response) def test_documentation_types_document(self): response = self.api_session.get('@types/Document') save_response_for_documentation('types_document.json', response) def test_documentation_login(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post('{}/@login'.format( self.portal.absolute_url()), json={ 'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD }) save_response_for_documentation('login.json', response) def test_documentation_login_renew(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post('{}/@login'.format( self.portal.absolute_url()), json={ 'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD }) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@login-renew'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_response_for_documentation('login_renew.json', response) def test_documentation_logout(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 self.portal.acl_users.jwt_auth.store_tokens = True import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post('{}/@login'.format( self.portal.absolute_url()), json={ 'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD }) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@logout'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_response_for_documentation('logout.json', response) def test_documentation_batching(self): folder = self.portal[self.portal.invokeFactory('Folder', id='folder', title='Folder')] for i in range(7): folder.invokeFactory('Document', id='doc-%s' % str(i + 1), title='Document %s' % str(i + 1)) transaction.commit() query = {'sort_on': 'path'} response = self.api_session.get('/folder/@search?b_size=5', params=query) save_response_for_documentation('batching.json', response) def test_documentation_users(self): test_user = api.user.get(username=TEST_USER_ID) properties = { "description": "This is a test user", "email": "*****@*****.**", "fullname": "Test User", "home_page": "http://www.example.com", "location": "Bonn", "username": "******" } test_user.setMemberProperties(mapping=properties) admin = api.user.get(username='******') properties = { "description": "This is an admin user", "email": "*****@*****.**", "fullname": "Administrator", "home_page": "http://www.example.com", "location": "Berlin", "username": "******" } admin.setMemberProperties(mapping=properties) transaction.commit() response = self.api_session.get('/@users') save_response_for_documentation('users.json', response) def test_documentation_users_get(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create(email='*****@*****.**', username='******', properties=properties) transaction.commit() response = self.api_session.get('@users/noam') save_response_for_documentation('users_get.json', response) def test_documentation_users_created(self): response = self.api_session.post( '/@users', json={ 'username': '******', 'email': '*****@*****.**', 'password': '******', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' }, ) save_response_for_documentation('users_created.json', response) def test_documentation_users_update(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create(email='*****@*****.**', username='******', properties=properties) transaction.commit() response = self.api_session.patch( '/@users/noam', json={ 'email': '*****@*****.**', }, ) save_response_for_documentation('users_update.json', response) def test_documentation_users_delete(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create(email='*****@*****.**', username='******', properties=properties) transaction.commit() response = self.api_session.delete('/@users/noam') save_response_for_documentation('users_delete.json', response) def test_documentation_breadcrumbs(self): response = self.api_session.get('{}/@components/breadcrumbs'.format( self.document.absolute_url())) save_response_for_documentation('breadcrumbs.json', response) def test_documentation_navigation(self): response = self.api_session.get('{}/@components/navigation'.format( self.document.absolute_url())) save_response_for_documentation('navigation.json', response)
class TestGroupsEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.portal = self.layer['portal'] self.request = self.layer['request'] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ['Manager']) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } self.gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() def tearDown(self): self.api_session.close() def test_list_groups(self): response = self.api_session.get('/@groups') self.assertEqual(200, response.status_code) self.assertEqual(5, len(response.json())) user_ids = [group['id'] for group in response.json()] self.assertIn('Administrators', user_ids) self.assertIn('Reviewers', user_ids) self.assertIn('AuthenticatedUsers', user_ids) self.assertIn('ploneteam', user_ids) ptgroup = [ x for x in response.json() if x.get('groupname') == 'ploneteam' ][0] self.assertEqual('ploneteam', ptgroup.get('id')) self.assertEqual(self.portal.absolute_url() + '/@groups/ploneteam', ptgroup.get('@id')) self.assertEqual('*****@*****.**', ptgroup.get('email')) self.assertEqual('Plone Team', ptgroup.get('title')) self.assertEqual('We are Plone', ptgroup.get('description')) # We don't want the group members listed in the overview as there # might be loads. self.assertTrue( not any(['users' in group for group in response.json()]), "Users key found in groups listing") def test_add_group(self): response = self.api_session.post( '/@groups', json={ 'groupname': 'fwt', 'email': '*****@*****.**', 'title': 'Framework Team', 'description': 'The Plone Framework Team', 'roles': ['Manager'], 'groups': ['Administrators'], 'users': [SITE_OWNER_NAME, TEST_USER_ID] }, ) transaction.commit() self.assertEqual(201, response.status_code) fwt = self.gtool.getGroupById('fwt') self.assertEqual("*****@*****.**", fwt.getProperty('email')) self.assertTrue( set([SITE_OWNER_NAME, TEST_USER_ID]).issubset(set(fwt.getGroupMemberIds())), "Userids not found in group") def test_add_group_groupname_is_required(self): response = self.api_session.post( '/@groups', json={"title": "Framework Team"}, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('"Property \'groupname\' is required' in response.text) def test_get_group(self): response = self.api_session.get('/@groups/ploneteam') self.assertEqual(response.status_code, 200) self.assertEqual('ploneteam', response.json().get('id')) self.assertEqual(self.portal.absolute_url() + '/@groups/ploneteam', response.json().get('@id')) self.assertEqual('*****@*****.**', response.json().get('email')) self.assertEqual('*****@*****.**', response.json().get('email')) self.assertEqual('Plone Team', response.json().get('title')) self.assertEqual('We are Plone', response.json().get('description')) self.assertIn('users', response.json()) def test_get_search_group_with_filter(self): response = self.api_session.get('/@groups', params={'query': 'plo'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('ploneteam', response.json()[0].get('id')) self.assertEqual(self.portal.absolute_url() + '/@groups/ploneteam', response.json()[0].get('@id')) self.assertEqual('*****@*****.**', response.json()[0].get('email')) response = self.api_session.get('/@groups', params={'query': 'Auth'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('AuthenticatedUsers', response.json()[0].get('id')) def test_get_non_existing_group(self): response = self.api_session.get('/@groups/non-existing-group') self.assertEqual(response.status_code, 404) def test_update_group(self): ploneteam = self.gtool.getGroupById('ploneteam') ploneteam.addMember(SITE_OWNER_NAME) transaction.commit() self.assertNotIn(TEST_USER_ID, ploneteam.getGroupMemberIds()) self.assertIn(SITE_OWNER_NAME, ploneteam.getGroupMemberIds()) payload = { 'groupname': 'ploneteam', 'email': '*****@*****.**', 'users': { TEST_USER_ID: True, SITE_OWNER_NAME: False, } } response = self.api_session.patch('/@groups/ploneteam', json=payload) transaction.commit() self.assertEqual(response.status_code, 204) ploneteam = self.gtool.getGroupById('ploneteam') self.assertEqual('ploneteam', ploneteam.id) self.assertEqual('Plone Team', ploneteam.getProperty('title')) self.assertEqual('*****@*****.**', ploneteam.getProperty('email')) self.assertIn(TEST_USER_ID, ploneteam.getGroupMemberIds()) self.assertNotIn(SITE_OWNER_NAME, ploneteam.getGroupMemberIds()) def test_delete_group(self): response = self.api_session.delete('/@groups/ploneteam') transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, self.gtool.getGroupById('ploneteam')) def test_delete_non_existing_group(self): response = self.api_session.delete('/@groups/non-existing-group') transaction.commit() self.assertEqual(response.status_code, 404)
class TestUsersEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.mailhost = getUtility(IMailHost) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.anon_api_session = RelativeSession(self.portal_url) self.anon_api_session.headers.update({"Accept": "application/json"}) properties = { "email": "*****@*****.**", "username": "******", "fullname": "Noam Avram Chomsky", "home_page": "web.mit.edu/chomsky", "description": "Professor of Linguistics", "location": "Cambridge, MA", } api.user.create( email="*****@*****.**", username="******", properties=properties, password=u"password", ) properties = { "email": "*****@*****.**", "username": "******", "fullname": "Other user", } api.user.create( email="*****@*****.**", username="******", properties=properties, password=u"otherpassword", ) transaction.commit() def tearDown(self): self.api_session.close() self.anon_api_session.close() def test_list_users(self): response = self.api_session.get("/@users") self.assertEqual(200, response.status_code) self.assertEqual(4, len(response.json())) user_ids = [user["id"] for user in response.json()] self.assertIn("admin", user_ids) self.assertIn("test_user_1_", user_ids) self.assertIn("noam", user_ids) noam = [x for x in response.json() if x.get("username") == "noam"][0] self.assertEqual("noam", noam.get("id")) self.assertEqual(self.portal.absolute_url() + "/@users/noam", noam.get("@id")) self.assertEqual("*****@*****.**", noam.get("email")) self.assertEqual("Noam Avram Chomsky", noam.get("fullname")) self.assertEqual("web.mit.edu/chomsky", noam.get("home_page")) # noqa self.assertEqual("Professor of Linguistics", noam.get("description")) # noqa self.assertEqual("Cambridge, MA", noam.get("location")) def test_list_users_without_being_manager(self): noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({"Accept": "application/json"}) noam_api_session.auth = ("noam", "password") response = noam_api_session.get("/@users") self.assertEqual(response.status_code, 401) noam_api_session.close() def test_list_users_as_anonymous(self): response = self.anon_api_session.get("/@users") self.assertEqual(response.status_code, 401) def test_add_user(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", "roles": ["Contributor"], }, ) transaction.commit() self.assertEqual(201, response.status_code) howard = api.user.get(userid="howard") self.assertEqual("*****@*****.**", howard.getProperty("email")) self.assertIn("Contributor", api.user.get_roles(username="******")) def test_add_user_username_is_required(self): response = self.api_session.post("/@users", json={"password": "******"}) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue("Property 'username' is required" in response.text) def test_add_user_password_is_required(self): response = self.api_session.post("/@users", json={"username": "******"}) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue( ("You have to either send a " "password or sendPasswordReset") in response.text ) def test_add_user_email_is_required_if_email_login_is_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( "/@users", json={"username": "******", "password": "******"} ) self.assertEqual(400, response.status_code) self.assertTrue("Property 'username' is not allowed" in response.text) def test_add_user_email_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue(api.user.get(userid="*****@*****.**")) def test_username_is_not_allowed_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue("Property 'username' is not allowed" in response.text) def test_add_user_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) user = api.user.get(userid="*****@*****.**") self.assertTrue(user) self.assertEqual("*****@*****.**", user.getUserName()) self.assertEqual("*****@*****.**", user.getProperty("email")) def test_add_user_with_sendPasswordRest_sends_email(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "sendPasswordReset": True, }, ) transaction.commit() self.assertEqual(201, response.status_code) msg = self.mailhost.messages[0] if isinstance(msg, bytes) and bytes is not str: # Python 3 with Products.MailHost 4.10+ msg = msg.decode("utf-8") self.assertTrue("To: [email protected]" in msg) def test_add_user_send_properties(self): response = self.api_session.post( "/@users", json={ "username": "******", "password": "******", "email": "*****@*****.**", "fullname": "Howard Zinn", }, ) transaction.commit() self.assertEqual(201, response.status_code) member = api.user.get(username="******") self.assertEqual(member.getProperty("fullname"), "Howard Zinn") def test_add_anon_user_sends_properties_are_saved(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "fullname": "Howard Zinn", }, ) transaction.commit() self.assertEqual(201, response.status_code) member = api.user.get(username="******") self.assertEqual(member.getProperty("fullname"), "Howard Zinn") def test_add_anon_no_roles(self): """Make sure anonymous users cannot set their own roles. Allowing so would make them Manager. """ security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "roles": ["Manager"], }, ) transaction.commit() self.assertEqual(400, response.status_code) errors = response.json()["error"]["errors"] fields = [x["field"] for x in errors] self.assertEqual(["roles"], fields) def test_add_user_with_uuid_as_userid_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()["id"] user = api.user.get(userid=user_id) self.assertTrue(user) self.assertEqual("*****@*****.**", user.getUserName()) self.assertEqual("*****@*****.**", user.getProperty("email")) def test_get_user(self): response = self.api_session.get("/@users/noam") self.assertEqual(response.status_code, 200) self.assertEqual("noam", response.json().get("id")) self.assertEqual( self.portal.absolute_url() + "/@users/noam", response.json().get("@id") ) self.assertEqual("*****@*****.**", response.json().get("email")) self.assertEqual("Noam Avram Chomsky", response.json().get("fullname")) self.assertEqual( "web.mit.edu/chomsky", response.json().get("home_page") ) # noqa self.assertEqual( "Professor of Linguistics", response.json().get("description") ) # noqa self.assertEqual("Cambridge, MA", response.json().get("location")) def test_get_user_as_anonymous(self): response = self.anon_api_session.get("/@users/noam") self.assertEqual(response.status_code, 401) def test_get_other_user_info_when_logged_in(self): noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({"Accept": "application/json"}) noam_api_session.auth = ("noam", "password") response = noam_api_session.get("/@users/otheruser") self.assertEqual(response.status_code, 401) noam_api_session.close() def test_get_search_user_with_filter(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() response = self.api_session.get("/@users", params={"query": "noa"}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual("noam", response.json()[0].get("id")) self.assertEqual( self.portal.absolute_url() + "/@users/noam", response.json()[0].get("@id") ) self.assertEqual("*****@*****.**", response.json()[0].get("email")) self.assertEqual( "Noam Avram Chomsky", response.json()[0].get("fullname") ) # noqa response = self.api_session.get("/@users", params={"query": "howa"}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual("howard", response.json()[0].get("id")) def test_get_search_user_with_filter_as_anonymous(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() response = self.anon_api_session.get("/@users", params={"query": "howa"}) self.assertEqual(response.status_code, 401) def test_get_search_user_with_filter_as_unauthorized_user(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() noam_api_session = RelativeSession(self.portal_url) noam_api_session.headers.update({"Accept": "application/json"}) noam_api_session.auth = ("noam", "password") response = noam_api_session.get("/@users", params={"query": "howa"}) self.assertEqual(response.status_code, 401) noam_api_session.close() def test_get_non_existing_user(self): response = self.api_session.get("/@users/non-existing-user") self.assertEqual(response.status_code, 404) def test_update_user(self): payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", } response = self.api_session.patch("/@users/noam", json=payload) transaction.commit() self.assertEqual(response.status_code, 204) noam = api.user.get(userid="noam") self.assertEqual("noam", noam.getUserId()) # user id never changes self.assertEqual("avram", noam.getUserName()) self.assertEqual("Noam A. Chomsky", noam.getProperty("fullname")) self.assertEqual("*****@*****.**", noam.getProperty("email")) def test_user_can_update_himself(self): payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() noam = api.user.get(userid="noam") self.assertEqual("noam", noam.getUserId()) # user id never changes self.assertEqual("Noam A. Chomsky", noam.getProperty("fullname")) self.assertEqual("*****@*****.**", noam.getProperty("email")) def test_user_can_update_himself_remove_values(self): payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", "home_page": None, } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() noam = api.user.get(userid="noam") self.assertEqual(None, noam.getProperty("home_page")) def test_update_roles(self): self.assertNotIn("Contributor", api.user.get_roles(username="******")) self.api_session.patch("/@users/noam", json={"roles": {"Contributor": True}}) transaction.commit() self.assertIn("Contributor", api.user.get_roles(username="******")) self.api_session.patch("/@users/noam", json={"roles": {"Contributor": False}}) transaction.commit() self.assertNotIn("Contributor", api.user.get_roles(username="******")) def test_update_user_password(self): old_password_hashes = dict(self.portal.acl_users.source_users._user_passwords) payload = {"password": "******"} response = self.api_session.patch("/@users/noam", json=payload) transaction.commit() self.assertEqual(response.status_code, 204) new_password_hashes = dict(self.portal.acl_users.source_users._user_passwords) self.assertNotEqual(old_password_hashes["noam"], new_password_hashes["noam"]) def test_update_portrait(self): payload = { "portrait": { "filename": "image.gif", "encoding": "base64", "data": u"R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=", "content-type": "image/gif", } } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue( user.get("portrait").endswith("plone/portal_memberdata/portraits/noam") ) def test_update_portrait_with_default_plone_scaling(self): payload = { "portrait": { "filename": "image.gif", "encoding": "base64", "data": u"R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=", "content-type": "image/gif", "scale": True, } } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue( user.get("portrait").endswith("plone/portal_memberdata/portraits/noam") ) def test_update_portrait_by_manager(self): payload = { "portrait": { "filename": "image.gif", "encoding": "base64", "data": u"R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=", "content-type": "image/gif", } } response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue( user.get("portrait").endswith("plone/portal_memberdata/portraits/noam") ) def test_delete_portrait(self): payload = { "portrait": None, } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue(user.get("portrait") is None) def test_delete_portrait_by_manager(self): payload = { "portrait": None, } response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue(user.get("portrait") is None) def test_update_user_with_portrait_set_without_updating_portrait(self): payload = { "portrait": { "filename": "image.gif", "encoding": "base64", "data": u"R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=", "content-type": "image/gif", } } self.api_session.auth = ("noam", "password") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", "portrait": "http://*****:*****@users/noam", json=payload) self.assertEqual(response.status_code, 204) transaction.commit() user = self.api_session.get("/@users/noam").json() self.assertTrue( user.get("portrait").endswith("plone/portal_memberdata/portraits/noam") ) def test_anonymous_user_can_not_update_existing_user(self): payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", } self.api_session.auth = ("noam", "password") response = self.anon_api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 401) def test_user_can_not_update_another_user(self): payload = { "fullname": "Noam A. Chomsky", "username": "******", "email": "*****@*****.**", } self.api_session.auth = ("otheruser", "otherpassword") response = self.api_session.patch("/@users/noam", json=payload) self.assertEqual(response.status_code, 403) def test_user_requests_password_sends_password_via_mail(self): self.api_session.auth = ("noam", "password") payload = {} response = self.api_session.post("/@users/noam/reset-password", json=payload) transaction.commit() self.assertEqual(response.status_code, 200) # FIXME: Test that mail is sent def test_user_can_set_her_own_password(self): self.api_session.auth = ("noam", "password") self.portal.manage_permission( SetOwnPassword, roles=["Authenticated", "Manager"], acquire=False ) transaction.commit() payload = {"old_password": "******", "new_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) transaction.commit() self.assertEqual(response.status_code, 200) authed = self.portal.acl_users.authenticate("noam", "new_password", {}) self.assertTrue(authed) def test_normal_authenticated_user_cannot_set_other_users_password(self): self.api_session.auth = ("noam", "password") self.portal.manage_permission( SetOwnPassword, roles=["Authenticated", "Manager"], acquire=False ) transaction.commit() payload = {"old_password": "******", "new_password": "******"} response = self.api_session.post( "/@users/otheruser/reset-password", json=payload ) transaction.commit() self.assertEqual(response.status_code, 403) self.assertEqual(response.json()["error"]["type"], "Wrong user") def test_user_set_own_password_requires_set_own_password_permission(self): self.api_session.auth = ("noam", "password") self.portal.manage_permission(SetOwnPassword, roles=["Manager"], acquire=False) transaction.commit() payload = {"old_password": "******", "new_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) transaction.commit() self.assertEqual(response.status_code, 403) def test_user_set_own_password_requires_old_and_new_password(self): self.api_session.auth = ("noam", "password") payload = {"old_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()["error"]["type"], "Invalid parameters") payload = {"new_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()["error"]["type"], "Invalid parameters") def test_user_set_own_password_checks_old_password(self): self.api_session.auth = ("noam", "password") payload = {"new_password": "******", "old_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) self.assertEqual(response.status_code, 403) self.assertEqual(response.json()["error"]["type"], "Wrong password") def test_user_set_reset_token_requires_new_password(self): self.api_session.auth = ("noam", "password") payload = {"reset_token": "abc"} response = self.api_session.post("/@users/noam/reset-password", json=payload) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()["error"]["type"], "Invalid parameters") def test_reset_with_token(self): reset_tool = getToolByName(self.portal, "portal_password_reset") reset_info = reset_tool.requestReset("noam") token = reset_info["randomstring"] transaction.commit() payload = {"reset_token": token, "new_password": "******"} response = self.api_session.post("/@users/noam/reset-password", json=payload) transaction.commit() self.assertEqual(response.status_code, 200) authed = self.portal.acl_users.authenticate("noam", "new_password", {}) self.assertTrue(authed) def test_reset_with_uuid_as_userid_and_login_email_using_id(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()["id"] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, "portal_password_reset") reset_info = reset_tool.requestReset(user.id) token = reset_info["randomstring"] transaction.commit() payload = {"reset_token": token, "new_password": "******"} response = self.api_session.post( "/@users/{}/reset-password".format(user.id), json=payload ) self.assertEqual(response.status_code, 200) def test_reset_with_uuid_as_userid_and_login_email_using_mail(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True security_settings.use_uuid_as_userid = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()["id"] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, "portal_password_reset") reset_info = reset_tool.requestReset(user.id) token = reset_info["randomstring"] transaction.commit() payload = {"reset_token": token, "new_password": "******"} response = self.api_session.post( "/@users/{}/reset-password".format(user.getUserName()), json=payload ) self.assertEqual(response.status_code, 200) def test_reset_and_login_email_using_mail(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( "/@users", json={"email": "*****@*****.**", "password": "******"} ) transaction.commit() self.assertEqual(201, response.status_code) user_id = response.json()["id"] user = api.user.get(userid=user_id) self.assertTrue(user) reset_tool = getToolByName(self.portal, "portal_password_reset") reset_info = reset_tool.requestReset(user.id) token = reset_info["randomstring"] transaction.commit() payload = {"reset_token": token, "new_password": "******"} response = self.api_session.post( "/@users/{}/reset-password".format(user.getUserName()), json=payload ) self.assertEqual(response.status_code, 200) def test_delete_user(self): response = self.api_session.delete("/@users/noam") transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, api.user.get(userid="noam")) def test_delete_non_existing_user(self): response = self.api_session.delete("/@users/non-existing-user") transaction.commit() self.assertEqual(response.status_code, 404) def test_anonymous_requires_enable_self_reg(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = False transaction.commit() response = self.anon_api_session.post( "/@users", json={"password": "******"} ) transaction.commit() self.assertEqual(403, response.status_code) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( "/@users", json={"username": "******", "email": "*****@*****.**"}, ) transaction.commit() self.assertEqual(201, response.status_code) def test_anonymous_without_enable_user_pwd_choice_sends_mail(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( "/@users", json={"username": "******", "email": "*****@*****.**"}, ) transaction.commit() self.assertEqual(201, response.status_code) msg = self.mailhost.messages[0] if isinstance(msg, bytes) and bytes is not str: # Python 3 with Products.MailHost 4.10+ msg = msg.decode("utf-8") self.assertTrue("To: [email protected]" in msg) def test_anonymous_can_set_password_with_enable_user_pwd_choice(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue("Property 'password' is not allowed" in response.text) security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() self.assertEqual(201, response.status_code) def test_anonymous_with_enable_user_pwd_choice_doent_send_email(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() self.assertEqual(self.mailhost.messages, []) self.assertEqual(201, response.status_code) def test_anonymous_with_enable_user_sets_only_member_role(self): security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.enable_self_reg = True security_settings.enable_user_pwd_choice = True transaction.commit() response = self.anon_api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) response = response.json() self.assertIn("Member", response["roles"]) self.assertEqual(1, len(response["roles"])) def test_add_user_no_roles_sets_member_as_sensible_default(self): response = self.api_session.post( "/@users", json={ "username": "******", "email": "*****@*****.**", "password": "******", }, ) transaction.commit() self.assertEqual(201, response.status_code) response = response.json() self.assertIn("Member", response["roles"]) self.assertEqual(1, len(response["roles"]))
class TestCommentsEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.request = self.layer["request"] self.portal_url = self.portal.absolute_url() # Allow discussion registry = getUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) settings.globally_enabled = True settings.edit_comment_enabled = True settings.delete_own_comment_enabled = True # doc with comments self.doc = api.content.create( container=self.portal, type="Document", id="doc_with_comments", title="Document with comments", allow_discussion=True, ) api.content.transition(self.doc, "publish") api.user.create(username="******", password="******", email="*****@*****.**") # Admin session self.api_session = RelativeSession(self.portal_url, test=self) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) # User session self.user_session = RelativeSession(self.portal_url, test=self) self.user_session.headers.update({"Accept": "application/json"}) self.user_session.auth = ("jos", "jos") transaction.commit() def tearDown(self): self.api_session.close() self.user_session.close() def test_list_datastructure(self): url = f"{self.doc.absolute_url()}/@comments" response = self.api_session.get(url) self.assertEqual(200, response.status_code) data = response.json() self.assertEqual({"items_total", "items", "@id"}, set(data)) def test_list_batching(self): url = f"{self.doc.absolute_url()}/@comments" self.api_session.post(url, json={"text": "comment 1"}) self.api_session.post(url, json={"text": "comment 2"}) response = self.api_session.get(url, params={"b_size": 1}) self.assertEqual(200, response.status_code) data = response.json() self.assertIn("batching", data) def test_add_comment_to_root(self): url = f"{self.doc.absolute_url()}/@comments" response = self.api_session.get(url) self.assertEqual(0, response.json()["items_total"]) response = self.api_session.post(url, json={"text": "comment 1"}) self.assertEqual(204, response.status_code) self.assertIn("location", response.headers) response = self.api_session.get(url) data = response.json() self.assertEqual(1, data["items_total"]) self.assertIsNone(data["items"][0]["in_reply_to"]) self.assertIsNone(data["items"][0]["@parent"]) def test_add_comment_to_comment(self): url = f"{self.doc.absolute_url()}/@comments" response = self.api_session.post(url, json={"text": "comment 1"}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) data = response.json() parent_id = data["items"][0]["comment_id"] SUBTEXT = "sub comment" payload = {"text": SUBTEXT, "in_reply_to": parent_id} response = self.api_session.post(url, json=payload) self.assertEqual(204, response.status_code) response = self.api_session.get(url) data = response.json() sub = [x for x in data["items"] if x["text"]["data"] == SUBTEXT][0] self.assertEqual(parent_id, sub["in_reply_to"]) def test_update(self): url = f"{self.doc.absolute_url()}/@comments" OLD_TEXT = "comment 1" NEW_TEXT = "new text" self.api_session.post(url, json={"text": OLD_TEXT}) response = self.api_session.get(url) data = response.json() item_texts = [x["text"]["data"] for x in data["items"]] self.assertNotIn(NEW_TEXT, item_texts) self.assertIn(OLD_TEXT, item_texts) comment = data["items"][0] payload = {"text": NEW_TEXT} response = self.api_session.patch(comment["@id"], json=payload) self.assertEqual(204, response.status_code) self.assertIn("location", response.headers) response = self.api_session.get(url) data = response.json() item_texts = [x["text"]["data"] for x in data["items"]] self.assertIn(NEW_TEXT, item_texts) self.assertNotIn(OLD_TEXT, item_texts) def test_permissions_delete_comment(self): url = f"{self.doc.absolute_url()}/@comments" response = self.api_session.post(url, json={"text": "comment"}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) comment_url = response.json()["items"][0]["@id"] self.assertFalse(comment_url.endswith("@comments")) self.assertTrue(response.json()["items"][0]["is_deletable"]) # Other user may not delete this response = self.user_session.delete(comment_url) self.assertEqual(401, response.status_code) response = self.user_session.get(url) self.assertFalse(response.json()["items"][0]["is_deletable"]) # The owner may response = self.api_session.delete(comment_url) self.assertEqual(204, response.status_code) def test_permissions_update_comment(self): url = f"{self.doc.absolute_url()}/@comments" response = self.api_session.post(url, json={"text": "comment"}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) comment_url = response.json()["items"][0]["@id"] self.assertFalse(comment_url.endswith("@comments")) self.assertTrue(response.json()["items"][0]["is_editable"]) # Other user may not update this response = self.user_session.patch(comment_url, json={"text": "new"}) self.assertEqual(401, response.status_code) response = self.user_session.get(url) self.assertFalse(response.json()["items"][0]["is_editable"]) # The owner may response = self.api_session.patch(comment_url, json={"text": "new"}) self.assertEqual(204, response.status_code)
class TestUsersEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ['Manager']) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() def test_list_users(self): response = self.api_session.get('/@users') self.assertEqual(200, response.status_code) self.assertEqual(3, len(response.json())) user_ids = [user['id'] for user in response.json()] self.assertIn('admin', user_ids) self.assertIn('test_user_1_', user_ids) self.assertIn('noam', user_ids) noam = [x for x in response.json() if x.get('username') == 'noam'][0] self.assertEqual('noam', noam.get('id')) self.assertEqual( self.portal.absolute_url() + '/@users/noam', noam.get('@id') ) self.assertEqual('*****@*****.**', noam.get('email')) self.assertEqual('Noam Avram Chomsky', noam.get('fullname')) self.assertEqual('web.mit.edu/chomsky', noam.get('home_page')) # noqa self.assertEqual('Professor of Linguistics', noam.get('description')) # noqa self.assertEqual('Cambridge, MA', noam.get('location')) def test_add_user(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) howard = api.user.get(userid='howard') self.assertEqual( "*****@*****.**", howard.getProperty('email') ) def test_add_user_username_is_required(self): response = self.api_session.post( '/@users', json={ "password": "******" }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('"Property \'username\' is required' in response.text) def test_add_user_password_is_required(self): response = self.api_session.post( '/@users', json={ "username": "******" }, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('"Property \'password\' is required' in response.text) def test_add_user_email_is_required_if_email_login_is_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "password": "******" }, ) self.assertEqual(400, response.status_code) self.assertTrue('"Property \'email\' is required' in response.text) def test_add_user_email_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue(api.user.get(userid='*****@*****.**')) def test_add_user_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user = api.user.get(userid='*****@*****.**') self.assertTrue(user) self.assertEqual('*****@*****.**', user.getUserName()) self.assertEqual('*****@*****.**', user.getProperty('email')) def test_get_user(self): response = self.api_session.get('/@users/noam') self.assertEqual(response.status_code, 200) self.assertEqual('noam', response.json().get('id')) self.assertEqual( self.portal.absolute_url() + '/@users/noam', response.json().get('@id') ) self.assertEqual( '*****@*****.**', response.json().get('email') ) self.assertEqual('Noam Avram Chomsky', response.json().get('fullname')) self.assertEqual('web.mit.edu/chomsky', response.json().get('home_page')) # noqa self.assertEqual('Professor of Linguistics', response.json().get('description')) # noqa self.assertEqual('Cambridge, MA', response.json().get('location')) def test_get_search_user_with_filter(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() response = self.api_session.get('/@users', params={'query': 'noa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('noam', response.json()[0].get('id')) self.assertEqual( self.portal.absolute_url() + '/@users/noam', response.json()[0].get('@id') ) self.assertEqual( '*****@*****.**', response.json()[0].get('email') ) self.assertEqual('Noam Avram Chomsky', response.json()[0].get('fullname')) # noqa response = self.api_session.get('/@users', params={'query': 'howa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('howard', response.json()[0].get('id')) def test_get_non_existing_user(self): response = self.api_session.get('/@users/non-existing-user') self.assertEqual(response.status_code, 404) def test_update_user(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } response = self.api_session.patch('/@users/noam', json=payload) transaction.commit() self.assertEqual(response.status_code, 204) noam = api.user.get(userid='noam') self.assertEqual('noam', noam.getUserId()) # user id never changes self.assertEqual('avram', noam.getUserName()) self.assertEqual('Noam A. Chomsky', noam.getProperty('fullname')) self.assertEqual( '*****@*****.**', noam.getProperty('email') ) def test_update_user_password(self): old_password_hashes = dict( self.portal.acl_users.source_users._user_passwords ) payload = {'password': '******'} self.api_session.patch('/@users/noam', json=payload) transaction.commit() new_password_hashes = dict( self.portal.acl_users.source_users._user_passwords ) self.assertNotEqual( old_password_hashes['noam'], new_password_hashes['noam'] ) def test_delete_user(self): response = self.api_session.delete('/@users/noam') transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, api.user.get(userid='noam')) def test_delete_non_existing_user(self): response = self.api_session.delete('/@users/non-existing-user') transaction.commit() self.assertEqual(response.status_code, 404)
class TestUsersEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ['Manager']) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create(email='*****@*****.**', username='******', properties=properties) transaction.commit() def test_list_users(self): response = self.api_session.get('/@users') self.assertEqual(200, response.status_code) self.assertEqual(3, len(response.json())) user_ids = [user['id'] for user in response.json()] self.assertIn('admin', user_ids) self.assertIn('test_user_1_', user_ids) self.assertIn('noam', user_ids) noam = [x for x in response.json() if x.get('username') == 'noam'][0] self.assertEqual('noam', noam.get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', noam.get('@id')) self.assertEqual('*****@*****.**', noam.get('email')) self.assertEqual('Noam Avram Chomsky', noam.get('fullname')) self.assertEqual('web.mit.edu/chomsky', noam.get('home_page')) # noqa self.assertEqual('Professor of Linguistics', noam.get('description')) # noqa self.assertEqual('Cambridge, MA', noam.get('location')) def test_add_user(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) howard = api.user.get(userid='howard') self.assertEqual("*****@*****.**", howard.getProperty('email')) def test_add_user_username_is_required(self): response = self.api_session.post( '/@users', json={"password": "******"}, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('"Property \'username\' is required' in response.text) def test_add_user_password_is_required(self): response = self.api_session.post( '/@users', json={"username": "******"}, ) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue('"Property \'password\' is required' in response.text) def test_add_user_email_is_required_if_email_login_is_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "password": "******" }, ) self.assertEqual(400, response.status_code) self.assertTrue('"Property \'email\' is required' in response.text) def test_add_user_email_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) self.assertTrue(api.user.get(userid='*****@*****.**')) def test_add_user_with_email_login_enabled(self): # enable use_email_as_login security_settings = getAdapter(self.portal, ISecuritySchema) security_settings.use_email_as_login = True transaction.commit() response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() self.assertEqual(201, response.status_code) user = api.user.get(userid='*****@*****.**') self.assertTrue(user) self.assertEqual('*****@*****.**', user.getUserName()) self.assertEqual('*****@*****.**', user.getProperty('email')) def test_get_user(self): response = self.api_session.get('/@users/noam') self.assertEqual(response.status_code, 200) self.assertEqual('noam', response.json().get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', response.json().get('@id')) self.assertEqual('*****@*****.**', response.json().get('email')) self.assertEqual('Noam Avram Chomsky', response.json().get('fullname')) self.assertEqual('web.mit.edu/chomsky', response.json().get('home_page')) # noqa self.assertEqual('Professor of Linguistics', response.json().get('description')) # noqa self.assertEqual('Cambridge, MA', response.json().get('location')) def test_get_search_user_with_filter(self): response = self.api_session.post( '/@users', json={ "username": "******", "email": "*****@*****.**", "password": "******" }, ) transaction.commit() response = self.api_session.get('/@users', params={'query': 'noa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('noam', response.json()[0].get('id')) self.assertEqual(self.portal.absolute_url() + '/@users/noam', response.json()[0].get('@id')) self.assertEqual('*****@*****.**', response.json()[0].get('email')) self.assertEqual('Noam Avram Chomsky', response.json()[0].get('fullname')) # noqa response = self.api_session.get('/@users', params={'query': 'howa'}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual('howard', response.json()[0].get('id')) def test_get_non_existing_user(self): response = self.api_session.get('/@users/non-existing-user') self.assertEqual(response.status_code, 404) def test_update_user(self): payload = { 'fullname': 'Noam A. Chomsky', 'username': '******', 'email': '*****@*****.**' } response = self.api_session.patch('/@users/noam', json=payload) transaction.commit() self.assertEqual(response.status_code, 204) noam = api.user.get(userid='noam') self.assertEqual('noam', noam.getUserId()) # user id never changes self.assertEqual('avram', noam.getUserName()) self.assertEqual('Noam A. Chomsky', noam.getProperty('fullname')) self.assertEqual('*****@*****.**', noam.getProperty('email')) def test_update_user_password(self): old_password_hashes = dict( self.portal.acl_users.source_users._user_passwords) payload = {'password': '******'} self.api_session.patch('/@users/noam', json=payload) transaction.commit() new_password_hashes = dict( self.portal.acl_users.source_users._user_passwords) self.assertNotEqual(old_password_hashes['noam'], new_password_hashes['noam']) def test_delete_user(self): response = self.api_session.delete('/@users/noam') transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, api.user.get(userid='noam')) def test_delete_non_existing_user(self): response = self.api_session.delete('/@users/non-existing-user') transaction.commit() self.assertEqual(response.status_code, 404)
class TestCommentsEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.portal = self.layer['portal'] self.request = self.layer['request'] self.portal_url = self.portal.absolute_url() # Allow discussion registry = getUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) settings.globally_enabled = True settings.edit_comment_enabled = True settings.delete_own_comment_enabled = True # doc with comments self.doc = api.content.create(container=self.portal, type='Document', id='doc_with_comments', title='Document with comments', allow_discussion=True) api.content.transition(self.doc, 'publish') api.user.create(username='******', password='******', email='*****@*****.**') # Admin session self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) # User session self.user_session = RelativeSession(self.portal_url) self.user_session.headers.update({'Accept': 'application/json'}) self.user_session.auth = ('jos', 'jos') transaction.commit() def test_list_datastructure(self): url = '{}/@comments'.format(self.doc.absolute_url()) response = self.api_session.get(url) self.assertEqual(200, response.status_code) data = response.json() self.assertEqual(set(['items_total', 'items', '@id']), set(data)) def test_list_batching(self): url = '{}/@comments'.format(self.doc.absolute_url()) self.api_session.post(url, json={'text': 'comment 1'}) self.api_session.post(url, json={'text': 'comment 2'}) response = self.api_session.get(url, params={'b_size': 1}) self.assertEqual(200, response.status_code) data = response.json() self.assertIn('batching', data) def test_add_comment_to_root(self): url = '{}/@comments'.format(self.doc.absolute_url()) response = self.api_session.get(url) self.assertEqual(0, response.json()['items_total']) response = self.api_session.post(url, json={'text': 'comment 1'}) self.assertEqual(204, response.status_code) self.assertIn('location', response.headers) response = self.api_session.get(url) data = response.json() self.assertEqual(1, data['items_total']) self.assertIsNone(data['items'][0]['in_reply_to']) self.assertIsNone(data['items'][0]['@parent']) def test_add_comment_to_comment(self): url = '{}/@comments'.format(self.doc.absolute_url()) response = self.api_session.post(url, json={'text': 'comment 1'}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) data = response.json() parent_id = data['items'][0]['comment_id'] SUBTEXT = 'sub comment' payload = {'text': SUBTEXT, 'in_reply_to': parent_id} response = self.api_session.post(url, json=payload) self.assertEqual(204, response.status_code) response = self.api_session.get(url) data = response.json() sub = [x for x in data['items'] if x['text']['data'] == SUBTEXT][0] self.assertEqual(parent_id, sub['in_reply_to']) def test_update(self): url = '{}/@comments'.format(self.doc.absolute_url()) OLD_TEXT = 'comment 1' NEW_TEXT = 'new text' self.api_session.post(url, json={'text': OLD_TEXT}) response = self.api_session.get(url) data = response.json() item_texts = [x['text']['data'] for x in data['items']] self.assertNotIn(NEW_TEXT, item_texts) self.assertIn(OLD_TEXT, item_texts) comment = data['items'][0] payload = {'text': NEW_TEXT} response = self.api_session.patch(comment['@id'], json=payload) self.assertEqual(204, response.status_code) self.assertIn('location', response.headers) response = self.api_session.get(url) data = response.json() item_texts = [x['text']['data'] for x in data['items']] self.assertIn(NEW_TEXT, item_texts) self.assertNotIn(OLD_TEXT, item_texts) def test_permissions_delete_comment(self): url = '{}/@comments'.format(self.doc.absolute_url()) response = self.api_session.post(url, json={'text': 'comment'}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) comment_url = response.json()['items'][0]['@id'] self.assertFalse(comment_url.endswith('@comments')) self.assertTrue(response.json()['items'][0]['is_deletable']) # Other user may not delete this response = self.user_session.delete(comment_url) self.assertEqual(401, response.status_code) response = self.user_session.get(url) self.assertFalse(response.json()['items'][0]['is_deletable']) # The owner may response = self.api_session.delete(comment_url) self.assertEqual(204, response.status_code) def test_permissions_update_comment(self): url = '{}/@comments'.format(self.doc.absolute_url()) response = self.api_session.post(url, json={'text': 'comment'}) self.assertEqual(204, response.status_code) response = self.api_session.get(url) comment_url = response.json()['items'][0]['@id'] self.assertFalse(comment_url.endswith('@comments')) self.assertTrue(response.json()['items'][0]['is_editable']) # Other user may not update this response = self.user_session.patch(comment_url, json={'text': 'new'}) self.assertEqual(401, response.status_code) response = self.user_session.get(url) self.assertFalse(response.json()['items'][0]['is_editable']) # The owner may response = self.api_session.patch(comment_url, json={'text': 'new'}) self.assertEqual(204, response.status_code)
class TestServicesTypes(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.api_session.post( "/@types/Document", json={ "factory": "fieldset", "title": "Contact Info", "description": "Contact information", }, ) self.api_session.post( "/@types/Document", json={ "factory": "fieldset", "title": "Location", "description": "Location", }, ) self.api_session.post( "/@types/Document", json={ "factory": "Email", "title": "Author email", "description": "Email of the author", }, ) self.api_session.post( "/@types/Document", json={ "factory": "URL", "title": "Author url", "description": "Website of the author", }, ) def tearDown(self): # Remove all custom changed on Document self.api_session.put("/@types/Document", json={}) self.api_session.close() def test_get_types(self): response = self.api_session.get("{}/@types".format( self.portal.absolute_url())) # noqa self.assertEqual(response.status_code, 200) self.assertEqual( response.headers.get("Content-Type"), "application/json", "Sending a GET request to @types endpoint should respond with " + 'Content-Type: "application/json", not ' + '"{}"'.format(response.headers.get("Content-Type")), ) for item in response.json(): self.assertEqual(sorted(item), sorted(["@id", "title", "addable"])) def test_get_types_document(self): response = self.api_session.get("{}/@types/Document".format( self.portal.absolute_url())) self.assertEqual(response.status_code, 200) self.assertEqual( response.headers.get("Content-Type"), "application/json+schema", "Sending a GET request to @types endpoint should respond with " + 'Content-Type: "application/json+schema", not ' + '"{}"'.format(response.headers.get("Content-Type")), ) def test_get_types_document_edit(self): response = self.api_session.get("/@types/Document") self.assertEqual(response.status_code, 200) # Fields are present self.assertIn("author_email", response.json().get("properties")) self.assertIn("author_url", response.json().get("properties")) # All fieldsets are present even empty ones self.assertIn("location", [f["id"] for f in response.json().get("fieldsets")]) # noqa self.assertIn("contact_info", [f["id"] for f in response.json().get("fieldsets")]) # noqa def test_types_document_get_fieldset(self): response = self.api_session.get("/@types/Document/contact_info") self.assertEqual(response.status_code, 200) self.assertEqual("Contact Info", response.json().get("title")) self.assertEqual("Contact information", response.json().get("description")) # noqa self.assertEqual("contact_info", response.json().get("id")) self.assertEqual([], response.json().get("fields")) def test_types_document_get_field(self): response = self.api_session.get("/@types/Document/author_email") self.assertEqual(response.status_code, 200) self.assertEqual("Author email", response.json().get("title")) # noqa self.assertEqual("Email of the author", response.json().get("description")) # noqa self.assertTrue(response.json().get("behavior").startswith( "plone.dexterity.schema.generated.plone_")) # noqa self.assertEqual("string", response.json().get("type")) self.assertEqual("email", response.json().get("widget")) def test_types_document_post_fieldset(self): response = self.api_session.post( "/@types/Document", json={ "factory": "fieldset", "title": "Foo bar", "description": "Foo bar tab", }, ) self.assertEqual(response.status_code, 201) self.assertEqual("Foo bar", response.json().get("title")) self.assertEqual("Foo bar tab", response.json().get("description")) # noqa self.assertEqual("foo_bar", response.json().get("id")) self.assertEqual([], response.json().get("fields")) def test_types_document_post_field(self): response = self.api_session.post( "/@types/Document", json={ "factory": "Email", "title": "Email", "description": "Foo bar email", "required": True, }, ) self.assertEqual(response.status_code, 201) self.assertEqual("Email", response.json().get("title")) self.assertEqual("Foo bar email", response.json().get("description")) self.assertTrue(response.json().get("behavior").startswith( "plone.dexterity.schema.generated.plone_")) # noqa self.assertEqual("string", response.json().get("type")) self.assertEqual("email", response.json().get("widget")) def test_types_document_patch_properties(self): response = self.api_session.patch( "/@types/Document", json={ "properties": { "author_email": { "default": "*****@*****.**", "minLength": 5, "maxLength": 100, } } }, ) # PATCH returns no content self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document/author_email") self.assertEqual(200, response.status_code) self.assertEqual("*****@*****.**", response.json().get("default")) self.assertEqual(5, response.json().get("minLength")) self.assertEqual(100, response.json().get("maxLength")) def test_types_document_patch_fieldsets(self): response = self.api_session.patch( "/@types/Document", json={ "fieldsets": [{ "id": "contact_info", "title": "Contact information", "fields": ["author_email"], }] }, ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document/contact_info") self.assertEqual(200, response.status_code) self.assertEqual("Contact information", response.json().get("title")) self.assertEqual(["author_email"], response.json().get("fields")) def test_types_document_patch_one_fieldset(self): response = self.api_session.patch( "/@types/Document/contact_info", json={ "title": "Contact the author", "description": "Reach the author", "fields": [ "author_url", "author_email", ], }, ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document/contact_info") self.assertEqual(200, response.status_code) self.assertEqual("Contact the author", response.json().get("title")) self.assertEqual("Reach the author", response.json().get("description")) # noqa self.assertEqual(["author_url", "author_email"], response.json().get("fields")) # noqa def test_types_document_patch_one_field(self): response = self.api_session.patch( "/@types/Document/author_email", json={ "title": "Author e-mail", "description": "The e-mail address of the author", "minLength": 10, "maxLength": 200, "required": False, }, ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document/author_email") self.assertEqual(200, response.status_code) self.assertEqual("Author e-mail", response.json().get("title")) self.assertEqual("The e-mail address of the author", response.json().get("description")) # noqa self.assertEqual(10, response.json().get("minLength")) self.assertEqual(200, response.json().get("maxLength")) def test_types_document_patch_create_missing(self): response = self.api_session.patch( "/@types/Document", json={ "fieldsets": [{ "title": "Layout", "fields": ["blocks", "blocks_layout"] }], "properties": { "blocks": { "title": "Blocks", "type": "dict", "widget": "json", "factory": "JSONField", "default": { "230bdd04-6a0d-4cd2-ab60-4c09b315cc2c": { "@type": "title" }, "338013ce-acca-454f-a6f4-14113c187dca": { "@type": "text", "text": { "blocks": [{ "data": {}, "depth": 0, "entityRanges": [], "inlineStyleRanges": [], "key": "99pvk", "text": "Book summary", "type": "unstyled", }], "entityMap": {}, }, }, "5060e030-727b-47bc-8023-b80b7cccd96f": { "@type": "image" }, "e3d8f8e4-8fee-47e7-9451-28724bf74a90": { "@type": "text" }, }, }, "blocks_layout": { "title": "Blocks Layout", "type": "dict", "widget": "json", "factory": "JSONField", "default": { "items": [ "230bdd04-6a0d-4cd2-ab60-4c09b315cc2c", "338013ce-acca-454f-a6f4-14113c187dca", "5060e030-727b-47bc-8023-b80b7cccd96f", "e3d8f8e4-8fee-47e7-9451-28724bf74a90", ] }, }, }, }, ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document") self.assertEqual(200, response.status_code) self.assertIn("blocks", response.json().get("properties")) self.assertIn("blocks_layout", response.json().get("properties")) fieldsets = [ f for f in response.json().get("fieldsets") if f.get("id") == "layout" ] # noqa self.assertTrue(len(fieldsets) == 1) self.assertTrue(["blocks", "blocks_layout"], fieldsets[0].get("fields")) # noqa def test_types_document_update_min_max(self): response = self.api_session.patch( "/@types/Document", json={ "properties": { "custom_text": { "factory": "Text line (String)", "minLength": 2, "maxLength": 20, "title": "Custom text", }, "custom_float": { "title": "Custom float", "factory": "Floating-point number", "minimum": 2.0, "maximum": 14.0, }, } }, ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document/custom_text") self.assertEqual(200, response.status_code) self.assertEqual(2, response.json().get("minLength")) self.assertEqual(20, response.json().get("maxLength")) response = self.api_session.get("/@types/Document/custom_float") self.assertEqual(200, response.status_code) self.assertEqual(2, response.json().get("minimum")) self.assertEqual(14.0, response.json().get("maximum")) def test_types_document_put(self): response = self.api_session.get("/@types/Document") doc_json = response.json() doc_json["layouts"] = ["thumbnail_view", "table_view"] doc_json["fieldsets"] = [ { "id": "author", "title": "Contact the author", "fields": ["author_email", "author_name"], }, { "id": "contact_info", "title": "Contact info", "fields": [] }, ] doc_json["properties"]["author_name"] = { "description": "Name of the author", "factory": "Text line (String)", "title": "Author name", } doc_json["properties"].pop("author_url") doc_json["properties"]["author_email"] = { "minLength": 0, "maxLength": 100, "default": None, } response = self.api_session.put("/@types/Document", json=doc_json) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document") self.assertEqual(200, response.status_code) # Layouts updated self.assertEqual(["thumbnail_view", "table_view"], response.json().get("layouts")) # noqa # Field added self.assertIn("author_name", response.json().get("properties")) # Field removed self.assertTrue("author_url" not in response.json().get("properties")) # Field updated self.assertEqual(None, response.json().get("properties").get( "author_email").get("default")) # noqa # Fieldset added self.assertIn("author", [f["id"] for f in response.json().get("fieldsets")]) # noqa # Fieldset removed self.assertTrue("location" not in [ f["id"] for f in response.json().get("fieldsets") ]) # noqa # Fieldset updated self.assertIn("contact_info", [f["id"] for f in response.json().get("fieldsets")]) # noqa def test_types_document_remove_field(self): response = self.api_session.delete("/@types/Document/author_email", ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document") self.assertEqual(200, response.status_code) self.assertTrue("author_email" not in response.json().get("properties")) # noqa def test_types_document_remove_fieldset(self): response = self.api_session.delete("/@types/Document/contact_info", ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/@types/Document") self.assertEqual(200, response.status_code) self.assertTrue("contact_info" not in [ f["id"] for f in response.json().get("fieldsets") ]) # noqa def test_get_types_with_unknown_type(self): response = self.api_session.get("{}/@types/UnknownType".format( self.portal.absolute_url())) self.assertEqual(response.status_code, 404) self.assertEqual( "application/json", response.headers.get("Content-Type"), "Sending a GET request to @types endpoint should respond with " + 'Content-Type: "application/json", not ' + '"{}"'.format(response.headers.get("Content-Type")), ) def test_types_endpoint_only_accessible_for_authenticated_users(self): self.api_session.auth = () response = self.api_session.get("{}/@types".format( self.portal.absolute_url())) # noqa self.assertEqual(response.status_code, 401) def test_contextaware_addable(self): response = self.api_session.get("{}/@types".format( self.portal.absolute_url())) # noqa allowed_ids = [x.getId() for x in self.portal.allowedContentTypes()] response_allowed_ids = [ x["@id"].split("/")[-1] for x in response.json() if x["addable"] ] # We check subset here, because only DX types are returned by the # endpoint. self.assertNotEqual([], allowed_ids) self.assertTrue(set(response_allowed_ids).issubset(set(allowed_ids))) def test_image_type(self): response = self.api_session.get("/@types/Image") response = response.json() self.assertIn("fieldsets", response) self.assertIn("image.data", response["properties"]["image"]["properties"]) # noqa def test_file_type(self): response = self.api_session.get("/@types/File") response = response.json() self.assertIn("fieldsets", response) self.assertIn("file.data", response["properties"]["file"]["properties"]) # noqa def test_event_type(self): response = self.api_session.get("/@types/Event") response = response.json() self.assertIn("title", response["properties"]["start"]) def test_addable_types_for_non_manager_user(self): user = api.user.create(email="*****@*****.**", username="******", password="******") folder = api.content.create(container=self.portal, id="folder", type="Folder", title=u"folder") folder_cant_add = api.content.create( container=self.portal, id="folder_cant_add", type="Folder", title=u"folder_cant_add", ) api.user.grant_roles(user=user, obj=folder, roles=["Contributor"]) api.user.grant_roles(user=user, obj=folder_cant_add, roles=["Reader"]) transaction.commit() self.api_session.auth = ("noam", "12345") # In the folder, the user should be able to add types since we granted # Contributor role on it response = self.api_session.get("/folder/@types") response = response.json() # Any addable type will do. self.assertTrue(any(a["addable"] for a in response)) # In the folder where the user only have Reader role, no types are # addable response = self.api_session.get("/folder_cant_add/@types") response = response.json() self.assertEqual(len([a for a in response if a["addable"]]), 0) # and in the root Plone site there's no addable types response = self.api_session.get("/@types") response = response.json() self.assertEqual(len([a for a in response if a["addable"]]), 0)
class TestTraversal(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.request = self.layer['request'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() # Register custom UUID generator to produce stable UUIDs during tests pushGlobalRegistry(getSite()) register_static_uuid_utility(prefix='SomeUUID') self.time_freezer = freeze_time("2016-10-21 19:00:00") self.frozen_time = self.time_freezer.start() self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) setRoles(self.portal, TEST_USER_ID, ['Manager']) self.document = self.create_document() transaction.commit() self.browser = Browser(self.app) self.browser.handleErrors = False self.browser.addHeader( 'Authorization', 'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,) ) def create_document(self): self.portal.invokeFactory('Document', id='front-page') document = self.portal['front-page'] document.title = u"Welcome to Plone" document.description = \ u"Congratulations! You have successfully installed Plone." document.text = RichTextValue( u"If you're seeing this instead of the web site you were " + u"expecting, the owner of this web site has just installed " + u"Plone. Do not contact the Plone Team or the Plone mailing " + u"lists about this.", 'text/plain', 'text/html' ) document.creation_date = DateTime('2016-01-21T01:14:48+00:00') document.reindexObject() document.modification_date = DateTime('2016-01-21T01:24:11+00:00') return document def create_folder(self): self.portal.invokeFactory('Folder', id='folder') folder = self.portal['folder'] folder.title = 'My Folder' folder.description = u'This is a folder with two documents' folder.invokeFactory( 'Document', id='doc1', title='A document within a folder' ) folder.invokeFactory( 'Document', id='doc2', title='A document within a folder' ) folder.creation_date = DateTime( '2016-01-21T07:14:48+00:00') folder.modification_date = DateTime( '2016-01-21T07:24:11+00:00') return folder def tearDown(self): self.time_freezer.stop() popGlobalRegistry(getSite()) def test_documentation_content_crud(self): folder = self.create_folder() transaction.commit() response = self.api_session.post( folder.absolute_url(), json={ '@type': 'Document', 'title': 'My Document', } ) save_request_and_response_for_docs('content_post', response) transaction.commit() document = folder['my-document'] response = self.api_session.get(document.absolute_url()) save_request_and_response_for_docs('content_get', response) response = self.api_session.patch( document.absolute_url(), json={ 'title': 'My New Document Title', } ) save_request_and_response_for_docs('content_patch', response) transaction.commit() response = self.api_session.delete(document.absolute_url()) save_request_and_response_for_docs('content_delete', response) def test_documentation_document(self): response = self.api_session.get(self.document.absolute_url()) save_request_and_response_for_docs('document', response) def test_documentation_news_item(self): self.portal.invokeFactory('News Item', id='newsitem') self.portal.newsitem.title = 'My News Item' self.portal.newsitem.description = u'This is a news item' self.portal.newsitem.text = RichTextValue( u"Lorem ipsum", 'text/plain', 'text/html' ) image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.newsitem.image = NamedBlobImage( data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png' ) self.portal.newsitem.image_caption = u'This is an image caption.' self.portal.newsitem.creation_date = DateTime( '2016-01-21T02:14:48+00:00') self.portal.newsitem.modification_date = DateTime( '2016-01-21T02:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.newsitem.absolute_url()) save_request_and_response_for_docs('newsitem', response) def test_documentation_event(self): self.portal.invokeFactory('Event', id='event') self.portal.event.title = 'Event' self.portal.event.description = u'This is an event' self.portal.event.start = datetime(2013, 1, 1, 10, 0) self.portal.event.end = datetime(2013, 1, 1, 12, 0) self.portal.event.creation_date = DateTime('2016-01-21T03:14:48+00:00') self.portal.event.modification_date = DateTime( '2016-01-21T03:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.event.absolute_url()) save_request_and_response_for_docs('event', response) def test_documentation_link(self): self.portal.invokeFactory('Link', id='link') self.portal.link.title = 'My Link' self.portal.link.description = u'This is a link' self.portal.remoteUrl = 'http://plone.org' self.portal.link.creation_date = DateTime('2016-01-21T04:14:48+00:00') self.portal.link.modification_date = DateTime( '2016-01-21T04:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.link.absolute_url()) save_request_and_response_for_docs('link', response) def test_documentation_file(self): self.portal.invokeFactory('File', id='file') self.portal.file.title = 'My File' self.portal.file.description = u'This is a file' pdf_file = os.path.join( os.path.dirname(__file__), u'file.pdf' ) self.portal.file.file = NamedBlobFile( data=open(pdf_file, 'r').read(), contentType='application/pdf', filename=u'file.pdf' ) self.portal.file.creation_date = DateTime('2016-01-21T05:14:48+00:00') self.portal.file.modification_date = DateTime( '2016-01-21T05:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.file.absolute_url()) save_request_and_response_for_docs('file', response) def test_documentation_image(self): self.portal.invokeFactory('Image', id='image') self.portal.image.title = 'My Image' self.portal.image.description = u'This is an image' image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.image.image = NamedBlobImage( data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png' ) self.portal.image.creation_date = DateTime('2016-01-21T06:14:48+00:00') self.portal.image.modification_date = DateTime( '2016-01-21T06:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.image.absolute_url()) save_request_and_response_for_docs('image', response) def test_documentation_folder(self): folder = self.create_folder() import transaction transaction.commit() response = self.api_session.get(folder.absolute_url()) save_request_and_response_for_docs('folder', response) def test_documentation_collection(self): self.portal.invokeFactory('Collection', id='collection') self.portal.collection.title = 'My Collection' self.portal.collection.description = \ u'This is a collection with two documents' self.portal.collection.query = [{ 'i': 'portal_type', 'o': 'plone.app.querystring.operation.string.is', 'v': 'Document', }] self.portal.invokeFactory( 'Document', id='doc1', title='Document 1' ) self.portal.invokeFactory( 'Document', id='doc2', title='Document 2' ) self.portal.collection.creation_date = DateTime( '2016-01-21T08:14:48+00:00') self.portal.collection.modification_date = DateTime( '2016-01-21T08:24:11+00:00') import transaction transaction.commit() response = self.api_session.get(self.portal.collection.absolute_url()) save_request_and_response_for_docs('collection', response) def test_documentation_siteroot(self): response = self.api_session.get(self.portal.absolute_url()) save_request_and_response_for_docs('siteroot', response) def test_documentation_404_not_found(self): response = self.api_session.get('non-existing-resource') save_request_and_response_for_docs('404_not_found', response) def test_documentation_search(self): query = {'sort_on': 'path'} response = self.api_session.get('/@search', params=query) save_request_and_response_for_docs('search', response) def test_documentation_workflow(self): response = self.api_session.get( '{}/@workflow'.format(self.document.absolute_url())) save_request_and_response_for_docs('workflow_get', response) def test_documentation_workflow_transition(self): self.frozen_time.tick(timedelta(minutes=5)) response = self.api_session.post( '{}/@workflow/publish'.format(self.document.absolute_url())) save_request_and_response_for_docs('workflow_post', response) def test_documentation_registry_get(self): response = self.api_session.get( '/@registry/plone.app.querystring.field.path.title') save_request_and_response_for_docs('registry_get', response) def test_documentation_registry_update(self): response = self.api_session.patch( '/@registry/', json={'plone.app.querystring.field.path.title': 'Value'}) save_request_and_response_for_docs('registry_update', response) def test_documentation_types(self): response = self.api_session.get('/@types') save_request_and_response_for_docs('types', response) def test_documentation_types_document(self): response = self.api_session.get('@types/Document') save_request_and_response_for_docs('types_document', response) def test_documentation_jwt_login(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) save_request_and_response_for_docs('jwt_login', response) def test_documentation_jwt_logged_in(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 self.portal.acl_users.jwt_auth.store_tokens = True import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) token = json.loads(response.content)['token'] response = self.api_session.get( '/', headers={'Authorization': 'Bearer {}'.format(token)}) save_request_and_response_for_docs('jwt_logged_in', response) def test_documentation_jwt_login_renew(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@login-renew'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_request_and_response_for_docs('jwt_login_renew', response) def test_documentation_jwt_logout(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 self.portal.acl_users.jwt_auth.store_tokens = True import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@logout'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_request_and_response_for_docs('jwt_logout', response) def test_documentation_batching(self): folder = self.portal[self.portal.invokeFactory( 'Folder', id='folder', title='Folder' )] for i in range(7): folder.invokeFactory( 'Document', id='doc-%s' % str(i + 1), title='Document %s' % str(i + 1) ) transaction.commit() query = {'sort_on': 'path'} response = self.api_session.get( '/folder/@search?b_size=5', params=query) save_request_and_response_for_docs('batching', response) def test_documentation_users(self): test_user = api.user.get(username=TEST_USER_ID) properties = { "description": "This is a test user", "email": "*****@*****.**", "fullname": "Test User", "home_page": "http://www.example.com", "location": "Bonn", "username": "******" } test_user.setMemberProperties(mapping=properties) admin = api.user.get(username='******') properties = { "description": "This is an admin user", "email": "*****@*****.**", "fullname": "Administrator", "home_page": "http://www.example.com", "location": "Berlin", "username": "******" } admin.setMemberProperties(mapping=properties) transaction.commit() response = self.api_session.get('/@users') save_request_and_response_for_docs('users', response) def test_documentation_users_get(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.get('@users/noam') save_request_and_response_for_docs('users_get', response) def test_documentation_users_filtered_get(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.get('@users', params={'query': 'noa'}) save_request_and_response_for_docs('users_filtered_by_username', response) # noqa def test_documentation_users_created(self): response = self.api_session.post( '/@users', json={ 'email': '*****@*****.**', 'password': '******', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' }, ) save_request_and_response_for_docs('users_created', response) def test_documentation_users_update(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.patch( '/@users/noam', json={ 'email': '*****@*****.**', }, ) save_request_and_response_for_docs('users_update', response) def test_documentation_users_delete(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.delete( '/@users/noam') save_request_and_response_for_docs('users_delete', response) def test_documentation_groups(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.get('/@groups') save_request_and_response_for_docs('groups', response) def test_documentation_groups_get(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.get('@groups/ploneteam') save_request_and_response_for_docs('groups_get', response) def test_documentation_groups_filtered_get(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.get('@groups', params={'query': 'plo'}) save_request_and_response_for_docs('groups_filtered_by_groupname', response) # noqa def test_documentation_groups_created(self): response = self.api_session.post( '/@groups', json={ 'groupname': 'fwt', 'email': '*****@*****.**', 'title': 'Framework Team', 'description': 'The Plone Framework Team', 'roles': ['Manager'], 'groups': ['Administrators'] }, ) save_request_and_response_for_docs('groups_created', response) def test_documentation_groups_update(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.patch( '/@groups/ploneteam', json={ 'email': '*****@*****.**', }, ) save_request_and_response_for_docs('groups_update', response) def test_documentation_groups_delete(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.delete( '/@groups/ploneteam') save_request_and_response_for_docs('groups_delete', response) def test_documentation_breadcrumbs(self): response = self.api_session.get( '{}/@components/breadcrumbs'.format(self.document.absolute_url())) save_request_and_response_for_docs('breadcrumbs', response) def test_documentation_navigation(self): response = self.api_session.get( '{}/@components/navigation'.format(self.document.absolute_url())) save_request_and_response_for_docs('navigation', response) def test_documentation_principals(self): gtool = api.portal.get_tool('portal_groups') properties = { 'title': 'Plone Team', 'description': 'We are Plone', 'email': '*****@*****.**', } gtool.addGroup('ploneteam', (), (), properties=properties, title=properties['title'], description=properties['description']) transaction.commit() response = self.api_session.get( '/@principals', params={ "search": "ploneteam" } ) save_request_and_response_for_docs('principals', response) def test_documentation_copy(self): response = self.api_session.post( '/@copy', json={ 'source': self.document.absolute_url(), }, ) save_request_and_response_for_docs('copy', response) def test_documentation_copy_multiple(self): newsitem = self.portal[self.portal.invokeFactory( 'News Item', id='newsitem')] newsitem.title = 'My News Item' transaction.commit() response = self.api_session.post( '/@copy', json={ 'source': [ self.document.absolute_url(), newsitem.absolute_url(), ], }, ) save_request_and_response_for_docs('copy_multiple', response) def test_documentation_move(self): self.portal.invokeFactory('Folder', id='folder') transaction.commit() response = self.api_session.post( '/folder/@move', json={ 'source': self.document.absolute_url(), }, ) save_request_and_response_for_docs('move', response) def test_documentation_vocabularies_all(self): response = self.api_session.get('/@vocabularies') save_request_and_response_for_docs('vocabularies', response) def test_documentation_vocabularies_get(self): response = self.api_session.get( '/@vocabularies/plone.app.vocabularies.ReallyUserFriendlyTypes' ) save_request_and_response_for_docs('vocabularies_get', response) def test_documentation_sharing_folder_get(self): self.portal.invokeFactory('Folder', id='folder') transaction.commit() response = self.api_session.get( '/folder/@sharing' ) save_request_and_response_for_docs('sharing_folder_get', response) def test_documentation_sharing_folder_post(self): self.portal.invokeFactory('Folder', id='folder') transaction.commit() payload = { "inherit": True, "entries": [ { "id": "test_user_1_", "roles": { "Reviewer": True, "Editor": False, "Reader": True, "Contributor": False }, "type": "user" } ] } response = self.api_session.post( '/folder/@sharing', json=payload ) save_request_and_response_for_docs('sharing_folder_post', response)
class TestWorkingCopyEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_ITERATE_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url, test=self) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.portal.invokeFactory("Document", "document", title="Test Document") self.doc = self.portal.document transaction.commit() def tearDown(self): self.api_session.close() def test_workingcopy_checkout(self): response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) self.assertIn("@id", response.json()) self.assertEqual( response.json()["@id"], f"{self.portal_url}/copy_of_document", ) def test_workingcopy_get(self): # We create the working copy response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) # endpoint GET in the baseline object response = self.api_session.get("/document/@workingcopy", ) self.assertEqual(response.status_code, 200) self.assertEqual( response.json()["working_copy"]["@id"], f"{self.portal_url}/copy_of_document", ) self.assertEqual( response.json()["working_copy"]["creator_name"], "admin", ) self.assertEqual( response.json()["working_copy"]["creator_url"], f"{self.portal_url}/author/admin", ) # endpoint GET in the working_copy response = self.api_session.get("/copy_of_document/@workingcopy", ) self.assertEqual(response.status_code, 200) self.assertEqual( response.json()["working_copy_of"]["@id"], f"{self.portal_url}/document", ) self.assertEqual( response.json()["working_copy"]["@id"], f"{self.portal_url}/copy_of_document", ) self.assertEqual( response.json()["working_copy"]["creator_name"], "admin", ) self.assertEqual( response.json()["working_copy"]["creator_url"], f"{self.portal_url}/author/admin", ) # Serialization on the baseline object response = self.api_session.get("/document", ) self.assertEqual( response.json()["working_copy"]["@id"], f"{self.portal_url}/copy_of_document", ) self.assertEqual( response.json()["working_copy"]["creator_name"], "admin", ) self.assertEqual( response.json()["working_copy"]["creator_url"], f"{self.portal_url}/author/admin", ) self.assertEqual(response.json()["working_copy_of"], None) # Serialization on the working copy object response = self.api_session.get("/copy_of_document", ) self.assertEqual( response.json()["working_copy_of"]["@id"], f"{self.portal_url}/document", ) self.assertEqual( response.json()["working_copy"]["@id"], f"{self.portal_url}/copy_of_document", ) self.assertEqual( response.json()["working_copy"]["creator_name"], "admin", ) self.assertEqual( response.json()["working_copy"]["creator_url"], f"{self.portal_url}/author/admin", ) def test_workingcopy_notworkingcopy_get(self): # endpoint GET in the working_copy response = self.api_session.get("/document/", ) self.assertEqual(response.status_code, 200) self.assertEqual( response.json()["working_copy_of"], None, ) def test_workingcopy_delete_on_the_baseline(self): # We create the working copy response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) # Deleting in the baseline deletes the working copy response = self.api_session.delete("/document/@workingcopy", ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/copy_of_document", ) self.assertEqual(response.status_code, 404) def test_workingcopy_delete_on_the_working_copy(self): # We create the working copy response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) # Deleting in the working copy deletes it too response = self.api_session.delete("/copy_of_document/@workingcopy", ) self.assertEqual(response.status_code, 204) response = self.api_session.get("/copy_of_document", ) self.assertEqual(response.status_code, 404) def test_workingcopy_patch_on_the_baseline(self): # We create the working copy response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) # Modify the working copy response = self.api_session.patch( "/copy_of_document", json={"title": "I just changed the title"}) # Checking in response = self.api_session.patch("/document/@workingcopy", ) # Check if the change is there response = self.api_session.get("/document", ) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()["title"], "I just changed the title") def test_workingcopy_patch_on_the_working_copy(self): # We create the working copy response = self.api_session.post("/document/@workingcopy", ) self.assertEqual(response.status_code, 201) # Modify the working copy response = self.api_session.patch( "/copy_of_document", json={"title": "I just changed the title"}) # Checking in response = self.api_session.patch("/copy_of_document/@workingcopy", ) # Check if the change is there response = self.api_session.get("/document", ) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()["title"], "I just changed the title")
class TestTraversal(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer['app'] self.request = self.layer['request'] self.portal = self.layer['portal'] self.portal_url = self.portal.absolute_url() self.time_freezer = freeze_time("2016-10-21 19:00:00") self.frozen_time = self.time_freezer.start() self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({'Accept': 'application/json'}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory('Document', id='front-page') self.document = self.portal['front-page'] self.document.title = u"Welcome to Plone" self.document.description = \ u"Congratulations! You have successfully installed Plone." self.document.text = RichTextValue( u"If you're seeing this instead of the web site you were " + u"expecting, the owner of this web site has just installed " + u"Plone. Do not contact the Plone Team or the Plone mailing " + u"lists about this.", 'text/plain', 'text/html' ) self.document.creation_date = DateTime('2016-01-21T01:14:48+00:00') IMutableUUID(self.document).set('1f699ffa110e45afb1ba502f75f7ec33') self.document.reindexObject() self.document.modification_date = DateTime('2016-01-21T01:24:11+00:00') import transaction transaction.commit() self.browser = Browser(self.app) self.browser.handleErrors = False self.browser.addHeader( 'Authorization', 'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,) ) def tearDown(self): self.time_freezer.stop() def test_documentation_document(self): response = self.api_session.get(self.document.absolute_url()) save_response_for_documentation('document.json', response) def test_documentation_news_item(self): self.portal.invokeFactory('News Item', id='newsitem') self.portal.newsitem.title = 'My News Item' self.portal.newsitem.description = u'This is a news item' self.portal.newsitem.text = RichTextValue( u"Lorem ipsum", 'text/plain', 'text/html' ) image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.newsitem.image = NamedBlobImage( data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png' ) self.portal.newsitem.image_caption = u'This is an image caption.' self.portal.newsitem.creation_date = DateTime( '2016-01-21T02:14:48+00:00') self.portal.newsitem.modification_date = DateTime( '2016-01-21T02:24:11+00:00') IMutableUUID(self.portal.newsitem).set( '80c2a074cb4240d08c9a129e3a834c74') import transaction transaction.commit() response = self.api_session.get(self.portal.newsitem.absolute_url()) save_response_for_documentation('newsitem.json', response) def test_documentation_event(self): self.portal.invokeFactory('Event', id='event') self.portal.event.title = 'Event' self.portal.event.description = u'This is an event' self.portal.event.start = datetime(2013, 1, 1, 10, 0) self.portal.event.end = datetime(2013, 1, 1, 12, 0) self.portal.event.creation_date = DateTime('2016-01-21T03:14:48+00:00') self.portal.event.modification_date = DateTime( '2016-01-21T03:24:11+00:00') IMutableUUID(self.portal.event).set('846d632bc0854c5aa6d3dcae171ed2db') import transaction transaction.commit() response = self.api_session.get(self.portal.event.absolute_url()) save_response_for_documentation('event.json', response) def test_documentation_link(self): self.portal.invokeFactory('Link', id='link') self.portal.link.title = 'My Link' self.portal.link.description = u'This is a link' self.portal.remoteUrl = 'http://plone.org' self.portal.link.creation_date = DateTime('2016-01-21T04:14:48+00:00') self.portal.link.modification_date = DateTime( '2016-01-21T04:24:11+00:00') IMutableUUID(self.portal.link).set('6ff48d27762143a0ae8d63cee73d9fc2') import transaction transaction.commit() response = self.api_session.get(self.portal.link.absolute_url()) save_response_for_documentation('link.json', response) def test_documentation_file(self): self.portal.invokeFactory('File', id='file') self.portal.file.title = 'My File' self.portal.file.description = u'This is a file' pdf_file = os.path.join( os.path.dirname(__file__), u'file.pdf' ) self.portal.file.file = NamedBlobFile( data=open(pdf_file, 'r').read(), contentType='application/pdf', filename=u'file.pdf' ) self.portal.file.creation_date = DateTime('2016-01-21T05:14:48+00:00') self.portal.file.modification_date = DateTime( '2016-01-21T05:24:11+00:00') IMutableUUID(self.portal.file).set('9b6a4eadb9074dde97d86171bb332ae9') import transaction transaction.commit() response = self.api_session.get(self.portal.file.absolute_url()) save_response_for_documentation('file.json', response) def test_documentation_image(self): self.portal.invokeFactory('Image', id='image') self.portal.image.title = 'My Image' self.portal.image.description = u'This is an image' image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.image.image = NamedBlobImage( data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png' ) self.portal.image.creation_date = DateTime('2016-01-21T06:14:48+00:00') self.portal.image.modification_date = DateTime( '2016-01-21T06:24:11+00:00') IMutableUUID(self.portal.image).set('2166e81a0c224fe3b62e197c7fdc9c3e') import transaction transaction.commit() response = self.api_session.get(self.portal.image.absolute_url()) save_response_for_documentation('image.json', response) def test_documentation_folder(self): self.portal.invokeFactory('Folder', id='folder') self.portal.folder.title = 'My Folder' self.portal.folder.description = u'This is a folder with two documents' self.portal.folder.invokeFactory( 'Document', id='doc1', title='A document within a folder' ) self.portal.folder.invokeFactory( 'Document', id='doc2', title='A document within a folder' ) self.portal.folder.creation_date = DateTime( '2016-01-21T07:14:48+00:00') self.portal.folder.modification_date = DateTime( '2016-01-21T07:24:11+00:00') IMutableUUID(self.portal.folder).set( 'fc7881c46d61452db4177bc059d9dcb5') import transaction transaction.commit() response = self.api_session.get(self.portal.folder.absolute_url()) save_response_for_documentation('folder.json', response) def test_documentation_collection(self): self.portal.invokeFactory('Collection', id='collection') self.portal.collection.title = 'My Collection' self.portal.collection.description = \ u'This is a collection with two documents' self.portal.collection.query = [{ 'i': 'portal_type', 'o': 'plone.app.querystring.operation.string.is', 'v': 'Document', }] self.portal.invokeFactory( 'Document', id='doc1', title='Document 1' ) self.portal.invokeFactory( 'Document', id='doc2', title='Document 2' ) self.portal.collection.creation_date = DateTime( '2016-01-21T08:14:48+00:00') self.portal.collection.modification_date = DateTime( '2016-01-21T08:24:11+00:00') IMutableUUID(self.portal.collection).set( 'd0c89bc77f874ce1aad5720921d875c0') import transaction transaction.commit() response = self.api_session.get(self.portal.collection.absolute_url()) save_response_for_documentation('collection.json', response) def test_documentation_siteroot(self): response = self.api_session.get(self.portal.absolute_url()) save_response_for_documentation('siteroot.json', response) def test_documentation_404_not_found(self): response = self.api_session.get('non-existing-resource') save_response_for_documentation('404_not_found.json', response) def test_documentation_search(self): query = {'sort_on': 'path'} response = self.api_session.get('/@search', params=query) save_response_for_documentation('search.json', response) def test_documentation_workflow(self): response = self.api_session.get( '{}/@workflow'.format(self.document.absolute_url())) save_response_for_documentation('workflow_get.json', response) def test_documentation_workflow_transition(self): self.frozen_time.tick(timedelta(minutes=5)) response = self.api_session.post( '{}/@workflow/publish'.format(self.document.absolute_url())) save_response_for_documentation('workflow_post.json', response) def test_documentation_registry_get(self): response = self.api_session.get( '/@registry/plone.app.querystring.field.path.title') save_response_for_documentation('registry_get.json', response) def test_documentation_registry_update(self): response = self.api_session.patch( '/@registry/', json={'plone.app.querystring.field.path.title': 'Value'}) save_response_for_documentation('registry_update.json', response) def test_documentation_types(self): response = self.api_session.get('/@types') save_response_for_documentation('types.json', response) def test_documentation_types_document(self): response = self.api_session.get('@types/Document') save_response_for_documentation('types_document.json', response) def test_documentation_login(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) save_response_for_documentation('login.json', response) def test_documentation_login_renew(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@login-renew'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_response_for_documentation('login_renew.json', response) def test_documentation_logout(self): self.portal.acl_users.jwt_auth._secret = 'secret' self.portal.acl_users.jwt_auth.use_keyring = False self.portal.acl_users.jwt_auth.token_timeout = 0 self.portal.acl_users.jwt_auth.store_tokens = True import transaction transaction.commit() self.api_session.auth = None response = self.api_session.post( '{}/@login'.format(self.portal.absolute_url()), json={'login': SITE_OWNER_NAME, 'password': SITE_OWNER_PASSWORD}) token = json.loads(response.content)['token'] response = self.api_session.post( '{}/@logout'.format(self.portal.absolute_url()), headers={'Authorization': 'Bearer {}'.format(token)}) save_response_for_documentation('logout.json', response) def test_documentation_batching(self): folder = self.portal[self.portal.invokeFactory( 'Folder', id='folder', title='Folder' )] for i in range(7): folder.invokeFactory( 'Document', id='doc-%s' % str(i + 1), title='Document %s' % str(i + 1) ) transaction.commit() query = {'sort_on': 'path'} response = self.api_session.get( '/folder/@search?b_size=5', params=query) save_response_for_documentation('batching.json', response) def test_documentation_users(self): test_user = api.user.get(username=TEST_USER_ID) properties = { "description": "This is a test user", "email": "*****@*****.**", "fullname": "Test User", "home_page": "http://www.example.com", "location": "Bonn", "username": "******" } test_user.setMemberProperties(mapping=properties) admin = api.user.get(username='******') properties = { "description": "This is an admin user", "email": "*****@*****.**", "fullname": "Administrator", "home_page": "http://www.example.com", "location": "Berlin", "username": "******" } admin.setMemberProperties(mapping=properties) transaction.commit() response = self.api_session.get('/@users') save_response_for_documentation('users.json', response) def test_documentation_users_get(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.get('@users/noam') save_response_for_documentation('users_get.json', response) def test_documentation_users_filtered_get(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.get('@users', params={'query': 'noa'}) save_response_for_documentation('users_filtered_by_username.json', response) # noqa def test_documentation_users_created(self): response = self.api_session.post( '/@users', json={ 'username': '******', 'email': '*****@*****.**', 'password': '******', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' }, ) save_response_for_documentation('users_created.json', response) def test_documentation_users_update(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.patch( '/@users/noam', json={ 'email': '*****@*****.**', }, ) save_response_for_documentation('users_update.json', response) def test_documentation_users_delete(self): properties = { 'email': '*****@*****.**', 'username': '******', 'fullname': 'Noam Avram Chomsky', 'home_page': 'web.mit.edu/chomsky', 'description': 'Professor of Linguistics', 'location': 'Cambridge, MA' } api.user.create( email='*****@*****.**', username='******', properties=properties ) transaction.commit() response = self.api_session.delete( '/@users/noam') save_response_for_documentation('users_delete.json', response) def test_documentation_breadcrumbs(self): response = self.api_session.get( '{}/@components/breadcrumbs'.format(self.document.absolute_url())) save_response_for_documentation('breadcrumbs.json', response) def test_documentation_navigation(self): response = self.api_session.get( '{}/@components/navigation'.format(self.document.absolute_url())) save_response_for_documentation('navigation.json', response)
class TestGroupsEndpoint(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.request = self.layer["request"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url, test=self) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.gtool = api.portal.get_tool("portal_groups") properties = { "title": "Plone Team", "description": "We are Plone", "email": "*****@*****.**", } self.gtool.addGroup( "ploneteam", (), (), properties=properties, title=properties["title"], description=properties["description"], ) transaction.commit() def tearDown(self): self.api_session.close() def test_list_groups(self): response = self.api_session.get("/@groups") self.assertEqual(200, response.status_code) self.assertEqual(5, len(response.json())) user_ids = [group["id"] for group in response.json()] self.assertIn("Administrators", user_ids) self.assertIn("Reviewers", user_ids) self.assertIn("AuthenticatedUsers", user_ids) self.assertIn("ploneteam", user_ids) ptgroup = [x for x in response.json() if x.get("groupname") == "ploneteam"][0] self.assertEqual("ploneteam", ptgroup.get("id")) self.assertEqual( self.portal.absolute_url() + "/@groups/ploneteam", ptgroup.get("@id") ) self.assertEqual("*****@*****.**", ptgroup.get("email")) self.assertEqual("Plone Team", ptgroup.get("title")) self.assertEqual("We are Plone", ptgroup.get("description")) self.assertEqual(ptgroup.get("roles"), ["Authenticated"]) # # Assert batched list of group members self.assertTrue( all(["members" in group for group in response.json()]), "Members key found in groups listing", ) def test_add_group(self): response = self.api_session.post( "/@groups", json={ "groupname": "fwt", "email": "*****@*****.**", "title": "Framework Team", "description": "The Plone Framework Team", "roles": ["Manager"], "groups": ["Administrators"], "users": [SITE_OWNER_NAME, TEST_USER_ID], }, ) transaction.commit() self.assertEqual(201, response.status_code) fwt = self.gtool.getGroupById("fwt") self.assertEqual("*****@*****.**", fwt.getProperty("email")) self.assertTrue( {SITE_OWNER_NAME, TEST_USER_ID}.issubset(set(fwt.getGroupMemberIds())), "Userids not found in group", ) def test_add_group_groupname_is_required(self): response = self.api_session.post("/@groups", json={"title": "Framework Team"}) transaction.commit() self.assertEqual(400, response.status_code) self.assertTrue("\"Property 'groupname' is required" in response.text) def test_get_group(self): response = self.api_session.get("/@groups/ploneteam") self.assertEqual(response.status_code, 200) self.assertEqual("ploneteam", response.json().get("id")) self.assertEqual( self.portal.absolute_url() + "/@groups/ploneteam", response.json().get("@id"), ) self.assertEqual("*****@*****.**", response.json().get("email")) self.assertEqual("*****@*****.**", response.json().get("email")) self.assertEqual("Plone Team", response.json().get("title")) self.assertEqual("We are Plone", response.json().get("description")) self.assertIn("members", response.json()) def test_get_search_group_with_filter(self): response = self.api_session.get("/@groups", params={"query": "plo"}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual("ploneteam", response.json()[0].get("id")) self.assertEqual( self.portal.absolute_url() + "/@groups/ploneteam", response.json()[0].get("@id"), ) self.assertEqual("*****@*****.**", response.json()[0].get("email")) response = self.api_session.get("/@groups", params={"query": "Auth"}) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 1) self.assertEqual("AuthenticatedUsers", response.json()[0].get("id")) def test_get_non_existing_group(self): response = self.api_session.get("/@groups/non-existing-group") self.assertEqual(response.status_code, 404) def test_update_group(self): ploneteam = self.gtool.getGroupById("ploneteam") ploneteam.addMember(SITE_OWNER_NAME) transaction.commit() self.assertNotIn(TEST_USER_ID, ploneteam.getGroupMemberIds()) self.assertIn(SITE_OWNER_NAME, ploneteam.getGroupMemberIds()) payload = { "groupname": "ploneteam", "email": "*****@*****.**", "users": {TEST_USER_ID: True, SITE_OWNER_NAME: False}, } response = self.api_session.patch("/@groups/ploneteam", json=payload) transaction.commit() self.assertEqual(response.status_code, 204) ploneteam = self.gtool.getGroupById("ploneteam") self.assertEqual("ploneteam", ploneteam.id) self.assertEqual("Plone Team", ploneteam.getProperty("title")) self.assertEqual("*****@*****.**", ploneteam.getProperty("email")) self.assertIn(TEST_USER_ID, ploneteam.getGroupMemberIds()) self.assertNotIn(SITE_OWNER_NAME, ploneteam.getGroupMemberIds()) def test_delete_group(self): response = self.api_session.delete("/@groups/ploneteam") transaction.commit() self.assertEqual(response.status_code, 204) self.assertEqual(None, self.gtool.getGroupById("ploneteam")) def test_delete_non_existing_group(self): response = self.api_session.delete("/@groups/non-existing-group") transaction.commit() self.assertEqual(response.status_code, 404)
class TestDexterityTypesControlpanel(unittest.TestCase): layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.request = self.layer["request"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) def tearDown(self): self.api_session.close() def test_controlpanels_dexterity_types_get(self): response = self.api_session.get("/@controlpanels/dexterity-types") self.assertEqual(200, response.status_code) self.assertEqual( [ "Collection", "Document", "Folder", "Link", "File", "Image", "News Item", "Event", "DXTestDocument", ], [ x.get("id") for x in self.api_session.get( "/@controlpanels/dexterity-types").json().get("items") ], ) def test_controlpanels_dexterity_types_document_get(self): response = self.api_session.get( "/@controlpanels/dexterity-types/Document") self.assertEqual(200, response.status_code) self.assertEqual( "{}/@controlpanels/dexterity-types/Document".format( self.portal_url), response.json().get("@id"), ) self.assertEqual("Page", response.json().get("title")) def test_controlpanels_dexterity_types_post(self): response = self.api_session.post( "/@controlpanels/dexterity-types", json={ "title": "My Custom Content Type", "description": "A custom content-type", }, ) self.assertEqual(201, response.status_code) self.assertEqual( "{}/@controlpanels/dexterity-types/my_custom_content_type".format( self.portal_url), response.json().get("@id"), ) self.assertEqual("My Custom Content Type", response.json().get("title")) self.assertEqual("A custom content-type", response.json().get("description")) def test_controlpanels_dexterity_types_document_patch(self): response = self.api_session.patch( "/@controlpanels/dexterity-types/Document", json={ "title": "New Content Type Title", "description": "New content type description", }, ) # PATCH returns no content self.assertEqual(204, response.status_code) response = self.api_session.get( "/@controlpanels/dexterity-types/Document") self.assertEqual(200, response.status_code) self.assertEqual("New Content Type Title", response.json().get("title")) self.assertEqual("New content type description", response.json().get("description")) def test_controlpanels_dexterity_types_document_delete(self): response = self.api_session.delete( "/@controlpanels/dexterity-types/Document") self.assertEqual(204, response.status_code) self.assertEqual( [ "Collection", "Folder", "Link", "File", "Image", "News Item", "Event", "DXTestDocument", ], [ x.get("id") for x in self.api_session.get( "/@controlpanels/dexterity-types").json().get("items") ], )
class TestSubscriptionsDelete(unittest.TestCase): layer = RER_UFFICIOSTAMPA_API_FUNCTIONAL_TESTING def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) api.user.create( email="*****@*****.**", username="******", password="******", ) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.anon_api_session = RelativeSession(self.portal_url) self.anon_api_session.headers.update({"Accept": "application/json"}) self.url = "{}/@subscriptions".format(self.portal_url) self.tool = getUtility(ISubscriptionsStore) self.id_1 = self.tool.add( { "channels": ["foo"], "email": "*****@*****.**", "name": "John", "surname": "Doe", "phone": "123456", }, ) self.id_2 = self.tool.add( { "channels": ["bar"], "email": "*****@*****.**", "name": "John", "surname": "Smith", "phone": "98765", }, ) transaction.commit() def tearDown(self): self.api_session.close() self.anon_api_session.close() def test_delete_should_be_called_with_id(self): res = self.api_session.delete(self.url, json={}) self.assertEqual( self.api_session.delete(self.url, json={}).status_code, 400) self.assertEqual("Missing id", res.json()["message"]) def test_anon_cant_delete_data(self): url = "{}/123".format(self.url) self.assertEqual( self.anon_api_session.delete(url, json={}).status_code, 401) def test_gestore_comunicati_can_delete_data(self): api_session = RelativeSession(self.portal_url) api_session.headers.update({"Accept": "application/json"}) api_session.auth = ("memberuser", "secret") url = "{}/123".format(self.url) self.assertEqual(api_session.delete(url, json={}).status_code, 401) setRoles(self.portal, "memberuser", ["Gestore Comunicati"]) transaction.commit() # 400 because it's a fake id self.assertEqual( api_session.delete(self.url, json={}).status_code, 400) api_session.close() def test_bad_request_if_pass_wrong_id(self): res = self.api_session.delete("{}/foo".format(self.url), json={}) self.assertEqual(res.status_code, 400) self.assertEqual(res.json()["message"], "Id should be a number.") res = self.api_session.delete("{}/123".format(self.url), json={}) self.assertEqual(res.status_code, 400) self.assertEqual(res.json()["message"], 'Unable to find item with id "123"') def test_correctly_delete_data(self): url = "{}/{}".format(self.url, self.id_1) records = self.api_session.get(self.url).json() self.assertEqual(records["items_total"], 2) self.assertEqual(records["items"][0]["email"], "*****@*****.**") self.assertEqual(records["items"][1]["email"], "*****@*****.**") self.api_session.delete(url) records = self.api_session.get(self.url).json() self.assertEqual(records["items_total"], 1) self.assertEqual(records["items"][0]["email"], "*****@*****.**")