Example #1
0
    def test_has_home_project(self):
        from pillar.api.blender_cloud import home_project
        from pillar.api.utils.authentication import validate_token

        user_id = self._create_user_with_token(roles={'subscriber'},
                                               token='token')

        # Test home project creation
        with self.app.test_request_context(
                headers={'Authorization': self.make_header('token')}):
            validate_token()

            self.assertFalse(home_project.has_home_project(user_id))
            proj = home_project.create_home_project(user_id, write_access=True)
            self.assertTrue(home_project.has_home_project(user_id))

            # Delete the project.
            resp = self.client.delete('/api/projects/%s' % proj['_id'],
                                      headers={
                                          'Authorization':
                                          self.make_header('token'),
                                          'If-Match':
                                          proj['_etag']
                                      })
            self.assertEqual(204, resp.status_code, resp.data)
            self.assertFalse(home_project.has_home_project(user_id))
Example #2
0
    def test_create_home_project(self):
        from pillar.api.blender_cloud import home_project
        from pillar.api.utils.authentication import validate_token

        user_id = self._create_user_with_token(roles={'subscriber'},
                                               token='token')

        # Test home project creation
        with self.app.test_request_context(
                headers={'Authorization': self.make_header('token')}):
            validate_token()

            proj = home_project.create_home_project(user_id, write_access=True)
            self.assertEqual('home', proj['category'])
            self.assertEqual({'group', 'asset', 'comment'},
                             set(nt['name'] for nt in proj['node_types']))

            endpoint = url_for('blender_cloud.home_project.home_project')
            db_proj = self.app.data.driver.db['projects'].find_one(proj['_id'])

        # Test availability at end-point
        resp = self.client.get(endpoint)
        # While we're still AB-testing, unauthenticated users should get a 404.
        # When that's over, it should result in a 403.
        self.assertEqual(403, resp.status_code)

        resp = self.client.get(
            endpoint, headers={'Authorization': self.make_header('token')})
        self.assertEqual(200, resp.status_code)

        json_proj = json.loads(resp.data)
        self.assertEqual(ObjectId(json_proj['_id']), proj['_id'])
        self.assertEqual(json_proj['_etag'], db_proj['_etag'])
    def test_multiple_users_with_home_project(self):
        from pillar.api.blender_cloud import home_project
        from pillar.api.utils.authentication import validate_token

        uid1 = self._create_user_with_token(roles={'subscriber'}, token='token1', user_id=24 * 'a')
        uid2 = self._create_user_with_token(roles={'subscriber'}, token='token2', user_id=24 * 'b')

        # Create home projects
        with self.app.test_request_context(headers={'Authorization': self.make_header('token1')}):
            validate_token()
            proj1 = home_project.create_home_project(uid1, write_access=True)
            db_proj1 = self.app.data.driver.db['projects'].find_one(proj1['_id'])

        with self.app.test_request_context(headers={'Authorization': self.make_header('token2')}):
            validate_token()
            proj2 = home_project.create_home_project(uid2, write_access=True)
            db_proj2 = self.app.data.driver.db['projects'].find_one(proj2['_id'])

        # Test availability at end-point
        resp1 = self.client.get('/api/bcloud/home-project',
                                headers={'Authorization': self.make_header('token1')})
        resp2 = self.client.get('/api/bcloud/home-project',
                                headers={'Authorization': self.make_header('token2')})
        self.assertEqual(200, resp1.status_code)
        self.assertEqual(200, resp2.status_code)

        json_proj1 = json.loads(resp1.data)
        json_proj2 = json.loads(resp2.data)

        self.assertEqual(ObjectId(json_proj1['_id']), proj1['_id'])
        self.assertEqual(ObjectId(json_proj2['_id']), proj2['_id'])
        self.assertEqual(json_proj1['_etag'], db_proj1['_etag'])
        self.assertEqual(json_proj2['_etag'], db_proj2['_etag'])
        self.assertNotEqual(db_proj1['_etag'], db_proj2['_etag'])
        self.assertNotEqual(db_proj1['_id'], db_proj2['_id'])
    def test_revoking_subscriber_role(self):
        from pillar.api.blender_cloud import home_project
        from pillar.api.utils.authentication import validate_token

        self.user_id = self.create_user(roles=set('subscriber'))
        self.create_valid_auth_token(self.user_id, 'token')

        with self.app.test_request_context(headers={'Authorization': self.make_header('token')}):
            validate_token()

            home_proj = home_project.create_home_project(self.user_id, write_access=True)
            changed = home_project.user_changed_role(None, {'_id': self.user_id,
                                                            'roles': []})
            self.assertTrue(changed)

        # The home project should NOT be writable, so we should NOT be able to create a node.
        self.create_test_node(home_proj['_id'], 403)
Example #5
0
    def test_validate_token__unknown_but_valid_token(self):
        """Test validating of valid token, unknown to us but known to Blender ID."""

        from pillar.api.utils import authentication as auth

        self.mock_blenderid_validate_happy()
        with self.app.test_request_context(
                headers={'Authorization': self.make_header('knowntoken')}):
            self.assertTrue(auth.validate_token())
Example #6
0
    def test_validate_token__force_not_logged_in(self):
        from pillar.api.utils import authentication as auth
        from pillar.auth import UserClass, current_user

        with self.app.test_request_context():
            from flask import g
            g.current_user = UserClass('12345')
            self.assertTrue(g.current_user.is_authenticated)

            self.assertFalse(auth.validate_token(force=True))
            self.assertFalse(g.current_user.is_authenticated)
