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']))
示例#3
0
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")
示例#4
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()

        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)
示例#5
0
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)
示例#6
0
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)
示例#11
0
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")
示例#14
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()

        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)
示例#15
0
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)
示例#16
0
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"], "*****@*****.**")