Example #7
0
    def test_validate_token__force_logged_in(self):
        from pillar.api.utils import authentication as auth
        from pillar.auth import UserClass

        self.mock_blenderid_validate_happy()
        with self.app.test_request_context(
                headers={'Authorization': self.make_header('knowntoken')}):
            from flask import g
            g.current_user = UserClass('12345')
            self.assertTrue(g.current_user.is_authenticated)

            self.assertTrue(auth.validate_token(force=True))
            self.assertTrue(g.current_user.is_authenticated)
Example #8
0
    def test_authenticate_with_scst(self):
        # Make sure there is a user and SCST.
        db_user = self._common_user_test(201)

        # Make a call that's authenticated with the SCST
        from pillar.api.utils import authentication as auth

        subclient_id = self.app.config['BLENDER_ID_SUBCLIENT_ID']
        auth_header = self.make_header(TEST_SUBCLIENT_TOKEN, subclient_id)

        with self.app.test_request_context(headers={'Authorization': auth_header}):
            self.assertTrue(auth.validate_token())
            self.assertIsNotNone(g.current_user)
            self.assertEqual(db_user['_id'], g.current_user.user_id)
Example #9
0
    def test_find_token(self):
        """Test finding of various tokens."""

        from pillar.api.utils import authentication as auth

        user_id = self.create_user()

        now = datetime.datetime.now(tz_util.utc)
        future = now + datetime.timedelta(days=1)
        past = now - datetime.timedelta(days=1)
        subclient = self.app.config['BLENDER_ID_SUBCLIENT_ID']

        with self.app.test_request_context():
            auth.store_token(user_id, 'nonexpired-main', future, None)
            auth.store_token(user_id, 'nonexpired-sub', future, subclient)
            token3 = auth.store_token(user_id, 'expired-sub', past, subclient)

        with self.app.test_request_context(
                headers={'Authorization': self.make_header('nonexpired-main')
                         }):
            self.assertTrue(auth.validate_token())

        with self.app.test_request_context(headers={
                'Authorization':
                self.make_header('nonexpired-main', subclient)
        }):
            self.assertFalse(auth.validate_token())

        with self.app.test_request_context(
                headers={'Authorization': self.make_header('nonexpired-sub')}):
            self.assertFalse(auth.validate_token())

        with self.app.test_request_context(headers={
                'Authorization':
                self.make_header('nonexpired-sub', subclient)
        }):
            self.assertTrue(auth.validate_token())

        with self.app.test_request_context(
                headers={
                    'Authorization': self.make_header('expired-sub', subclient)
                }):
            self.assertFalse(auth.validate_token())

        self.mock_blenderid_validate_happy()
        with self.app.test_request_context(
                headers={
                    'Authorization': self.make_header('expired-sub', subclient)
                }):
            self.assertTrue(auth.validate_token())

            # We now should be able to find a new token for this user.
            found_token = auth.find_token('expired-sub', subclient)
            self.assertIsNotNone(found_token)
            self.assertNotEqual(token3['_id'], found_token['_id'])
Example #10
0
def create_home_project(user_id, write_access):
    """Creates a home project for the given user.

    :param user_id: the user ID of the owner
    :param write_access: whether the user has full write access to the home project.
    :type write_access: bool
    :returns: the project
    :rtype: dict
    """

    log.info('Creating home project for user %s', user_id)
    overrides = {
        'category': 'home',
        'url': 'home',
        'summary': HOME_PROJECT_SUMMARY,
        'description': HOME_PROJECT_DESCRIPTION
    }

    # Maybe the user has a deleted home project.
    proj_coll = current_app.data.driver.db['projects']
    deleted_proj = proj_coll.find_one({
        'user': user_id,
        'category': 'home',
        '_deleted': True
    })
    if deleted_proj:
        log.info('User %s has a deleted project %s, restoring', user_id,
                 deleted_proj['_id'])
        project = deleted_proj
    else:
        log.debug('User %s does not have a deleted project', user_id)
        project = proj_utils.create_new_project(project_name='Home',
                                                user_id=ObjectId(user_id),
                                                overrides=overrides)

    # Re-validate the authentication token, so that the put_internal call sees the
    # new group created for the project.
    authentication.validate_token(force=True)

    # There are a few things in the on_insert_projects hook we need to adjust.

    # Ensure that the project is private, even for admins.
    project['permissions']['world'] = []

    # Set up the correct node types. No need to set permissions for them,
    # as the inherited project permissions are fine.
    from pillar.api.node_types.group import node_type_group
    from pillar.api.node_types.asset import node_type_asset
    # from pillar.api.node_types.text import node_type_text
    from pillar.api.node_types.comment import node_type_comment

    # For non-subscribers: take away write access from the admin group,
    # and grant it to certain node types.
    project['permissions']['groups'][0]['methods'] = home_project_permissions(
        write_access)

    # Everybody should be able to comment on anything in this project.
    # This allows people to comment on shared images and see comments.
    node_type_comment = assign_permissions(node_type_comment,
                                           subscriber_methods=['GET', 'POST'],
                                           world_methods=['GET'])

    project['node_types'] = [
        node_type_group,
        node_type_asset,
        # node_type_text,
        node_type_comment,
    ]

    result, _, _, status = current_app.put_internal(
        'projects', utils.remove_private_keys(project), _id=project['_id'])
    if status != 200:
        log.error('Unable to update home project %s for user %s: %s',
                  project['_id'], user_id, result)
        raise wz_exceptions.InternalServerError(
            'Unable to update home project')
    project.update(result)

    # Create the Blender Sync node, with explicit write permissions on the node itself.
    create_blender_sync_node(project['_id'],
                             project['permissions']['groups'][0]['group'],
                             user_id)

    return project
Example #11
0
    def test_validate_token__not_logged_in(self):
        from pillar.api.utils import authentication as auth

        with self.app.test_request_context():
            self.assertFalse(auth.validate_token())